6 * aim_readtlvchain - Read a TLV chain from a buffer.
8 * @maxlen: Length of input buffer
10 * Reads and parses a series of TLV patterns from a data buffer; the
11 * returned structure is manipulatable with the rest of the TLV
12 * routines. When done with a TLV chain, aim_freetlvchain() should
13 * be called to free the dynamic substructures.
16 faim_export struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
19 struct aim_tlvlist_t *list;
20 struct aim_tlvlist_t *cur;
34 type = aimutil_get16(buf+pos);
39 length = aimutil_get16(buf+pos);
42 if ((pos+length) <= maxlen)
45 * Okay, so now AOL has decided that any TLV of
46 * type 0x0013 can only be two bytes, despite
47 * what the actual given length is. So here
48 * we dump any invalid TLVs of that sort. Hopefully
49 * theres no special cases to this special case.
52 if ((type == 0x0013) && (length != 0x0002)) {
53 printf("faim: skipping TLV t(0013) with invalid length (0x%04x)\n", length);
56 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
57 memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
59 cur->tlv = aim_createtlv();
60 cur->tlv->type = type;
61 cur->tlv->length = length;
63 cur->tlv->value = (unsigned char *)malloc(length);
64 memcpy(cur->tlv->value, buf+pos, length);
79 * aim_freetlvchain - Free a TLV chain structure
80 * @list: Chain to be freed
82 * Walks the list of TLVs in the passed TLV chain and
83 * frees each one. Note that any references to this data
84 * should be removed before calling this.
87 faim_export void aim_freetlvchain(struct aim_tlvlist_t **list)
89 struct aim_tlvlist_t *cur, *cur2;
91 if (!list || !(*list))
97 aim_freetlv(&cur->tlv);
107 * aim_counttlvchain - Count the number of TLVs in a chain
108 * @list: Chain to be counted
110 * Returns the number of TLVs stored in the passed chain.
113 faim_export int aim_counttlvchain(struct aim_tlvlist_t **list)
115 struct aim_tlvlist_t *cur;
118 if (!list || !(*list))
121 for (cur = *list; cur; cur = cur->next)
128 * aim_sizetlvchain - Count the number of bytes in a TLV chain
129 * @list: Chain to be sized
131 * Returns the number of bytes that would be needed to
132 * write the passed TLV chain to a data buffer.
135 faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list)
137 struct aim_tlvlist_t *cur;
140 if (!list || !(*list))
143 for (cur = *list; cur; cur = cur->next)
144 size += (4 + cur->tlv->length);
150 * aim_addtlvtochain_str - Add a string to a TLV chain
151 * @list: Desination chain (%NULL pointer if empty)
153 * @str: String to add
154 * @len: Length of string to add (not including %NULL)
156 * Adds the passed string as a TLV element of the passed type
160 faim_export int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
162 struct aim_tlvlist_t *newtlv;
163 struct aim_tlvlist_t *cur;
168 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
169 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
171 newtlv->tlv = aim_createtlv();
172 newtlv->tlv->type = type;
173 newtlv->tlv->length = len;
174 newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char));
175 memcpy(newtlv->tlv->value, str, newtlv->tlv->length);
181 } else if ((*list)->next == NULL) {
182 (*list)->next = newtlv;
184 for(cur = *list; cur->next; cur = cur->next)
188 return newtlv->tlv->length;
192 * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
193 * @list: Destination chain
194 * @type: TLV type to add
197 * Adds a two-byte unsigned integer to a TLV chain.
200 faim_export int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
202 struct aim_tlvlist_t *newtl;
203 struct aim_tlvlist_t *cur;
208 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
209 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
211 newtl->tlv = aim_createtlv();
212 newtl->tlv->type = type;
213 newtl->tlv->length = 2;
214 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
215 aimutil_put16(newtl->tlv->value, val);
221 } else if ((*list)->next == NULL) {
222 (*list)->next = newtl;
224 for(cur = *list; cur->next; cur = cur->next)
232 * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain
233 * @list: Destination chain
234 * @type: TLV type to add
237 * Adds a four-byte unsigned integer to a TLV chain.
240 faim_export int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
242 struct aim_tlvlist_t *newtl;
243 struct aim_tlvlist_t *cur;
248 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
249 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
251 newtl->tlv = aim_createtlv();
252 newtl->tlv->type = type;
253 newtl->tlv->length = 4;
254 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
255 aimutil_put32(newtl->tlv->value, val);
261 } else if ((*list)->next == NULL) {
262 (*list)->next = newtl;
264 for(cur = *list; cur->next; cur = cur->next)
272 * aim_addtlvtochain_caps - Add a capability block to a TLV chain
273 * @list: Destination chain
274 * @type: TLV type to add
275 * @caps: Bitfield of capability flags to send
277 * Adds a block of capability blocks to a TLV chain. The bitfield
278 * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
280 * %AIM_CAPS_BUDDYICON Supports Buddy Icons
282 * %AIM_CAPS_VOICE Supports Voice Chat
284 * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage
286 * %AIM_CAPS_CHAT Supports Chat
288 * %AIM_CAPS_GETFILE Supports Get File functions
290 * %AIM_CAPS_SENDFILE Supports Send File functions
293 faim_export int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps)
295 unsigned char buf[128]; /* icky fixed length buffer */
296 struct aim_tlvlist_t *newtl;
297 struct aim_tlvlist_t *cur;
302 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
303 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
305 newtl->tlv = aim_createtlv();
306 newtl->tlv->type = type;
308 newtl->tlv->length = aim_putcap(buf, sizeof(buf), caps);
309 newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length);
310 memcpy(newtl->tlv->value, buf, newtl->tlv->length);
316 } else if ((*list)->next == NULL) {
317 (*list)->next = newtl;
319 for(cur = *list; cur->next; cur = cur->next)
323 return newtl->tlv->length;
327 * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain
328 * @list: Destination chain
329 * @type: TLV type to add
331 * Adds a TLV with a zero length to a TLV chain.
334 faim_internal int aim_addtlvtochain_noval(struct aim_tlvlist_t **list, unsigned short type)
336 struct aim_tlvlist_t *newtlv;
337 struct aim_tlvlist_t *cur;
339 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
340 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
342 newtlv->tlv = aim_createtlv();
343 newtlv->tlv->type = type;
344 newtlv->tlv->length = 0;
345 newtlv->tlv->value = NULL;
351 } else if ((*list)->next == NULL) {
352 (*list)->next = newtlv;
354 for(cur = *list; cur->next; cur = cur->next)
358 return newtlv->tlv->length;
362 * aim_writetlvchain - Write a TLV chain into a data buffer.
363 * @buf: Destination buffer
364 * @buflen: Maximum number of bytes that will be written to buffer
365 * @list: Source TLV chain
367 * Copies a TLV chain into a raw data buffer, writing only the number
368 * of bytes specified. This operation does not free the chain;
369 * aim_freetlvchain() must still be called to free up the memory used
370 * by the chain structures.
373 faim_export int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
377 struct aim_tlvlist_t *cur;
379 if (!list || !buf || !buflen)
382 /* do an initial run to test total length */
383 for (cur = *list; cur; cur = cur->next) {
384 goodbuflen += 2 + 2; /* type + len */
385 goodbuflen += cur->tlv->length;
388 if (goodbuflen > buflen)
389 return 0; /* not enough buffer */
391 /* do the real write-out */
392 for (cur = *list; cur; cur = cur->next) {
393 i += aimutil_put16(buf+i, cur->tlv->type);
394 i += aimutil_put16(buf+i, cur->tlv->length);
395 memcpy(buf+i, cur->tlv->value, cur->tlv->length);
396 i += cur->tlv->length;
404 * aim_gettlv - Grab the Nth TLV of type type in the TLV list list.
405 * @list: Source chain
406 * @type: Requested TLV type
407 * @nth: Index of TLV of type to get
409 * Returns a pointer to an aim_tlv_t of the specified type;
410 * %NULL on error. The @nth parameter is specified starting at %1.
411 * In most cases, there will be no more than one TLV of any type
415 faim_export struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
418 struct aim_tlvlist_t *cur;
421 for (cur = list; cur != NULL; cur = cur->next)
425 if (cur->tlv->type == type)
435 * aim_gettlv_str - Retrieve the Nth TLV in chain as a string.
436 * @list: Source TLV chain
437 * @type: TLV type to search for
438 * @nth: Index of TLV to return
440 * Same as aim_gettlv(), except that the return value is a %NULL-
441 * terminated string instead of an aim_tlv_t. This is a
442 * dynamic buffer and must be freed by the caller.
445 faim_export char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
447 struct aim_tlv_t *tlv;
450 if (!(tlv = aim_gettlv(list, type, nth)))
453 newstr = (char *) malloc(tlv->length + 1);
454 memcpy(newstr, tlv->value, tlv->length);
455 *(newstr + tlv->length) = '\0';
461 * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer.
462 * @list: Source TLV chain
463 * @type: TLV type to search for
464 * @nth: Index of TLV to return
466 * Same as aim_gettlv(), except that the return value is a
467 * 8bit integer instead of an aim_tlv_t.
470 faim_internal unsigned char aim_gettlv8(struct aim_tlvlist_t *list, unsigned short type, int num)
472 struct aim_tlv_t *tlv;
474 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value)
476 return aimutil_get8(tlv->value);
480 * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer.
481 * @list: Source TLV chain
482 * @type: TLV type to search for
483 * @nth: Index of TLV to return
485 * Same as aim_gettlv(), except that the return value is a
486 * 16bit integer instead of an aim_tlv_t.
489 faim_internal unsigned short aim_gettlv16(struct aim_tlvlist_t *list, unsigned short type, int num)
491 struct aim_tlv_t *tlv;
493 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value)
495 return aimutil_get16(tlv->value);
499 * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer.
500 * @list: Source TLV chain
501 * @type: TLV type to search for
502 * @nth: Index of TLV to return
504 * Same as aim_gettlv(), except that the return value is a
505 * 32bit integer instead of an aim_tlv_t.
508 faim_internal unsigned long aim_gettlv32(struct aim_tlvlist_t *list, unsigned short type, int num)
510 struct aim_tlv_t *tlv;
512 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value)
514 return aimutil_get32(tlv->value);
518 * aim_grabtlv - Grab a single TLV from a data buffer
519 * @src: Source data buffer (must be at least 4 bytes long)
521 * Creates a TLV structure aim_tlv_t and returns it
522 * filled with values from a buffer, possibly including a
523 * dynamically allocated buffer for the value portion.
525 * Both the aim_tlv_t and the tlv->value pointer
526 * must be freed by the caller if non-%NULL.
529 faim_export struct aim_tlv_t *aim_grabtlv(u_char *src)
531 struct aim_tlv_t *dest = NULL;
533 dest = aim_createtlv();
535 dest->type = src[0] << 8;
536 dest->type += src[1];
538 dest->length = src[2] << 8;
539 dest->length += src[3];
541 dest->value = (u_char *) malloc(dest->length*sizeof(u_char));
542 memset(dest->value, 0, dest->length*sizeof(u_char));
544 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
550 * aim_grabtlvstr - Grab a single TLV from a data buffer as string
551 * @src: Source data buffer (must be at least 4 bytes long)
553 * Creates a TLV structure aim_tlv_t and returns it
554 * filled with values from a buffer, possibly including a
555 * dynamically allocated buffer for the value portion, which
556 * is %NULL-terminated as a string.
558 * Both the aim_tlv_t and the tlv->value pointer
559 * must be freed by the caller if non-%NULL.
562 faim_export struct aim_tlv_t *aim_grabtlvstr(u_char *src)
564 struct aim_tlv_t *dest = NULL;
566 dest = aim_createtlv();
568 dest->type = src[0] << 8;
569 dest->type += src[1];
571 dest->length = src[2] << 8;
572 dest->length += src[3];
574 dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char));
575 memset(dest->value, 0, (dest->length+1)*sizeof(u_char));
577 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
578 dest->value[dest->length] = '\0';
584 * aim_puttlv - Write a aim_tlv_t into a data buffer
585 * @dest: Destination data buffer
586 * @newtlv: Source TLV structure
588 * Writes out the passed TLV structure into the buffer. No bounds
589 * checking is done on the output buffer.
591 * The passed aim_tlv_t is not freed. aim_freetlv() should
592 * still be called by the caller to free the structure.
595 faim_export int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
599 dest[i++] = newtlv->type >> 8;
600 dest[i++] = newtlv->type & 0x00FF;
601 dest[i++] = newtlv->length >> 8;
602 dest[i++] = newtlv->length & 0x00FF;
603 memcpy(&(dest[i]), newtlv->value, newtlv->length);
609 * aim_createtlv - Generate an aim_tlv_t structure.
611 * Allocates an empty TLV structure and returns a pointer
612 * to it; %NULL on error.
615 faim_export struct aim_tlv_t *aim_createtlv(void)
617 struct aim_tlv_t *newtlv;
619 if (!(newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t))))
621 memset(newtlv, 0, sizeof(struct aim_tlv_t));
626 * aim_freetlv - Free a aim_tlv_t structure
627 * @oldtlv: TLV to be destroyed
629 * Frees both the TLV structure and the value portion.
632 faim_export int aim_freetlv(struct aim_tlv_t **oldtlv)
638 if ((*oldtlv)->value)
639 free((*oldtlv)->value);
647 * aim_puttlv_8 - Write a one-byte TLV.
648 * @buf: Destination buffer
652 * Writes a TLV with a one-byte integer value portion.
655 faim_export int aim_puttlv_8(unsigned char *buf, unsigned short t, unsigned char v)
659 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff));
660 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0001);
661 curbyte += aimutil_put8(buf+curbyte, (unsigned char)(v&0xff));
667 * aim_puttlv_16 - Write a two-byte TLV.
668 * @buf: Destination buffer
672 * Writes a TLV with a two-byte integer value portion.
675 faim_export int aim_puttlv_16(u_char *buf, u_short t, u_short v)
678 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
679 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0002);
680 curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff));
685 * aim_puttlv_32 - Write a four-byte TLV.
686 * @buf: Destination buffer
690 * Writes a TLV with a four-byte integer value portion.
693 faim_export int aim_puttlv_32(u_char *buf, u_short t, u_long v)
696 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
697 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004);
698 curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff));
703 * aim_puttlv_str - Write a string TLV.
704 * @buf: Destination buffer
706 * @l: Length of string
707 * @v: String to write
709 * Writes a TLV with a string value portion. (Only the first @l
710 * bytes of the passed string will be written, which should not
711 * include the terminating NULL.)
714 faim_export int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
719 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
720 curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
722 memcpy(buf+curbyte, (unsigned char *)v, l);