1535
|
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 }
|