blob: 1afdfabbc4c74f472ef917a850ea5f1f4fe0ad9f [file] [log] [blame]
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +07001/*
Vadim Yanitskiy6e722822019-12-19 17:22:22 +09002 * (C) 2018-2019 by Vadim Yanitskiy <axilirator@gmail.com>
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +07003 *
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <stdio.h>
22#include <errno.h>
23
24#include <osmocom/core/linuxlist.h>
25#include <osmocom/core/utils.h>
26#include <osmocom/core/msgb.h>
27
28#include <osmocom/gsupclient/gsup_client.h>
29#include <osmocom/msc/gsm_subscriber.h>
30#include <osmocom/msc/transaction.h>
31#include <osmocom/msc/msc_common.h>
32#include <osmocom/msc/debug.h>
33#include <osmocom/msc/vlr.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010034#include <osmocom/msc/msub.h>
35#include <osmocom/msc/gsup_client_mux.h>
Andreas Eversberge24636c2023-04-23 12:20:55 +020036#include <osmocom/msc/msc_a.h>
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070037
38/* Common helper for preparing to be encoded GSUP message */
39static void gsup_sm_msg_init(struct osmo_gsup_message *gsup_msg,
40 enum osmo_gsup_message_type msg_type, const char *imsi,
41 uint8_t *sm_rp_mr)
42{
43 /* Init a mew GSUP message */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010044 *gsup_msg = (struct osmo_gsup_message){
45 .message_type = msg_type,
46 .sm_rp_mr = sm_rp_mr,
47 .message_class = OSMO_GSUP_MESSAGE_CLASS_SMS,
48 };
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070049
50 /* Fill in subscriber's IMSI */
51 OSMO_STRLCPY_ARRAY(gsup_msg->imsi, imsi);
52}
53
54int gsm411_gsup_mo_fwd_sm_req(struct gsm_trans *trans, struct msgb *msg,
55 uint8_t sm_rp_mr, uint8_t *sm_rp_da, uint8_t sm_rp_da_len)
56{
Vadim Yanitskiy61f47802019-12-19 22:08:14 +090057 uint8_t bcd_buf[GSM48_MI_SIZE];
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070058 struct osmo_gsup_message gsup_msg;
59 size_t bcd_len;
60
61 /* Associate logging messages with this subscriber */
62 log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
63
Neels Hofmeyrff7074a2019-02-28 05:50:06 +010064 LOG_TRANS(trans, LOGL_DEBUG, "TX GSUP MO-forwardSM-Req\n");
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070065
66 /* Assign SM-RP-MR to transaction state */
67 trans->sms.sm_rp_mr = sm_rp_mr;
68
Vadim Yanitskiy6e722822019-12-19 17:22:22 +090069 /* Encode subscriber's MSISDN as LHV (with room for ToN/NPI header) */
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070070 bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf),
Vadim Yanitskiy6e722822019-12-19 17:22:22 +090071 1, trans->vsub->msisdn);
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070072 if (bcd_len <= 0 || bcd_len > sizeof(bcd_buf)) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +010073 LOG_TRANS(trans, LOGL_ERROR, "Failed to encode subscriber's MSISDN\n");
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070074 return -EINVAL;
75 }
76
Vadim Yanitskiy6e722822019-12-19 17:22:22 +090077 /* NOTE: assuming default ToN/NPI values as we don't have this info */
78 bcd_buf[1] = 0x01 /* NPI: ISDN/Telephony Numbering (ITU-T Rec. E.164 / ITU-T Rec. E.163) */
79 | (0x01 << 4) /* ToN: International Number */
80 | (0x01 << 7); /* No Extension */
81
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070082 /* Initialize a new GSUP message */
83 gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST,
84 trans->vsub->imsi, &sm_rp_mr);
85
Vadim Yanitskiy6e722822019-12-19 17:22:22 +090086 /* According to 12.2.3, the MSISDN from VLR is inserted here.
87 * NOTE: redundant BCD length octet is not included. */
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070088 gsup_msg.sm_rp_oa_type = OSMO_GSUP_SMS_SM_RP_ODA_MSISDN;
Vadim Yanitskiy6e722822019-12-19 17:22:22 +090089 gsup_msg.sm_rp_oa_len = bcd_len - 1;
90 gsup_msg.sm_rp_oa = bcd_buf + 1;
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070091
92 /* SM-RP-DA should (already) contain SMSC address */
93 gsup_msg.sm_rp_da_type = OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR;
94 gsup_msg.sm_rp_da_len = sm_rp_da_len;
95 gsup_msg.sm_rp_da = sm_rp_da;
96
97 /* SM-RP-UI (TPDU) is pointed by msgb->l4h */
98 gsup_msg.sm_rp_ui_len = msgb_l4len(msg);
99 gsup_msg.sm_rp_ui = (uint8_t *) msgb_sms(msg);
100
Vadim Yanitskiy82361842024-01-09 22:18:08 +0700101 gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100102 return gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700103}
104
105int gsm411_gsup_mo_ready_for_sm_req(struct gsm_trans *trans, uint8_t sm_rp_mr)
106{
107 struct osmo_gsup_message gsup_msg;
108
109 /* Associate logging messages with this subscriber */
110 log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
111
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100112 LOG_TRANS(trans, LOGL_DEBUG, "TX GSUP READY-FOR-SM Req\n");
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700113
114 /* Assign SM-RP-MR to transaction state */
115 trans->sms.sm_rp_mr = sm_rp_mr;
116
117 /* Initialize a new GSUP message */
118 gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST,
119 trans->vsub->imsi, &sm_rp_mr);
120
121 /* Indicate SMMA as the Alert Reason */
122 gsup_msg.sm_alert_rsn = OSMO_GSUP_SMS_SM_ALERT_RSN_MEM_AVAIL;
123
Vadim Yanitskiy82361842024-01-09 22:18:08 +0700124 gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100125 return gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700126}
127
128/* Triggers either RP-ACK or RP-ERROR on response from SMSC */
Vadim Yanitskiy805eca22019-06-15 17:30:23 +0700129static int gsm411_gsup_mo_handler(struct gsm_network *net, struct vlr_subscr *vsub,
130 const struct osmo_gsup_message *gsup_msg)
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700131{
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700132 struct gsm_trans *trans;
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700133 const char *msg_name;
134 bool msg_is_err;
135
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700136 /* Associate logging messages with this subscriber */
137 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
138
139 /* Determine the message type and name */
140 msg_is_err = OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type);
141 switch (gsup_msg->message_type) {
142 case OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR:
143 case OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT:
144 msg_name = "MO-forwardSM";
145 break;
146 case OSMO_GSUP_MSGT_READY_FOR_SM_ERROR:
147 case OSMO_GSUP_MSGT_READY_FOR_SM_RESULT:
148 msg_name = "MO-ReadyForSM";
149 break;
150 default:
151 /* Shall not happen */
152 OSMO_ASSERT(0);
153 }
154
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700155 /* Verify GSUP message */
156 if (!gsup_msg->sm_rp_mr)
157 goto msg_error;
158 if (msg_is_err && !gsup_msg->sm_rp_cause)
159 goto msg_error;
160
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700161 /* Attempt to find DTAP-transaction */
Vadim Yanitskiy36c44b22019-01-23 21:22:27 +0700162 trans = trans_find_by_sm_rp_mr(net, vsub, *(gsup_msg->sm_rp_mr));
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700163 if (!trans) {
164 LOGP(DLSMS, LOGL_NOTICE, "No transaction found for %s, "
165 "ignoring %s-%s message...\n", vlr_subscr_name(vsub),
166 msg_name, msg_is_err ? "Err" : "Res");
Vadim Yanitskiya361cab2020-04-20 10:50:14 +0700167 gsup_client_mux_tx_error_reply(net->gcm, gsup_msg, GMM_CAUSE_NO_PDP_ACTIVATED);
168 return -EIO;
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700169 }
170
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100171 LOG_TRANS(trans, LOGL_DEBUG, "RX %s-%s\n", msg_name, msg_is_err ? "Err" : "Res");
172
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700173 /* Send either RP-ERROR, or RP-ACK */
174 if (msg_is_err) {
175 /* TODO: handle optional SM-RP-UI payload (requires API change) */
176 gsm411_send_rp_error(trans, *(gsup_msg->sm_rp_mr),
177 *(gsup_msg->sm_rp_cause));
178 } else {
179 gsm411_send_rp_ack(trans, *(gsup_msg->sm_rp_mr));
180 }
181
182 return 0;
183
184msg_error:
Vadim Yanitskiy4547cf12020-04-20 10:42:28 +0700185 LOGP(DLSMS, LOGL_NOTICE, "RX malformed %s-%s\n", msg_name, msg_is_err ? "Err" : "Res");
186 gsup_client_mux_tx_error_reply(net->gcm, gsup_msg, GMM_CAUSE_INV_MAND_INFO);
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700187 return -EINVAL;
188}
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700189
190int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr)
191{
192 struct osmo_gsup_message gsup_msg;
193
194 /* Associate logging messages with this subscriber */
195 log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
196
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100197 LOG_TRANS(trans, LOGL_DEBUG, "TX MT-forwardSM-Res\n");
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700198
199 /* Initialize a new GSUP message */
200 gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,
201 trans->vsub->imsi, &sm_rp_mr);
202
Mychaela N. Falconia02c49372023-09-25 05:13:49 +0000203 /* Ensure routing through OsmoHLR to the MT-sending SMSC */
204 gsup_msg.destination_name = trans->sms.gsup_source_name;
205 gsup_msg.destination_name_len = trans->sms.gsup_source_name_len;
Mychaela N. Falconiadbe88892023-09-25 05:20:02 +0000206 gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg);
Mychaela N. Falconia02c49372023-09-25 05:13:49 +0000207
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100208 return gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700209}
210
211int gsm411_gsup_mt_fwd_sm_err(struct gsm_trans *trans,
212 uint8_t sm_rp_mr, uint8_t cause)
213{
214 struct osmo_gsup_message gsup_msg;
215
216 /* Associate logging messages with this subscriber */
217 log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
218
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100219 LOG_TRANS(trans, LOGL_DEBUG, "TX MT-forwardSM-Err\n");
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700220
221 /* Initialize a new GSUP message */
222 gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR,
223 trans->vsub->imsi, &sm_rp_mr);
224
Mychaela N. Falconia02c49372023-09-25 05:13:49 +0000225 /* Ensure routing through OsmoHLR to the MT-sending SMSC */
226 gsup_msg.destination_name = trans->sms.gsup_source_name;
227 gsup_msg.destination_name_len = trans->sms.gsup_source_name_len;
Mychaela N. Falconiadbe88892023-09-25 05:20:02 +0000228 gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg);
Mychaela N. Falconia02c49372023-09-25 05:13:49 +0000229
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700230 /* SM-RP-Cause value */
231 gsup_msg.sm_rp_cause = &cause;
232
233 /* TODO: include optional SM-RP-UI field if present */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100234 return gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700235}
236
237/* Handles MT SMS (and triggers Paging Request if required) */
Vadim Yanitskiy805eca22019-06-15 17:30:23 +0700238static int gsm411_gsup_mt_handler(struct gsm_network *net, struct vlr_subscr *vsub,
239 const struct osmo_gsup_message *gsup_msg)
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700240{
Vadim Yanitskiy643270f2019-05-12 05:38:41 +0700241 bool sm_rp_mmts_ind;
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700242 int rc;
243
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700244 /* Associate logging messages with this subscriber */
245 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
246
247 LOGP(DLSMS, LOGL_DEBUG, "RX MT-forwardSM-Req\n");
248
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700249 /**
250 * Verify GSUP message
251 *
252 * FIXME: SM-RP-MR is not known yet (to be assigned by MSC)
253 * NOTE: SM-RP-DA is out of our interest
254 */
255 if (!gsup_msg->sm_rp_mr)
256 goto msg_error;
257 if (!gsup_msg->sm_rp_ui)
258 goto msg_error;
259
260 /* SM-RP-OA shall contain SMSC address */
261 if (gsup_msg->sm_rp_oa_type != OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR)
262 goto msg_error;
263
Vadim Yanitskiy643270f2019-05-12 05:38:41 +0700264 /* MMS (More Messages to Send) IE is optional */
265 if (gsup_msg->sm_rp_mms)
266 sm_rp_mmts_ind = *gsup_msg->sm_rp_mms > 0;
267 else
268 sm_rp_mmts_ind = false;
269
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700270 /* Send RP-DATA */
271 rc = gsm411_send_rp_data(net, vsub,
272 gsup_msg->sm_rp_oa_len, gsup_msg->sm_rp_oa,
Vadim Yanitskiy643270f2019-05-12 05:38:41 +0700273 gsup_msg->sm_rp_ui_len, gsup_msg->sm_rp_ui,
Mychaela N. Falconia02c49372023-09-25 05:13:49 +0000274 sm_rp_mmts_ind, gsup_msg->source_name,
275 gsup_msg->source_name_len);
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700276 if (rc) {
277 LOGP(DLSMS, LOGL_NOTICE, "Failed to send MT SMS, "
278 "ignoring MT-forwardSM-Req message...\n");
Vadim Yanitskiy3c8fc132020-04-20 10:49:14 +0700279 gsup_client_mux_tx_error_reply(net->gcm, gsup_msg, GMM_CAUSE_NET_FAIL);
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700280 return rc;
281 }
282
283 return 0;
284
285msg_error:
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700286 LOGP(DLSMS, LOGL_NOTICE, "RX malformed MT-forwardSM-Req\n");
Vadim Yanitskiy4547cf12020-04-20 10:42:28 +0700287 gsup_client_mux_tx_error_reply(net->gcm, gsup_msg, GMM_CAUSE_INV_MAND_INFO);
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700288 return -EINVAL;
289}
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100290
291int gsm411_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_message *gsup_msg)
292{
Vadim Yanitskiy805eca22019-06-15 17:30:23 +0700293 struct gsm_network *net = (struct gsm_network *) data;
Vadim Yanitskiy59e0c6b2019-06-19 19:48:37 +0700294 struct vlr_subscr *vsub;
295 int rc;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100296
Vadim Yanitskiy531d3a42020-04-20 10:29:19 +0700297 /* Make sure that 'SMS over GSUP' is expected */
298 if (!net->sms_over_gsup) {
Vadim Yanitskiy531d3a42020-04-20 10:29:19 +0700299 LOGP(DLSMS, LOGL_NOTICE, "Unexpected MO/MT SMS over GSUP "
300 "(sms-over-gsup is not enabled), ignoring message...\n");
Vadim Yanitskiyb6ec0992020-04-20 10:33:36 +0700301 gsup_client_mux_tx_error_reply(gcm, gsup_msg, GMM_CAUSE_GPRS_NOTALLOWED);
Vadim Yanitskiy531d3a42020-04-20 10:29:19 +0700302 return -EIO;
303 }
304
Vadim Yanitskiy59e0c6b2019-06-19 19:48:37 +0700305 vsub = vlr_subscr_find_by_imsi(net->vlr, gsup_msg->imsi, __func__);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100306 if (!vsub) {
Vadim Yanitskiy3d603032019-06-15 00:54:30 +0700307 LOGP(DLSMS, LOGL_ERROR, "Rx %s for unknown subscriber, rejecting\n",
308 osmo_gsup_message_type_name(gsup_msg->message_type));
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100309 gsup_client_mux_tx_error_reply(gcm, gsup_msg, GMM_CAUSE_IMSI_UNKNOWN);
310 return -GMM_CAUSE_IMSI_UNKNOWN;
311 }
312
313 switch (gsup_msg->message_type) {
314 /* GSM 04.11 code implementing MO SMS */
315 case OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR:
316 case OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT:
317 case OSMO_GSUP_MSGT_READY_FOR_SM_ERROR:
318 case OSMO_GSUP_MSGT_READY_FOR_SM_RESULT:
319 DEBUGP(DMSC, "Routed to GSM 04.11 MO handler\n");
Vadim Yanitskiy59e0c6b2019-06-19 19:48:37 +0700320 rc = gsm411_gsup_mo_handler(net, vsub, gsup_msg);
321 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100322
323 /* GSM 04.11 code implementing MT SMS */
324 case OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST:
325 DEBUGP(DMSC, "Routed to GSM 04.11 MT handler\n");
Vadim Yanitskiy59e0c6b2019-06-19 19:48:37 +0700326 rc = gsm411_gsup_mt_handler(net, vsub, gsup_msg);
327 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100328
329 default:
330 LOGP(DMM, LOGL_ERROR, "No handler found for %s, dropping message...\n",
331 osmo_gsup_message_type_name(gsup_msg->message_type));
Vadim Yanitskiyb1e46b12020-04-20 10:38:14 +0700332 gsup_client_mux_tx_error_reply(gcm, gsup_msg, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
Vadim Yanitskiy59e0c6b2019-06-19 19:48:37 +0700333 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100334 }
Vadim Yanitskiy59e0c6b2019-06-19 19:48:37 +0700335
336 vlr_subscr_put(vsub, __func__);
337 return rc;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100338}