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