comparison src/protocols/oscar/tlv.c @ 2246:933346315b9b

[gaim-migrate @ 2256] heh. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sun, 09 Sep 2001 10:07:14 +0000
parents 424a40f12a6c
children d82efea341ef
comparison
equal deleted inserted replaced
2245:31157c54fe6e 2246:933346315b9b
1 1
2 #define FAIM_INTERNAL 2 #define FAIM_INTERNAL
3 #include <aim.h> 3 #include <aim.h>
4
5 static aim_tlv_t *createtlv(void)
6 {
7 aim_tlv_t *newtlv;
8
9 if (!(newtlv = (aim_tlv_t *)malloc(sizeof(aim_tlv_t))))
10 return NULL;
11 memset(newtlv, 0, sizeof(aim_tlv_t));
12
13 return newtlv;
14 }
15
16 static void freetlv(aim_tlv_t **oldtlv)
17 {
18
19 if (!oldtlv || !*oldtlv)
20 return;
21
22 free((*oldtlv)->value);
23 free(*oldtlv);
24 *oldtlv = NULL;
25
26 return;
27 }
4 28
5 /** 29 /**
6 * aim_readtlvchain - Read a TLV chain from a buffer. 30 * aim_readtlvchain - Read a TLV chain from a buffer.
7 * @buf: Input buffer 31 * @buf: Input buffer
8 * @maxlen: Length of input buffer 32 * @maxlen: Length of input buffer
10 * Reads and parses a series of TLV patterns from a data buffer; the 34 * Reads and parses a series of TLV patterns from a data buffer; the
11 * returned structure is manipulatable with the rest of the TLV 35 * returned structure is manipulatable with the rest of the TLV
12 * routines. When done with a TLV chain, aim_freetlvchain() should 36 * routines. When done with a TLV chain, aim_freetlvchain() should
13 * be called to free the dynamic substructures. 37 * be called to free the dynamic substructures.
14 * 38 *
15 */ 39 * XXX There should be a flag setable here to have the tlvlist contain
16 faim_export struct aim_tlvlist_t *aim_readtlvchain(const unsigned char *buf, const int maxlen) 40 * bstream references, so that at least the ->value portion of each
17 { 41 * element doesn't need to be malloc/memcpy'd. This could prove to be
18 int pos; 42 * just as effecient as the in-place TLV parsing used in a couple places
19 struct aim_tlvlist_t *list; 43 * in libfaim.
20 struct aim_tlvlist_t *cur; 44 *
21 45 */
22 unsigned short type, length; 46 faim_export aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs)
23 47 {
24 if (!buf) 48 aim_tlvlist_t *list = NULL, *cur;
25 return NULL; 49 fu16_t type, length;
26 50
27 list = NULL; 51 while (aim_bstream_empty(bs)) {
28 52
29 pos = 0; 53 type = aimbs_get16(bs);
30 54 length = aimbs_get16(bs);
31 while (pos < maxlen) 55
32 { 56 #if 0 /* temporarily disabled until I know if they're still doing it or not */
33 type = aimutil_get16(buf+pos); 57 /*
34 pos += 2; 58 * Okay, so now AOL has decided that any TLV of
35 59 * type 0x0013 can only be two bytes, despite
36 if (pos < maxlen) 60 * what the actual given length is. So here
37 { 61 * we dump any invalid TLVs of that sort. Hopefully
38 length = aimutil_get16(buf+pos); 62 * theres no special cases to this special case.
39 pos += 2; 63 * - mid (30jun2000)
40 64 */
41 if ((pos+length) <= maxlen) 65 if ((type == 0x0013) && (length != 0x0002))
42 { 66 length = 0x0002;
43 /* 67 #else
44 * Okay, so now AOL has decided that any TLV of 68 if (0)
45 * type 0x0013 can only be two bytes, despite 69 ;
46 * what the actual given length is. So here 70 #endif
47 * we dump any invalid TLVs of that sort. Hopefully 71 else {
48 * theres no special cases to this special case. 72
49 * - mid (30jun2000) 73 cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
50 */ 74 memset(cur, 0, sizeof(aim_tlvlist_t));
51 if ((type == 0x0013) && (length != 0x0002)) 75
52 length = 0x0002; 76 cur->tlv = createtlv();
53 else { 77 cur->tlv->type = type;
54 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); 78 if ((cur->tlv->length = length))
55 memset(cur, 0x00, sizeof(struct aim_tlvlist_t)); 79 cur->tlv->value = aimbs_getraw(bs, length);
56 80
57 cur->tlv = aim_createtlv(); 81 cur->next = list;
58 cur->tlv->type = type; 82 list = cur;
59 cur->tlv->length = length; 83 }
60 if (length) { 84 }
61 cur->tlv->value = (unsigned char *)malloc(length); 85
62 memcpy(cur->tlv->value, buf+pos, length); 86 return list;
63 }
64
65 cur->next = list;
66 list = cur;
67 }
68 pos += length;
69 }
70 }
71 }
72
73 return list;
74 } 87 }
75 88
76 /** 89 /**
77 * aim_freetlvchain - Free a TLV chain structure 90 * aim_freetlvchain - Free a TLV chain structure
78 * @list: Chain to be freed 91 * @list: Chain to be freed
80 * Walks the list of TLVs in the passed TLV chain and 93 * Walks the list of TLVs in the passed TLV chain and
81 * frees each one. Note that any references to this data 94 * frees each one. Note that any references to this data
82 * should be removed before calling this. 95 * should be removed before calling this.
83 * 96 *
84 */ 97 */
85 faim_export void aim_freetlvchain(struct aim_tlvlist_t **list) 98 faim_export void aim_freetlvchain(aim_tlvlist_t **list)
86 { 99 {
87 struct aim_tlvlist_t *cur, *cur2; 100 aim_tlvlist_t *cur;
88 101
89 if (!list || !(*list)) 102 if (!list || !*list)
90 return; 103 return;
91 104
92 cur = *list; 105 for (cur = *list; cur; ) {
93 while (cur) 106 aim_tlvlist_t *tmp;
94 { 107
95 aim_freetlv(&cur->tlv); 108 freetlv(&cur->tlv);
96 cur2 = cur->next; 109
97 free(cur); 110 tmp = cur->next;
98 cur = cur2; 111 free(cur);
99 } 112 cur = tmp;
100 list = NULL; 113 }
101 return; 114
115 list = NULL;
116
117 return;
102 } 118 }
103 119
104 /** 120 /**
105 * aim_counttlvchain - Count the number of TLVs in a chain 121 * aim_counttlvchain - Count the number of TLVs in a chain
106 * @list: Chain to be counted 122 * @list: Chain to be counted
107 * 123 *
108 * Returns the number of TLVs stored in the passed chain. 124 * Returns the number of TLVs stored in the passed chain.
109 * 125 *
110 */ 126 */
111 faim_export int aim_counttlvchain(struct aim_tlvlist_t **list) 127 faim_export int aim_counttlvchain(aim_tlvlist_t **list)
112 { 128 {
113 struct aim_tlvlist_t *cur; 129 aim_tlvlist_t *cur;
114 int count = 0; 130 int count;
115 131
116 if (!list || !(*list)) 132 if (!list || !*list)
117 return 0; 133 return 0;
118 134
119 for (cur = *list; cur; cur = cur->next) 135 for (cur = *list, count = 0; cur; cur = cur->next)
120 count++; 136 count++;
121 137
122 return count; 138 return count;
123 } 139 }
124 140
125 /** 141 /**
126 * aim_sizetlvchain - Count the number of bytes in a TLV chain 142 * aim_sizetlvchain - Count the number of bytes in a TLV chain
127 * @list: Chain to be sized 143 * @list: Chain to be sized
128 * 144 *
129 * Returns the number of bytes that would be needed to 145 * Returns the number of bytes that would be needed to
130 * write the passed TLV chain to a data buffer. 146 * write the passed TLV chain to a data buffer.
131 * 147 *
132 */ 148 */
133 faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list) 149 faim_export int aim_sizetlvchain(aim_tlvlist_t **list)
134 { 150 {
135 struct aim_tlvlist_t *cur; 151 aim_tlvlist_t *cur;
136 int size = 0; 152 int size;
137 153
138 if (!list || !(*list)) 154 if (!list || !*list)
139 return 0; 155 return 0;
140 156
141 for (cur = *list; cur; cur = cur->next) 157 for (cur = *list, size = 0; cur; cur = cur->next)
142 size += (4 + cur->tlv->length); 158 size += (4 + cur->tlv->length);
143 159
144 return size; 160 return size;
145 } 161 }
146 162
147 /** 163 /**
148 * aim_addtlvtochain_str - Add a string to a TLV chain 164 * aim_addtlvtochain_str - Add a string to a TLV chain
149 * @list: Desination chain (%NULL pointer if empty) 165 * @list: Desination chain (%NULL pointer if empty)
153 * 169 *
154 * Adds the passed string as a TLV element of the passed type 170 * Adds the passed string as a TLV element of the passed type
155 * to the TLV chain. 171 * to the TLV chain.
156 * 172 *
157 */ 173 */
158 faim_export int aim_addtlvtochain_str(struct aim_tlvlist_t **list, const unsigned short type, const char *str, const int len) 174 faim_export int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v)
159 { 175 {
160 struct aim_tlvlist_t *newtlv; 176 aim_tlvlist_t *newtlv, *cur;
161 struct aim_tlvlist_t *cur; 177
162 178 if (!list)
163 if (!list) 179 return 0;
164 return 0; 180
165 181 if (!(newtlv = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t))))
166 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); 182 return 0;
167 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t)); 183 memset(newtlv, 0x00, sizeof(aim_tlvlist_t));
168 184
169 newtlv->tlv = aim_createtlv(); 185 if (!(newtlv->tlv = createtlv())) {
170 newtlv->tlv->type = type; 186 free(newtlv);
171 newtlv->tlv->length = len; 187 return 0;
172 newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char)); 188 }
173 memcpy(newtlv->tlv->value, str, newtlv->tlv->length); 189 newtlv->tlv->type = t;
174 190 if ((newtlv->tlv->length = l)) {
175 newtlv->next = NULL; 191 newtlv->tlv->value = (fu8_t *)malloc(newtlv->tlv->length);
176 192 memcpy(newtlv->tlv->value, v, newtlv->tlv->length);
177 if (*list == NULL) { 193 }
178 *list = newtlv; 194
179 } else if ((*list)->next == NULL) { 195 if (!*list)
180 (*list)->next = newtlv; 196 *list = newtlv;
181 } else { 197 else {
182 for(cur = *list; cur->next; cur = cur->next) 198 for(cur = *list; cur->next; cur = cur->next)
183 ; 199 ;
184 cur->next = newtlv; 200 cur->next = newtlv;
185 } 201 }
186 return newtlv->tlv->length; 202
203 return newtlv->tlv->length;
187 } 204 }
188 205
189 /** 206 /**
190 * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain 207 * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
191 * @list: Destination chain 208 * @list: Destination chain
193 * @val: Value to add 210 * @val: Value to add
194 * 211 *
195 * Adds a two-byte unsigned integer to a TLV chain. 212 * Adds a two-byte unsigned integer to a TLV chain.
196 * 213 *
197 */ 214 */
198 faim_export int aim_addtlvtochain16(struct aim_tlvlist_t **list, const unsigned short type, const unsigned short val) 215 faim_export int aim_addtlvtochain16(aim_tlvlist_t **list, const fu16_t t, const fu16_t v)
199 { 216 {
200 struct aim_tlvlist_t *newtl; 217 fu8_t v16[2];
201 struct aim_tlvlist_t *cur; 218
202 219 aimutil_put16(v16, v);
203 if (!list) 220
204 return 0; 221 return aim_addtlvtochain_raw(list, t, 2, v16);
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 } 222 }
228 223
229 /** 224 /**
230 * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain 225 * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain
231 * @list: Destination chain 226 * @list: Destination chain
233 * @val: Value to add 228 * @val: Value to add
234 * 229 *
235 * Adds a four-byte unsigned integer to a TLV chain. 230 * Adds a four-byte unsigned integer to a TLV chain.
236 * 231 *
237 */ 232 */
238 faim_export int aim_addtlvtochain32(struct aim_tlvlist_t **list, const unsigned short type, const unsigned long val) 233 faim_export int aim_addtlvtochain32(aim_tlvlist_t **list, const fu16_t t, const fu32_t v)
239 { 234 {
240 struct aim_tlvlist_t *newtl; 235 fu8_t v32[4];
241 struct aim_tlvlist_t *cur; 236
242 237 aimutil_put32(v32, v);
243 if (!list) 238
244 return 0; 239 return aim_addtlvtochain_raw(list, t, 4, v32);
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 } 240 }
268 241
269 /** 242 /**
270 * aim_addtlvtochain_caps - Add a capability block to a TLV chain 243 * aim_addtlvtochain_caps - Add a capability block to a TLV chain
271 * @list: Destination chain 244 * @list: Destination chain
286 * %AIM_CAPS_GETFILE Supports Get File functions 259 * %AIM_CAPS_GETFILE Supports Get File functions
287 * 260 *
288 * %AIM_CAPS_SENDFILE Supports Send File functions 261 * %AIM_CAPS_SENDFILE Supports Send File functions
289 * 262 *
290 */ 263 */
291 faim_export int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, const unsigned short type, const unsigned short caps) 264 faim_export int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu16_t caps)
292 { 265 {
293 unsigned char buf[128]; /* icky fixed length buffer */ 266 fu8_t buf[16*16]; /* icky fixed length buffer */
294 struct aim_tlvlist_t *newtl; 267 aim_bstream_t bs;
295 struct aim_tlvlist_t *cur; 268
296 269 aim_bstream_init(&bs, buf, sizeof(buf));
297 if(!list) 270
298 return 0; 271 aim_putcap(&bs, caps);
299 272
300 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); 273 return aim_addtlvtochain_raw(list, t, aim_bstream_curpos(&bs), buf);
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 } 274 }
323 275
324 /** 276 /**
325 * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain 277 * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain
326 * @list: Destination chain 278 * @list: Destination chain
327 * @type: TLV type to add 279 * @type: TLV type to add
328 * 280 *
329 * Adds a TLV with a zero length to a TLV chain. 281 * Adds a TLV with a zero length to a TLV chain.
330 * 282 *
331 */ 283 */
332 faim_internal int aim_addtlvtochain_noval(struct aim_tlvlist_t **list, const unsigned short type) 284 faim_internal int aim_addtlvtochain_noval(aim_tlvlist_t **list, const fu16_t t)
333 { 285 {
334 struct aim_tlvlist_t *newtlv; 286 return aim_addtlvtochain_raw(list, t, 0, NULL);
335 struct aim_tlvlist_t *cur; 287 }
336 288
337 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); 289 /*
338 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t)); 290 * Note that the inner TLV chain will not be modifiable as a tlvchain once
339 291 * it is written using this. Or rather, it can be, but updates won't be
340 newtlv->tlv = aim_createtlv(); 292 * made to this.
341 newtlv->tlv->type = type; 293 *
342 newtlv->tlv->length = 0; 294 * XXX should probably support sublists for real.
343 newtlv->tlv->value = NULL; 295 *
344 296 * This is so neat.
345 newtlv->next = NULL; 297 *
346 298 */
347 if (*list == NULL) { 299 faim_internal int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl)
348 *list = newtlv; 300 {
349 } else if ((*list)->next == NULL) { 301 fu8_t *buf;
350 (*list)->next = newtlv; 302 int buflen;
351 } else { 303 aim_bstream_t bs;
352 for(cur = *list; cur->next; cur = cur->next) 304
353 ; 305 buflen = aim_sizetlvchain(tl);
354 cur->next = newtlv; 306
355 } 307 if (buflen <= 0)
356 return newtlv->tlv->length; 308 return 0;
309
310 if (!(buf = malloc(buflen)))
311 return 0;
312
313 aim_bstream_init(&bs, buf, buflen);
314
315 aim_writetlvchain(&bs, tl);
316
317 aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
318
319 free(buf);
320
321 return buflen;
357 } 322 }
358 323
359 /** 324 /**
360 * aim_writetlvchain - Write a TLV chain into a data buffer. 325 * aim_writetlvchain - Write a TLV chain into a data buffer.
361 * @buf: Destination buffer 326 * @buf: Destination buffer
365 * Copies a TLV chain into a raw data buffer, writing only the number 330 * Copies a TLV chain into a raw data buffer, writing only the number
366 * of bytes specified. This operation does not free the chain; 331 * of bytes specified. This operation does not free the chain;
367 * aim_freetlvchain() must still be called to free up the memory used 332 * aim_freetlvchain() must still be called to free up the memory used
368 * by the chain structures. 333 * by the chain structures.
369 * 334 *
370 */ 335 * XXX clean this up, make better use of bstreams
371 faim_export int aim_writetlvchain(unsigned char *buf, int buflen, struct aim_tlvlist_t **list) 336 */
372 { 337 faim_export int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list)
373 int goodbuflen = 0; 338 {
374 int i = 0; 339 int goodbuflen;
375 struct aim_tlvlist_t *cur; 340 aim_tlvlist_t *cur;
376 341
377 if (!list || !buf || !buflen) 342 /* do an initial run to test total length */
378 return 0; 343 for (cur = *list, goodbuflen = 0; cur; cur = cur->next) {
379 344 goodbuflen += 2 + 2; /* type + len */
380 /* do an initial run to test total length */ 345 goodbuflen += cur->tlv->length;
381 for (cur = *list; cur; cur = cur->next) { 346 }
382 goodbuflen += 2 + 2; /* type + len */ 347
383 goodbuflen += cur->tlv->length; 348 if (goodbuflen > aim_bstream_empty(bs))
384 } 349 return 0; /* not enough buffer */
385 350
386 if (goodbuflen > buflen) 351 /* do the real write-out */
387 return 0; /* not enough buffer */ 352 for (cur = *list; cur; cur = cur->next) {
388 353 aimbs_put16(bs, cur->tlv->type);
389 /* do the real write-out */ 354 aimbs_put16(bs, cur->tlv->length);
390 for (cur = *list; cur; cur = cur->next) { 355 if (cur->tlv->length)
391 i += aimutil_put16(buf+i, cur->tlv->type); 356 aimbs_putraw(bs, cur->tlv->value, cur->tlv->length);
392 i += aimutil_put16(buf+i, cur->tlv->length); 357 }
393 memcpy(buf+i, cur->tlv->value, cur->tlv->length); 358
394 i += cur->tlv->length; 359 return 1; /* XXX this is a nonsensical return */
395 }
396
397 return i;
398 } 360 }
399 361
400 362
401 /** 363 /**
402 * aim_gettlv - Grab the Nth TLV of type type in the TLV list list. 364 * aim_gettlv - Grab the Nth TLV of type type in the TLV list list.
408 * %NULL on error. The @nth parameter is specified starting at %1. 370 * %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 371 * In most cases, there will be no more than one TLV of any type
410 * in a chain. 372 * in a chain.
411 * 373 *
412 */ 374 */
413 faim_export struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, const unsigned short type, const int nth) 375 faim_export aim_tlv_t *aim_gettlv(aim_tlvlist_t *list, const fu16_t t, const int n)
414 { 376 {
415 int i; 377 aim_tlvlist_t *cur;
416 struct aim_tlvlist_t *cur; 378 int i;
417 379
418 i = 0; 380 for (cur = list, i = 0; cur; cur = cur->next) {
419 for (cur = list; cur != NULL; cur = cur->next) 381 if (cur && cur->tlv) {
420 { 382 if (cur->tlv->type == t)
421 if (cur && cur->tlv) 383 i++;
422 { 384 if (i >= n)
423 if (cur->tlv->type == type) 385 return cur->tlv;
424 i++; 386 }
425 if (i >= nth) 387 }
426 return cur->tlv; 388
427 } 389 return NULL;
428 }
429 return NULL;
430 } 390 }
431 391
432 /** 392 /**
433 * aim_gettlv_str - Retrieve the Nth TLV in chain as a string. 393 * aim_gettlv_str - Retrieve the Nth TLV in chain as a string.
434 * @list: Source TLV chain 394 * @list: Source TLV chain
438 * Same as aim_gettlv(), except that the return value is a %NULL- 398 * Same as aim_gettlv(), except that the return value is a %NULL-
439 * terminated string instead of an aim_tlv_t. This is a 399 * terminated string instead of an aim_tlv_t. This is a
440 * dynamic buffer and must be freed by the caller. 400 * dynamic buffer and must be freed by the caller.
441 * 401 *
442 */ 402 */
443 faim_export char *aim_gettlv_str(struct aim_tlvlist_t *list, const unsigned short type, const int nth) 403 faim_export char *aim_gettlv_str(aim_tlvlist_t *list, const fu16_t t, const int n)
444 { 404 {
445 struct aim_tlv_t *tlv; 405 aim_tlv_t *tlv;
446 char *newstr; 406 char *newstr;
447 407
448 if (!(tlv = aim_gettlv(list, type, nth))) 408 if (!(tlv = aim_gettlv(list, t, n)))
449 return NULL; 409 return NULL;
450 410
451 newstr = (char *) malloc(tlv->length + 1); 411 newstr = (char *) malloc(tlv->length + 1);
452 memcpy(newstr, tlv->value, tlv->length); 412 memcpy(newstr, tlv->value, tlv->length);
453 *(newstr + tlv->length) = '\0'; 413 *(newstr + tlv->length) = '\0';
454 414
455 return newstr; 415 return newstr;
456 } 416 }
457 417
458 /** 418 /**
459 * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer. 419 * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer.
460 * @list: Source TLV chain 420 * @list: Source TLV chain
463 * 423 *
464 * Same as aim_gettlv(), except that the return value is a 424 * Same as aim_gettlv(), except that the return value is a
465 * 8bit integer instead of an aim_tlv_t. 425 * 8bit integer instead of an aim_tlv_t.
466 * 426 *
467 */ 427 */
468 faim_internal unsigned char aim_gettlv8(struct aim_tlvlist_t *list, const unsigned short type, const int num) 428 faim_internal fu8_t aim_gettlv8(aim_tlvlist_t *list, const fu16_t t, const int n)
469 { 429 {
470 struct aim_tlv_t *tlv; 430 aim_tlv_t *tlv;
471 431
472 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) 432 if (!(tlv = aim_gettlv(list, t, n)))
473 return 0; /* erm */ 433 return 0; /* erm */
474 return aimutil_get8(tlv->value); 434 return aimutil_get8(tlv->value);
475 } 435 }
476 436
477 /** 437 /**
478 * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer. 438 * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer.
479 * @list: Source TLV chain 439 * @list: Source TLV chain
482 * 442 *
483 * Same as aim_gettlv(), except that the return value is a 443 * Same as aim_gettlv(), except that the return value is a
484 * 16bit integer instead of an aim_tlv_t. 444 * 16bit integer instead of an aim_tlv_t.
485 * 445 *
486 */ 446 */
487 faim_internal unsigned short aim_gettlv16(struct aim_tlvlist_t *list, const unsigned short type, const int num) 447 faim_internal fu16_t aim_gettlv16(aim_tlvlist_t *list, const fu16_t t, const int n)
488 { 448 {
489 struct aim_tlv_t *tlv; 449 aim_tlv_t *tlv;
490 450
491 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) 451 if (!(tlv = aim_gettlv(list, t, n)))
492 return 0; /* erm */ 452 return 0; /* erm */
493 return aimutil_get16(tlv->value); 453 return aimutil_get16(tlv->value);
494 } 454 }
495 455
496 /** 456 /**
497 * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer. 457 * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer.
498 * @list: Source TLV chain 458 * @list: Source TLV chain
501 * 461 *
502 * Same as aim_gettlv(), except that the return value is a 462 * Same as aim_gettlv(), except that the return value is a
503 * 32bit integer instead of an aim_tlv_t. 463 * 32bit integer instead of an aim_tlv_t.
504 * 464 *
505 */ 465 */
506 faim_internal unsigned long aim_gettlv32(struct aim_tlvlist_t *list, const unsigned short type, const int num) 466 faim_internal fu32_t aim_gettlv32(aim_tlvlist_t *list, const fu16_t t, const int n)
507 { 467 {
508 struct aim_tlv_t *tlv; 468 aim_tlv_t *tlv;
509 469
510 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) 470 if (!(tlv = aim_gettlv(list, t, n)))
511 return 0; /* erm */ 471 return 0; /* erm */
512 return aimutil_get32(tlv->value); 472 return aimutil_get32(tlv->value);
513 } 473 }
514 474
515 /** 475 #if 0
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 /** 476 /**
645 * aim_puttlv_8 - Write a one-byte TLV. 477 * aim_puttlv_8 - Write a one-byte TLV.
646 * @buf: Destination buffer 478 * @buf: Destination buffer
647 * @t: TLV type 479 * @t: TLV type
648 * @v: Value 480 * @v: Value
649 * 481 *
650 * Writes a TLV with a one-byte integer value portion. 482 * Writes a TLV with a one-byte integer value portion.
651 * 483 *
652 */ 484 */
653 faim_export int aim_puttlv_8(unsigned char *buf, const unsigned short t, const unsigned char v) 485 faim_export int aim_puttlv_8(fu8_t *buf, const fu16_t t, const fu8_t v)
654 { 486 {
655 int curbyte=0; 487 fu8_t v8[1];
656 488
657 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); 489 aimutil_put8(v8, v);
658 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0001); 490
659 curbyte += aimutil_put8(buf+curbyte, (unsigned char)(v&0xff)); 491 return aim_puttlv_raw(buf, t, 1, v8);
660
661 return curbyte;
662 } 492 }
663 493
664 /** 494 /**
665 * aim_puttlv_16 - Write a two-byte TLV. 495 * aim_puttlv_16 - Write a two-byte TLV.
666 * @buf: Destination buffer 496 * @buf: Destination buffer
668 * @v: Value 498 * @v: Value
669 * 499 *
670 * Writes a TLV with a two-byte integer value portion. 500 * Writes a TLV with a two-byte integer value portion.
671 * 501 *
672 */ 502 */
673 faim_export int aim_puttlv_16(unsigned char *buf, const unsigned short t, const unsigned short v) 503 faim_export int aim_puttlv_16(fu8_t *buf, const fu16_t t, const fu16_t v)
674 { 504 {
675 int curbyte=0; 505 fu8_t v16[2];
676 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); 506
677 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0002); 507 aimutil_put16(v16, v);
678 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(v&0xffff)); 508
679 return curbyte; 509 return aim_puttlv_raw(buf, t, 2, v16);
680 } 510 }
511
681 512
682 /** 513 /**
683 * aim_puttlv_32 - Write a four-byte TLV. 514 * aim_puttlv_32 - Write a four-byte TLV.
684 * @buf: Destination buffer 515 * @buf: Destination buffer
685 * @t: TLV type 516 * @t: TLV type
686 * @v: Value 517 * @v: Value
687 * 518 *
688 * Writes a TLV with a four-byte integer value portion. 519 * Writes a TLV with a four-byte integer value portion.
689 * 520 *
690 */ 521 */
691 faim_export int aim_puttlv_32(unsigned char *buf, const unsigned short t, const unsigned long v) 522 faim_export int aim_puttlv_32(fu8_t *buf, const fu16_t t, const fu32_t v)
692 { 523 {
693 int curbyte=0; 524 fu8_t v32[4];
694 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); 525
695 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0004); 526 aimutil_put32(v32, v);
696 curbyte += aimutil_put32(buf+curbyte, (unsigned long)(v&0xffffffff)); 527
697 return curbyte; 528 return aim_puttlv_raw(buf, t, 4, v32);
698 } 529 }
699 530
700 /** 531 /**
701 * aim_puttlv_str - Write a string TLV. 532 * aim_puttlv_raw - Write a raw TLV.
702 * @buf: Destination buffer 533 * @buf: Destination buffer
703 * @t: TLV type 534 * @t: TLV type
704 * @l: Length of string 535 * @l: Length of string
705 * @v: String to write 536 * @v: String to write
706 * 537 *
707 * Writes a TLV with a string value portion. (Only the first @l 538 * Writes a TLV with a raw value portion. (Only the first @l
708 * bytes of the passed string will be written, which should not 539 * bytes of the passed buffer will be written, which should not
709 * include the terminating NULL.) 540 * include a terminating NULL.)
710 * 541 *
711 */ 542 */
712 faim_export int aim_puttlv_str(unsigned char *buf, const unsigned short t, const int l, const char *v) 543 faim_export int aim_puttlv_raw(fu8_t *buf, const fu16_t t, const fu16_t l, const fu8_t *v)
713 { 544 {
714 int curbyte; 545 int i;
715 546
716 curbyte = 0; 547 i = aimutil_put16(buf, t);
717 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); 548 i += aimutil_put16(buf+i, l);
718 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(l&0xffff)); 549 if (l)
719 if (v) 550 memcpy(buf+i, v, l);
720 memcpy(buf+curbyte, (unsigned char *)v, l); 551 i += l;
721 curbyte += l; 552
722 return curbyte; 553 return i;
723 } 554 }
555 #endif
556