libmsc/gsm_04_11.c: accept MT SMS messages over GSUP

Change-Id: I57357982ca0e51f6722c24a4aa1d0fb3e6caef88
Depends-on: (core) Ibe325c64ae2d6c626b232533bb4cbc65fc2b5d71
Depends-on: (OsmoHLR) I0589ff27933e9bca2bcf93b8259004935778db8f
Related Change-Id: (TTCN) I63a25c8366cce0852df6b628365151661a22a25f
Related: OS#3587
diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c
index 788a0a9..15a92d4 100644
--- a/src/libmsc/gsm_04_11.c
+++ b/src/libmsc/gsm_04_11.c
@@ -158,10 +158,13 @@
 		gsm411_smc_recv(&trans->sms.smc_inst,
 			GSM411_MMSMS_REL_IND, NULL, 0);
 
-		/* Notify the SMSqueue and free stored SMS */
-		send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, event);
-		trans->sms.sms = NULL;
-		sms_free(sms);
+		/* gsm411_send_rp_data() doesn't set trans->sms.sms */
+		if (sms != NULL) {
+			/* Notify the SMSqueue and free stored SMS */
+			send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, event);
+			trans->sms.sms = NULL;
+			sms_free(sms);
+		}
 
 		/* Destroy this transaction */
 		trans_free(trans);
@@ -794,6 +797,11 @@
 	 * successfully received a SMS.  We can now safely mark it as
 	 * transmitted */
 
+	if (trans->net->sms_over_gsup) {
+		/* Forward towards SMSC via GSUP */
+		return gsm411_gsup_mt_fwd_sm_res(trans, rph->msg_ref);
+	}
+
 	if (!sms) {
 		LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
 		return gsm411_send_rp_error(trans, rph->msg_ref,
@@ -830,6 +838,11 @@
 	     vlr_subscr_name(trans->conn->vsub), cause_len, cause,
 	     get_value_string(gsm411_rp_cause_strs, cause));
 
+	if (trans->net->sms_over_gsup) {
+		/* Forward towards SMSC via GSUP */
+		return gsm411_gsup_mt_fwd_sm_err(trans, rph->msg_ref, cause);
+	}
+
 	if (!sms) {
 		LOGP(DLSMS, LOGL_ERROR,
 			"RX RP-ERR, but no sms in transaction?!?\n");
@@ -1112,6 +1125,42 @@
 		GSM411_SM_RL_DATA_REQ);
 }
 
+/* Low-level function to send raw RP-DATA to a given subscriber */
+int gsm411_send_rp_data(struct gsm_network *net, struct vlr_subscr *vsub,
+			size_t sm_rp_oa_len, const uint8_t *sm_rp_oa,
+			size_t sm_rp_ud_len, const uint8_t *sm_rp_ud)
+{
+	struct gsm_trans *trans;
+	struct msgb *msg;
+
+	/* Allocate a new transaction for MT SMS */
+	trans = gsm411_alloc_mt_trans(net, vsub);
+	if (!trans)
+		return -ENOMEM;
+
+	/* Allocate a message buffer for to be encoded SMS */
+	msg = gsm411_msgb_alloc();
+	if (!msg) {
+		trans_free(trans);
+		return -ENOMEM;
+	}
+
+	/* Encode SM-RP-OA (SMSC address) */
+	msgb_lv_put(msg, sm_rp_oa_len, sm_rp_oa);
+
+	/* Encode SM-RP-DA (shall be empty, len=0) */
+	msgb_v_put(msg, 0x00);
+
+	/* Encode RP-UD itself (SM TPDU) */
+	msgb_lv_put(msg, sm_rp_ud_len, sm_rp_ud);
+
+	rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED]);
+
+	return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg,
+		GSM411_MT_RP_DATA_MT, trans->sms.sm_rp_mr,
+		GSM411_SM_RL_DATA_REQ);
+}
+
 /* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
 int gsm0411_rcv_sms(struct ran_conn *conn,
 		    struct msgb *msg)