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:
/*
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);
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
}
}
u_short family;
u_short subtype;
- if (workingPtr->type == 0x04) {
+ if (workingPtr->hdr.oscar.type == 0x04) {
workingPtr->handled = aim_negchan_middle(sess, workingPtr);
break;
}
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;
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);
}
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;
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);
}
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;
}
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;
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,
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;
}
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;
}
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;
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;
}