SMPP: add small utility program 'smpp_mirror'

This program binds as ESME transceiver to a SMSC and simply mirrors back
all SMS that it receives.
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 790cde3..9a5f18d 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -993,7 +993,7 @@
 	/* FIXME: generate validity timestamp based on validity_minutes */
 
 	dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text);
-	dbi_conn_quote_string_copy(conn, (char *)sms->dest_addr, &q_daddr);
+	dbi_conn_quote_string_copy(conn, (char *)sms->dst.addr, &q_daddr);
 	dbi_conn_quote_binary_copy(conn, sms->user_data, sms->user_data_len,
 				   &q_udata);
 	/* FIXME: correct validity period */
@@ -1035,6 +1035,7 @@
 
 	sender_id = dbi_result_get_ulonglong(result, "sender_id");
 	sms->sender = subscr_get_by_id(net, sender_id);
+	strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1);
 
 	receiver_id = dbi_result_get_ulonglong(result, "receiver_id");
 	sms->receiver = subscr_get_by_id(net, receiver_id);
@@ -1051,8 +1052,8 @@
 
 	daddr = dbi_result_get_string(result, "dest_addr");
 	if (daddr) {
-		strncpy(sms->dest_addr, daddr, sizeof(sms->dest_addr));
-		sms->dest_addr[sizeof(sms->dest_addr)-1] = '\0';
+		strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr));
+		sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0';
 	}
 
 	sms->user_data_len = dbi_result_get_field_length(result, "user_data");
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index 5beae53..be6b5b0 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -143,12 +143,13 @@
 
 	/* FIXME: don't use ID 1 static */
 	sms->sender = subscr_get_by_id(receiver->net, 1);
+	strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1);
 	sms->reply_path_req = 0;
 	sms->status_rep_req = 0;
 	sms->ud_hdr_ind = 0;
 	sms->protocol_id = 0; /* implicit */
 	sms->data_coding_scheme = dcs;
-	strncpy(sms->dest_addr, receiver->extension, sizeof(sms->dest_addr)-1);
+	strncpy(sms->dst.addr, receiver->extension, sizeof(sms->dst.addr)-1);
 	/* Generate user_data */
 	sms->user_data_len = gsm_7bit_encode(sms->user_data, sms->text);
 
@@ -270,10 +271,10 @@
 
 /* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
 static int gsm340_gen_oa_sub(uint8_t *oa, unsigned int oa_len,
-			 struct gsm_subscriber *subscr)
+			 const struct gsm_sms_addr *src)
 {
 	/* network specific, private numbering plan */
-	return gsm340_gen_oa(oa, oa_len, 0x3, 0x9, subscr->extension);
+	return gsm340_gen_oa(oa, oa_len, src->ton, src->npi, src->addr);
 }
 
 /* generate a msgb containing a TPDU derived from struct gsm_sms,
@@ -299,9 +300,9 @@
 	/* TP-UDHI (indicating TP-UD contains a header) */
 	if (sms->ud_hdr_ind)
 		*smsp |= 0x40;
-	
+
 	/* generate originator address */
-	oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), sms->sender);
+	oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
 	smsp = msgb_put(msg, oa_len);
 	memcpy(smsp, oa, oa_len);
 
@@ -392,11 +393,11 @@
 	/* mangle first byte to reflect length in bytes, not digits */
 	address_lv[0] = da_len_bytes - 1;
 
-	gsms->destination.ton = (address_lv[1] >> 4) & 7;
-	gsms->destination.npi = address_lv[1] & 0xF;
+	gsms->dst.ton = (address_lv[1] >> 4) & 7;
+	gsms->dst.npi = address_lv[1] & 0xF;
 	/* convert to real number */
-	gsm48_decode_bcd_number(gsms->destination.addr,
-				sizeof(gsms->destination.addr), address_lv, 1);
+	gsm48_decode_bcd_number(gsms->dst.addr,
+				sizeof(gsms->dst.addr), address_lv, 1);
 	smsp += da_len_bytes;
 
 	gsms->protocol_id = *smsp++;
@@ -449,7 +450,7 @@
 	     "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
 	     "UserDataLength: 0x%02x, UserData: \"%s\"\n",
 	     subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
-	     gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
+	     gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr,
 	     gsms->user_data_len,
 			sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
 				osmo_hexdump(gsms->user_data, gsms->user_data_len));
@@ -460,7 +461,7 @@
 	send_signal(0, NULL, gsms, 0);
 
 	/* determine gsms->receiver based on dialled number */
-	gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dest_addr);
+	gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dst.addr);
 	if (!gsms->receiver) {
 #ifdef BUILD_SMPP
 		rc = smpp_try_deliver(gsms);
diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c
index b3b8d36..378cbf6 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -118,9 +118,18 @@
 	sms = sms_alloc();
 	sms->source = SMS_SOURCE_SMPP;
 	sms->smpp.sequence_nr = submit->sequence_number;
+
+	/* fill in the destination address */
 	sms->receiver = dest;
-	strncpy(sms->dest_addr, dest->extension, sizeof(sms->dest_addr)-1);
+	sms->dst.ton = submit->dest_addr_ton;
+	sms->dst.npi = submit->dest_addr_npi;
+	strncpy(sms->dst.addr, dest->extension, sizeof(sms->dst.addr)-1);
+
+	/* fill in the source address */
 	sms->sender = subscr_get_by_id(net, 1);
+	sms->src.ton = submit->source_addr_ton;
+	sms->src.npi = submit->source_addr_npi;
+	strncpy(sms->src.addr, (char *)submit->source_addr, sizeof(sms->src.addr)-1);
 
 	if (submit->esm_class & 0x40)
 		sms->ud_hdr_ind = 1;
@@ -312,9 +321,9 @@
 			 sms->sender->extension);
 	}
 
-	deliver.dest_addr_ton	= sms->destination.ton;
-	deliver.dest_addr_npi	= sms->destination.npi;
-	memcpy(deliver.destination_addr, sms->destination.addr,
+	deliver.dest_addr_ton	= sms->dst.ton;
+	deliver.dest_addr_npi	= sms->dst.npi;
+	memcpy(deliver.destination_addr, sms->dst.addr,
 		sizeof(deliver.destination_addr));
 
 	deliver.esm_class	= 1;	/* datagram mode */
@@ -368,9 +377,9 @@
 	struct osmo_smpp_addr dst;
 
 	memset(&dst, 0, sizeof(dst));
-	dst.ton = sms->destination.ton;
-	dst.npi = sms->destination.npi;
-	memcpy(dst.addr, sms->destination.addr, sizeof(dst.addr));
+	dst.ton = sms->dst.ton;
+	dst.npi = sms->dst.npi;
+	memcpy(dst.addr, sms->dst.addr, sizeof(dst.addr));
 
 	esme = smpp_route(g_smsc, &dst);
 	if (!esme)