-#include <aim.h>
+#include <faim/aim.h>
+
+struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
+{
+ int pos;
+ struct aim_tlvlist_t *list;
+ struct aim_tlvlist_t *cur;
+
+ u_short type;
+ u_short length;
+
+ if (!buf)
+ return NULL;
+
+ list = NULL;
+
+ pos = 0;
+
+ while (pos < maxlen)
+ {
+ type = aimutil_get16(buf+pos);
+ pos += 2;
+
+ if (pos < maxlen)
+ {
+ length = aimutil_get16(buf+pos);
+ pos += 2;
+
+ if ((pos+length) <= maxlen)
+ {
+ cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
+
+ cur->tlv = aim_createtlv();
+ cur->tlv->type = type;
+ cur->tlv->length = length;
+ cur->tlv->value = (u_char *)malloc(length*sizeof(u_char));
+ memcpy(cur->tlv->value, buf+pos, length);
+
+ cur->next = list;
+ list = cur;
+
+ pos += length;
+ }
+ }
+ }
+
+ return list;
+}
+
+void aim_freetlvchain(struct aim_tlvlist_t **list)
+{
+ struct aim_tlvlist_t *cur, *cur2;
+
+ if (!list || !(*list))
+ return;
+
+ cur = *list;
+ while (cur)
+ {
+ aim_freetlv(&cur->tlv);
+ cur2 = cur->next;
+ free(cur);
+ cur = cur2;
+ }
+ list = NULL;
+ return;
+}
+
+int aim_counttlvchain(struct aim_tlvlist_t **list)
+{
+ struct aim_tlvlist_t *cur;
+ int count = 0;
+
+ if (!list || !(*list))
+ return 0;
+
+ for (cur = *list; cur; cur = cur->next)
+ count++;
+
+ return count;
+}
+
+int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
+{
+ struct aim_tlvlist_t *new;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(new, 0x00, sizeof(struct aim_tlvlist_t));
+
+ new->tlv = aim_createtlv();
+ new->tlv->type = type;
+ new->tlv->length = len;
+ new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
+ memcpy(new->tlv->value, str, new->tlv->length);
+
+ new->next = NULL;
+
+ if (*list == NULL) {
+ *list = new;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = new;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = new;
+ }
+ return new->tlv->length;
+}
+
+int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
+{
+ struct aim_tlvlist_t *new;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(new, 0x00, sizeof(struct aim_tlvlist_t));
+
+ new->tlv = aim_createtlv();
+ new->tlv->type = type;
+ new->tlv->length = 2;
+ new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
+ aimutil_put16(new->tlv->value, val);
+
+ new->next = NULL;
+
+ if (*list == NULL) {
+ *list = new;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = new;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = new;
+ }
+ return 2;
+}
+
+int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
+{
+ struct aim_tlvlist_t *new;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ new = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(new, 0x00, sizeof(struct aim_tlvlist_t));
+
+ new->tlv = aim_createtlv();
+ new->tlv->type = type;
+ new->tlv->length = 4;
+ new->tlv->value = (u_char *)malloc(new->tlv->length*sizeof(u_char));
+ aimutil_put32(new->tlv->value, val);
+
+ new->next = NULL;
+
+ if (*list == NULL) {
+ *list = new;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = new;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = new;
+ }
+ return 4;
+}
+
+int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
+{
+ int goodbuflen = 0;
+ int i = 0;
+ struct aim_tlvlist_t *cur;
+
+ if (!list || !buf || !buflen)
+ return 0;
+
+ /* do an initial run to test total length */
+ for (cur = *list; cur; cur = cur->next) {
+ goodbuflen += 2 + 2; /* type + len */
+ goodbuflen += cur->tlv->length;
+ }
+
+ if (goodbuflen > buflen)
+ return 0; /* not enough buffer */
+
+ /* do the real write-out */
+ for (cur = *list; cur; cur = cur->next) {
+ i += aimutil_put16(buf+i, cur->tlv->type);
+ i += aimutil_put16(buf+i, cur->tlv->length);
+ memcpy(buf+i, cur->tlv->value, cur->tlv->length);
+ i += cur->tlv->length;
+ }
+
+ return i;
+}
+
+
+/*
+ * Grab the Nth TLV of type type in the TLV list list.
+ */
+struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
+{
+ int i;
+ struct aim_tlvlist_t *cur;
+
+ i = 0;
+ for (cur = list; cur != NULL; cur = cur->next)
+ {
+ if (cur && cur->tlv)
+ {
+ if (cur->tlv->type == type)
+ i++;
+ if (i >= nth)
+ return cur->tlv;
+ }
+ }
+ return NULL;
+}
+
+char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
+{
+ struct aim_tlv_t *tlv;
+ char *newstr;
+
+ if (!(tlv = aim_gettlv(list, type, nth)))
+ return NULL;
+
+ newstr = (char *) malloc(tlv->length + 1);
+ memcpy(newstr, tlv->value, tlv->length);
+ *(newstr + tlv->length) = '\0';
+
+ return newstr;
+}
struct aim_tlv_t *aim_grabtlv(u_char *src)
{
curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff));
return curbyte;
}
+
+int aim_puttlv_32(u_char *buf, u_short t, u_long v)
+{
+ int curbyte=0;
+ curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
+ curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004);
+ curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff));
+ return curbyte;
+}
+
+int aim_puttlv_str(u_char *buf, u_short t, u_short l, u_char *v)
+{
+ int curbyte;
+
+ curbyte = 0;
+ curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
+ curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
+ if (v)
+ memcpy(buf+curbyte, v, l);
+ curbyte += l;
+ return curbyte;
+}