]> andersk Git - libfaim.git/blob - aim_tlv.c
- Mon Oct 16 20:56:59 UTC 2000
[libfaim.git] / aim_tlv.c
1 #include <faim/aim.h>
2
3 faim_internal struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
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             {
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));
45
46                 cur->tlv = aim_createtlv();     
47                 cur->tlv->type = type;
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                 } 
53
54                 cur->next = list;
55                 list = cur;
56               }
57               pos += length;
58             }
59         }
60     }
61
62   return list;
63 }
64
65 faim_internal void aim_freetlvchain(struct aim_tlvlist_t **list)
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
84 faim_internal int aim_counttlvchain(struct aim_tlvlist_t **list)
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
98 faim_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
113 faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
114 {
115   struct aim_tlvlist_t *newtlv;
116   struct aim_tlvlist_t *cur;
117
118   if (!list)
119     return 0;
120
121   newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
122   memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
123
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);
129
130   newtlv->next = NULL;
131
132   if (*list == NULL) {
133     *list = newtlv;
134   } else if ((*list)->next == NULL) {
135     (*list)->next = newtlv;
136   } else {
137     for(cur = *list; cur->next; cur = cur->next)
138       ;
139     cur->next = newtlv;
140   }
141   return newtlv->tlv->length;
142 }
143
144 faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
145 {
146   struct aim_tlvlist_t *newtl;
147   struct aim_tlvlist_t *cur;
148
149   if (!list)
150     return 0;
151
152   newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
153   memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
154
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);
160
161   newtl->next = NULL;
162
163   if (*list == NULL) {
164     *list = newtl;
165   } else if ((*list)->next == NULL) {
166     (*list)->next = newtl;
167   } else {
168     for(cur = *list; cur->next; cur = cur->next)
169       ;
170     cur->next = newtl;
171   }
172   return 2;
173 }
174
175 faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
176 {
177   struct aim_tlvlist_t *newtl;
178   struct aim_tlvlist_t *cur;
179
180   if (!list)
181     return 0;
182
183   newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
184   memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
185
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);
191
192   newtl->next = NULL;
193
194   if (*list == NULL) {
195     *list = newtl;
196   } else if ((*list)->next == NULL) {
197     (*list)->next = newtl;
198   } else {
199     for(cur = *list; cur->next; cur = cur->next)
200       ;
201     cur->next = newtl;
202   }
203   return 4;
204 }
205
206 faim_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
236 faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
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
266 /*
267  * Grab the Nth TLV of type type in the TLV list list.
268  */
269 faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
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
288 faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
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
303 faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src)
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
323 faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src)
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
344 faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
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
357 faim_internal struct aim_tlv_t *aim_createtlv(void)
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
365 faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv)
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
379 faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v)
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 }
387
388 faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v)
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
397 faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
398 {
399   int curbyte;
400   
401   curbyte  = 0;
402   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
403   curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
404   if (v)
405     memcpy(buf+curbyte, (unsigned char *)v, l);
406   curbyte += l;
407   return curbyte;
408 }
This page took 0.065878 seconds and 5 git commands to generate.