]>
Commit | Line | Data |
---|---|---|
a25832e6 | 1 | #include <faim/aim.h> |
9de3ca7e | 2 | |
78b3fb13 | 3 | faim_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 | 65 | faim_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 | 84 | faim_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 | ||
78b3fb13 | 98 | faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len) |
0e2be272 | 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; | |
e6b05d80 | 111 | new->tlv->length = len; |
0e2be272 | 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 | ||
78b3fb13 | 129 | faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val) |
0e2be272 | 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 | ||
78b3fb13 | 160 | faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val) |
0e2be272 | 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 | ||
78b3fb13 | 191 | faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list) |
0e2be272 | 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 | ||
49c8a2fa | 221 | /* |
222 | * Grab the Nth TLV of type type in the TLV list list. | |
223 | */ | |
78b3fb13 | 224 | faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth) |
49c8a2fa | 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 | ||
78b3fb13 | 243 | faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth) |
49c8a2fa | 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 | ||
78b3fb13 | 258 | faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src) |
9de3ca7e | 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 | ||
78b3fb13 | 278 | faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src) |
9de3ca7e | 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 | ||
78b3fb13 | 299 | faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv) |
9de3ca7e | 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 | ||
78b3fb13 | 312 | faim_internal struct aim_tlv_t *aim_createtlv(void) |
9de3ca7e | 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 | ||
78b3fb13 | 320 | faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv) |
9de3ca7e | 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 | ||
78b3fb13 | 334 | faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v) |
9de3ca7e | 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 | } | |
01b59e1e | 342 | |
78b3fb13 | 343 | faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v) |
01b59e1e | 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 | ||
5ac21963 | 352 | faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v) |
01b59e1e | 353 | { |
354 | int curbyte; | |
01b59e1e | 355 | |
356 | curbyte = 0; | |
357 | curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff)); | |
358 | curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff)); | |
0c20631f | 359 | if (v) |
78b3fb13 | 360 | memcpy(buf+curbyte, (unsigned char *)v, l); |
01b59e1e | 361 | curbyte += l; |
362 | return curbyte; | |
363 | } |