]> andersk Git - libfaim.git/blob - aim_tlv.c
One more.
[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_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
99 {
100   struct aim_tlvlist_t *new;
101   struct aim_tlvlist_t *cur;
102
103   if (!list)
104     return 0;
105
106   new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
107   memset(new, 0x00, sizeof(struct aim_tlvlist_t));
108
109   new->tlv = aim_createtlv();   
110   new->tlv->type = type;
111   new->tlv->length = len;
112   new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
113   memcpy(new->tlv->value, str, new->tlv->length);
114
115   new->next = NULL;
116
117   if (*list == NULL) {
118     *list = new;
119   } else if ((*list)->next == NULL) {
120     (*list)->next = new;
121   } else {
122     for(cur = *list; cur->next; cur = cur->next)
123       ;
124     cur->next = new;
125   }
126   return new->tlv->length;
127 }
128
129 faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
130 {
131   struct aim_tlvlist_t *new;
132   struct aim_tlvlist_t *cur;
133
134   if (!list)
135     return 0;
136
137   new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
138   memset(new, 0x00, sizeof(struct aim_tlvlist_t));
139
140   new->tlv = aim_createtlv();   
141   new->tlv->type = type;
142   new->tlv->length = 2;
143   new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
144   aimutil_put16(new->tlv->value, val);
145
146   new->next = NULL;
147
148   if (*list == NULL) {
149     *list = new;
150   } else if ((*list)->next == NULL) {
151     (*list)->next = new;
152   } else {
153     for(cur = *list; cur->next; cur = cur->next)
154       ;
155     cur->next = new;
156   }
157   return 2;
158 }
159
160 faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
161 {
162   struct aim_tlvlist_t *new;
163   struct aim_tlvlist_t *cur;
164
165   if (!list)
166     return 0;
167
168   new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
169   memset(new, 0x00, sizeof(struct aim_tlvlist_t));
170
171   new->tlv = aim_createtlv();   
172   new->tlv->type = type;
173   new->tlv->length = 4;
174   new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
175   aimutil_put32(new->tlv->value, val);
176
177   new->next = NULL;
178
179   if (*list == NULL) {
180     *list = new;
181   } else if ((*list)->next == NULL) {
182     (*list)->next = new;
183   } else {
184     for(cur = *list; cur->next; cur = cur->next)
185       ;
186     cur->next = new;
187   }
188   return 4;
189 }
190
191 faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
192 {
193   int goodbuflen = 0;
194   int i = 0;
195   struct aim_tlvlist_t *cur;
196
197   if (!list || !buf || !buflen)
198     return 0;
199
200   /* do an initial run to test total length */
201   for (cur = *list; cur; cur = cur->next) {
202     goodbuflen += 2 + 2; /* type + len */
203     goodbuflen += cur->tlv->length;
204   }
205
206   if (goodbuflen > buflen)
207     return 0; /* not enough buffer */
208
209   /* do the real write-out */
210   for (cur = *list; cur; cur = cur->next) {
211     i += aimutil_put16(buf+i, cur->tlv->type);
212     i += aimutil_put16(buf+i, cur->tlv->length);
213     memcpy(buf+i, cur->tlv->value, cur->tlv->length);
214     i += cur->tlv->length;
215   }
216
217   return i;
218 }
219
220
221 /*
222  * Grab the Nth TLV of type type in the TLV list list.
223  */
224 faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
225 {
226   int i;
227   struct aim_tlvlist_t *cur;
228   
229   i = 0;
230   for (cur = list; cur != NULL; cur = cur->next)
231     {
232       if (cur && cur->tlv)
233         {
234           if (cur->tlv->type == type)
235             i++;
236           if (i >= nth)
237             return cur->tlv;
238         }
239     }
240   return NULL;
241 }
242
243 faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
244 {
245   struct aim_tlv_t *tlv;
246   char *newstr;
247
248   if (!(tlv = aim_gettlv(list, type, nth)))
249     return NULL;
250   
251   newstr = (char *) malloc(tlv->length + 1);
252   memcpy(newstr, tlv->value, tlv->length);
253   *(newstr + tlv->length) = '\0';
254
255   return newstr;
256 }
257
258 faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src)
259 {
260   struct aim_tlv_t *dest = NULL;
261
262   dest = aim_createtlv();
263
264   dest->type = src[0] << 8;
265   dest->type += src[1];
266
267   dest->length = src[2] << 8;
268   dest->length += src[3];
269
270   dest->value = (u_char *) malloc(dest->length*sizeof(u_char));
271   memset(dest->value, 0, dest->length*sizeof(u_char));
272
273   memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
274   
275   return dest;
276 }
277
278 faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src)
279 {
280   struct aim_tlv_t *dest = NULL;
281
282   dest = aim_createtlv();
283
284   dest->type = src[0] << 8;
285   dest->type += src[1];
286
287   dest->length = src[2] << 8;
288   dest->length += src[3];
289
290   dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char));
291   memset(dest->value, 0, (dest->length+1)*sizeof(u_char));
292
293   memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
294   dest->value[dest->length] = '\0';
295
296   return dest;
297 }
298
299 faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
300 {
301   int i=0;
302
303   dest[i++] = newtlv->type >> 8;
304   dest[i++] = newtlv->type & 0x00FF;
305   dest[i++] = newtlv->length >> 8;
306   dest[i++] = newtlv->length & 0x00FF;
307   memcpy(&(dest[i]), newtlv->value, newtlv->length);
308   i+=newtlv->length;
309   return i;
310 }
311
312 faim_internal struct aim_tlv_t *aim_createtlv(void)
313 {
314   struct aim_tlv_t *newtlv = NULL;
315   newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t));
316   memset(newtlv, 0, sizeof(struct aim_tlv_t));
317   return newtlv;
318 }
319
320 faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv)
321 {
322   if (!oldtlv)
323     return -1;
324   if (!*oldtlv)
325     return -1;
326   if ((*oldtlv)->value)
327     free((*oldtlv)->value);
328   free(*(oldtlv));
329   (*oldtlv) = NULL;
330
331   return 0;
332 }
333
334 faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v)
335 {
336   int curbyte=0;
337   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
338   curbyte += aimutil_put16(buf+curbyte, (u_short)0x0002);
339   curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff));
340   return curbyte;
341 }
342
343 faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v)
344 {
345   int curbyte=0;
346   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
347   curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004);
348   curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff));
349   return curbyte;
350 }
351
352 faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
353 {
354   int curbyte;
355   
356   curbyte  = 0;
357   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
358   curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
359   if (v)
360     memcpy(buf+curbyte, (unsigned char *)v, l);
361   curbyte += l;
362   return curbyte;
363 }
This page took 0.1643 seconds and 5 git commands to generate.