]> andersk Git - libfaim.git/blame - aim_tlv.c
- Mon Oct 16 20:56:59 UTC 2000
[libfaim.git] / aim_tlv.c
CommitLineData
a25832e6 1#include <faim/aim.h>
9de3ca7e 2
78b3fb13 3faim_internal struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
49c8a2fa 4{
5 int pos;
6 struct aim_tlvlist_t *list;
7 struct aim_tlvlist_t *cur;
8
9 u_short type;
10 u_short length;
11
12 if (!buf)
13 return NULL;
14
15 list = NULL;
16
17 pos = 0;
18
19 while (pos < maxlen)
20 {
21 type = aimutil_get16(buf+pos);
22 pos += 2;
23
24 if (pos < maxlen)
25 {
26 length = aimutil_get16(buf+pos);
27 pos += 2;
28
29 if ((pos+length) <= maxlen)
30 {
13ebc4c4 31 /*
32 * Okay, so now AOL has decided that any TLV of
33 * type 0x0013 can only be two bytes, despite
34 * what the actual given length is. So here
35 * we dump any invalid TLVs of that sort. Hopefully
36 * theres no special cases to this special case.
37 * - mid (30jun2000)
38 */
39 if ((type == 0x0013) && (length != 0x0002)) {
40 printf("faim: skipping TLV t(0013) with invalid length (0x%04x)\n", length);
41 length = 0x0002;
42 } else {
43 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
44 memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
49c8a2fa 45
13ebc4c4 46 cur->tlv = aim_createtlv();
47 cur->tlv->type = type;
8515d6a5 48 cur->tlv->length = length;
49 if (length) {
50 cur->tlv->value = (unsigned char *)malloc(length);
51 memcpy(cur->tlv->value, buf+pos, length);
52 }
98c88242 53
13ebc4c4 54 cur->next = list;
55 list = cur;
56 }
49c8a2fa 57 pos += length;
58 }
59 }
60 }
61
62 return list;
63}
64
78b3fb13 65faim_internal void aim_freetlvchain(struct aim_tlvlist_t **list)
49c8a2fa 66{
67 struct aim_tlvlist_t *cur, *cur2;
68
69 if (!list || !(*list))
70 return;
71
72 cur = *list;
73 while (cur)
74 {
75 aim_freetlv(&cur->tlv);
76 cur2 = cur->next;
77 free(cur);
78 cur = cur2;
79 }
80 list = NULL;
81 return;
82}
83
78b3fb13 84faim_internal int aim_counttlvchain(struct aim_tlvlist_t **list)
e6b05d80 85{
86 struct aim_tlvlist_t *cur;
87 int count = 0;
88
89 if (!list || !(*list))
90 return 0;
91
92 for (cur = *list; cur; cur = cur->next)
93 count++;
94
95 return count;
96}
97
3b101546 98faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list)
99{
100 struct aim_tlvlist_t *cur;
101 int size = 0;
102
103 if (!list || !(*list))
104 return 0;
105
106 for (cur = *list; cur; cur = cur->next)
107 size += (4 + cur->tlv->length);
108
109 return size;
110}
111
112
78b3fb13 113faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
0e2be272 114{
a15d82b1 115 struct aim_tlvlist_t *newtlv;
0e2be272 116 struct aim_tlvlist_t *cur;
117
118 if (!list)
119 return 0;
120
a15d82b1 121 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
122 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
0e2be272 123
a15d82b1 124 newtlv->tlv = aim_createtlv();
125 newtlv->tlv->type = type;
126 newtlv->tlv->length = len;
127 newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char));
128 memcpy(newtlv->tlv->value, str, newtlv->tlv->length);
0e2be272 129
a15d82b1 130 newtlv->next = NULL;
0e2be272 131
132 if (*list == NULL) {
a15d82b1 133 *list = newtlv;
0e2be272 134 } else if ((*list)->next == NULL) {
a15d82b1 135 (*list)->next = newtlv;
0e2be272 136 } else {
137 for(cur = *list; cur->next; cur = cur->next)
138 ;
a15d82b1 139 cur->next = newtlv;
0e2be272 140 }
a15d82b1 141 return newtlv->tlv->length;
0e2be272 142}
143
78b3fb13 144faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
0e2be272 145{
a15d82b1 146 struct aim_tlvlist_t *newtl;
0e2be272 147 struct aim_tlvlist_t *cur;
148
149 if (!list)
150 return 0;
151
a15d82b1 152 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
153 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
0e2be272 154
a15d82b1 155 newtl->tlv = aim_createtlv();
156 newtl->tlv->type = type;
157 newtl->tlv->length = 2;
158 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
159 aimutil_put16(newtl->tlv->value, val);
0e2be272 160
a15d82b1 161 newtl->next = NULL;
0e2be272 162
163 if (*list == NULL) {
a15d82b1 164 *list = newtl;
0e2be272 165 } else if ((*list)->next == NULL) {
a15d82b1 166 (*list)->next = newtl;
0e2be272 167 } else {
168 for(cur = *list; cur->next; cur = cur->next)
169 ;
a15d82b1 170 cur->next = newtl;
0e2be272 171 }
172 return 2;
173}
174
78b3fb13 175faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
0e2be272 176{
a15d82b1 177 struct aim_tlvlist_t *newtl;
0e2be272 178 struct aim_tlvlist_t *cur;
179
180 if (!list)
181 return 0;
182
a15d82b1 183 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
184 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
0e2be272 185
a15d82b1 186 newtl->tlv = aim_createtlv();
187 newtl->tlv->type = type;
188 newtl->tlv->length = 4;
189 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
190 aimutil_put32(newtl->tlv->value, val);
0e2be272 191
a15d82b1 192 newtl->next = NULL;
0e2be272 193
194 if (*list == NULL) {
a15d82b1 195 *list = newtl;
0e2be272 196 } else if ((*list)->next == NULL) {
a15d82b1 197 (*list)->next = newtl;
0e2be272 198 } else {
199 for(cur = *list; cur->next; cur = cur->next)
200 ;
a15d82b1 201 cur->next = newtl;
0e2be272 202 }
203 return 4;
204}
205
3b101546 206faim_internal int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps)
207{
208 unsigned char buf[128]; /* icky fixed length buffer */
209 struct aim_tlvlist_t *newtl;
210 struct aim_tlvlist_t *cur;
211
212 if(!list)
213 return 0;
214
215 newtl->tlv = aim_createtlv();
216 newtl->tlv->type = type;
217
218 newtl->tlv->length = aim_putcap(buf, 128, caps);
219 newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length);
220 memcpy(newtl->tlv->value, &buf, newtl->tlv->length);
221
222 newtl->next = NULL;
223
224 if (*list == NULL) {
225 *list = newtl;
226 } else if ((*list)->next == NULL) {
227 (*list)->next = newtl;
228 } else {
229 for(cur = *list; cur->next; cur = cur->next)
230 ;
231 cur->next = newtl;
232 }
233 return newtl->tlv->length;
234}
235
78b3fb13 236faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
0e2be272 237{
238 int goodbuflen = 0;
239 int i = 0;
240 struct aim_tlvlist_t *cur;
241
242 if (!list || !buf || !buflen)
243 return 0;
244
245 /* do an initial run to test total length */
246 for (cur = *list; cur; cur = cur->next) {
247 goodbuflen += 2 + 2; /* type + len */
248 goodbuflen += cur->tlv->length;
249 }
250
251 if (goodbuflen > buflen)
252 return 0; /* not enough buffer */
253
254 /* do the real write-out */
255 for (cur = *list; cur; cur = cur->next) {
256 i += aimutil_put16(buf+i, cur->tlv->type);
257 i += aimutil_put16(buf+i, cur->tlv->length);
258 memcpy(buf+i, cur->tlv->value, cur->tlv->length);
259 i += cur->tlv->length;
260 }
261
262 return i;
263}
264
265
49c8a2fa 266/*
267 * Grab the Nth TLV of type type in the TLV list list.
268 */
78b3fb13 269faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
49c8a2fa 270{
271 int i;
272 struct aim_tlvlist_t *cur;
273
274 i = 0;
275 for (cur = list; cur != NULL; cur = cur->next)
276 {
277 if (cur && cur->tlv)
278 {
279 if (cur->tlv->type == type)
280 i++;
281 if (i >= nth)
282 return cur->tlv;
283 }
284 }
285 return NULL;
286}
287
78b3fb13 288faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
49c8a2fa 289{
290 struct aim_tlv_t *tlv;
291 char *newstr;
292
293 if (!(tlv = aim_gettlv(list, type, nth)))
294 return NULL;
295
296 newstr = (char *) malloc(tlv->length + 1);
297 memcpy(newstr, tlv->value, tlv->length);
298 *(newstr + tlv->length) = '\0';
299
300 return newstr;
301}
302
78b3fb13 303faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src)
9de3ca7e 304{
305 struct aim_tlv_t *dest = NULL;
306
307 dest = aim_createtlv();
308
309 dest->type = src[0] << 8;
310 dest->type += src[1];
311
312 dest->length = src[2] << 8;
313 dest->length += src[3];
314
315 dest->value = (u_char *) malloc(dest->length*sizeof(u_char));
316 memset(dest->value, 0, dest->length*sizeof(u_char));
317
318 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
319
320 return dest;
321}
322
78b3fb13 323faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src)
9de3ca7e 324{
325 struct aim_tlv_t *dest = NULL;
326
327 dest = aim_createtlv();
328
329 dest->type = src[0] << 8;
330 dest->type += src[1];
331
332 dest->length = src[2] << 8;
333 dest->length += src[3];
334
335 dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char));
336 memset(dest->value, 0, (dest->length+1)*sizeof(u_char));
337
338 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
339 dest->value[dest->length] = '\0';
340
341 return dest;
342}
343
78b3fb13 344faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
9de3ca7e 345{
346 int i=0;
347
348 dest[i++] = newtlv->type >> 8;
349 dest[i++] = newtlv->type & 0x00FF;
350 dest[i++] = newtlv->length >> 8;
351 dest[i++] = newtlv->length & 0x00FF;
352 memcpy(&(dest[i]), newtlv->value, newtlv->length);
353 i+=newtlv->length;
354 return i;
355}
356
78b3fb13 357faim_internal struct aim_tlv_t *aim_createtlv(void)
9de3ca7e 358{
359 struct aim_tlv_t *newtlv = NULL;
360 newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t));
361 memset(newtlv, 0, sizeof(struct aim_tlv_t));
362 return newtlv;
363}
364
78b3fb13 365faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv)
9de3ca7e 366{
367 if (!oldtlv)
368 return -1;
369 if (!*oldtlv)
370 return -1;
371 if ((*oldtlv)->value)
372 free((*oldtlv)->value);
373 free(*(oldtlv));
374 (*oldtlv) = NULL;
375
376 return 0;
377}
378
78b3fb13 379faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v)
9de3ca7e 380{
381 int curbyte=0;
382 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
383 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0002);
384 curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff));
385 return curbyte;
386}
01b59e1e 387
78b3fb13 388faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v)
01b59e1e 389{
390 int curbyte=0;
391 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
392 curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004);
393 curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff));
394 return curbyte;
395}
396
5ac21963 397faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
01b59e1e 398{
399 int curbyte;
01b59e1e 400
401 curbyte = 0;
402 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
403 curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
0c20631f 404 if (v)
78b3fb13 405 memcpy(buf+curbyte, (unsigned char *)v, l);
01b59e1e 406 curbyte += l;
407 return curbyte;
408}
This page took 0.105562 seconds and 5 git commands to generate.