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