diff -Nur openbsc.8_paging/include/openbsc/tlv.h openbsc.9_tlv/include/openbsc/tlv.h
--- openbsc.8_paging/include/openbsc/tlv.h	2009-05-21 07:20:43.000000000 +0200
+++ openbsc.9_tlv/include/openbsc/tlv.h	2009-05-21 09:43:41.000000000 +0200
@@ -6,12 +6,21 @@
 
 #include <openbsc/msgb.h>
 
+#define LV_GROSS_LEN(x)		(x+1)
 #define TLV_GROSS_LEN(x)	(x+2)
 #define TLV16_GROSS_LEN(x)	((2*x)+2)
 #define TL16V_GROSS_LEN(x)	(x+3)
 
 /* TLV generation */
 
+static inline u_int8_t *lv_put(u_int8_t *buf, u_int8_t len,
+				const u_int8_t *val)
+{
+	*buf++ = len;
+	memcpy(buf, val, len);
+	return buf + len;
+}
+
 static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
 				const u_int8_t *val)
 {
@@ -53,6 +62,12 @@
 	return tl16v_put(buf, tag, len, val);
 }
 
+static inline u_int8_t *v_put(u_int8_t *buf, u_int8_t val)
+{
+	*buf++ = val;
+	return buf;
+}
+
 static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag, 
 				u_int8_t val)
 {
@@ -70,6 +85,12 @@
 	return buf;
 }
 
+static inline u_int8_t *msgb_lv_put(struct msgb *msg, u_int8_t len, const u_int8_t *val)
+{
+	u_int8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
+	return lv_put(buf, len, val);
+}
+
 static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
 {
 	u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
@@ -82,6 +103,12 @@
 	return tv_put(buf, tag, val);
 }
 
+static inline u_int8_t *msgb_v_put(struct msgb *msg, u_int8_t val)
+{
+	u_int8_t *buf = msgb_put(msg, 1);
+	return v_put(buf, val);
+}
+
 static inline u_int8_t *msgb_tv16_put(struct msgb *msg, u_int8_t tag, u_int16_t val)
 {
 	u_int8_t *buf = msgb_put(msg, 3);
@@ -135,7 +162,7 @@
 };
 
 int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
-	      const u_int8_t *buf, int buf_len);
+	      const u_int8_t *buf, int buf_len, u_int8_t lv_tag, u_int8_t lv_tag2);
 
 #define TLVP_PRESENT(x, y)	((x)->lv[y].val)
 #define TLVP_LEN(x, y)		(x)->lv[y].len
diff -Nur openbsc.8_paging/src/abis_nm.c openbsc.9_tlv/src/abis_nm.c
--- openbsc.8_paging/src/abis_nm.c	2009-05-21 09:38:00.000000000 +0200
+++ openbsc.9_tlv/src/abis_nm.c	2009-05-21 09:43:41.000000000 +0200
@@ -365,7 +365,7 @@
 
 int abis_nm_tlv_parse(struct tlv_parsed *tp, const u_int8_t *buf, int len)
 {
-	return tlv_parse(tp, &nm_att_tlvdef, buf, len);
+	return tlv_parse(tp, &nm_att_tlvdef, buf, len, 0, 0);
 }
 
 static int is_in_arr(enum abis_nm_msgtype mt, const enum abis_nm_msgtype *arr, int size)
diff -Nur openbsc.8_paging/src/abis_rsl.c openbsc.9_tlv/src/abis_rsl.c
--- openbsc.8_paging/src/abis_rsl.c	2009-05-21 07:20:44.000000000 +0200
+++ openbsc.9_tlv/src/abis_rsl.c	2009-05-21 09:43:41.000000000 +0200
@@ -112,7 +112,7 @@
 		[0xfc]				= { TLV_TYPE_TV },
 	},
 };
-#define rsl_tlv_parse(dec, buf, len)     tlv_parse(dec, &rsl_att_tlvdef, buf, len)
+#define rsl_tlv_parse(dec, buf, len)     tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
 
 static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
 {
diff -Nur openbsc.8_paging/src/gsm_04_08.c openbsc.9_tlv/src/gsm_04_08.c
--- openbsc.8_paging/src/gsm_04_08.c	2009-05-21 07:51:25.000000000 +0200
+++ openbsc.9_tlv/src/gsm_04_08.c	2009-05-21 09:47:20.000000000 +0200
@@ -1119,7 +1119,7 @@
 	call->local_lchan = msg->lchan;
 	call->transaction_id = gh->proto_discr & 0xf0;
 
-	tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
+	tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
 	if (!TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD))
 		goto err;
 
diff -Nur openbsc.8_paging/src/tlv_parser.c openbsc.9_tlv/src/tlv_parser.c
--- openbsc.8_paging/src/tlv_parser.c	2009-05-21 07:20:44.000000000 +0200
+++ openbsc.9_tlv/src/tlv_parser.c	2009-05-21 09:43:41.000000000 +0200
@@ -14,15 +14,38 @@
 }
 
 int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
-	      const u_int8_t *buf, int buf_len)
+	      const u_int8_t *buf, int buf_len, u_int8_t lv_tag, u_int8_t lv_tag2)
 {
 	u_int8_t tag, len = 1;
-	const u_int8_t *pos;
+	const u_int8_t *pos = buf;
 	int num_parsed = 0;
 
 	memset(dec, 0, sizeof(*dec));
 
-	for (pos = buf; pos < buf+buf_len; pos += len) {
+	if (lv_tag) {
+		if (pos > buf + buf_len)
+			return -1;
+		dec->lv[lv_tag].val = pos+1;
+		dec->lv[lv_tag].len = *pos;
+		len = dec->lv[lv_tag].len + 1;
+		if (pos + len > buf + buf_len)
+			return -2;
+		num_parsed++;
+		pos += len;
+	}
+	if (lv_tag2) {
+		if (pos > buf + buf_len)
+			return -1;
+		dec->lv[lv_tag2].val = pos+1;
+		dec->lv[lv_tag2].len = *pos;
+		len = dec->lv[lv_tag2].len + 1;
+		if (pos + len > buf + buf_len)
+			return -2;
+		num_parsed++;
+		pos += len;
+	}
+
+	for (; pos < buf+buf_len; pos += len) {
 		tag = *pos;
 		/* FIXME: use tables for knwon IEI */
 		switch (def->def[tag].type) {
