X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/blobdiff_plain/49c8a2fa4d66462a98cd44074818ca2e942d0f6f..3b101546ec5eb89988837c6134b01281dd0cfe0d:/aim_tlv.c diff --git a/aim_tlv.c b/aim_tlv.c index a8cf05b..3557d5a 100644 --- a/aim_tlv.c +++ b/aim_tlv.c @@ -1,6 +1,6 @@ -#include +#include -struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen) +faim_internal struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen) { int pos; struct aim_tlvlist_t *list; @@ -28,18 +28,32 @@ struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen) if ((pos+length) <= maxlen) { - cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); - memset(cur, 0x00, sizeof(struct aim_tlvlist_t)); - - cur->tlv = aim_createtlv(); - cur->tlv->type = type; - cur->tlv->length = length; - cur->tlv->value = (u_char *)malloc(length*sizeof(u_char)); - memcpy(cur->tlv->value, buf+pos, length); - - cur->next = list; - list = cur; - + /* + * Okay, so now AOL has decided that any TLV of + * type 0x0013 can only be two bytes, despite + * what the actual given length is. So here + * we dump any invalid TLVs of that sort. Hopefully + * theres no special cases to this special case. + * - mid (30jun2000) + */ + if ((type == 0x0013) && (length != 0x0002)) { + printf("faim: skipping TLV t(0013) with invalid length (0x%04x)\n", length); + length = 0x0002; + } else { + cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); + memset(cur, 0x00, sizeof(struct aim_tlvlist_t)); + + cur->tlv = aim_createtlv(); + cur->tlv->type = type; + cur->tlv->length = length; + if (length) { + cur->tlv->value = (unsigned char *)malloc(length); + memcpy(cur->tlv->value, buf+pos, length); + } + + cur->next = list; + list = cur; + } pos += length; } } @@ -48,7 +62,7 @@ struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen) return list; } -void aim_freetlvchain(struct aim_tlvlist_t **list) +faim_internal void aim_freetlvchain(struct aim_tlvlist_t **list) { struct aim_tlvlist_t *cur, *cur2; @@ -67,10 +81,192 @@ void aim_freetlvchain(struct aim_tlvlist_t **list) return; } +faim_internal int aim_counttlvchain(struct aim_tlvlist_t **list) +{ + struct aim_tlvlist_t *cur; + int count = 0; + + if (!list || !(*list)) + return 0; + + for (cur = *list; cur; cur = cur->next) + count++; + + return count; +} + +faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list) +{ + struct aim_tlvlist_t *cur; + int size = 0; + + if (!list || !(*list)) + return 0; + + for (cur = *list; cur; cur = cur->next) + size += (4 + cur->tlv->length); + + return size; +} + + +faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len) +{ + struct aim_tlvlist_t *newtlv; + struct aim_tlvlist_t *cur; + + if (!list) + return 0; + + newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); + memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t)); + + newtlv->tlv = aim_createtlv(); + newtlv->tlv->type = type; + newtlv->tlv->length = len; + newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char)); + memcpy(newtlv->tlv->value, str, newtlv->tlv->length); + + newtlv->next = NULL; + + if (*list == NULL) { + *list = newtlv; + } else if ((*list)->next == NULL) { + (*list)->next = newtlv; + } else { + for(cur = *list; cur->next; cur = cur->next) + ; + cur->next = newtlv; + } + return newtlv->tlv->length; +} + +faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val) +{ + struct aim_tlvlist_t *newtl; + struct aim_tlvlist_t *cur; + + if (!list) + return 0; + + newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); + memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); + + newtl->tlv = aim_createtlv(); + newtl->tlv->type = type; + newtl->tlv->length = 2; + newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char)); + aimutil_put16(newtl->tlv->value, val); + + newtl->next = NULL; + + if (*list == NULL) { + *list = newtl; + } else if ((*list)->next == NULL) { + (*list)->next = newtl; + } else { + for(cur = *list; cur->next; cur = cur->next) + ; + cur->next = newtl; + } + return 2; +} + +faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val) +{ + struct aim_tlvlist_t *newtl; + struct aim_tlvlist_t *cur; + + if (!list) + return 0; + + newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); + memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); + + newtl->tlv = aim_createtlv(); + newtl->tlv->type = type; + newtl->tlv->length = 4; + newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char)); + aimutil_put32(newtl->tlv->value, val); + + newtl->next = NULL; + + if (*list == NULL) { + *list = newtl; + } else if ((*list)->next == NULL) { + (*list)->next = newtl; + } else { + for(cur = *list; cur->next; cur = cur->next) + ; + cur->next = newtl; + } + return 4; +} + +faim_internal int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps) +{ + unsigned char buf[128]; /* icky fixed length buffer */ + struct aim_tlvlist_t *newtl; + struct aim_tlvlist_t *cur; + + if(!list) + return 0; + + newtl->tlv = aim_createtlv(); + newtl->tlv->type = type; + + newtl->tlv->length = aim_putcap(buf, 128, caps); + newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length); + memcpy(newtl->tlv->value, &buf, newtl->tlv->length); + + newtl->next = NULL; + + if (*list == NULL) { + *list = newtl; + } else if ((*list)->next == NULL) { + (*list)->next = newtl; + } else { + for(cur = *list; cur->next; cur = cur->next) + ; + cur->next = newtl; + } + return newtl->tlv->length; +} + +faim_internal 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. */ -struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth) +faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth) { int i; struct aim_tlvlist_t *cur; @@ -89,7 +285,7 @@ struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth) return NULL; } -char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth) +faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth) { struct aim_tlv_t *tlv; char *newstr; @@ -104,7 +300,7 @@ char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth) return newstr; } -struct aim_tlv_t *aim_grabtlv(u_char *src) +faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src) { struct aim_tlv_t *dest = NULL; @@ -124,7 +320,7 @@ struct aim_tlv_t *aim_grabtlv(u_char *src) return dest; } -struct aim_tlv_t *aim_grabtlvstr(u_char *src) +faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src) { struct aim_tlv_t *dest = NULL; @@ -145,7 +341,7 @@ struct aim_tlv_t *aim_grabtlvstr(u_char *src) return dest; } -int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv) +faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv) { int i=0; @@ -158,7 +354,7 @@ int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv) return i; } -struct aim_tlv_t *aim_createtlv(void) +faim_internal struct aim_tlv_t *aim_createtlv(void) { struct aim_tlv_t *newtlv = NULL; newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t)); @@ -166,7 +362,7 @@ struct aim_tlv_t *aim_createtlv(void) return newtlv; } -int aim_freetlv(struct aim_tlv_t **oldtlv) +faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv) { if (!oldtlv) return -1; @@ -180,7 +376,7 @@ int aim_freetlv(struct aim_tlv_t **oldtlv) return 0; } -int aim_puttlv_16(u_char *buf, u_short t, u_short v) +faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v) { int curbyte=0; curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); @@ -188,3 +384,25 @@ int aim_puttlv_16(u_char *buf, u_short t, u_short v) curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff)); return curbyte; } + +faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v) +{ + int curbyte=0; + curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); + curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004); + curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff)); + return curbyte; +} + +faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v) +{ + int curbyte; + + curbyte = 0; + curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); + curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff)); + if (v) + memcpy(buf+curbyte, (unsigned char *)v, l); + curbyte += l; + return curbyte; +}