3 faim_internal struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
6 struct aim_tlvlist_t *list;
7 struct aim_tlvlist_t *cur;
21 type = aimutil_get16(buf+pos);
26 length = aimutil_get16(buf+pos);
29 if ((pos+length) <= maxlen)
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.
39 if ((type == 0x0013) && (length != 0x0002)) {
40 printf("faim: skipping TLV t(0013) with invalid length (0x%04x)\n", length);
43 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
44 memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
46 cur->tlv = aim_createtlv();
47 cur->tlv->type = type;
48 cur->tlv->length = length;
50 cur->tlv->value = (unsigned char *)malloc(length);
51 memcpy(cur->tlv->value, buf+pos, length);
65 faim_internal void aim_freetlvchain(struct aim_tlvlist_t **list)
67 struct aim_tlvlist_t *cur, *cur2;
69 if (!list || !(*list))
75 aim_freetlv(&cur->tlv);
84 faim_internal int aim_counttlvchain(struct aim_tlvlist_t **list)
86 struct aim_tlvlist_t *cur;
89 if (!list || !(*list))
92 for (cur = *list; cur; cur = cur->next)
98 faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list)
100 struct aim_tlvlist_t *cur;
103 if (!list || !(*list))
106 for (cur = *list; cur; cur = cur->next)
107 size += (4 + cur->tlv->length);
113 faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
115 struct aim_tlvlist_t *newtlv;
116 struct aim_tlvlist_t *cur;
121 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
122 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
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);
134 } else if ((*list)->next == NULL) {
135 (*list)->next = newtlv;
137 for(cur = *list; cur->next; cur = cur->next)
141 return newtlv->tlv->length;
144 faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
146 struct aim_tlvlist_t *newtl;
147 struct aim_tlvlist_t *cur;
152 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
153 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
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);
165 } else if ((*list)->next == NULL) {
166 (*list)->next = newtl;
168 for(cur = *list; cur->next; cur = cur->next)
175 faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
177 struct aim_tlvlist_t *newtl;
178 struct aim_tlvlist_t *cur;
183 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
184 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
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);
196 } else if ((*list)->next == NULL) {
197 (*list)->next = newtl;
199 for(cur = *list; cur->next; cur = cur->next)
206 faim_internal int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps)
208 unsigned char buf[128]; /* icky fixed length buffer */
209 struct aim_tlvlist_t *newtl;
210 struct aim_tlvlist_t *cur;
215 newtl->tlv = aim_createtlv();
216 newtl->tlv->type = type;
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);
226 } else if ((*list)->next == NULL) {
227 (*list)->next = newtl;
229 for(cur = *list; cur->next; cur = cur->next)
233 return newtl->tlv->length;
236 faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
240 struct aim_tlvlist_t *cur;
242 if (!list || !buf || !buflen)
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;
251 if (goodbuflen > buflen)
252 return 0; /* not enough buffer */
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;
267 * Grab the Nth TLV of type type in the TLV list list.
269 faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
272 struct aim_tlvlist_t *cur;
275 for (cur = list; cur != NULL; cur = cur->next)
279 if (cur->tlv->type == type)
288 faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
290 struct aim_tlv_t *tlv;
293 if (!(tlv = aim_gettlv(list, type, nth)))
296 newstr = (char *) malloc(tlv->length + 1);
297 memcpy(newstr, tlv->value, tlv->length);
298 *(newstr + tlv->length) = '\0';
303 faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src)
305 struct aim_tlv_t *dest = NULL;
307 dest = aim_createtlv();
309 dest->type = src[0] << 8;
310 dest->type += src[1];
312 dest->length = src[2] << 8;
313 dest->length += src[3];
315 dest->value = (u_char *) malloc(dest->length*sizeof(u_char));
316 memset(dest->value, 0, dest->length*sizeof(u_char));
318 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
323 faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src)
325 struct aim_tlv_t *dest = NULL;
327 dest = aim_createtlv();
329 dest->type = src[0] << 8;
330 dest->type += src[1];
332 dest->length = src[2] << 8;
333 dest->length += src[3];
335 dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char));
336 memset(dest->value, 0, (dest->length+1)*sizeof(u_char));
338 memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
339 dest->value[dest->length] = '\0';
344 faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
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);
357 faim_internal struct aim_tlv_t *aim_createtlv(void)
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));
365 faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv)
371 if ((*oldtlv)->value)
372 free((*oldtlv)->value);
379 faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v)
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));
388 faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v)
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));
397 faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
402 curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
403 curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
405 memcpy(buf+curbyte, (unsigned char *)v, l);