blob: b4d74c7dd2698b98266ce9e6d88fb0b9deb7677c [file] [log] [blame]
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +07001/*
2 * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
3 *
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>
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070036
37/* Common helper for preparing to be encoded GSUP message */
38static void gsup_sm_msg_init(struct osmo_gsup_message *gsup_msg,
39 enum osmo_gsup_message_type msg_type, const char *imsi,
40 uint8_t *sm_rp_mr)
41{
42 /* Init a mew GSUP message */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010043 *gsup_msg = (struct osmo_gsup_message){
44 .message_type = msg_type,
45 .sm_rp_mr = sm_rp_mr,
46 .message_class = OSMO_GSUP_MESSAGE_CLASS_SMS,
47 };
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070048
49 /* Fill in subscriber's IMSI */
50 OSMO_STRLCPY_ARRAY(gsup_msg->imsi, imsi);
51}
52
53int gsm411_gsup_mo_fwd_sm_req(struct gsm_trans *trans, struct msgb *msg,
54 uint8_t sm_rp_mr, uint8_t *sm_rp_da, uint8_t sm_rp_da_len)
55{
56 uint8_t bcd_buf[GSM48_MI_SIZE] = { 0 };
57 struct osmo_gsup_message gsup_msg;
58 size_t bcd_len;
59
60 /* Associate logging messages with this subscriber */
61 log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
62
Neels Hofmeyrff7074a2019-02-28 05:50:06 +010063 LOG_TRANS(trans, LOGL_DEBUG, "TX GSUP MO-forwardSM-Req\n");
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070064
65 /* Assign SM-RP-MR to transaction state */
66 trans->sms.sm_rp_mr = sm_rp_mr;
67
68 /* Encode subscriber's MSISDN */
69 bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf),
70 0, trans->vsub->msisdn);
71 if (bcd_len <= 0 || bcd_len > sizeof(bcd_buf)) {
Neels Hofmeyrff7074a2019-02-28 05:50:06 +010072 LOG_TRANS(trans, LOGL_ERROR, "Failed to encode subscriber's MSISDN\n");
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070073 return -EINVAL;
74 }
75
76 /* Initialize a new GSUP message */
77 gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST,
78 trans->vsub->imsi, &sm_rp_mr);
79
80 /* According to 12.2.3, the MSISDN from VLR is inserted here */
81 gsup_msg.sm_rp_oa_type = OSMO_GSUP_SMS_SM_RP_ODA_MSISDN;
82 gsup_msg.sm_rp_oa_len = bcd_len;
83 gsup_msg.sm_rp_oa = bcd_buf;
84
85 /* SM-RP-DA should (already) contain SMSC address */
86 gsup_msg.sm_rp_da_type = OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR;
87 gsup_msg.sm_rp_da_len = sm_rp_da_len;
88 gsup_msg.sm_rp_da = sm_rp_da;
89
90 /* SM-RP-UI (TPDU) is pointed by msgb->l4h */
91 gsup_msg.sm_rp_ui_len = msgb_l4len(msg);
92 gsup_msg.sm_rp_ui = (uint8_t *) msgb_sms(msg);
93
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010094 return gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +070095}
96
97int gsm411_gsup_mo_ready_for_sm_req(struct gsm_trans *trans, uint8_t sm_rp_mr)
98{
99 struct osmo_gsup_message gsup_msg;
100
101 /* Associate logging messages with this subscriber */
102 log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
103
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100104 LOG_TRANS(trans, LOGL_DEBUG, "TX GSUP READY-FOR-SM Req\n");
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700105
106 /* Assign SM-RP-MR to transaction state */
107 trans->sms.sm_rp_mr = sm_rp_mr;
108
109 /* Initialize a new GSUP message */
110 gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST,
111 trans->vsub->imsi, &sm_rp_mr);
112
113 /* Indicate SMMA as the Alert Reason */
114 gsup_msg.sm_alert_rsn = OSMO_GSUP_SMS_SM_ALERT_RSN_MEM_AVAIL;
115
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100116 return gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700117}
118
119/* Triggers either RP-ACK or RP-ERROR on response from SMSC */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100120static int gsm411_gsup_mo_handler(struct vlr_subscr *vsub,
121 const struct osmo_gsup_message *gsup_msg)
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700122{
123 struct vlr_instance *vlr;
124 struct gsm_network *net;
125 struct gsm_trans *trans;
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700126 const char *msg_name;
127 bool msg_is_err;
128
129 /* Obtain required pointers */
130 vlr = vsub->vlr;
131 net = (struct gsm_network *) vlr->user_ctx;
132
133 /* Associate logging messages with this subscriber */
134 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
135
136 /* Determine the message type and name */
137 msg_is_err = OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type);
138 switch (gsup_msg->message_type) {
139 case OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR:
140 case OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT:
141 msg_name = "MO-forwardSM";
142 break;
143 case OSMO_GSUP_MSGT_READY_FOR_SM_ERROR:
144 case OSMO_GSUP_MSGT_READY_FOR_SM_RESULT:
145 msg_name = "MO-ReadyForSM";
146 break;
147 default:
148 /* Shall not happen */
149 OSMO_ASSERT(0);
150 }
151
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700152 /* Make sure that 'SMS over GSUP' is expected */
153 if (!net->sms_over_gsup) {
154 /* TODO: notify sender about that? */
155 LOGP(DLSMS, LOGL_NOTICE, "Unexpected MO SMS over GSUP, "
156 "ignoring message...\n");
157 return -EIO;
158 }
159
160 /* Verify GSUP message */
161 if (!gsup_msg->sm_rp_mr)
162 goto msg_error;
163 if (msg_is_err && !gsup_msg->sm_rp_cause)
164 goto msg_error;
165
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700166 /* Attempt to find DTAP-transaction */
Vadim Yanitskiy36c44b22019-01-23 21:22:27 +0700167 trans = trans_find_by_sm_rp_mr(net, vsub, *(gsup_msg->sm_rp_mr));
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700168 if (!trans) {
169 LOGP(DLSMS, LOGL_NOTICE, "No transaction found for %s, "
170 "ignoring %s-%s message...\n", vlr_subscr_name(vsub),
171 msg_name, msg_is_err ? "Err" : "Res");
172 return -EIO; /* TODO: notify sender about that? */
173 }
174
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100175 LOG_TRANS(trans, LOGL_DEBUG, "RX %s-%s\n", msg_name, msg_is_err ? "Err" : "Res");
176
Vadim Yanitskiy76ef72d2018-11-07 05:08:18 +0700177 /* Send either RP-ERROR, or RP-ACK */
178 if (msg_is_err) {
179 /* TODO: handle optional SM-RP-UI payload (requires API change) */
180 gsm411_send_rp_error(trans, *(gsup_msg->sm_rp_mr),
181 *(gsup_msg->sm_rp_cause));
182 } else {
183 gsm411_send_rp_ack(trans, *(gsup_msg->sm_rp_mr));
184 }
185
186 return 0;
187
188msg_error:
189 /* TODO: notify sender about that? */
190 LOGP(DLSMS, LOGL_NOTICE, "RX malformed %s-%s\n",
191 msg_name, msg_is_err ? "Err" : "Res");
192 return -EINVAL;
193}
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700194
195int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr)
196{
197 struct osmo_gsup_message gsup_msg;
198
199 /* Associate logging messages with this subscriber */
200 log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
201
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100202 LOG_TRANS(trans, LOGL_DEBUG, "TX MT-forwardSM-Res\n");
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700203
204 /* Initialize a new GSUP message */
205 gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,
206 trans->vsub->imsi, &sm_rp_mr);
207
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
225 /* SM-RP-Cause value */
226 gsup_msg.sm_rp_cause = &cause;
227
228 /* TODO: include optional SM-RP-UI field if present */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100229 return gsup_client_mux_tx(trans->net->gcm, &gsup_msg);
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700230}
231
232/* Handles MT SMS (and triggers Paging Request if required) */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100233static int gsm411_gsup_mt_handler(struct vlr_subscr *vsub,
234 const struct osmo_gsup_message *gsup_msg)
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700235{
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700236 struct gsm_network *net;
Vadim Yanitskiy643270f2019-05-12 05:38:41 +0700237 bool sm_rp_mmts_ind;
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700238 int rc;
239
240 /* Obtain required pointers */
Vadim Yanitskiy59ed7922019-05-12 06:24:11 +0700241 net = (struct gsm_network *) vsub->vlr->user_ctx;
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700242
243 /* Associate logging messages with this subscriber */
244 log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
245
246 LOGP(DLSMS, LOGL_DEBUG, "RX MT-forwardSM-Req\n");
247
248 /* Make sure that 'SMS over GSUP' is expected */
249 if (!net->sms_over_gsup) {
250 LOGP(DLSMS, LOGL_NOTICE, "Unexpected MT SMS over GSUP, "
251 "ignoring message...\n");
252 /* TODO: notify sender about that? */
253 return -EIO;
254 }
255
256 /**
257 * Verify GSUP message
258 *
259 * FIXME: SM-RP-MR is not known yet (to be assigned by MSC)
260 * NOTE: SM-RP-DA is out of our interest
261 */
262 if (!gsup_msg->sm_rp_mr)
263 goto msg_error;
264 if (!gsup_msg->sm_rp_ui)
265 goto msg_error;
266
267 /* SM-RP-OA shall contain SMSC address */
268 if (gsup_msg->sm_rp_oa_type != OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR)
269 goto msg_error;
270
Vadim Yanitskiy643270f2019-05-12 05:38:41 +0700271 /* MMS (More Messages to Send) IE is optional */
272 if (gsup_msg->sm_rp_mms)
273 sm_rp_mmts_ind = *gsup_msg->sm_rp_mms > 0;
274 else
275 sm_rp_mmts_ind = false;
276
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700277 /* Send RP-DATA */
278 rc = gsm411_send_rp_data(net, vsub,
279 gsup_msg->sm_rp_oa_len, gsup_msg->sm_rp_oa,
Vadim Yanitskiy643270f2019-05-12 05:38:41 +0700280 gsup_msg->sm_rp_ui_len, gsup_msg->sm_rp_ui,
281 sm_rp_mmts_ind);
Vadim Yanitskiy82cc8a52018-11-15 01:05:53 +0700282 if (rc) {
283 LOGP(DLSMS, LOGL_NOTICE, "Failed to send MT SMS, "
284 "ignoring MT-forwardSM-Req message...\n");
285 /* TODO: notify sender about that? */
286 return rc;
287 }
288
289 return 0;
290
291msg_error:
292 /* TODO: notify sender about that? */
293 LOGP(DLSMS, LOGL_NOTICE, "RX malformed MT-forwardSM-Req\n");
294 return -EINVAL;
295}
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100296
297int gsm411_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_message *gsup_msg)
298{
299 struct vlr_instance *vlr = data;
300 struct vlr_subscr *vsub = vlr_subscr_find_by_imsi(vlr, gsup_msg->imsi, __func__);
301
302 if (!vsub) {
Vadim Yanitskiy3d603032019-06-15 00:54:30 +0700303 LOGP(DLSMS, LOGL_ERROR, "Rx %s for unknown subscriber, rejecting\n",
304 osmo_gsup_message_type_name(gsup_msg->message_type));
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100305 gsup_client_mux_tx_error_reply(gcm, gsup_msg, GMM_CAUSE_IMSI_UNKNOWN);
306 return -GMM_CAUSE_IMSI_UNKNOWN;
307 }
308
309 switch (gsup_msg->message_type) {
310 /* GSM 04.11 code implementing MO SMS */
311 case OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR:
312 case OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT:
313 case OSMO_GSUP_MSGT_READY_FOR_SM_ERROR:
314 case OSMO_GSUP_MSGT_READY_FOR_SM_RESULT:
315 DEBUGP(DMSC, "Routed to GSM 04.11 MO handler\n");
316 return gsm411_gsup_mo_handler(vsub, gsup_msg);
317
318 /* GSM 04.11 code implementing MT SMS */
319 case OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST:
320 DEBUGP(DMSC, "Routed to GSM 04.11 MT handler\n");
321 return gsm411_gsup_mt_handler(vsub, gsup_msg);
322
323 default:
324 LOGP(DMM, LOGL_ERROR, "No handler found for %s, dropping message...\n",
325 osmo_gsup_message_type_name(gsup_msg->message_type));
326 return -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
327 }
328}