+faim_internal 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;
+}
+
+faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
+{
+ struct aim_tlvlist_t *newtlv;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
+
+ newtlv->tlv = aim_createtlv();
+ newtlv->tlv->type = type;
+ newtlv->tlv->length = len;
+ newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char));
+ memcpy(newtlv->tlv->value, str, newtlv->tlv->length);
+
+ newtlv->next = NULL;
+
+ if (*list == NULL) {
+ *list = newtlv;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = newtlv;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = newtlv;
+ }
+ return newtlv->tlv->length;
+}
+
+faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
+{
+ struct aim_tlvlist_t *newtl;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
+
+ newtl->tlv = aim_createtlv();
+ newtl->tlv->type = type;
+ newtl->tlv->length = 2;
+ newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
+ aimutil_put16(newtl->tlv->value, val);
+
+ newtl->next = NULL;
+
+ if (*list == NULL) {
+ *list = newtl;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = newtl;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = newtl;
+ }
+ return 2;
+}
+
+faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
+{
+ struct aim_tlvlist_t *newtl;
+ struct aim_tlvlist_t *cur;
+
+ if (!list)
+ return 0;
+
+ newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+ memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
+
+ newtl->tlv = aim_createtlv();
+ newtl->tlv->type = type;
+ newtl->tlv->length = 4;
+ newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
+ aimutil_put32(newtl->tlv->value, val);
+
+ newtl->next = NULL;
+
+ if (*list == NULL) {
+ *list = newtl;
+ } else if ((*list)->next == NULL) {
+ (*list)->next = newtl;
+ } else {
+ for(cur = *list; cur->next; cur = cur->next)
+ ;
+ cur->next = newtl;
+ }
+ return 4;
+}
+
+faim_internal 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;
+}
+
+