struct aim_tlvlist_t *tlvlist;
int ret = 1;
- tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
+ if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
+ {
+ printf("libfaim: major bug: unable to read tlvchain from redirect\n");
+ return ret;
+ }
- tmptlv = aim_gettlv(tlvlist, 0x000d, 1);
+ if (!(tmptlv = aim_gettlv(tlvlist, 0x000d, 1)))
+ {
+ printf("libfaim: major bug: no service ID in tlvchain from redirect\n");
+ aim_freetlvchain(&tlvlist);
+ return ret;
+ }
serviceid = aimutil_get16(tmptlv->value);
- ip = aim_gettlv_str(tlvlist, 0x0005, 1);
+ if (!(ip = aim_gettlv_str(tlvlist, 0x0005, 1)))
+ {
+ printf("libfaim: major bug: no IP in tlvchain from redirect (service 0x%02x)\n", serviceid);
+ aim_freetlvchain(&tlvlist);
+ return ret;
+ }
- tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
+ if (!(tmptlv = aim_gettlv(tlvlist, 0x0006, 1)))
+ {
+ printf("libfaim: major bug: no cookie in tlvchain from redirect (service 0x%02x)\n", serviceid);
+ aim_freetlvchain(&tlvlist);
+ return ret;
+ }
memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
if (serviceid == AIM_CONN_TYPE_CHAT)
if (userfunc)
ret = userfunc(sess, command, serviceid, ip, cookie);
}
+
+ /*
+ * XXX: Is there a leak here? Where does IP get freed?
+ */
aim_freetlvchain(&tlvlist);
return ret;
return;
}
+int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str)
+{
+ struct aim_tlvlist_t *new;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(new, 0x00, sizeof(struct aim_tlvlist_t));
+
+ new->tlv = aim_createtlv();
+ new->tlv->type = type;
+ new->tlv->length = strlen(str);
+ new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
+ memcpy(new->tlv->value, str, new->tlv->length);
+
+ new->next = NULL;
+
+ if (*list == NULL) {
+ *list = new;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = new;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = new;
+ }
+ return new->tlv->length;
+}
+
+int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
+{
+ struct aim_tlvlist_t *new;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(new, 0x00, sizeof(struct aim_tlvlist_t));
+
+ new->tlv = aim_createtlv();
+ new->tlv->type = type;
+ new->tlv->length = 2;
+ new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
+ aimutil_put16(new->tlv->value, val);
+
+ new->next = NULL;
+
+ if (*list == NULL) {
+ *list = new;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = new;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = new;
+ }
+ return 2;
+}
+
+int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
+{
+ struct aim_tlvlist_t *new;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(new, 0x00, sizeof(struct aim_tlvlist_t));
+
+ new->tlv = aim_createtlv();
+ new->tlv->type = type;
+ new->tlv->length = 4;
+ new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
+ aimutil_put32(new->tlv->value, val);
+
+ new->next = NULL;
+
+ if (*list == NULL) {
+ *list = new;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = new;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = new;
+ }
+ return 4;
+}
+
+int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
+{
+ int goodbuflen = 0;
+ int i = 0;
+ struct aim_tlvlist_t *cur;
+
+ if (!list || !buf || !buflen)
+ return 0;
+
+ /* do an initial run to test total length */
+ for (cur = *list; cur; cur = cur->next) {
+ goodbuflen += 2 + 2; /* type + len */
+ goodbuflen += cur->tlv->length;
+ }
+
+ if (goodbuflen > buflen)
+ return 0; /* not enough buffer */
+
+ /* do the real write-out */
+ for (cur = *list; cur; cur = cur->next) {
+ i += aimutil_put16(buf+i, cur->tlv->type);
+ i += aimutil_put16(buf+i, cur->tlv->length);
+ memcpy(buf+i, cur->tlv->value, cur->tlv->length);
+ i += cur->tlv->length;
+ }
+
+ return i;
+}
+
+
/*
* Grab the Nth TLV of type type in the TLV list list.
*/
int aim_puttlv_16(u_char *, u_short, u_short);
int aim_puttlv_32(u_char *, u_short, u_long);
int aim_puttlv_str(u_char *buf, u_short t, u_short l, u_char *v);
-
+int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list);
+int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val);
+int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val);
+int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str);
/*
* Get command from connections / Dispatch commands