Merge commit '52b4abdcb351830f5493a50c4181ef3947f3feab'
diff --git a/libosmocore/include/osmocore/gsm48.h b/libosmocore/include/osmocore/gsm48.h
index 787cdd0..1e96357 100644
--- a/libosmocore/include/osmocore/gsm48.h
+++ b/libosmocore/include/osmocore/gsm48.h
@@ -5,8 +5,8 @@
 #include <osmocore/gsm48_ie.h>
 
 extern const struct tlv_definition gsm48_att_tlvdef;
-extern const char *cc_state_names[32];
-extern const char *gsm48_cc_msg_names[0x40];
+const char *gsm48_cc_state_name(uint8_t state);
+const char *gsm48_cc_msg_name(uint8_t msgtype);
 const char *rr_cause_name(uint8_t cause);
 
 void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
diff --git a/libosmocore/include/osmocore/rsl.h b/libosmocore/include/osmocore/rsl.h
index c108081..99b90d6 100644
--- a/libosmocore/include/osmocore/rsl.h
+++ b/libosmocore/include/osmocore/rsl.h
@@ -16,9 +16,8 @@
 /* decode channel number as per Section 9.3.1 */
 int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot);
 
-extern const struct value_string rsl_rlm_cause_strs[];
-
 const char *rsl_err_name(uint8_t err);
+const char *rsl_rlm_cause_name(uint8_t err);
 
 /* Section 3.3.2.3 TS 05.02. I think this looks like a table */
 int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
diff --git a/libosmocore/m4/DUMMY b/libosmocore/m4/DUMMY
new file mode 100644
index 0000000..fda557a
--- /dev/null
+++ b/libosmocore/m4/DUMMY
@@ -0,0 +1 @@
+Dummply placeholder.
diff --git a/libosmocore/src/gsm48.c b/libosmocore/src/gsm48.c
index ff989ea..5761c67 100644
--- a/libosmocore/src/gsm48.c
+++ b/libosmocore/src/gsm48.c
@@ -1,7 +1,7 @@
 /* GSM Mobile Radio Interface Layer 3 messages
  * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
 
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
  * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
  *
  * All Rights Reserved
@@ -75,27 +75,29 @@
 	},
 };
 
-static const char *rr_cause_names[] = {
-	[GSM48_RR_CAUSE_NORMAL]			= "Normal event",
-	[GSM48_RR_CAUSE_ABNORMAL_UNSPEC]	= "Abnormal release, unspecified",
-	[GSM48_RR_CAUSE_ABNORMAL_UNACCT]	= "Abnormal release, channel unacceptable",
-	[GSM48_RR_CAUSE_ABNORMAL_TIMER]		= "Abnormal release, timer expired",
-	[GSM48_RR_CAUSE_ABNORMAL_NOACT]		= "Abnormal release, no activity on radio path",
-	[GSM48_RR_CAUSE_PREMPTIVE_REL]		= "Preemptive release",
-	[GSM48_RR_CAUSE_HNDOVER_IMP]		= "Handover impossible, timing advance out of range",
-	[GSM48_RR_CAUSE_CHAN_MODE_UNACCT]	= "Channel mode unacceptable",
-	[GSM48_RR_CAUSE_FREQ_NOT_IMPL]		= "Frequency not implemented",
-	[GSM48_RR_CAUSE_CALL_CLEARED]		= "Call already cleared",
-	[GSM48_RR_CAUSE_SEMANT_INCORR]		= "Semantically incorrect message",
-	[GSM48_RR_CAUSE_INVALID_MAND_INF]	= "Invalid mandatory information",
-	[GSM48_RR_CAUSE_MSG_TYPE_N]		= "Message type non-existant or not implemented",
-	[GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT]	= "Message type not compatible with protocol state",
-	[GSM48_RR_CAUSE_COND_IE_ERROR]		= "Conditional IE error",
-	[GSM48_RR_CAUSE_NO_CELL_ALLOC_A]	= "No cell allocation available",
-	[GSM48_RR_CAUSE_PROT_ERROR_UNSPC]	= "Protocol error unspecified",
+static const struct value_string rr_cause_names[] = {
+	{ GSM48_RR_CAUSE_NORMAL,		"Normal event" },
+	{ GSM48_RR_CAUSE_ABNORMAL_UNSPEC,	"Abnormal release, unspecified" },
+	{ GSM48_RR_CAUSE_ABNORMAL_UNACCT,	"Abnormal release, channel unacceptable" },
+	{ GSM48_RR_CAUSE_ABNORMAL_TIMER,	"Abnormal release, timer expired" },
+	{ GSM48_RR_CAUSE_ABNORMAL_NOACT,	"Abnormal release, no activity on radio path" },
+	{ GSM48_RR_CAUSE_PREMPTIVE_REL,		"Preemptive release" },
+	{ GSM48_RR_CAUSE_HNDOVER_IMP,		"Handover impossible, timing advance out of range" },
+	{ GSM48_RR_CAUSE_CHAN_MODE_UNACCT,	"Channel mode unacceptable" },
+	{ GSM48_RR_CAUSE_FREQ_NOT_IMPL,		"Frequency not implemented" },
+	{ GSM48_RR_CAUSE_CALL_CLEARED,		"Call already cleared" },
+	{ GSM48_RR_CAUSE_SEMANT_INCORR,		"Semantically incorrect message" },
+	{ GSM48_RR_CAUSE_INVALID_MAND_INF,	"Invalid mandatory information" },
+	{ GSM48_RR_CAUSE_MSG_TYPE_N,		"Message type non-existant or not implemented" },
+	{ GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT,	"Message type not compatible with protocol state" },
+	{ GSM48_RR_CAUSE_COND_IE_ERROR,		"Conditional IE error" },
+	{ GSM48_RR_CAUSE_NO_CELL_ALLOC_A,	"No cell allocation available" },
+	{ GSM48_RR_CAUSE_PROT_ERROR_UNSPC,	"Protocol error unspecified" },
+	{ 0,					NULL },
 };
 
-const char *cc_state_names[32] = {
+/* FIXME: convert to value_string */
+static const char *cc_state_names[32] = {
 	"NULL",
 	"INITIATED",
 	"illegal state 2",
@@ -130,83 +132,61 @@
 	"illegal state 31",
 };
 
-const char *gsm48_cc_msg_names[0x40] = {
-	"unknown 0x00",
-	"ALERTING",
-	"CALL_PROC",
-	"PROGRESS",
-	"ESTAB",
-	"SETUP",
-	"ESTAB_CONF",
-	"CONNECT",
-	"CALL_CONF",
-	"START_CC",
-	"unknown 0x0a",
-	"RECALL",
-	"unknown 0x0c",
-	"unknown 0x0d",
-	"EMERG_SETUP",
-	"CONNECT_ACK",
-	"USER_INFO",
-	"unknown 0x11",
-	"unknown 0x12",
-	"MODIFY_REJECT",
-	"unknown 0x14",
-	"unknown 0x15",
-	"unknown 0x16",
-	"MODIFY",
-	"HOLD",
-	"HOLD_ACK",
-	"HOLD_REJ",
-	"unknown 0x1b",
-	"RETR",
-	"RETR_ACK",
-	"RETR_REJ",
-	"MODIFY_COMPL",
-	"unknown 0x20",
-	"unknown 0x21",
-	"unknown 0x22",
-	"unknown 0x23",
-	"unknown 0x24",
-	"DISCONNECT",
-	"unknown 0x26",
-	"unknown 0x27",
-	"unknown 0x28",
-	"unknown 0x29",
-	"RELEASE_COMPL",
-	"unknown 0x2b",
-	"unknown 0x2c",
-	"RELEASE",
-	"unknown 0x2e",
-	"unknown 0x2f",
-	"unknown 0x30",
-	"STOP_DTMF",
-	"STOP_DTMF_ACK",
-	"unknown 0x33",
-	"STATUS_ENQ",
-	"START_DTMF",
-	"START_DTMF_ACK",
-	"START_DTMF_REJ",
-	"unknown 0x38",
-	"CONG_CTRL",
-	"FACILITY",
-	"unknown 0x3b",
-	"STATUS",
-	"unknown 0x3d",
-	"NOTIFY",
-	"unknown 0x3f",
+const char *gsm48_cc_state_name(uint8_t state)
+{
+	if (state < ARRAY_SIZE(cc_state_names))
+		return cc_state_names[state];
+
+	return "invalid";
+}
+
+static const struct value_string cc_msg_names[] = {
+	{ GSM48_MT_CC_ALERTING,		"ALERTING" },
+	{ GSM48_MT_CC_CALL_PROC,	"CALL_PROC" },
+	{ GSM48_MT_CC_PROGRESS,		"PROGRESS" },
+	{ GSM48_MT_CC_ESTAB,		"ESTAB" },
+	{ GSM48_MT_CC_SETUP,		"SETUP" },
+	{ GSM48_MT_CC_ESTAB_CONF,	"ESTAB_CONF" },
+	{ GSM48_MT_CC_CONNECT,		"CONNECT" },
+	{ GSM48_MT_CC_CALL_CONF,	"CALL_CONF" },
+	{ GSM48_MT_CC_START_CC,		"START_CC" },
+	{ GSM48_MT_CC_RECALL,		"RECALL" },
+	{ GSM48_MT_CC_EMERG_SETUP,	"EMERG_SETUP" },
+	{ GSM48_MT_CC_CONNECT_ACK,	"CONNECT_ACK" },
+	{ GSM48_MT_CC_USER_INFO,	"USER_INFO" },
+	{ GSM48_MT_CC_MODIFY_REJECT,	"MODIFY_REJECT" },
+	{ GSM48_MT_CC_MODIFY,		"MODIFY" },
+	{ GSM48_MT_CC_HOLD,		"HOLD" },
+	{ GSM48_MT_CC_HOLD_ACK,		"HOLD_ACK" },
+	{ GSM48_MT_CC_HOLD_REJ,		"HOLD_REJ" },
+	{ GSM48_MT_CC_RETR,		"RETR" },
+	{ GSM48_MT_CC_RETR_ACK,		"RETR_ACK" },
+	{ GSM48_MT_CC_RETR_REJ,		"RETR_REJ" },
+	{ GSM48_MT_CC_MODIFY_COMPL,	"MODIFY_COMPL" },
+	{ GSM48_MT_CC_DISCONNECT,	"DISCONNECT" },
+	{ GSM48_MT_CC_RELEASE_COMPL,	"RELEASE_COMPL" },
+	{ GSM48_MT_CC_RELEASE,		"RELEASE" },
+	{ GSM48_MT_CC_STOP_DTMF,	"STOP_DTMF" },
+	{ GSM48_MT_CC_STOP_DTMF_ACK,	"STOP_DTMF_ACK" },
+	{ GSM48_MT_CC_STATUS_ENQ,	"STATUS_ENQ" },
+	{ GSM48_MT_CC_START_DTMF,	"START_DTMF" },
+	{ GSM48_MT_CC_START_DTMF_ACK,	"START_DTMF_ACK" },
+	{ GSM48_MT_CC_START_DTMF_REJ,	"START_DTMF_REJ" },
+	{ GSM48_MT_CC_CONG_CTRL,	"CONG_CTRL" },
+	{ GSM48_MT_CC_FACILITY,		"FACILITY" },
+	{ GSM48_MT_CC_STATUS,		"STATUS" },
+	{ GSM48_MT_CC_NOTIFY,		"NOTFIY" },
+	{ 0,				NULL }
 };
 
-static char strbuf[64];
+const char *gsm48_cc_msg_name(uint8_t msgtype)
+{
+	return get_value_string(cc_msg_names, msgtype);
+}
 
 const char *rr_cause_name(uint8_t cause)
 {
-	if (cause < ARRAY_SIZE(rr_cause_names) &&
-	    rr_cause_names[cause])
-		return rr_cause_names[cause];
-
-	snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
-	return strbuf;
+	return get_value_string(rr_cause_names, cause);
 }
 
 static void to_bcd(uint8_t *bcd, uint16_t val)
diff --git a/libosmocore/src/rsl.c b/libosmocore/src/rsl.c
index c864b12..c002d33 100644
--- a/libosmocore/src/rsl.c
+++ b/libosmocore/src/rsl.c
@@ -176,42 +176,47 @@
 	return 0;
 }
 
-/* FIXME: convert to value_string */
-static const char *rsl_err_vals[0xff] = {
-	[RSL_ERR_RADIO_IF_FAIL] =	"Radio Interface Failure",
-	[RSL_ERR_RADIO_LINK_FAIL] =	"Radio Link Failure",
-	[RSL_ERR_HANDOVER_ACC_FAIL] =	"Handover Access Failure",
-	[RSL_ERR_TALKER_ACC_FAIL] =	"Talker Access Failure",
-	[RSL_ERR_OM_INTERVENTION] =	"O&M Intervention",
-	[RSL_ERR_NORMAL_UNSPEC] =	"Normal event, unspecified",
-	[RSL_ERR_T_MSRFPCI_EXP] =	"Siemens: T_MSRFPCI Expired",
-	[RSL_ERR_EQUIPMENT_FAIL] =	"Equipment Failure",
-	[RSL_ERR_RR_UNAVAIL] =		"Radio Resource not available",
-	[RSL_ERR_TERR_CH_FAIL] =	"Terrestrial Channel Failure",
-	[RSL_ERR_CCCH_OVERLOAD] =	"CCCH Overload",
-	[RSL_ERR_ACCH_OVERLOAD] =	"ACCH Overload",
-	[RSL_ERR_PROCESSOR_OVERLOAD] =	"Processor Overload",
-	[RSL_ERR_RES_UNAVAIL] =		"Resource not available, unspecified",
-	[RSL_ERR_TRANSC_UNAVAIL] =	"Transcoding not available",
-	[RSL_ERR_SERV_OPT_UNAVAIL] =	"Service or Option not available",
-	[RSL_ERR_ENCR_UNIMPL] =		"Encryption algorithm not implemented",
-	[RSL_ERR_SERV_OPT_UNIMPL] =	"Service or Option not implemented",
-	[RSL_ERR_RCH_ALR_ACTV_ALLOC] =	"Radio channel already activated",
-	[RSL_ERR_INVALID_MESSAGE] =	"Invalid Message, unspecified",
-	[RSL_ERR_MSG_DISCR] =		"Message Discriminator Error",
-	[RSL_ERR_MSG_TYPE] =		"Message Type Error",
-	[RSL_ERR_MSG_SEQ] =		"Message Sequence Error",
-	[RSL_ERR_IE_ERROR] =		"General IE error",
-	[RSL_ERR_MAND_IE_ERROR] =	"Mandatory IE error",
-	[RSL_ERR_OPT_IE_ERROR] =	"Optional IE error",
-	[RSL_ERR_IE_NONEXIST] =		"IE non-existent",
-	[RSL_ERR_IE_LENGTH] =		"IE length error",
-	[RSL_ERR_IE_CONTENT] =		"IE content error",
-	[RSL_ERR_PROTO] =		"Protocol error, unspecified",
-	[RSL_ERR_INTERWORKING] =	"Interworking error, unspecified",
+static const struct value_string rsl_err_vals[] = {
+	{ RSL_ERR_RADIO_IF_FAIL,	"Radio Interface Failure" },
+	{ RSL_ERR_RADIO_LINK_FAIL,	"Radio Link Failure" },
+	{ RSL_ERR_HANDOVER_ACC_FAIL,	"Handover Access Failure" },
+	{ RSL_ERR_TALKER_ACC_FAIL,	"Talker Access Failure" },
+	{ RSL_ERR_OM_INTERVENTION,	"O&M Intervention" },
+	{ RSL_ERR_NORMAL_UNSPEC,	"Normal event, unspecified" },
+	{ RSL_ERR_T_MSRFPCI_EXP,	"Siemens: T_MSRFPCI Expired" },
+	{ RSL_ERR_EQUIPMENT_FAIL,	"Equipment Failure" },
+	{ RSL_ERR_RR_UNAVAIL,		"Radio Resource not available" },
+	{ RSL_ERR_TERR_CH_FAIL,		"Terrestrial Channel Failure" },
+	{ RSL_ERR_CCCH_OVERLOAD,	"CCCH Overload" },
+	{ RSL_ERR_ACCH_OVERLOAD,	"ACCH Overload" },
+	{ RSL_ERR_PROCESSOR_OVERLOAD,	"Processor Overload" },
+	{ RSL_ERR_RES_UNAVAIL,		"Resource not available, unspecified" },
+	{ RSL_ERR_TRANSC_UNAVAIL,	"Transcoding not available" },
+	{ RSL_ERR_SERV_OPT_UNAVAIL,	"Service or Option not available" },
+	{ RSL_ERR_ENCR_UNIMPL,		"Encryption algorithm not implemented" },
+	{ RSL_ERR_SERV_OPT_UNIMPL,	"Service or Option not implemented" },
+	{ RSL_ERR_RCH_ALR_ACTV_ALLOC,	"Radio channel already activated" },
+	{ RSL_ERR_INVALID_MESSAGE,	"Invalid Message, unspecified" },
+	{ RSL_ERR_MSG_DISCR,		"Message Discriminator Error" },
+	{ RSL_ERR_MSG_TYPE,		"Message Type Error" },
+	{ RSL_ERR_MSG_SEQ,		"Message Sequence Error" },
+	{ RSL_ERR_IE_ERROR,		"General IE error" },
+	{ RSL_ERR_MAND_IE_ERROR,	"Mandatory IE error" },
+	{ RSL_ERR_OPT_IE_ERROR,		"Optional IE error" },
+	{ RSL_ERR_IE_NONEXIST,		"IE non-existent" },
+	{ RSL_ERR_IE_LENGTH,		"IE length error" },
+	{ RSL_ERR_IE_CONTENT,		"IE content error" },
+	{ RSL_ERR_PROTO,		"Protocol error, unspecified" },
+	{ RSL_ERR_INTERWORKING,		"Interworking error, unspecified" },
+	{ 0,				NULL }
 };
 
-const struct value_string rsl_rlm_cause_strs[] = {
+const char *rsl_err_name(uint8_t err)
+{
+	return get_value_string(rsl_err_vals, err);
+}
+
+static const struct value_string rsl_rlm_cause_strs[] = {
 	{ RLL_CAUSE_T200_EXPIRED,	"Timer T200 expired (N200+1) times" },
 	{ RLL_CAUSE_REEST_REQ,		"Re-establishment request" },
 	{ RLL_CAUSE_UNSOL_UA_RESP,	"Unsolicited UA response" },
@@ -229,12 +234,9 @@
 	{ 0,				NULL },
 };
 
-const char *rsl_err_name(uint8_t err)
+const char *rsl_rlm_cause_name(uint8_t err)
 {
-	if (rsl_err_vals[err])
-		return rsl_err_vals[err];
-	else
-		return "unknown";
+	return get_value_string(rsl_rlm_cause_strs, err);
 }
 
 /* Section 3.3.2.3 TS 05.02. I think this looks like a table */
diff --git a/libosmocore/src/utils.c b/libosmocore/src/utils.c
index 2a73d39..4dab064 100644
--- a/libosmocore/src/utils.c
+++ b/libosmocore/src/utils.c
@@ -2,9 +2,11 @@
 #include <string.h>
 #include <stdint.h>
 #include <errno.h>
+#include <stdio.h>
 
 #include <osmocore/utils.h>
 
+static char namebuf[255];
 const char *get_value_string(const struct value_string *vs, uint32_t val)
 {
 	int i;
@@ -15,7 +17,9 @@
 		if (vs[i].value == val)
 			return vs[i].str;
 	}
-	return "unknown";
+
+	snprintf(namebuf, sizeof(namebuf), "unknown 0x%x", val);
+	return namebuf;
 }
 
 int get_string_value(const struct value_string *vs, const char *str)