Mercurial > pidgin.yaz
comparison libfaim/tlv.c @ 1535:1e2cc8c8bf3c
[gaim-migrate @ 1545]
libfaim updates.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Mon, 05 Mar 2001 03:59:32 +0000 |
parents | |
children | ec31e23aadc7 |
comparison
equal
deleted
inserted
replaced
1534:d98b92e3d9ff | 1535:1e2cc8c8bf3c |
---|---|
1 | |
2 #define FAIM_INTERNAL | |
3 #include <aim.h> | |
4 | |
5 /** | |
6 * aim_readtlvchain - Read a TLV chain from a buffer. | |
7 * @buf: Input buffer | |
8 * @maxlen: Length of input buffer | |
9 * | |
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. | |
14 * | |
15 */ | |
16 faim_export struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen) | |
17 { | |
18 int pos; | |
19 struct aim_tlvlist_t *list; | |
20 struct aim_tlvlist_t *cur; | |
21 | |
22 u_short type; | |
23 u_short length; | |
24 | |
25 if (!buf) | |
26 return NULL; | |
27 | |
28 list = NULL; | |
29 | |
30 pos = 0; | |
31 | |
32 while (pos < maxlen) | |
33 { | |
34 type = aimutil_get16(buf+pos); | |
35 pos += 2; | |
36 | |
37 if (pos < maxlen) | |
38 { | |
39 length = aimutil_get16(buf+pos); | |
40 pos += 2; | |
41 | |
42 if ((pos+length) <= maxlen) | |
43 { | |
44 /* | |
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. | |
50 * - mid (30jun2000) | |
51 */ | |
52 if ((type == 0x0013) && (length != 0x0002)) | |
53 length = 0x0002; | |
54 else { | |
55 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
56 memset(cur, 0x00, sizeof(struct aim_tlvlist_t)); | |
57 | |
58 cur->tlv = aim_createtlv(); | |
59 cur->tlv->type = type; | |
60 cur->tlv->length = length; | |
61 if (length) { | |
62 cur->tlv->value = (unsigned char *)malloc(length); | |
63 memcpy(cur->tlv->value, buf+pos, length); | |
64 } | |
65 | |
66 cur->next = list; | |
67 list = cur; | |
68 } | |
69 pos += length; | |
70 } | |
71 } | |
72 } | |
73 | |
74 return list; | |
75 } | |
76 | |
77 /** | |
78 * aim_freetlvchain - Free a TLV chain structure | |
79 * @list: Chain to be freed | |
80 * | |
81 * Walks the list of TLVs in the passed TLV chain and | |
82 * frees each one. Note that any references to this data | |
83 * should be removed before calling this. | |
84 * | |
85 */ | |
86 faim_export void aim_freetlvchain(struct aim_tlvlist_t **list) | |
87 { | |
88 struct aim_tlvlist_t *cur, *cur2; | |
89 | |
90 if (!list || !(*list)) | |
91 return; | |
92 | |
93 cur = *list; | |
94 while (cur) | |
95 { | |
96 aim_freetlv(&cur->tlv); | |
97 cur2 = cur->next; | |
98 free(cur); | |
99 cur = cur2; | |
100 } | |
101 list = NULL; | |
102 return; | |
103 } | |
104 | |
105 /** | |
106 * aim_counttlvchain - Count the number of TLVs in a chain | |
107 * @list: Chain to be counted | |
108 * | |
109 * Returns the number of TLVs stored in the passed chain. | |
110 * | |
111 */ | |
112 faim_export int aim_counttlvchain(struct aim_tlvlist_t **list) | |
113 { | |
114 struct aim_tlvlist_t *cur; | |
115 int count = 0; | |
116 | |
117 if (!list || !(*list)) | |
118 return 0; | |
119 | |
120 for (cur = *list; cur; cur = cur->next) | |
121 count++; | |
122 | |
123 return count; | |
124 } | |
125 | |
126 /** | |
127 * aim_sizetlvchain - Count the number of bytes in a TLV chain | |
128 * @list: Chain to be sized | |
129 * | |
130 * Returns the number of bytes that would be needed to | |
131 * write the passed TLV chain to a data buffer. | |
132 * | |
133 */ | |
134 faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list) | |
135 { | |
136 struct aim_tlvlist_t *cur; | |
137 int size = 0; | |
138 | |
139 if (!list || !(*list)) | |
140 return 0; | |
141 | |
142 for (cur = *list; cur; cur = cur->next) | |
143 size += (4 + cur->tlv->length); | |
144 | |
145 return size; | |
146 } | |
147 | |
148 /** | |
149 * aim_addtlvtochain_str - Add a string to a TLV chain | |
150 * @list: Desination chain (%NULL pointer if empty) | |
151 * @type: TLV type | |
152 * @str: String to add | |
153 * @len: Length of string to add (not including %NULL) | |
154 * | |
155 * Adds the passed string as a TLV element of the passed type | |
156 * to the TLV chain. | |
157 * | |
158 */ | |
159 faim_export int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len) | |
160 { | |
161 struct aim_tlvlist_t *newtlv; | |
162 struct aim_tlvlist_t *cur; | |
163 | |
164 if (!list) | |
165 return 0; | |
166 | |
167 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
168 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t)); | |
169 | |
170 newtlv->tlv = aim_createtlv(); | |
171 newtlv->tlv->type = type; | |
172 newtlv->tlv->length = len; | |
173 newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char)); | |
174 memcpy(newtlv->tlv->value, str, newtlv->tlv->length); | |
175 | |
176 newtlv->next = NULL; | |
177 | |
178 if (*list == NULL) { | |
179 *list = newtlv; | |
180 } else if ((*list)->next == NULL) { | |
181 (*list)->next = newtlv; | |
182 } else { | |
183 for(cur = *list; cur->next; cur = cur->next) | |
184 ; | |
185 cur->next = newtlv; | |
186 } | |
187 return newtlv->tlv->length; | |
188 } | |
189 | |
190 /** | |
191 * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain | |
192 * @list: Destination chain | |
193 * @type: TLV type to add | |
194 * @val: Value to add | |
195 * | |
196 * Adds a two-byte unsigned integer to a TLV chain. | |
197 * | |
198 */ | |
199 faim_export int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val) | |
200 { | |
201 struct aim_tlvlist_t *newtl; | |
202 struct aim_tlvlist_t *cur; | |
203 | |
204 if (!list) | |
205 return 0; | |
206 | |
207 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
208 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); | |
209 | |
210 newtl->tlv = aim_createtlv(); | |
211 newtl->tlv->type = type; | |
212 newtl->tlv->length = 2; | |
213 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char)); | |
214 aimutil_put16(newtl->tlv->value, val); | |
215 | |
216 newtl->next = NULL; | |
217 | |
218 if (*list == NULL) { | |
219 *list = newtl; | |
220 } else if ((*list)->next == NULL) { | |
221 (*list)->next = newtl; | |
222 } else { | |
223 for(cur = *list; cur->next; cur = cur->next) | |
224 ; | |
225 cur->next = newtl; | |
226 } | |
227 return 2; | |
228 } | |
229 | |
230 /** | |
231 * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain | |
232 * @list: Destination chain | |
233 * @type: TLV type to add | |
234 * @val: Value to add | |
235 * | |
236 * Adds a four-byte unsigned integer to a TLV chain. | |
237 * | |
238 */ | |
239 faim_export int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val) | |
240 { | |
241 struct aim_tlvlist_t *newtl; | |
242 struct aim_tlvlist_t *cur; | |
243 | |
244 if (!list) | |
245 return 0; | |
246 | |
247 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
248 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); | |
249 | |
250 newtl->tlv = aim_createtlv(); | |
251 newtl->tlv->type = type; | |
252 newtl->tlv->length = 4; | |
253 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char)); | |
254 aimutil_put32(newtl->tlv->value, val); | |
255 | |
256 newtl->next = NULL; | |
257 | |
258 if (*list == NULL) { | |
259 *list = newtl; | |
260 } else if ((*list)->next == NULL) { | |
261 (*list)->next = newtl; | |
262 } else { | |
263 for(cur = *list; cur->next; cur = cur->next) | |
264 ; | |
265 cur->next = newtl; | |
266 } | |
267 return 4; | |
268 } | |
269 | |
270 /** | |
271 * aim_addtlvtochain_caps - Add a capability block to a TLV chain | |
272 * @list: Destination chain | |
273 * @type: TLV type to add | |
274 * @caps: Bitfield of capability flags to send | |
275 * | |
276 * Adds a block of capability blocks to a TLV chain. The bitfield | |
277 * passed in should be a bitwise %OR of any of the %AIM_CAPS constants: | |
278 * | |
279 * %AIM_CAPS_BUDDYICON Supports Buddy Icons | |
280 * | |
281 * %AIM_CAPS_VOICE Supports Voice Chat | |
282 * | |
283 * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage | |
284 * | |
285 * %AIM_CAPS_CHAT Supports Chat | |
286 * | |
287 * %AIM_CAPS_GETFILE Supports Get File functions | |
288 * | |
289 * %AIM_CAPS_SENDFILE Supports Send File functions | |
290 * | |
291 */ | |
292 faim_export int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps) | |
293 { | |
294 unsigned char buf[128]; /* icky fixed length buffer */ | |
295 struct aim_tlvlist_t *newtl; | |
296 struct aim_tlvlist_t *cur; | |
297 | |
298 if(!list) | |
299 return 0; | |
300 | |
301 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
302 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); | |
303 | |
304 newtl->tlv = aim_createtlv(); | |
305 newtl->tlv->type = type; | |
306 | |
307 newtl->tlv->length = aim_putcap(buf, sizeof(buf), caps); | |
308 newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length); | |
309 memcpy(newtl->tlv->value, buf, newtl->tlv->length); | |
310 | |
311 newtl->next = NULL; | |
312 | |
313 if (*list == NULL) { | |
314 *list = newtl; | |
315 } else if ((*list)->next == NULL) { | |
316 (*list)->next = newtl; | |
317 } else { | |
318 for(cur = *list; cur->next; cur = cur->next) | |
319 ; | |
320 cur->next = newtl; | |
321 } | |
322 return newtl->tlv->length; | |
323 } | |
324 | |
325 /** | |
326 * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain | |
327 * @list: Destination chain | |
328 * @type: TLV type to add | |
329 * | |
330 * Adds a TLV with a zero length to a TLV chain. | |
331 * | |
332 */ | |
333 faim_internal int aim_addtlvtochain_noval(struct aim_tlvlist_t **list, unsigned short type) | |
334 { | |
335 struct aim_tlvlist_t *newtlv; | |
336 struct aim_tlvlist_t *cur; | |
337 | |
338 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
339 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t)); | |
340 | |
341 newtlv->tlv = aim_createtlv(); | |
342 newtlv->tlv->type = type; | |
343 newtlv->tlv->length = 0; | |
344 newtlv->tlv->value = NULL; | |
345 | |
346 newtlv->next = NULL; | |
347 | |
348 if (*list == NULL) { | |
349 *list = newtlv; | |
350 } else if ((*list)->next == NULL) { | |
351 (*list)->next = newtlv; | |
352 } else { | |
353 for(cur = *list; cur->next; cur = cur->next) | |
354 ; | |
355 cur->next = newtlv; | |
356 } | |
357 return newtlv->tlv->length; | |
358 } | |
359 | |
360 /** | |
361 * aim_writetlvchain - Write a TLV chain into a data buffer. | |
362 * @buf: Destination buffer | |
363 * @buflen: Maximum number of bytes that will be written to buffer | |
364 * @list: Source TLV chain | |
365 * | |
366 * Copies a TLV chain into a raw data buffer, writing only the number | |
367 * of bytes specified. This operation does not free the chain; | |
368 * aim_freetlvchain() must still be called to free up the memory used | |
369 * by the chain structures. | |
370 * | |
371 */ | |
372 faim_export int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list) | |
373 { | |
374 int goodbuflen = 0; | |
375 int i = 0; | |
376 struct aim_tlvlist_t *cur; | |
377 | |
378 if (!list || !buf || !buflen) | |
379 return 0; | |
380 | |
381 /* do an initial run to test total length */ | |
382 for (cur = *list; cur; cur = cur->next) { | |
383 goodbuflen += 2 + 2; /* type + len */ | |
384 goodbuflen += cur->tlv->length; | |
385 } | |
386 | |
387 if (goodbuflen > buflen) | |
388 return 0; /* not enough buffer */ | |
389 | |
390 /* do the real write-out */ | |
391 for (cur = *list; cur; cur = cur->next) { | |
392 i += aimutil_put16(buf+i, cur->tlv->type); | |
393 i += aimutil_put16(buf+i, cur->tlv->length); | |
394 memcpy(buf+i, cur->tlv->value, cur->tlv->length); | |
395 i += cur->tlv->length; | |
396 } | |
397 | |
398 return i; | |
399 } | |
400 | |
401 | |
402 /** | |
403 * aim_gettlv - Grab the Nth TLV of type type in the TLV list list. | |
404 * @list: Source chain | |
405 * @type: Requested TLV type | |
406 * @nth: Index of TLV of type to get | |
407 * | |
408 * Returns a pointer to an aim_tlv_t of the specified type; | |
409 * %NULL on error. The @nth parameter is specified starting at %1. | |
410 * In most cases, there will be no more than one TLV of any type | |
411 * in a chain. | |
412 * | |
413 */ | |
414 faim_export struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth) | |
415 { | |
416 int i; | |
417 struct aim_tlvlist_t *cur; | |
418 | |
419 i = 0; | |
420 for (cur = list; cur != NULL; cur = cur->next) | |
421 { | |
422 if (cur && cur->tlv) | |
423 { | |
424 if (cur->tlv->type == type) | |
425 i++; | |
426 if (i >= nth) | |
427 return cur->tlv; | |
428 } | |
429 } | |
430 return NULL; | |
431 } | |
432 | |
433 /** | |
434 * aim_gettlv_str - Retrieve the Nth TLV in chain as a string. | |
435 * @list: Source TLV chain | |
436 * @type: TLV type to search for | |
437 * @nth: Index of TLV to return | |
438 * | |
439 * Same as aim_gettlv(), except that the return value is a %NULL- | |
440 * terminated string instead of an aim_tlv_t. This is a | |
441 * dynamic buffer and must be freed by the caller. | |
442 * | |
443 */ | |
444 faim_export char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth) | |
445 { | |
446 struct aim_tlv_t *tlv; | |
447 char *newstr; | |
448 | |
449 if (!(tlv = aim_gettlv(list, type, nth))) | |
450 return NULL; | |
451 | |
452 newstr = (char *) malloc(tlv->length + 1); | |
453 memcpy(newstr, tlv->value, tlv->length); | |
454 *(newstr + tlv->length) = '\0'; | |
455 | |
456 return newstr; | |
457 } | |
458 | |
459 /** | |
460 * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer. | |
461 * @list: Source TLV chain | |
462 * @type: TLV type to search for | |
463 * @nth: Index of TLV to return | |
464 * | |
465 * Same as aim_gettlv(), except that the return value is a | |
466 * 8bit integer instead of an aim_tlv_t. | |
467 * | |
468 */ | |
469 faim_internal unsigned char aim_gettlv8(struct aim_tlvlist_t *list, unsigned short type, int num) | |
470 { | |
471 struct aim_tlv_t *tlv; | |
472 | |
473 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) | |
474 return 0; /* erm */ | |
475 return aimutil_get8(tlv->value); | |
476 } | |
477 | |
478 /** | |
479 * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer. | |
480 * @list: Source TLV chain | |
481 * @type: TLV type to search for | |
482 * @nth: Index of TLV to return | |
483 * | |
484 * Same as aim_gettlv(), except that the return value is a | |
485 * 16bit integer instead of an aim_tlv_t. | |
486 * | |
487 */ | |
488 faim_internal unsigned short aim_gettlv16(struct aim_tlvlist_t *list, unsigned short type, int num) | |
489 { | |
490 struct aim_tlv_t *tlv; | |
491 | |
492 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) | |
493 return 0; /* erm */ | |
494 return aimutil_get16(tlv->value); | |
495 } | |
496 | |
497 /** | |
498 * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer. | |
499 * @list: Source TLV chain | |
500 * @type: TLV type to search for | |
501 * @nth: Index of TLV to return | |
502 * | |
503 * Same as aim_gettlv(), except that the return value is a | |
504 * 32bit integer instead of an aim_tlv_t. | |
505 * | |
506 */ | |
507 faim_internal unsigned long aim_gettlv32(struct aim_tlvlist_t *list, unsigned short type, int num) | |
508 { | |
509 struct aim_tlv_t *tlv; | |
510 | |
511 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) | |
512 return 0; /* erm */ | |
513 return aimutil_get32(tlv->value); | |
514 } | |
515 | |
516 /** | |
517 * aim_grabtlv - Grab a single TLV from a data buffer | |
518 * @src: Source data buffer (must be at least 4 bytes long) | |
519 * | |
520 * Creates a TLV structure aim_tlv_t and returns it | |
521 * filled with values from a buffer, possibly including a | |
522 * dynamically allocated buffer for the value portion. | |
523 * | |
524 * Both the aim_tlv_t and the tlv->value pointer | |
525 * must be freed by the caller if non-%NULL. | |
526 * | |
527 */ | |
528 faim_export struct aim_tlv_t *aim_grabtlv(u_char *src) | |
529 { | |
530 struct aim_tlv_t *dest = NULL; | |
531 | |
532 dest = aim_createtlv(); | |
533 | |
534 dest->type = src[0] << 8; | |
535 dest->type += src[1]; | |
536 | |
537 dest->length = src[2] << 8; | |
538 dest->length += src[3]; | |
539 | |
540 dest->value = (u_char *) malloc(dest->length*sizeof(u_char)); | |
541 memset(dest->value, 0, dest->length*sizeof(u_char)); | |
542 | |
543 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char)); | |
544 | |
545 return dest; | |
546 } | |
547 | |
548 /** | |
549 * aim_grabtlvstr - Grab a single TLV from a data buffer as string | |
550 * @src: Source data buffer (must be at least 4 bytes long) | |
551 * | |
552 * Creates a TLV structure aim_tlv_t and returns it | |
553 * filled with values from a buffer, possibly including a | |
554 * dynamically allocated buffer for the value portion, which | |
555 * is %NULL-terminated as a string. | |
556 * | |
557 * Both the aim_tlv_t and the tlv->value pointer | |
558 * must be freed by the caller if non-%NULL. | |
559 * | |
560 */ | |
561 faim_export struct aim_tlv_t *aim_grabtlvstr(u_char *src) | |
562 { | |
563 struct aim_tlv_t *dest = NULL; | |
564 | |
565 dest = aim_createtlv(); | |
566 | |
567 dest->type = src[0] << 8; | |
568 dest->type += src[1]; | |
569 | |
570 dest->length = src[2] << 8; | |
571 dest->length += src[3]; | |
572 | |
573 dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char)); | |
574 memset(dest->value, 0, (dest->length+1)*sizeof(u_char)); | |
575 | |
576 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char)); | |
577 dest->value[dest->length] = '\0'; | |
578 | |
579 return dest; | |
580 } | |
581 | |
582 /** | |
583 * aim_puttlv - Write a aim_tlv_t into a data buffer | |
584 * @dest: Destination data buffer | |
585 * @newtlv: Source TLV structure | |
586 * | |
587 * Writes out the passed TLV structure into the buffer. No bounds | |
588 * checking is done on the output buffer. | |
589 * | |
590 * The passed aim_tlv_t is not freed. aim_freetlv() should | |
591 * still be called by the caller to free the structure. | |
592 * | |
593 */ | |
594 faim_export int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv) | |
595 { | |
596 int i=0; | |
597 | |
598 dest[i++] = newtlv->type >> 8; | |
599 dest[i++] = newtlv->type & 0x00FF; | |
600 dest[i++] = newtlv->length >> 8; | |
601 dest[i++] = newtlv->length & 0x00FF; | |
602 memcpy(&(dest[i]), newtlv->value, newtlv->length); | |
603 i+=newtlv->length; | |
604 return i; | |
605 } | |
606 | |
607 /** | |
608 * aim_createtlv - Generate an aim_tlv_t structure. | |
609 * | |
610 * Allocates an empty TLV structure and returns a pointer | |
611 * to it; %NULL on error. | |
612 * | |
613 */ | |
614 faim_export struct aim_tlv_t *aim_createtlv(void) | |
615 { | |
616 struct aim_tlv_t *newtlv; | |
617 | |
618 if (!(newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t)))) | |
619 return NULL; | |
620 memset(newtlv, 0, sizeof(struct aim_tlv_t)); | |
621 return newtlv; | |
622 } | |
623 | |
624 /** | |
625 * aim_freetlv - Free a aim_tlv_t structure | |
626 * @oldtlv: TLV to be destroyed | |
627 * | |
628 * Frees both the TLV structure and the value portion. | |
629 * | |
630 */ | |
631 faim_export int aim_freetlv(struct aim_tlv_t **oldtlv) | |
632 { | |
633 if (!oldtlv) | |
634 return -1; | |
635 if (!*oldtlv) | |
636 return -1; | |
637 if ((*oldtlv)->value) | |
638 free((*oldtlv)->value); | |
639 free(*(oldtlv)); | |
640 (*oldtlv) = NULL; | |
641 | |
642 return 0; | |
643 } | |
644 | |
645 /** | |
646 * aim_puttlv_8 - Write a one-byte TLV. | |
647 * @buf: Destination buffer | |
648 * @t: TLV type | |
649 * @v: Value | |
650 * | |
651 * Writes a TLV with a one-byte integer value portion. | |
652 * | |
653 */ | |
654 faim_export int aim_puttlv_8(unsigned char *buf, unsigned short t, unsigned char v) | |
655 { | |
656 int curbyte=0; | |
657 | |
658 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); | |
659 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0001); | |
660 curbyte += aimutil_put8(buf+curbyte, (unsigned char)(v&0xff)); | |
661 | |
662 return curbyte; | |
663 } | |
664 | |
665 /** | |
666 * aim_puttlv_16 - Write a two-byte TLV. | |
667 * @buf: Destination buffer | |
668 * @t: TLV type | |
669 * @v: Value | |
670 * | |
671 * Writes a TLV with a two-byte integer value portion. | |
672 * | |
673 */ | |
674 faim_export int aim_puttlv_16(u_char *buf, u_short t, u_short v) | |
675 { | |
676 int curbyte=0; | |
677 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); | |
678 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0002); | |
679 curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff)); | |
680 return curbyte; | |
681 } | |
682 | |
683 /** | |
684 * aim_puttlv_32 - Write a four-byte TLV. | |
685 * @buf: Destination buffer | |
686 * @t: TLV type | |
687 * @v: Value | |
688 * | |
689 * Writes a TLV with a four-byte integer value portion. | |
690 * | |
691 */ | |
692 faim_export int aim_puttlv_32(u_char *buf, u_short t, u_long v) | |
693 { | |
694 int curbyte=0; | |
695 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); | |
696 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004); | |
697 curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff)); | |
698 return curbyte; | |
699 } | |
700 | |
701 /** | |
702 * aim_puttlv_str - Write a string TLV. | |
703 * @buf: Destination buffer | |
704 * @t: TLV type | |
705 * @l: Length of string | |
706 * @v: String to write | |
707 * | |
708 * Writes a TLV with a string value portion. (Only the first @l | |
709 * bytes of the passed string will be written, which should not | |
710 * include the terminating NULL.) | |
711 * | |
712 */ | |
713 faim_export int aim_puttlv_str(u_char *buf, u_short t, int l, char *v) | |
714 { | |
715 int curbyte; | |
716 | |
717 curbyte = 0; | |
718 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); | |
719 curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff)); | |
720 if (v) | |
721 memcpy(buf+curbyte, (unsigned char *)v, l); | |
722 curbyte += l; | |
723 return curbyte; | |
724 } |