This is the first patch of the series. The first two patches are
improvements of the log output and are independent of the 3rd patch in
terms of code - proposed logging improvements just make it easier to
debug issues with MNCC cause codes.

The code is also a part of the achemeris/mncc_cause_fixes_master branch.

-- 
Regards,
Alexander Chemeris.
CEO, Fairwaves, Inc.
https://fairwaves.co

Subscribe to Fairwaves news: http://eepurl.com/baL_pf
From cdedf561ba3ff265c005e339aec76c9f41f2f2b7 Mon Sep 17 00:00:00 2001
From: Alexander Chemeris <[email protected]>
Date: Sat, 12 Sep 2015 20:18:33 -0400
Subject: [PATCH 1/3] mncc: Implement helper functions to convert MNCC cause to
 a string.

---
 openbsc/include/openbsc/mncc.h |   5 +-
 openbsc/src/libmsc/mncc.c      | 103 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 100 insertions(+), 8 deletions(-)

diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h
index ffac7fd..654480c 100644
--- a/openbsc/include/openbsc/mncc.h
+++ b/openbsc/include/openbsc/mncc.h
@@ -179,8 +179,11 @@ struct gsm_mncc_hello {
 	uint32_t	lchan_type_offset;
 };
 
-char *get_mncc_name(int value);
+const char *get_mncc_name(int value);
 void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
+int mncc_has_cause(struct gsm_mncc *data);
+const char *get_mncc_location(int value);
+const char *get_mncc_cause(int value);
 void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
 
 /* input from CC code into mncc_builtin */
diff --git a/openbsc/src/libmsc/mncc.c b/openbsc/src/libmsc/mncc.c
index 73db5f0..23ee940 100644
--- a/openbsc/src/libmsc/mncc.c
+++ b/openbsc/src/libmsc/mncc.c
@@ -34,10 +34,12 @@
 #include <openbsc/transaction.h>
 #include <openbsc/rtp_proxy.h>
 
-static struct mncc_names {
+struct name_value {
 	char *name;
 	int value;
-} mncc_names[] = {
+};
+
+static struct name_value mncc_names[] = {
 	{"MNCC_SETUP_REQ",	0x0101},
 	{"MNCC_SETUP_IND",	0x0102},
 	{"MNCC_SETUP_RSP",	0x0103},
@@ -92,16 +94,103 @@ static struct mncc_names {
 
 	{NULL, 0} };
 
-char *get_mncc_name(int value)
+static struct name_value mncc_locations[] = {
+	{"GSM48_CAUSE_LOC_USER",		0x00},
+	{"GSM48_CAUSE_LOC_PRN_S_LU",	0x01},
+	{"GSM48_CAUSE_LOC_PUN_S_LU",	0x02},
+	{"GSM48_CAUSE_LOC_TRANS_NET",	0x03},
+	{"GSM48_CAUSE_LOC_PUN_S_RU",	0x04},
+	{"GSM48_CAUSE_LOC_PRN_S_RU",	0x05},
+	/* not defined */
+	{"GSM48_CAUSE_LOC_INN_NET",		0x07},
+	{"GSM48_CAUSE_LOC_NET_BEYOND",	0x0a},
+
+	{NULL, 0} };
+
+static struct name_value mncc_causes[] = {
+	{"GSM48_CC_CAUSE_UNASSIGNED_NR",	1},
+	{"GSM48_CC_CAUSE_NO_ROUTE",	3},
+	{"GSM48_CC_CAUSE_CHAN_UNACCEPT",	6},
+	{"GSM48_CC_CAUSE_OP_DET_BARRING",	8},
+	{"GSM48_CC_CAUSE_NORM_CALL_CLEAR",	16},
+	{"GSM48_CC_CAUSE_USER_BUSY",	17},
+	{"GSM48_CC_CAUSE_USER_NOTRESPOND",	18},
+	{"GSM48_CC_CAUSE_USER_ALERTING_NA",	19},
+	{"GSM48_CC_CAUSE_CALL_REJECTED",	21},
+	{"GSM48_CC_CAUSE_NUMBER_CHANGED",	22},
+	{"GSM48_CC_CAUSE_PRE_EMPTION",	25},
+	{"GSM48_CC_CAUSE_NONSE_USER_CLR",	26},
+	{"GSM48_CC_CAUSE_DEST_OOO",	27},
+	{"GSM48_CC_CAUSE_INV_NR_FORMAT",	28},
+	{"GSM48_CC_CAUSE_FACILITY_REJ",	29},
+	{"GSM48_CC_CAUSE_RESP_STATUS_INQ",	30},
+	{"GSM48_CC_CAUSE_NORMAL_UNSPEC",	31},
+	{"GSM48_CC_CAUSE_NO_CIRCUIT_CHAN",	34},
+	{"GSM48_CC_CAUSE_NETWORK_OOO",	38},
+	{"GSM48_CC_CAUSE_TEMP_FAILURE",	41},
+	{"GSM48_CC_CAUSE_SWITCH_CONG",	42},
+	{"GSM48_CC_CAUSE_ACC_INF_DISCARD",	43},
+	{"GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL",	44},
+	{"GSM48_CC_CAUSE_RESOURCE_UNAVAIL",	47},
+	{"GSM48_CC_CAUSE_QOS_UNAVAIL",	49},
+	{"GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC",	50},
+	{"GSM48_CC_CAUSE_INC_BARRED_CUG",	55},
+	{"GSM48_CC_CAUSE_BEARER_CAP_UNAUTH",	57},
+	{"GSM48_CC_CAUSE_BEARER_CA_UNAVAIL",	58},
+	{"GSM48_CC_CAUSE_SERV_OPT_UNAVAIL",	63},
+	{"GSM48_CC_CAUSE_BEARERSERV_UNIMPL",	65},
+	{"GSM48_CC_CAUSE_ACM_GE_ACM_MAX",	68},
+	{"GSM48_CC_CAUSE_REQ_FAC_NOTIMPL",	69},
+	{"GSM48_CC_CAUSE_RESTR_BCAP_AVAIL",	70},
+	{"GSM48_CC_CAUSE_SERV_OPT_UNIMPL",	79},
+	{"GSM48_CC_CAUSE_INVAL_TRANS_ID",	81},
+	{"GSM48_CC_CAUSE_USER_NOT_IN_CUG",	87},
+	{"GSM48_CC_CAUSE_INCOMPAT_DEST",	88},
+	{"GSM48_CC_CAUSE_INVAL_TRANS_NET",	91},
+	{"GSM48_CC_CAUSE_SEMANTIC_INCORR",	95},
+	{"GSM48_CC_CAUSE_INVAL_MAND_INF",	96},
+	{"GSM48_CC_CAUSE_MSGTYPE_NOTEXIST",	97},
+	{"GSM48_CC_CAUSE_MSGTYPE_INCOMPAT",	98},
+	{"GSM48_CC_CAUSE_IE_NOTEXIST",	99},
+	{"GSM48_CC_CAUSE_COND_IE_ERR",	100},
+	{"GSM48_CC_CAUSE_MSG_INCOMP_STATE",	101},
+	{"GSM48_CC_CAUSE_RECOVERY_TIMER",	102},
+	{"GSM48_CC_CAUSE_PROTO_ERR",	111},
+	{"GSM48_CC_CAUSE_INTERWORKING",	127},
+
+	{NULL, 0} };
+
+const char *get_name_by_value(struct name_value *pairs, int value, const char *default_val)
 {
 	int i;
 
-	for (i = 0; mncc_names[i].name; i++) {
-		if (mncc_names[i].value == value)
-			return mncc_names[i].name;
+	for (i = 0; pairs[i].name; i++) {
+		if (pairs[i].value == value)
+			return pairs[i].name;
 	}
 
-	return "MNCC_Unknown";
+	return default_val;
+}
+
+
+const char *get_mncc_name(int value)
+{
+	return get_name_by_value(mncc_names, value, "MNCC_Unknown");
+}
+
+const char *get_mncc_location(int value)
+{
+	return get_name_by_value(mncc_locations, value, "GSM48_CAUSE_LOC_Unknown");
+}
+
+const char *get_mncc_cause(int value)
+{
+	return get_name_by_value(mncc_causes, value, "GSM48_CC_CAUSE_Unknown");
+}
+
+int mncc_has_cause(struct gsm_mncc *data)
+{
+	return data->fields & MNCC_F_CAUSE;
 }
 
 void mncc_set_cause(struct gsm_mncc *data, int loc, int val)
-- 
1.9.1

Reply via email to