4 * aim_readtlvchain - Read a TLV chain from a buffer.
6 * @maxlen: Length of input buffer
8 * Reads and parses a series of TLV patterns from a data buffer; the
9 * returned structure is manipulatable with the rest of the TLV
10 * routines. When done with a TLV chain, aim_freetlvchain() should
11 * be called to free the dynamic substructures.
14 faim_export struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
17 struct aim_tlvlist_t *list;
18 struct aim_tlvlist_t *cur;
32 type = aimutil_get16(buf+pos);
37 length = aimutil_get16(buf+pos);
40 if ((pos+length) <= maxlen)
43 * Okay, so now AOL has decided that any TLV of
44 * type 0x0013 can only be two bytes, despite
45 * what the actual given length is. So here
46 * we dump any invalid TLVs of that sort. Hopefully
47 * theres no special cases to this special case.
50 if ((type == 0x0013) && (length != 0x0002)) {
51 printf("faim: skipping TLV t(0013) with invalid length (0x%04x)\n", length);
54 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
55 memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
57 cur->tlv = aim_createtlv();
58 cur->tlv->type = type;
59 cur->tlv->length = length;
61 cur->tlv->value = (unsigned char *)malloc(length);
62 memcpy(cur->tlv->value, buf+pos, length);
77 * aim_freetlvchain - Free a TLV chain structure
78 * @list: Chain to be freed
80 * Walks the list of TLVs in the passed TLV chain and
81 * frees each one. Note that any references to this data
82 * should be removed before calling this.
85 faim_export void aim_freetlvchain(struct aim_tlvlist_t **list)
87 struct aim_tlvlist_t *cur, *cur2;
89 if (!list || !(*list))
95 aim_freetlv(&cur->tlv);
105 * aim_counttlvchain - Count the number of TLVs in a chain
106 * @list: Chain to be counted
108 * Returns the number of TLVs stored in the passed chain.
111 faim_export int aim_counttlvchain(struct aim_tlvlist_t **list)
113 struct aim_tlvlist_t *cur;
116 if (!list || !(*list))
119 for (cur = *list; cur; cur = cur->next)
126 * aim_sizetlvchain - Count the number of bytes in a TLV chain
127 * @list: Chain to be sized
129 * Returns the number of bytes that would be needed to
130 * write the passed TLV chain to a data buffer.
133 faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list)
135 struct aim_tlvlist_t *cur;
138 if (!list || !(*list))
141 for (cur = *list; cur; cur = cur->next)
142 size += (4 + cur->tlv->length);
148 * aim_addtlvtochain_str - Add a string to a TLV chain
149 * @list: Desination chain (%NULL pointer if empty)
151 * @str: String to add
152 * @len: Length of string to add (not including %NULL)
154 * Adds the passed string as a TLV element of the passed type
158 faim_export int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
160 struct aim_tlvlist_t *newtlv;
161 struct aim_tlvlist_t *cur;
166 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
167 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
169 newtlv->tlv = aim_createtlv();
170 newtlv->tlv->type = type;
171 newtlv->tlv->length = len;
172 newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char));
173 memcpy(newtlv->tlv->value, str, newtlv->tlv->length);
179 } else if ((*list)->next == NULL) {
180 (*list)->next = newtlv;
182 for(cur = *list; cur->next; cur = cur->next)
186 return newtlv->tlv->length;
190 * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
191 * @list: Destination chain
192 * @type: TLV type to add
195 * Adds a two-byte unsigned integer to a TLV chain.
198 faim_export int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
200 struct aim_tlvlist_t *newtl;
201 struct aim_tlvlist_t *cur;
206 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
207 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
209 newtl->tlv = aim_createtlv();
210 newtl->tlv->type = type;
211 newtl->tlv->length = 2;
212 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
213 aimutil_put16(newtl->tlv->value, val);
219 } else if ((*list)->next == NULL) {
220 (*list)->next = newtl;
222 for(cur = *list; cur->next; cur = cur->next)
230 * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain
231 * @list: Destination chain
232 * @type: TLV type to add
235 * Adds a four-byte unsigned integer to a TLV chain.
238 faim_export int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
240 struct aim_tlvlist_t *newtl;
241 struct aim_tlvlist_t *cur;
246 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
247 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
249 newtl->tlv = aim_createtlv();
250 newtl->tlv->type = type;
251 newtl->tlv->length = 4;
252 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
253 aimutil_put32(newtl->tlv->value, val);
259 } else if ((*list)->next == NULL) {
260 (*list)->next = newtl;
262 for(cur = *list; cur->next; cur = cur->next)
270 * aim_addtlvtochain_caps - Add a capability block to a TLV chain
271 * @list: Destination chain
272 * @type: TLV type to add
273 * @caps: Bitfield of capability flags to send
275 * Adds a block of capability blocks to a TLV chain. The bitfield
276 * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
278 * %AIM_CAPS_BUDDYICON Supports Buddy Icons
280 * %AIM_CAPS_VOICE Supports Voice Chat
282 * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage
284 * %AIM_CAPS_CHAT Supports Chat
286 * %AIM_CAPS_GETFILE Supports Get File functions
288 * %AIM_CAPS_SENDFILE Supports Send File functions
291 faim_export int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps)
293 unsigned char buf[128]; /* icky fixed length buffer */
294 struct aim_tlvlist_t *newtl;
295 struct aim_tlvlist_t *cur;
300 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
301 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
303 newtl->tlv = aim_createtlv();
304 newtl->tlv->type = type;
306 newtl->tlv->length = aim_putcap(buf, sizeof(buf), caps);
307 newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length);
308 memcpy(newtl->tlv->value, buf, newtl->tlv->length);
314 } else if ((*list)->next == NULL) {
315 (*list)->next = newtl;
317 for(cur = *list; cur->next; cur = cur->next)
321 return newtl->tlv->length;
325 * aim_writetlvchain - Write a TLV chain into a data buffer.
326 * @buf: Destination buffer
327 * @buflen: Maximum number of bytes that will be written to buffer
328 * @list: Source TLV chain
330 * Copies a TLV chain into a raw data buffer, writing only the number
331 * of bytes specified. This operation does not free the chain;
332 * aim_freetlvchain() must still be called to free up the memory used
333 * by the chain structures.
336 faim_export int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
340 struct aim_tlvlist_t *cur;
342 if (!list || !buf || !buflen)
345 /* do an initial run to test total length */
346 for (cur = *list; cur; cur = cur->next) {
347 goodbuflen += 2 + 2; /* type + len */
348 goodbuflen += cur->tlv->length;
351 if (goodbuflen > buflen)
352 return 0; /* not enough buffer */
354 /* do the real write-out */
355 for (cur = *list; cur; cur = cur->next) {
356 i += aimutil_put16(buf+i, cur->tlv->type);
357 i += aimutil_put16(buf+i, cur->tlv->length);
358 memcpy(buf+i, cur->tlv->value, cur->tlv->length);
359 i += cur->tlv->length;
367 * aim_gettlv - Grab the Nth TLV of type type in the TLV list list.
368 * @list: Source chain
369 * @type: Requested TLV type
370 * @nth: Index of TLV of type to get
372 * Returns a pointer to an aim_tlv_t of the specified type;
373 * %NULL on error. The @nth parameter is specified starting at %1.
374 * In most cases, there will be no more than one TLV of any type
378 faim_export struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
381 struct aim_tlvlist_t *cur;
384 for (cur = list; cur != NULL; cur = cur->next)
388 if (cur->tlv->type == type)
398 * aim_gettlv_str - Retrieve the Nth TLV in chain as a string.
399 * @list: Source TLV chain
400 * @type: TLV type to search for
401 * @nth: Index of TLV to return
403 * Same as aim_gettlv(), except that the return value is a %NULL-
404 * terminated string instead of an aim_tlv_t. This is a
405 * dynamic buffer and must be freed by the caller.
408 faim_export char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
410 struct aim_tlv_t *tlv;
413 if (!(tlv = aim_gettlv(list, type, nth)))
416 newstr = (char *) malloc(tlv->length + 1);
417 memcpy(newstr, tlv->value, tlv->length);
418 *(newstr + tlv->length) = '\0';
424 * aim_grabtlv - Grab a single TLV from a data buffer
425 * @src: Source data buffer (must be at least 4 bytes long)
427 * Creates a TLV structure aim_tlv_t and returns it
428 * filled with values from a buffer, possibly including a
429 * dynamically allocated buffer for the value portion.
431 * Both the aim_tlv_t and the tlv->value pointer
432 * must be freed by the caller if non-%NULL.
435 faim_export struct aim_tlv_t *aim_grabtlv(u_char *src)
437 struct aim_tlv_t *dest = NULL;
439 dest = aim_createtlv();
441 dest->type = src[0] << 8;
442 dest->type += src[1];
444 dest->length = src[2] << 8;
445 dest->length += src[3];
447 dest->value = (u_char *) malloc(dest->length*sizeof(u_char));
448 memset(dest->value, 0, dest->length*sizeof(u_char));
450 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
456 * aim_grabtlvstr - Grab a single TLV from a data buffer as string
457 * @src: Source data buffer (must be at least 4 bytes long)
459 * Creates a TLV structure aim_tlv_t and returns it
460 * filled with values from a buffer, possibly including a
461 * dynamically allocated buffer for the value portion, which
462 * is %NULL-terminated as a string.
464 * Both the aim_tlv_t and the tlv->value pointer
465 * must be freed by the caller if non-%NULL.
468 faim_export struct aim_tlv_t *aim_grabtlvstr(u_char *src)
470 struct aim_tlv_t *dest = NULL;
472 dest = aim_createtlv();
474 dest->type = src[0] << 8;
475 dest->type += src[1];
477 dest->length = src[2] << 8;
478 dest->length += src[3];
480 dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char));
481 memset(dest->value, 0, (dest->length+1)*sizeof(u_char));
483 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
484 dest->value[dest->length] = '\0';
490 * aim_puttlv - Write a aim_tlv_t into a data buffer
491 * @dest: Destination data buffer
492 * @newtlv: Source TLV structure
494 * Writes out the passed TLV structure into the buffer. No bounds
495 * checking is done on the output buffer.
497 * The passed aim_tlv_t is not freed. aim_freetlv() should
498 * still be called by the caller to free the structure.
501 faim_export int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
505 dest[i++] = newtlv->type >> 8;
506 dest[i++] = newtlv->type & 0x00FF;
507 dest[i++] = newtlv->length >> 8;
508 dest[i++] = newtlv->length & 0x00FF;
509 memcpy(&(dest[i]), newtlv->value, newtlv->length);
515 * aim_createtlv - Generate an aim_tlv_t structure.
517 * Allocates an empty TLV structure and returns a pointer
518 * to it; %NULL on error.
521 faim_export struct aim_tlv_t *aim_createtlv(void)
523 struct aim_tlv_t *newtlv;
525 if (!(newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t))))
527 memset(newtlv, 0, sizeof(struct aim_tlv_t));
532 * aim_freetlv - Free a aim_tlv_t structure
533 * @oldtlv: TLV to be destroyed
535 * Frees both the TLV structure and the value portion.
538 faim_export int aim_freetlv(struct aim_tlv_t **oldtlv)
544 if ((*oldtlv)->value)
545 free((*oldtlv)->value);
553 * aim_puttlv_16 - Write a two-byte TLV.
554 * @buf: Destination buffer
558 * Writes a TLV with a two-byte integer value portion.
561 faim_export int aim_puttlv_16(u_char *buf, u_short t, u_short v)
564 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
565 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0002);
566 curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff));
571 * aim_puttlv_32 - Write a four-byte TLV.
572 * @buf: Destination buffer
576 * Writes a TLV with a four-byte integer value portion.
579 faim_export int aim_puttlv_32(u_char *buf, u_short t, u_long v)
582 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
583 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004);
584 curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff));
589 * aim_puttlv_str - Write a string TLV.
590 * @buf: Destination buffer
592 * @l: Length of string
593 * @v: String to write
595 * Writes a TLV with a string value portion. (Only the first @l
596 * bytes of the passed string will be written, which should not
597 * include the terminating NULL.)
600 faim_export int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
605 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
606 curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
608 memcpy(buf+curbyte, (unsigned char *)v, l);