SMPP: Pass on 0xFx style DCS from SMPP to GSM

There are multiple ways how the TS 03.38 TP-DCS can indicate 8bit or
7bit messages.  SMPP has it's own data coding specification, which is
different from TS 03.38.

However, some SMPP ESMEs want to be able to have fine-grained control
over the TP-DCS indicated in the TPDU header.  If such values like 0xF6
are used in SMPP, we now transparently pass them on to the GSM side.
diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c
index 2f410e9..fdef90e 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -78,6 +78,9 @@
 	return NULL;
 }
 
+#define MODE_7BIT	7
+#define MODE_8BIT	8
+
 /*! \brief convert from submit_sm_t to gsm_sms */
 static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
 			 const struct submit_sm_t *submit)
@@ -87,6 +90,7 @@
 	struct tlv_t *t;
 	const uint8_t *sms_msg;
 	unsigned int sms_msg_len;
+	int mode;
 
 	dest = subscr_by_dst(net, submit->dest_addr_npi,
 			     submit->dest_addr_ton,
@@ -141,8 +145,34 @@
 	}
 
 	if (submit->data_coding == 0x00 ||	/* SMSC default */
-	    submit->data_coding == 0x01 ||	/* GSM default alphabet */
-	    (submit->data_coding & 0xFC) == 0xF0) { /* 03.38 DCS default */
+	    submit->data_coding == 0x01) {	/* GSM default alphabet */
+		sms->data_coding_scheme = GSM338_DCS_1111_7BIT;
+		mode = MODE_7BIT;
+	} else if ((submit->data_coding & 0xFC) == 0xF0) { /* 03.38 DCS default */
+		/* pass DCS 1:1 through from SMPP to GSM */
+		sms->data_coding_scheme = submit->data_coding;
+		mode = MODE_7BIT;
+	} else if (submit->data_coding == 0x02 ||
+		   submit->data_coding == 0x04) {
+		/* 8-bit binary */
+		sms->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
+		mode = MODE_8BIT;
+	} else if ((submit->data_coding & 0xFC) == 0xF4) { /* 03.38 DCS 8bit */
+		/* pass DCS 1:1 through from SMPP to GSM */
+		sms->data_coding_scheme = submit->data_coding;
+		mode = MODE_8BIT;
+	} else if (submit->data_coding == 0x80) {
+		/* UCS-2 */
+		sms->data_coding_scheme = (2 << 2);
+		mode = MODE_8BIT;
+	} else {
+		sms_free(sms);
+		LOGP(DLSMS, LOGL_ERROR, "SMPP Unknown Data Coding 0x%02x\n",
+			submit->data_coding);
+		return ESME_RUNKNOWNERR;
+	}
+
+	if (mode ==  MODE_7BIT) {
 		uint8_t ud_len = 0, padbits = 0;
 		sms->data_coding_scheme = GSM338_DCS_1111_7BIT;
 		if (sms->ud_hdr_ind) {
@@ -158,23 +188,9 @@
 				   sms_msg_len, padbits);
 		sms->user_data_len = (ud_len*8 + padbits)/7 + sms_msg_len;/* SEPTETS */
 		/* FIXME: sms->text */
-	} else if (submit->data_coding == 0x02 ||
-		   submit->data_coding == 0x04 ||
-		   (submit->data_coding & 0xFC) == 0xF4) { /* 03.38 DCS 8bit */
-		/* 8-bit binary */
-		sms->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
+	} else {
 		memcpy(sms->user_data, sms_msg, sms_msg_len);
 		sms->user_data_len = sms_msg_len;
-	} else if (submit->data_coding == 0x80) {
-		/* UCS-2 */
-		sms->data_coding_scheme = (2 << 2);
-		memcpy(sms->user_data, sms_msg, submit->sm_length);
-		sms->user_data_len = sms_msg_len;
-	} else {
-		sms_free(sms);
-		LOGP(DLSMS, LOGL_ERROR, "SMPP Unknown Data Coding 0x%02x\n",
-			submit->data_coding);
-		return ESME_RUNKNOWNERR;
 	}
 
 	*psms = sms;