X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/blobdiff_plain/5e02cf4469b54ab840378d8830db7bdb28ef46ea..9797852cb1854c00f6d3caffb5a21b500fafe9bd:/aim_rxhandlers.c diff --git a/aim_rxhandlers.c b/aim_rxhandlers.c index 7e4fc75..aaeba3b 100644 --- a/aim_rxhandlers.c +++ b/aim_rxhandlers.c @@ -311,6 +311,19 @@ int aim_rxdispatch(struct aim_session_t *sess) if (workingPtr->handled) continue; + /* + * This is a debugging/sanity check only and probably could/should be removed + * for stable code. + */ + if (((workingPtr->hdrtype == AIM_FRAMETYPE_OFT) && + (workingPtr->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) || + ((workingPtr->hdrtype == AIM_FRAMETYPE_OSCAR) && + (workingPtr->conn->type == AIM_CONN_TYPE_RENDEZVOUS))) { + printf("faim: rxhandlers: incompatible frame type %d on connection type 0x%04x\n", workingPtr->hdrtype, workingPtr->conn->type); + workingPtr->handled = 1; + continue; + } + switch(workingPtr->conn->type) { case -1: /* @@ -329,7 +342,9 @@ int aim_rxdispatch(struct aim_session_t *sess) if (head == 0x00000001) { faimdprintf(1, "got connection ack on auth line\n"); workingPtr->handled = 1; - } else { + } else if (workingPtr->hdr.oscar.type == 0x0004) { + workingPtr->handled = aim_authparse(sess, workingPtr); + } else { u_short family,subtype; family = aimutil_get16(workingPtr->data); @@ -337,33 +352,31 @@ int aim_rxdispatch(struct aim_session_t *sess) switch (family) { /* New login protocol */ -#ifdef SNACLOGIN case 0x0017: if (subtype == 0x0001) workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr); else if (subtype == 0x0003) workingPtr->handled = aim_authparse(sess, workingPtr); else if (subtype == 0x0007) - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0007, workingPtr); + workingPtr->handled = aim_authkeyparse(sess, workingPtr); else workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr); break; -#else - /* XXX: this isnt foolproof */ - case 0x0001: - if (subtype == 0x0003) - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, workingPtr); - else - workingPtr->handled = aim_authparse(sess, workingPtr); - break; - case 0x0007: - if (subtype == 0x0005) - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr); + case 0x0007: + if (subtype == 0x0005) + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr); + break; + case AIM_CB_FAM_SPECIAL: + if (subtype == AIM_CB_SPECIAL_DEBUGCONN_CONNECT) { + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr); + break; + } /* others fall through */ + default: +#if 0 + /* Old login protocol */ + /* any user callbacks will be called from here */ + workingPtr->handled = aim_authparse(sess, workingPtr); break; - default: - /* Old login protocol */ - /* any user callbacks will be called from here */ - workingPtr->handled = aim_authparse(sess, workingPtr); #endif } } @@ -373,7 +386,7 @@ int aim_rxdispatch(struct aim_session_t *sess) u_short family; u_short subtype; - if (workingPtr->type == 0x04) { + if (workingPtr->hdr.oscar.type == 0x04) { workingPtr->handled = aim_negchan_middle(sess, workingPtr); break; } @@ -403,11 +416,14 @@ int aim_rxdispatch(struct aim_session_t *sess) workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr); break; case 0x000a: - workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000a, workingPtr); + workingPtr->handled = aim_parse_ratechange_middle(sess, workingPtr); break; case 0x000f: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x000f, workingPtr); break; + case 0x0010: + workingPtr->handled = aim_parse_evilnotify_middle(sess, workingPtr); + break; case 0x0013: workingPtr->handled = aim_parsemotd_middle(sess, workingPtr); break; @@ -456,12 +472,18 @@ int aim_rxdispatch(struct aim_session_t *sess) case 0x0005: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr); break; + case 0x0006: + workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr); + break; case 0x0007: workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr); break; case 0x000a: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x000a, workingPtr); break; + case 0x000c: + workingPtr->handled = aim_parse_msgack_middle(sess, workingPtr); + break; default: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr); } @@ -494,6 +516,9 @@ int aim_rxdispatch(struct aim_session_t *sess) else workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr); break; + case AIM_CB_FAM_SPECIAL: + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr); + break; default: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr); break; @@ -532,7 +557,7 @@ int aim_rxdispatch(struct aim_session_t *sess) else if (subtype == 0x0007) workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr); else - printf("Chat: unknown snac %04x/%04x\n", family, subtype); + workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr); } else if (family == 0x000e) { if (subtype == 0x0002) workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr); @@ -550,8 +575,25 @@ int aim_rxdispatch(struct aim_session_t *sess) } break; } + case AIM_CONN_TYPE_RENDEZVOUS: { + /* make sure that we only get OFT frames on these connections */ + if (workingPtr->hdrtype != AIM_FRAMETYPE_OFT) { + printf("faim: internal error: non-OFT frames on OFT connection\n"); + workingPtr->handled = 1; /* get rid of it */ + break; + } + + /* XXX: implement this */ + printf("faim: OFT frame!\n"); + + break; + } + case AIM_CONN_TYPE_RENDEZVOUS_OUT: { + /* not possible */ + break; + } default: - printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, channel = %02x, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->type, workingPtr->commandlen); + printf("\ninternal error: unknown connection type (very bad.) (type = %d, fd = %d, commandlen = %02x)\n\n", workingPtr->conn->type, workingPtr->conn->fd, workingPtr->commandlen); workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr); break; } @@ -569,8 +611,76 @@ int aim_rxdispatch(struct aim_session_t *sess) return 0; } +int aim_parse_msgack_middle(struct aim_session_t *sess, struct command_rx_struct *command) +{ + rxcallback_t userfunc = NULL; + char sn[MAXSNLEN]; + unsigned short type; + int i = 10+8; /* skip SNAC and cookie */ + int ret = 1; + unsigned char snlen; + + type = aimutil_get16(command->data+i); + i += 2; + + snlen = aimutil_get8(command->data+i); + i++; + + memset(sn, 0, sizeof(sn)); + strncpy(sn, command->data+i, snlen); + + if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x000c))) + ret = userfunc(sess, command, type, sn); + + return ret; +} + +int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command) +{ + rxcallback_t userfunc = NULL; + int ret = 1; + unsigned long newrate; + + if (command->commandlen != 0x2f) { + printf("faim: unknown rate change length 0x%04x\n", command->commandlen); + return 1; + } + + newrate = aimutil_get32(command->data+34); + + if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a))) + ret = userfunc(sess, command, newrate); + + return ret; +} + +int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command) +{ + rxcallback_t userfunc = NULL; + int ret = 1, pos; + char *sn = NULL; + + if(command->commandlen < 12) /* a warning level dec sends this */ + return 1; + + if ((pos = aimutil_get8(command->data+ 12)) > MAXSNLEN) + return 1; + + if(!(sn = (char *)calloc(1, pos+1))) + return 1; + + memcpy(sn, command->data+13, pos); + + if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010))) + ret = userfunc(sess, command, sn); + + free(sn); + + return ret; +} + int aim_parsemotd_middle(struct aim_session_t *sess, - struct command_rx_struct *command, ...) + struct command_rx_struct *command, ...) { rxcallback_t userfunc = NULL; char *msg; @@ -579,25 +689,36 @@ int aim_parsemotd_middle(struct aim_session_t *sess, u_short id; /* - * Dunno. + * Code. + * + * Valid values: + * 1 Mandatory upgrade + * 2 Advisory upgrade + * 3 System bulletin + * 4 Nothing's wrong ("top o the world" -- normal) + * */ id = aimutil_get16(command->data+10); /* * TLVs follow */ - tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12); - - msg = aim_gettlv_str(tlvlist, 0x000b, 1); + if (!(tlvlist = aim_readtlvchain(command->data+12, command->commandlen-12))) + return ret; + + if (!(msg = aim_gettlv_str(tlvlist, 0x000b, 1))) { + aim_freetlvchain(&tlvlist); + return ret; + } userfunc = aim_callhandler(command->conn, 0x0001, 0x0013); if (userfunc) ret = userfunc(sess, command, id, msg); aim_freetlvchain(&tlvlist); + free(msg); - return ret; - + return ret; } int aim_handleredirect_middle(struct aim_session_t *sess, @@ -628,6 +749,7 @@ int aim_handleredirect_middle(struct aim_session_t *sess, if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1))) { printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid); + free(ip); aim_freetlvchain(&tlvlist); return ret; } @@ -635,6 +757,7 @@ int aim_handleredirect_middle(struct aim_session_t *sess, if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1))) { printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid); + free(ip); aim_freetlvchain(&tlvlist); return ret; } @@ -659,9 +782,7 @@ int aim_handleredirect_middle(struct aim_session_t *sess, ret = userfunc(sess, command, serviceid, ip, cookie); } - /* - * XXX: Is there a leak here? Where does IP get freed? - */ + free(ip); aim_freetlvchain(&tlvlist); return ret; @@ -677,12 +798,12 @@ int aim_parse_unknown(struct aim_session_t *sess, for (i = 0; i < command->commandlen; i++) { if ((i % 8) == 0) - printf("\n\t"); + faimdprintf(1, "\n\t"); - printf("0x%2x ", command->data[i]); + faimdprintf(1, "0x%2x ", command->data[i]); } - printf("\n\n"); + faimdprintf(1, "\n\n"); return 1; }