Index: libfaim/tlv.c
===================================================================
--- libfaim/tlv.c	(revision 5e53c4a15eca8b264df0aedf726d4545bc5b4b46)
+++ libfaim/tlv.c	(revision 862371bb6a5ff5a6491550028e73824b698508bb)
@@ -29,6 +29,5 @@
 /**
  * aim_readtlvchain - Read a TLV chain from a buffer.
- * @buf: Input buffer
- * @maxlen: Length of input buffer
+ * @param bs Input bstream
  *
  * Reads and parses a series of TLV patterns from a data buffer; the
@@ -47,5 +46,5 @@
 {
 	aim_tlvlist_t *list = NULL, *cur;
-
+	
 	while (aim_bstream_empty(bs) > 0) {
 		fu16_t type, length;
@@ -71,17 +70,22 @@
 		else {
 
-			if (length > aim_bstream_empty(bs))
-				goto errout;
+			if (length > aim_bstream_empty(bs)) {
+				aim_freetlvchain(&list);
+				return NULL;
+			}
 
 			cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
-			if (!cur)
-				goto errout;
+			if (!cur) {
+				aim_freetlvchain(&list);
+				return NULL;
+			}
 
 			memset(cur, 0, sizeof(aim_tlvlist_t));
 
-			cur->tlv = createtlv();	
+			cur->tlv = createtlv();
 			if (!cur->tlv) {
 				free(cur);
-				goto errout;
+				aim_freetlvchain(&list);
+				return NULL;
 			}
 			cur->tlv->type = type;
@@ -91,5 +95,6 @@
 				       freetlv(&cur->tlv);
 				       free(cur);
-				       goto errout;
+				       aim_freetlvchain(&list);
+				       return NULL;
 			       }
 			}
@@ -101,8 +106,72 @@
 
 	return list;
-
-errout:
-	aim_freetlvchain(&list);
-	return NULL;
+}
+
+/**
+ * aim_readtlvchain_num - Read a TLV chain from a buffer.
+ * @param bs Input bstream
+ * @param num The max number of TLVs that will be read, or -1 if unlimited.  
+ *        There are a number of places where you want to read in a tlvchain, 
+ *        but the chain is not at the end of the SNAC, and the chain is 
+ *        preceeded by the number of TLVs.  So you can limit that.
+ *
+ * Reads and parses a series of TLV patterns from a data buffer; the
+ * returned structure is manipulatable with the rest of the TLV
+ * routines.  When done with a TLV chain, aim_freetlvchain() should
+ * be called to free the dynamic substructures.
+ *
+ * XXX There should be a flag setable here to have the tlvlist contain
+ * bstream references, so that at least the ->value portion of each 
+ * element doesn't need to be malloc/memcpy'd.  This could prove to be
+ * just as effecient as the in-place TLV parsing used in a couple places
+ * in libfaim.
+ *
+ */
+faim_internal aim_tlvlist_t *aim_readtlvchain_num(aim_bstream_t *bs, fu16_t num)
+{
+	aim_tlvlist_t *list = NULL, *cur;
+	
+	while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
+		fu16_t type, length;
+
+		type = aimbs_get16(bs);
+		length = aimbs_get16(bs);
+
+		if (length > aim_bstream_empty(bs)) {
+			aim_freetlvchain(&list);
+			return NULL;
+		}
+
+		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
+		if (!cur) {
+			aim_freetlvchain(&list);
+			return NULL;
+		}
+
+		memset(cur, 0, sizeof(aim_tlvlist_t));
+
+		cur->tlv = createtlv();
+		if (!cur->tlv) {
+			free(cur);
+			aim_freetlvchain(&list);
+			return NULL;
+		}
+		cur->tlv->type = type;
+		if ((cur->tlv->length = length)) {
+		       cur->tlv->value = aimbs_getraw(bs, length);	
+		       if (!cur->tlv->value) {
+			       freetlv(&cur->tlv);
+			       free(cur);
+			       aim_freetlvchain(&list);
+			       return NULL;
+		       }
+		}
+
+		num--;
+		cur->next = list;
+		list = cur;
+	}
+
+	return list;
 }
 
@@ -182,9 +251,9 @@
 
 /**
- * aim_addtlvtochain_str - Add a string to a TLV chain
+ * aim_addtlvtochain_raw - Add a string to a TLV chain
  * @list: Desination chain (%NULL pointer if empty)
- * @type: TLV type
- * @str: String to add
- * @len: Length of string to add (not including %NULL)
+ * @t: TLV type
+ * @l: Length of string to add (not including %NULL)
+ * @v: String to add
  *
  * Adds the passed string as a TLV element of the passed type
@@ -245,6 +314,6 @@
  * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
  * @list: Destination chain
- * @type: TLV type to add
- * @val: Value to add
+ * @t: TLV type to add
+ * @v: Value to add
  *
  * Adds a two-byte unsigned integer to a TLV chain.
@@ -607,3 +676,2 @@
 }
 #endif
-
