+/**
+ * aim_addtlvtochain_caps - Add a capability block to a TLV chain
+ * @list: Destination chain
+ * @type: TLV type to add
+ * @caps: Bitfield of capability flags to send
+ *
+ * Adds a block of capability blocks to a TLV chain. The bitfield
+ * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
+ *
+ * %AIM_CAPS_BUDDYICON Supports Buddy Icons
+ *
+ * %AIM_CAPS_VOICE Supports Voice Chat
+ *
+ * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage
+ *
+ * %AIM_CAPS_CHAT Supports Chat
+ *
+ * %AIM_CAPS_GETFILE Supports Get File functions
+ *
+ * %AIM_CAPS_SENDFILE Supports Send File functions
+ *
+ */
+faim_export int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps)
+{
+ unsigned char buf[128]; /* icky fixed length buffer */
+ 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 = aim_putcap(buf, sizeof(buf), caps);
+ newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length);
+ memcpy(newtl->tlv->value, buf, newtl->tlv->length);
+
+ 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 newtl->tlv->length;
+}
+
+/**
+ * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain
+ * @list: Destination chain
+ * @type: TLV type to add
+ *
+ * Adds a TLV with a zero length to a TLV chain.
+ *
+ */
+faim_internal int aim_addtlvtochain_noval(struct aim_tlvlist_t **list, unsigned short type)
+{
+ struct aim_tlvlist_t *newtlv;
+ struct aim_tlvlist_t *cur;
+
+ 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 = 0;
+ newtlv->tlv->value = NULL;
+
+ 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;
+}
+
+/**
+ * aim_writetlvchain - Write a TLV chain into a data buffer.
+ * @buf: Destination buffer
+ * @buflen: Maximum number of bytes that will be written to buffer
+ * @list: Source TLV chain
+ *
+ * Copies a TLV chain into a raw data buffer, writing only the number
+ * of bytes specified. This operation does not free the chain;
+ * aim_freetlvchain() must still be called to free up the memory used
+ * by the chain structures.
+ *
+ */
+faim_export int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)