SMPP: Implement transaction mode for SUBMIT-SM

WARNING: if the ESME disconnects, osmo_esme gets freed, and
sms->smpp.esme might point to invalid/unallocated memory!
diff --git a/openbsc/src/libmsc/smpp_smsc.c b/openbsc/src/libmsc/smpp_smsc.c
index ff6b1f9..dd6a2f9 100644
--- a/openbsc/src/libmsc/smpp_smsc.c
+++ b/openbsc/src/libmsc/smpp_smsc.c
@@ -46,6 +46,17 @@
 	ESME_BIND_TX = 0x02,
 };
 
+static struct osmo_esme *
+esme_by_system_id(const struct smsc *smsc, char *system_id)
+{
+	struct osmo_esme *e;
+
+	llist_for_each_entry(e, &smsc->esme_list, list) {
+		if (!strcmp(e->system_id, system_id))
+			return e;
+	}
+	return NULL;
+}
 
 
 #define INIT_RESP(type, resp, req) 		{ \
@@ -280,6 +291,21 @@
 	return PACK_AND_SEND(esme, &enq_r);
 }
 
+int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr,
+		     uint32_t command_status, char *msg_id)
+{
+	struct submit_sm_resp_t submit_r;
+
+	memset(&submit_r, 0, sizeof(submit_r));
+	submit_r.command_length	= 0;
+	submit_r.command_id	= SUBMIT_SM_RESP;
+	submit_r.command_status	= command_status;
+	submit_r.sequence_number= sequence_nr;
+	snprintf(submit_r.message_id, sizeof(submit_r.message_id), "%s", msg_id);
+
+	return PACK_AND_SEND(esme, &submit_r);
+}
+
 static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg)
 {
 	struct submit_sm_t submit;