/** * aim_addtlvtochain_str - Add a string to a TLV chain * @list: Desination chain (%NULL pointer if empty) * @type: TLV type * @str: String to add * @len: Length of string to add (not including %NULL) * * Adds the passed string as a TLV element of the passed type * to the TLV chain. * */ faim_internal int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v) { aim_tlvlist_t *newtlv, *cur; if (!list) return 0; if (!(newtlv = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)))) return 0; memset(newtlv, 0x00, sizeof(aim_tlvlist_t)); if (!(newtlv->tlv = createtlv())) { free(newtlv); return 0; } newtlv->tlv->type = t; if ((newtlv->tlv->length = l)) { newtlv->tlv->value = (fu8_t *)malloc(newtlv->tlv->length); memcpy(newtlv->tlv->value, v, newtlv->tlv->length); } if (!*list) *list = newtlv; else { for(cur = *list; cur->next; cur = cur->next) ; cur->next = newtlv; } return newtlv->tlv->length; }
GSList * msn_tlvlist_read(const char *bs, size_t bs_len) { GSList *list = NULL; while (bs_len > 0) { guint8 type, length; msn_tlv_t *tlv; if (bs_len == 3 && *bs == 0) { /* Padding to multiple of 4 */ break; } else if (bs_len == 2 && *bs == 0) { /* Padding to multiple of 4 */ break; } else if (bs_len == 1) { if (*bs == 0) { /* Padding to multiple of 4 */ break; } else { /* TLV is not small enough to fit here */ msn_tlvlist_free(list); return NULL; } } type = msn_pop8(bs); length = msn_pop8(bs); bs_len -= 2; if (length > bs_len) { msn_tlvlist_free(list); return NULL; } tlv = createtlv(type, length, NULL); if (length > 0) { tlv->value = g_memdup(bs, length); if (!tlv->value) { freetlv(tlv); msn_tlvlist_free(list); return NULL; } } bs_len -= length; bs += length; list = g_slist_prepend(list, tlv); } return g_slist_reverse(list); }
/** * Read a TLV chain from a buffer. * * Reads and parses a series of TLV patterns from a data buffer; the * returned structure is manipulatable with the rest of the TLV * routines. When done with a TLV chain, aim_tlvlist_free() should * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain * bstream references, so that at least the ->value portion of each * element doesn't need to be malloc/memcpy'd. This could prove to be * just as effecient as the in-place TLV parsing used in a couple places * in libfaim. * * @param bs Input bstream * @param num The max number of TLVs that will be read, or -1 if unlimited. * There are a number of places where you want to read in a tlvchain, * but the chain is not at the end of the SNAC, and the chain is * preceeded by the number of TLVs. So you can limit that with this. */ faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num) { aim_tlvlist_t *list = NULL, *cur; while ((aim_bstream_empty(bs) > 0) && (num != 0)) { fu16_t type, length; type = aimbs_get16(bs); length = aimbs_get16(bs); if (length > aim_bstream_empty(bs)) { aim_tlvlist_free(&list); return NULL; } cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)); if (!cur) { aim_tlvlist_free(&list); return NULL; } memset(cur, 0, sizeof(aim_tlvlist_t)); cur->tlv = createtlv(type, length, NULL); if (!cur->tlv) { free(cur); aim_tlvlist_free(&list); return NULL; } if (cur->tlv->length > 0) { cur->tlv->value = aimbs_getraw(bs, length); if (!cur->tlv->value) { freetlv(&cur->tlv); free(cur); aim_tlvlist_free(&list); return NULL; } } if (num > 0) num--; cur->next = list; list = cur; } return list; }
/** * aim_readtlvchain_len - Read a TLV chain from a buffer. * @param bs Input bstream * @param len The max length in bytes that will be read. * There are a number of places where you want to read in a tlvchain, * but the chain is not at the end of the SNAC, and the chain is * preceeded by the length of the TLVs. So you can limit that with this. * * Reads and parses a series of TLV patterns from a data buffer; the * returned structure is manipulatable with the rest of the TLV * routines. When done with a TLV chain, aim_freetlvchain() should * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain * bstream references, so that at least the ->value portion of each * element doesn't need to be malloc/memcpy'd. This could prove to be * just as effecient as the in-place TLV parsing used in a couple places * in libfaim. * */ faim_internal aim_tlvlist_t *aim_readtlvchain_len(aim_bstream_t *bs, fu16_t len) { aim_tlvlist_t *list = NULL, *cur; while ((aim_bstream_empty(bs) > 0) && (len > 0)) { fu16_t type, length; type = aimbs_get16(bs); length = aimbs_get16(bs); if (length > aim_bstream_empty(bs)) { aim_freetlvchain(&list); return NULL; } cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)); if (!cur) { aim_freetlvchain(&list); return NULL; } memset(cur, 0, sizeof(aim_tlvlist_t)); cur->tlv = createtlv(); if (!cur->tlv) { free(cur); aim_freetlvchain(&list); return NULL; } cur->tlv->type = type; if ((cur->tlv->length = length)) { cur->tlv->value = aimbs_getraw(bs, length); if (!cur->tlv->value) { freetlv(&cur->tlv); free(cur); aim_freetlvchain(&list); return NULL; } } len -= aim_sizetlvchain(&cur); cur->next = list; list = cur; } return list; }
static GSList * aim_tlv_read(GSList *list, ByteStream *bs) { guint16 type, length; aim_tlv_t *tlv; type = byte_stream_get16(bs); length = byte_stream_get16(bs); #if 0 /* * This code hasn't been needed in years. It's been commented * out since 2003, at the latest. It seems likely that it was * just a bug in their server code that has since been fixed. * In any case, here's the orignal comment, kept for historical * purposes: * * 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 * there's no special cases to this special case. * - mid (30jun2000) */ if ((type == 0x0013) && (length != 0x0002)) { length = 0x0002; return list; } #endif if (length > byte_stream_empty(bs)) { aim_tlvlist_free(list); return NULL; } tlv = createtlv(type, length, NULL); if (tlv->length > 0) { tlv->value = byte_stream_getraw(bs, length); if (!tlv->value) { freetlv(tlv); aim_tlvlist_free(list); return NULL; } } return g_slist_prepend(list, tlv); }
/** * aim_readtlvchain - Read a TLV chain from a buffer. * @buf: Input buffer * @maxlen: Length of input buffer * * Reads and parses a series of TLV patterns from a data buffer; the * returned structure is manipulatable with the rest of the TLV * routines. When done with a TLV chain, aim_freetlvchain() should * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain * bstream references, so that at least the ->value portion of each * element doesn't need to be malloc/memcpy'd. This could prove to be * just as effecient as the in-place TLV parsing used in a couple places * in libfaim. * */ faim_internal aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs) { aim_tlvlist_t *list = NULL, *cur; fu16_t type, length; while (aim_bstream_empty(bs)) { type = aimbs_get16(bs); length = aimbs_get16(bs); #if 0 /* temporarily disabled until I know if they're still doing it or not */ /* * 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)) length = 0x0002; #else if (0) ; #endif else { cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)); memset(cur, 0, sizeof(aim_tlvlist_t)); cur->tlv = createtlv(); cur->tlv->type = type; if ((cur->tlv->length = length)) cur->tlv->value = aimbs_getraw(bs, length); cur->next = list; list = cur; } } return list; }