blob: f2e74cbee80e31de8873279c45817addcba9e309 [file] [log] [blame]
Harald Welte0df904d2018-12-03 11:00:04 +01001/* SGs Interface according to 3GPP TS 23.272 + TS 29.118 */
2
3/* (C) 2018-2019 by sysmocom s.f.m.c. GmbH
4 * All Rights Reserved
5 *
6 * Author: Harald Welte, Philipp Maier
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <osmocom/core/utils.h>
24#include <osmocom/core/msgb.h>
25#include <osmocom/core/fsm.h>
26#include <osmocom/core/socket.h>
27#include <osmocom/core/select.h>
28
29#include <osmocom/gsm/tlv.h>
30#include <osmocom/gsm/gsm48.h>
31#include <osmocom/gsm/gsm23003.h>
32#include <osmocom/gsm/gsm29118.h>
33
34#include <osmocom/netif/stream.h>
35
36#include <osmocom/msc/vlr.h>
37#include <osmocom/msc/vlr_sgs.h>
38#include <osmocom/msc/gsm_data.h>
39#include <osmocom/msc/a_iface.h>
40#include <osmocom/msc/gsm_04_08.h>
41
42#include <osmocom/msc/debug.h>
43#include <osmocom/msc/sgs_iface.h>
44#include <osmocom/msc/sgs_server.h>
45#include <osmocom/msc/msc_ifaces.h>
46#include <osmocom/gsm/protocol/gsm_29_118.h>
47
48#include <osmocom/gsm/apn.h>
49
50#define S(x) (1 << (x))
51
52/* A pointer to the GSM network we work with. By the current paradigm,
53 * there can only be one gsm_network per MSC. The pointer is set once
Vadim Yanitskiy118a0b82019-03-21 20:51:55 +070054 * when calling sgs_iface_init() */
Harald Welte0df904d2018-12-03 11:00:04 +010055static struct gsm_network *gsm_network = NULL;
56
57static struct osmo_fsm sgs_vlr_reset_fsm;
58static void sgs_tx(struct sgs_connection *sgc, struct msgb *msg);
59
60struct sgs_state *g_sgs;
61
62/***********************************************************************
63 * SGs state per MME connection
64 ***********************************************************************/
65
66#define LOGSGC(sgc, lvl, fmt, args...) \
67 LOGP(DSGS, lvl, "%s: " fmt, sgc->sockname, ## args)
68
69#define LOGSGC_VSUB(sgc, sub_info, lvl, fmt, args...) \
70 LOGP(DSGS, lvl, "(sub %s) %s: " fmt, sub_info, sgc->sockname, ## args)
71
72#define LOGMME(mme, lvl, fmt, args...) \
73 LOGP(DSGS, lvl, "%s: " fmt, mme->fqdn ? mme->fqdn : mme->conn->sockname, ## args)
74
75enum sgs_vlr_reset_fsm_state {
76 SGS_VLRR_ST_NULL,
77 SGS_VLRR_ST_WAIT_ACK,
78 SGS_VLRR_ST_COMPLETE,
79};
80
81enum sgs_vlr_reset_fsm_event {
82 SGS_VLRR_E_START_RESET,
83 SGS_VLRR_E_RX_RESET_ACK,
84};
85
86/***********************************************************************
87 * SGs utility functions
88 ***********************************************************************/
89
90/* Allocate a new subscriber connection */
91static struct ran_conn *subscr_conn_allocate_sgs(struct sgs_connection *sgc, struct vlr_subscr *vsub, bool mt)
92{
93 struct ran_conn *conn;
94
95 conn = ran_conn_alloc(gsm_network, OSMO_RAT_EUTRAN_SGS, vsub->sgs.lai.lac);
96 if (!conn) {
97 LOGSGC_VSUB(sgc, vlr_subscr_name(vsub), LOGL_ERROR, "Connection allocation failed\n");
98 return NULL;
99 }
100
101 conn->vsub = vsub;
102 conn->vsub->cs.attached_via_ran = conn->via_ran;
103
104 /* Accept the connection immediately, since the UE is already
105 * authenticated by the MME no authentication is required. */
106 conn->complete_layer3_type = mt ? COMPLETE_LAYER3_PAGING_RESP : COMPLETE_LAYER3_CM_SERVICE_REQ;
107 ran_conn_update_id(conn);
108 osmo_fsm_inst_dispatch(conn->fi, RAN_CONN_E_COMPLETE_LAYER_3, NULL);
109 osmo_fsm_inst_dispatch(conn->fi, RAN_CONN_E_ACCEPTED, NULL);
110
111 LOG_RAN_CONN(conn, LOGL_DEBUG, "RAN connection successfully allocated!\n");
112 return conn;
113}
114
115/* Check if there are connections associated with a given subscriber. If yes,
116 * make sure that those connections are tossed. */
117static void subscr_conn_toss(struct vlr_subscr *vsub)
118{
119 struct ran_conn *conn;
120
121 conn = connection_for_subscr(vsub);
122 if (!conn)
123 return;
124
125 LOG_RAN_CONN(conn, LOGL_DEBUG, "RAN connection tossed because of unexpected RAN change!\n");
126
127 ran_conn_mo_close(conn, GSM48_REJECT_CONGESTION);
128}
129
130struct sgs_mme_ctx *sgs_mme_by_fqdn(struct sgs_state *sgs, const char *mme_fqdn)
131{
132 struct sgs_mme_ctx *mme;
133
134 llist_for_each_entry(mme, &sgs->mme_list, entry) {
135 if (!strcasecmp(mme_fqdn, mme->fqdn))
136 return mme;
137 }
138 return NULL;
139}
140
141static struct sgs_mme_ctx *sgs_mme_alloc(struct sgs_state *sgs, const char *mme_fqdn, const struct osmo_gummei *gummei)
142{
143 struct sgs_mme_ctx *mme;
144
145 OSMO_ASSERT(sgs_mme_by_fqdn(sgs, mme_fqdn) == NULL);
146
147 mme = talloc_zero(sgs, struct sgs_mme_ctx);
148 if (!mme)
149 return NULL;
150 mme->sgs = sgs;
151 OSMO_STRLCPY_ARRAY(mme->fqdn, mme_fqdn);
152 mme->fi = osmo_fsm_inst_alloc(&sgs_vlr_reset_fsm, mme, mme, LOGL_INFO, osmo_gummei_name(gummei));
153 if (!mme->fi) {
154 talloc_free(mme);
155 return NULL;
156 }
157 llist_add_tail(&mme->entry, &sgs->mme_list);
158 return mme;
159}
160
161/* Decode and verify MME name */
162static int decode_mme_name(char *mme_name, const struct tlv_parsed *tp)
163{
164 const uint8_t *mme_name_enc = TLVP_VAL_MINLEN(tp, SGSAP_IE_MME_NAME, SGS_MME_NAME_LEN);
165 struct osmo_gummei gummei;
166
167 if (!mme_name_enc)
168 return -EINVAL;
169
170 /* decode the MME name from DNS labels to string */
171 osmo_apn_to_str(mme_name, TLVP_VAL(tp, SGSAP_IE_MME_NAME), TLVP_LEN(tp, SGSAP_IE_MME_NAME));
172
173 /* try to parse the MME name into a GUMMEI as a test for the format */
174 if (osmo_parse_mme_domain(&gummei, mme_name) < 0)
175 return -EINVAL;
176
177 return 0;
178}
179
180/* A MME FQDN was received (e.g. RESET-IND/RESET-ACK/LU-REQ) */
181static int sgs_mme_fqdn_received(struct sgs_connection *sgc, const char *mme_fqdn)
182{
183 struct sgs_mme_ctx *mme;
184 struct osmo_gummei gummei;
185
186 /* caller must pass in a valid FQDN string syntax */
187 OSMO_ASSERT(osmo_parse_mme_domain(&gummei, mme_fqdn) == 0);
188
189 if (!sgc->mme) {
190 /* attempt to find MME with given name */
191 mme = sgs_mme_by_fqdn(sgc->sgs, mme_fqdn);
192 if (!mme)
193 mme = sgs_mme_alloc(sgc->sgs, mme_fqdn, &gummei);
194 OSMO_ASSERT(mme);
195
196 if (mme->conn) {
197 /* The MME context has another connection !?! */
198 LOGSGC(sgc, LOGL_ERROR, "Rx MME name %s, but that MME already has other "
199 "SCTP connection?!?\n", mme_fqdn);
200 return -1;
201 } else {
202 /* associate the two */
203 mme->conn = sgc;
204 sgc->mme = mme;
205 }
206 } else {
207 mme = sgc->mme;
208 if (strcasecmp(mme->fqdn, mme_fqdn) != 0) {
209 LOGMME(mme, LOGL_ERROR, "Rx MME name \"%s\" in packet from MME \"%s\" ?!?\n", mme_fqdn,
210 mme->fqdn);
211 return -2;
212 }
213 }
214 return 0;
215}
216
217/* Safely get the mme-name for an sgs-connection */
218static char *sgs_mme_fqdn_get(struct sgs_connection *sgc)
219{
220 if (!sgc)
221 return NULL;
222 if (!sgc->mme)
223 return NULL;
224 if (sgc->mme->fqdn[0] == '\0')
225 return NULL;
226 return sgc->mme->fqdn;
227}
228
229/* Find an sgs_mme_ctx for a given vlr subscriber, also check result */
230struct sgs_mme_ctx *sgs_mme_ctx_by_vsub(struct vlr_subscr *vsub, uint8_t msg_type)
231{
232 struct sgs_mme_ctx *mme;
233
234 /* Find SGS connection by MME name */
235 mme = sgs_mme_by_fqdn(g_sgs, vsub->sgs.mme_name);
236 if (!mme) {
237 LOGP(DSGS, LOGL_ERROR, "(sub %s) Tx %s cannot find suitable MME!\n",
238 vlr_subscr_name(vsub), sgsap_msg_type_name(msg_type));
239 return NULL;
240 }
241 if (!mme->conn) {
242 LOGP(DSGS, LOGL_ERROR,
243 "(sub %s) Tx %s suitable MME found, but no SGS connection present!\n",
244 vlr_subscr_name(vsub), sgsap_msg_type_name(msg_type));
245 return NULL;
246 }
247 if (!mme->sgs) {
248 LOGP(DSGS, LOGL_ERROR,
249 "(sub %s) Tx %s suitable MME found, but no SGS state present!\n",
250 vlr_subscr_name(vsub), sgsap_msg_type_name(msg_type));
251 return NULL;
252 }
253
254 return mme;
255}
256
257/* Make sure that the subscriber is known and that the subscriber is in the
258 * SGs associated state. In case of failure the function returns false and
259 * automatically sends a release message to the MME */
260static bool check_sgs_association(struct sgs_connection *sgc, struct msgb *msg, char *imsi)
261{
262 struct vlr_subscr *vsub;
263 struct msgb *resp;
264 uint8_t msg_type = msg->data[0];
265
266 /* Subscriber must be known by the VLR */
267 vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi);
268 if (!vsub) {
269 LOGSGC(sgc, LOGL_NOTICE, "SGsAP Message %s with unknown IMSI (%s), releasing\n",
270 sgsap_msg_type_name(msg_type), imsi);
271 resp = gsm29118_create_release_req(imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN);
272 sgs_tx(sgc, resp);
273 return false;
274 }
275
276 /* The SGs FSM must also be in SGs associated state */
277 if (vsub->sgs_fsm->state != SGS_UE_ST_ASSOCIATED) {
278 LOGSGC(sgc, LOGL_NOTICE, "(sub %s) SGsAP Message %s subscriber not SGs-associated, releasing\n",
279 vlr_subscr_name(vsub), sgsap_msg_type_name(msg_type));
280 resp = gsm29118_create_release_req(vsub->imsi, SGSAP_SGS_CAUSE_IMSI_DET_EPS_NONEPS);
281 sgs_tx(sgc, resp);
282 vlr_subscr_put(vsub);
283 return false;
284 }
285
286 vlr_subscr_put(vsub);
287 return true;
288}
289
290/***********************************************************************
291 * SGsAP transmit functions
292 ***********************************************************************/
293
294/* Send message out to remote end (final step) */
295static void sgs_tx(struct sgs_connection *sgc, struct msgb *msg)
296{
297 if (!msg) {
298 LOGSGC(sgc, LOGL_NOTICE, "Null message, cannot transmit!\n");
299 return;
300 }
301
302 msgb_sctp_ppid(msg) = 0;
303 if (!sgc) {
304 LOGSGC(sgc, LOGL_NOTICE, "Cannot transmit %s: connection dead. Discarding\n",
305 sgsap_msg_type_name(msg->data[0]));
306 msgb_free(msg);
307 return;
308 }
309 osmo_stream_srv_send(sgc->srv, msg);
310}
311
312/* Get some subscriber info from ISMI (for the log text) */
313const char *subscr_info(const char *imsi)
314{
315 const char *subscr_string = "<unknown>";
316 struct vlr_subscr *vsub;
317
318 if (imsi) {
319 vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi);
320 if (!vsub)
321 subscr_string = imsi;
322 else {
323 subscr_string = vlr_subscr_name(vsub);
324 vlr_subscr_put(vsub);
325 }
326 }
327
328 return subscr_string;
329}
330
331/* Comfortable status message generator that also generates some basic
332 * context-dependent dependand log output */
333static int sgs_tx_status(struct sgs_connection *sgc, const char *imsi, enum sgsap_sgs_cause cause, struct msgb *msg,
334 int sgsap_iei)
335{
336 struct msgb *resp;
337
338 if (sgsap_iei < 0) {
339 LOGSGC_VSUB(sgc, subscr_info(imsi), LOGL_ERROR, "Rx %s failed with cause %s!\n",
340 sgsap_msg_type_name(msg->data[0]), sgsap_sgs_cause_name(cause));
341 } else if (cause == SGSAP_SGS_CAUSE_MISSING_MAND_IE) {
342 LOGSGC_VSUB(sgc, subscr_info(imsi), LOGL_ERROR, "Rx %s with missing mandatory %s IEI!\n",
343 sgsap_msg_type_name(msg->data[0]), sgsap_iei_name(sgsap_iei));
344 } else if (cause == SGSAP_SGS_CAUSE_INVALID_MAND_IE) {
345 LOGSGC_VSUB(sgc, subscr_info(imsi), LOGL_ERROR, "Rx %s with invalid mandatory %s IEI!\n",
346 sgsap_msg_type_name(msg->data[0]), sgsap_iei_name(sgsap_iei));
347 } else if (cause == SGSAP_SGS_CAUSE_COND_IE_ERROR) {
348 LOGSGC_VSUB(sgc, subscr_info(imsi), LOGL_ERROR, "Rx %s with errornous conditional %s IEI!\n",
349 sgsap_msg_type_name(msg->data[0]), sgsap_iei_name(sgsap_iei));
350 } else {
351 LOGSGC_VSUB(sgc, subscr_info(imsi), LOGL_ERROR, "Rx %s failed with cause %s at %s IEI!\n",
352 sgsap_msg_type_name(msg->data[0]), sgsap_sgs_cause_name(cause), sgsap_iei_name(sgsap_iei));
353 }
354
355 resp = gsm29118_create_status(imsi, cause, msg);
356 sgs_tx(sgc, resp);
357 return 0;
358}
359
360/* Called by VLR via callback, transmits the the location update response or
361 * reject, depending on the outcome of the location update. */
362static void sgs_tx_loc_upd_resp_cb(struct sgs_lu_response *response)
363{
364 struct msgb *resp;
365 struct vlr_subscr *vsub = response->vsub;
366 struct sgs_mme_ctx *mme;
367 uint8_t new_id[2 + GSM48_TMSI_LEN];
368 uint8_t *new_id_ptr = new_id;
369 unsigned int new_id_len = 0;
370 uint8_t resp_msg_type;
371
372 if (response->accepted)
373 resp_msg_type = SGSAP_MSGT_LOC_UPD_ACK;
374 else
375 resp_msg_type = SGSAP_MSGT_LOC_UPD_REJ;
376
377 mme = sgs_mme_ctx_by_vsub(vsub, resp_msg_type);
378 if (!mme)
379 return;
380
381 if (response->accepted) {
382 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
383 new_id_len = gsm48_generate_mid_from_tmsi(new_id, vsub->tmsi_new);
384 new_id_ptr = new_id + 2;
385 new_id_len -= 2;
386 }
387 resp = gsm29118_create_lu_ack(vsub->imsi, &vsub->sgs.lai, new_id_ptr, new_id_len);
388 sgs_tx(mme->conn, resp);
389 vlr_sgs_loc_update_acc_sent(vsub);
390 } else {
391 resp = gsm29118_create_lu_rej(vsub->imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN, &vsub->sgs.lai);
392 sgs_tx(mme->conn, resp);
393 vlr_sgs_loc_update_rej_sent(vsub);
394 }
395}
396
397/* Called by VLR via callback, transmits MM information to the UE */
398static void sgs_tx_mm_info_cb(struct vlr_subscr *vsub)
399{
400 struct msgb *msg;
401 struct msgb *msg_mm_info;
402 struct sgs_mme_ctx *mme;
403
404 /* The sending of MM information requests is an optional feature and
405 * depends on the network configuration (VTY) */
406 if (!gsm_network->send_mm_info)
407 return;
408
409 mme = sgs_mme_ctx_by_vsub(vsub, SGSAP_MSGT_MM_INFO_REQ);
410 if (!mme)
411 return;
412
413 /* Create and send MM information request message, see also:
414 * 3GPP TS 29.118, chapter 8.12 SGsAP-MM-INFORMATION-REQUEST and
415 * 3GPP TS 29.018, chapter 18.4.16 MM information. */
416 msg_mm_info = gsm48_create_mm_info(gsm_network);
417 msg = gsm29118_create_mm_info_req(vsub->imsi, msg_mm_info->data + 2, msg_mm_info->len - 2);
418 sgs_tx(mme->conn, msg);
419 msgb_free(msg_mm_info);
420}
421
422/*! Page UE through SGs interface
423 * \param[in] vsub subscriber context
424 * \param[in] serv_ind service indicator (sms or voide)
425 * \returns 0 in case of success, -EINVAL in case of error. */
426int sgs_iface_tx_paging(struct vlr_subscr *vsub, enum sgsap_service_ind serv_ind)
427{
428 struct msgb *resp;
429 struct gsm29118_paging_req paging_params;
430 struct sgs_mme_ctx *mme;
431
432 /* See also: 3GPP TS 29.118, chapter 5.1.2.2 Paging Initiation */
433 if (vsub->sgs_fsm->state == SGS_UE_ST_NULL && vsub->conf_by_radio_contact_ind == true)
434 return -EINVAL;
435
436 mme = sgs_mme_ctx_by_vsub(vsub, SGSAP_MSGT_PAGING_REQ);
437 if (!mme)
438 return -EINVAL;
439
440 /* Check if there is still a paging in progress for this subscriber,
441 * if yes, don't initiate another paging request. */
442 if (vlr_sgs_pag_pend(vsub))
443 return 0;
444
445 memset(&paging_params, 0, sizeof(paging_params));
446 osmo_strlcpy(paging_params.imsi, vsub->imsi, sizeof(paging_params.imsi));
447 osmo_strlcpy(paging_params.vlr_name, mme->sgs->cfg.vlr_name, sizeof(paging_params.vlr_name));
448 paging_params.serv_ind = serv_ind;
449 if (vsub->conf_by_radio_contact_ind == true) {
450 memcpy(&paging_params.lai, &vsub->sgs.lai, sizeof(paging_params.lai));
451 paging_params.lai_present = true;
452 }
453 resp = gsm29118_create_paging_req(&paging_params);
454 sgs_tx(mme->conn, resp);
455
456 /* FIXME: If we are in SGS_UE_ST_NULL while sub->conf_by_radio_contact_ind == false,
457 * we are supposed to start a search procedure as defined in 3GPP TS 23.018 */
458
459 /* Inform the VLR that a paging via SGs is in progress */
460 vlr_sgs_pag(vsub, serv_ind);
461
462 /* Return a page count of 1 (success) */
463 return 1;
464}
465
466/***********************************************************************
467 * SGs incoming messages from the MME
468 ***********************************************************************/
469
470/* Safely read out the SGs cause code from a given message/tlv set, send status
471 * message in case the cause code is invalid or missing. */
472static int sgs_cause_from_msg(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp,
473 const char *imsi)
474{
475 enum sgsap_sgs_cause cause;
476 const uint8_t *cause_ptr;
477 cause_ptr = TLVP_VAL_MINLEN(tp, SGSAP_IE_SGS_CAUSE, 1);
478 if (!cause_ptr) {
479 sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_SGS_CAUSE);
480 return -1;
481 } else
482 cause = *cause_ptr;
483 return cause;
484}
485
486/* SGsAP-STATUS 3GPP TS 29.118, chapter 8.18 */
487static int sgs_rx_status(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, const char *imsi)
488{
489 int cause;
490 const uint8_t *err_msg;
491 const char *imsi_ptr;
492 char *err_msg_hex = "(none)";
493
494 cause = sgs_cause_from_msg(sgc, msg, tp, NULL);
495 if (cause < 0)
496 return 0;
497
498 if (imsi[0] != '\0')
499 imsi_ptr = imsi;
500 else
501 imsi_ptr = "<none>";
502
503 if (TLVP_PRESENT(tp, SGSAP_IE_ERR_MSG))
504 err_msg = TLVP_VAL(tp, SGSAP_IE_ERR_MSG);
505 else
506 err_msg = NULL;
507
508 if (err_msg)
509 err_msg_hex = osmo_hexdump(err_msg, TLVP_LEN(tp, SGSAP_IE_ERR_MSG));
510
511 LOGSGC(sgc, LOGL_NOTICE, "Rx STATUS cause=%s, IMSI=%s, err_msg=%s\n",
512 sgsap_sgs_cause_name(cause), imsi_ptr, err_msg_hex);
513
514 return 0;
515}
516
517/* SGsAP-RESET-INDICATION 3GPP TS 29.118, chapter 8.16 */
518static int sgs_rx_reset_ind(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp)
519{
520 struct gsm29118_reset_msg reset_params;
521 struct msgb *resp;
522
523 memset(&reset_params, 0, sizeof(reset_params));
524 osmo_strlcpy(reset_params.vlr_name, sgc->sgs->cfg.vlr_name, sizeof(reset_params.vlr_name));
525 reset_params.vlr_name_present = true;
526
527 resp = gsm29118_create_reset_ack(&reset_params);
528
529 /* Perform a reset of the SGS FSM of all subscribers that are present in the VLR */
530 vlr_sgs_reset(gsm_network->vlr);
531
532 sgs_tx(sgc, resp);
533 return 0;
534}
535
536/* SGsAP-RESET-ACK 3GPP TS 29.118, chapter 8.15 */
537static int sgs_rx_reset_ack(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp)
538{
539 /* dispatch event to VLR reset FSM for this MME */
540 if (sgc->mme && sgc->mme->fi)
541 osmo_fsm_inst_dispatch(sgc->mme->fi, SGS_VLRR_E_RX_RESET_ACK, msg);
542 return 0;
543}
544
545/* SGsAP-LOCATION-UPDATE-REQUEST 3GPP TS 29.118, chapter 8.11 */
546static int sgs_rx_loc_upd_req(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
547{
548 struct msgb *resp;
549 const uint8_t *lu_type_ie;
550 enum vlr_lu_type type;
551 struct osmo_location_area_id new_lai;
552 const struct gsm48_loc_area_id *gsm48_lai;
553 int rc;
554 char *mme_name;
555 struct vlr_sgs_cfg vlr_sgs_cfg;
556 struct vlr_subscr *vsub;
557
558 /* Check for lingering connections */
559 vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi);
560 if (vsub) {
561 subscr_conn_toss(vsub);
562 vlr_subscr_put(vsub);
563 }
564
565 /* Determine MME-Name */
566 mme_name = sgs_mme_fqdn_get(sgc);
567 if (!mme_name) {
568 resp = gsm29118_create_lu_rej(imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN, NULL);
569 sgs_tx(sgc, resp);
570 return 0;
571 }
572
573 /* Parse LU-Type */
574 lu_type_ie = TLVP_VAL_MINLEN(tp, SGSAP_IE_EPS_LU_TYPE, 1);
575 if (!lu_type_ie)
576 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_EPS_LU_TYPE);
577 if (lu_type_ie[0] == 0x01)
578 type = VLR_LU_TYPE_IMSI_ATTACH;
579 else
580 type = VLR_LU_TYPE_REGULAR;
581
582 /* Parse LAI of the new location */
583 gsm48_lai = (struct gsm48_loc_area_id *)TLVP_VAL_MINLEN(tp, SGSAP_IE_LAI, 5);
584 if (!gsm48_lai)
585 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_LAI);
586 gsm48_decode_lai2(gsm48_lai, &new_lai);
587
588 /* Perform actual location update */
589 memcpy(vlr_sgs_cfg.timer, sgc->sgs->cfg.timer, sizeof(vlr_sgs_cfg.timer));
590 memcpy(vlr_sgs_cfg.counter, sgc->sgs->cfg.counter, sizeof(vlr_sgs_cfg.counter));
591 rc = vlr_sgs_loc_update(gsm_network->vlr, &vlr_sgs_cfg, sgs_tx_loc_upd_resp_cb, sgs_iface_tx_paging,
592 sgs_tx_mm_info_cb, mme_name, type, imsi, &new_lai);
593 if (rc != 0) {
594 resp = gsm29118_create_lu_rej(imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN, NULL);
595 sgs_tx(sgc, resp);
596 }
597
598 return 0;
599}
600
601/* SGsAP-IMSI-DETACH-INDICATION 3GPP TS 29.118, chapter 8.8 */
602static int sgs_rx_imsi_det_ind(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
603{
604 struct msgb *resp;
605 enum sgsap_imsi_det_noneps_type type;
606 const uint8_t *type_ie;
607
608 type_ie = TLVP_VAL_MINLEN(tp, SGSAP_IE_IMSI_DET_NONEPS_TYPE, 1);
609 if (!type_ie)
610 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_IMSI_DET_NONEPS_TYPE);
611
612 switch (type_ie[0]) {
613 case SGSAP_ID_NONEPS_T_EXPLICIT_UE_NONEPS:
614 type = SGSAP_ID_NONEPS_T_EXPLICIT_UE_NONEPS;
615 break;
616 case SGSAP_ID_NONEPS_T_COMBINED_UE_EPS_NONEPS:
617 type = SGSAP_ID_NONEPS_T_COMBINED_UE_EPS_NONEPS;
618 break;
619 case SGSAP_ID_NONEPS_T_IMPLICIT_UE_EPS_NONEPS:
620 type = SGSAP_ID_NONEPS_T_IMPLICIT_UE_EPS_NONEPS;
621 break;
622 default:
623 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_INVALID_MAND_IE, msg, SGSAP_IE_IMSI_DET_NONEPS_TYPE);
624 break;
625 }
626
627 vlr_sgs_imsi_detach(gsm_network->vlr, imsi, type);
628 resp = gsm29118_create_imsi_det_ack(imsi);
629 sgs_tx(sgc, resp);
630
631 return 0;
632}
633
634/* SGsAP-EPS-DETACH-INDICATION 3GPP TS 29.118, chapter 8.6 */
635static int sgs_rx_eps_det_ind(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
636{
637 struct msgb *resp;
638 enum sgsap_imsi_det_eps_type type;
639 const uint8_t *type_ie;
640
641 type_ie = TLVP_VAL_MINLEN(tp, SGSAP_IE_IMSI_DET_EPS_TYPE, 1);
642 if (!type_ie)
643 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_IMSI_DET_EPS_TYPE);
644
645 switch (type_ie[0]) {
646 case SGSAP_ID_EPS_T_NETWORK_INITIATED:
647 type = SGSAP_ID_EPS_T_NETWORK_INITIATED;
648 break;
649 case SGSAP_ID_EPS_T_UE_INITIATED:
650 type = SGSAP_ID_EPS_T_UE_INITIATED;
651 break;
652 case SGSAP_ID_EPS_T_EPS_NOT_ALLOWED:
653 type = SGSAP_ID_EPS_T_EPS_NOT_ALLOWED;
654 break;
655 default:
656 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_INVALID_MAND_IE, msg, SGSAP_IE_IMSI_DET_EPS_TYPE);
657 break;
658 }
659
660 vlr_sgs_eps_detach(gsm_network->vlr, imsi, type);
661 resp = gsm29118_create_eps_det_ack(imsi);
662 sgs_tx(sgc, resp);
663
664 return 0;
665}
666
667/* SGsAP-PAGING-REJECT 3GPP TS 29.118, chapter 8.13 */
668static int sgs_rx_pag_rej(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
669{
670 int cause;
671 struct vlr_subscr *vsub;
672
673 cause = sgs_cause_from_msg(sgc, msg, tp, NULL);
674 if (cause < 0)
675 return 0;
676
677 /* Subscriber must be known by the VLR */
678 vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi);
679 if (!vsub)
680 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN, msg, SGSAP_IE_IMSI);
681
682 /* Inform the VLR */
683 vlr_sgs_pag_rej(gsm_network->vlr, imsi, cause);
684
685 /* Stop all paging activity */
686 subscr_paging_cancel(vsub, GSM_PAGING_EXPIRED);
687
688 /* Depending on the cause code some action is required */
689 if (cause == SGSAP_SGS_CAUSE_MT_CSFB_REJ_USER) {
690 /* FIXME: We are supposed to trigger a User Determined User Busy (UDUB)
691 * as specified in 3GPP TS 24.082 here, SGs association state shall not
692 * be changed */
693 LOGSGC(sgc, LOGL_ERROR,
694 "Rx %s with SGSAP_SGS_CAUSE_MT_CSFB_REJ_USER, but sending UDUP is not implemented yet!\n",
695 sgsap_msg_type_name(msg->data[0]));
696 } else if (cause == SGSAP_SGS_CAUSE_IMSI_DET_EPS) {
697 /* FIXME: In this case we should send the paging via A/Iu interface */
698 OSMO_ASSERT(false);
699 }
700
701 vlr_subscr_put(vsub);
702 return 0;
703}
704
705/* SGsAP-UE-UNREACHABLE 3GPP TS 29.118, chapter 8.21 */
706static int sgs_rx_ue_unr(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
707{
708 int cause;
709
710 cause = sgs_cause_from_msg(sgc, msg, tp, NULL);
711 if (cause < 0)
712 return 0;
713
714 vlr_sgs_ue_unr(gsm_network->vlr, imsi, cause);
715
716 return 0;
717}
718
719/* SGsAP-TMSI-REALLOCATION-COMPLETE 3GPP TS 29.118, chapter 8.19 */
720static int sgs_rx_tmsi_reall_cmpl(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
721{
722 vlr_sgs_tmsi_reall_compl(gsm_network->vlr, imsi);
723 return 0;
724}
725
726/* SGsAP-SERVICE-REQUEST 3GPP TS 29.118, chapter 8.17 */
727static int sgs_rx_service_req(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
728{
729 enum sgsap_service_ind serv_ind;
730 const uint8_t *serv_ind_ie;
731 struct ran_conn *conn;
732 struct vlr_subscr *vsub;
733
734 /* Note: While in other RAN concepts a service request is used to
735 * initiate mobile originated operation, the service request in SGsAP
736 * is comparable to a paging response. The SGsAP SERVICE REQUEST must
737 * not be confused or compared with a CM SERVICE REQUEST! */
738
739 if (!check_sgs_association(sgc, msg, imsi))
740 return 0;
741
742 vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi);
743 /* Note: vsub is already sufficiently verified by check_sgs_association(),
744 * we must have a vsub at this point! */
745 OSMO_ASSERT(vsub);
746
747 /* The Service request is intended as a paging response, if one is
748 * received while nothing is paging something is very wrong! */
749 if (!vlr_sgs_pag_pend(vsub)) {
750 vlr_subscr_put(vsub);
751 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MSG_INCOMP_STATE, msg, -1);
752 }
753 serv_ind_ie = TLVP_VAL_MINLEN(tp, SGSAP_IE_SERVICE_INDICATOR, 1);
754
755 if (!serv_ind_ie) {
756 vlr_subscr_put(vsub);
757 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_SERVICE_INDICATOR);
758 }
759 if (serv_ind_ie[0] == SGSAP_SERV_IND_CS_CALL)
760 serv_ind = serv_ind_ie[0];
761 else if (serv_ind_ie[0] == SGSAP_SERV_IND_SMS)
762 serv_ind = serv_ind_ie[0];
763 else {
764 vlr_subscr_put(vsub);
765 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_INVALID_MAND_IE, msg, SGSAP_IE_SERVICE_INDICATOR);
766 }
767
768 /* FIXME: The MME shall include an UE EMM Mode IE, but the field is
769 * marked optional. (Why do we need this info at all?) */
770
771 /* Report to the VLR that the paging has successfully completed */
772 vlr_sgs_pag_ack(gsm_network->vlr, imsi);
773
774 /* Exit early when the service indicator indicates that a call is being
775 * established. In those cases we do not allocate a connection, instead
776 * the connection will be allocated when the MS is appearing on the
777 * A-Interface. */
778 if (serv_ind == SGSAP_SERV_IND_CS_CALL) {
779 vlr_subscr_put(vsub);
780 return 0;
781 }
782
783 /* Allocate subscriber connection */
784 conn = subscr_conn_allocate_sgs(sgc, vsub, true);
785 if (!conn) {
786 vlr_subscr_put(vsub);
787 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MSG_INCOMP_STATE, msg, -1);
788 }
789
790 return 0;
791}
792
793/* SGsAP-UPLINK-UNITDATA 3GPP TS 29.118, chapter 8.22 */
794static int sgs_rx_ul_ud(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
795{
796 struct dtap_header *dtap;
797 struct ran_conn *conn;
798 bool ran_conn_created = false;
799 const uint8_t *nas_msg_container_ie;
800 struct vlr_subscr *vsub;
801
802 if (!check_sgs_association(sgc, msg, imsi))
803 return 0;
804
805 vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi);
806 /* Note: vsub is already sufficiently verified by check_sgs_association(),
807 * we must have a vsub at this point! */
808 OSMO_ASSERT(vsub);
809
810 /* Try to find existing connection (MT) or allocate a new one (MO) */
811 conn = connection_for_subscr(vsub);
812 if (!conn) {
813 conn = subscr_conn_allocate_sgs(sgc, vsub, false);
814 ran_conn_created = true;
815 } else {
816 if (conn->via_ran != OSMO_RAT_EUTRAN_SGS) {
817 LOGSGC(sgc, LOGL_ERROR,
818 "Receiving uplink unit-data for non-sgs connection -- discarding message!\n");
819 msgb_free(msg);
820 return 0;
821 }
822 }
823
824 /* If we do not find an existing connection and allocating a new one
825 * faild, give up and return status. */
826 if (!conn) {
827 vlr_subscr_put(vsub);
828 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MSG_INCOMP_STATE, msg, 0);
829 }
830
831 nas_msg_container_ie = TLVP_VAL_MINLEN(tp, SGSAP_IE_NAS_MSG_CONTAINER, 1);
832 if (!nas_msg_container_ie) {
833 vlr_subscr_put(vsub);
834 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_NAS_MSG_CONTAINER);
835 }
836
837 /* ran_conn_dtap expects the dtap payload in l3h */
838 dtap = (struct dtap_header *)nas_msg_container_ie;
839 msg->l3h = (uint8_t *) nas_msg_container_ie;
840 OMSC_LINKID_CB(msg) = dtap->link_id;
841
842 /* Forward dtap payload into the msc */
843 ran_conn_dtap(conn, msg);
844
845 /* If we did not create the conn right here, we just handle the ref
846 * counting normally. Otherwise we are in the same role as
847 * sgs_rx_service_req() and we want that the refcount says incremented
848 * througout the lifetime of the newly created conn. */
849 if (!ran_conn_created)
850 vlr_subscr_put(vsub);
851 return 0;
852}
853
854/* SGsAP-MO-CSFB-INDICATION, chapter 8.25 */
855static int sgs_rx_csfb_ind(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
856{
857 struct vlr_subscr *vsub;
858
859 /* The MME informs us with this message that the UE has returned back
860 * to the 4G network, so we use the SGs interface again for further
861 * communication with the UE. */
862
863 vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi);
864 if (!vsub)
865 return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN, msg, SGSAP_IE_IMSI);
866
867 /* Check for lingering connections */
868 subscr_conn_toss(vsub);
869
870 vsub->cs.attached_via_ran = OSMO_RAT_EUTRAN_SGS;
871 vlr_subscr_put(vsub);
872 return 0;
873}
874
875/* SGsAP-UE-ACTIVITY-INDICATION, chapter 8.20 */
876static int sgs_rx_ue_act_ind(struct sgs_connection *sgc, struct msgb *msg, const struct tlv_parsed *tp, char *imsi)
877{
878 /* In this MSC/VLR implementation we do not support the alerting
879 * procedure yet and therefore we will never request any alerting
880 * at the MME. Given that it is unlikely that we ever get activity
881 * indications from the MME, but if we do we should not act all too
882 * hostile and ignore the indication silently. */
883
884 LOGSGC(sgc, LOGL_ERROR, "Rx %s unexpected, we do not implement alerting yet, ignoring!\n",
885 sgsap_msg_type_name(msg->data[0]));
886
887 return 0;
888}
889
890#define TX_STATUS_AND_LOG(sgc, msg_type, cause, fmt) \
891 LOGSGC(sgc, LOGL_ERROR, fmt, sgsap_msg_type_name(msg_type)); \
892 resp = gsm29118_create_status(NULL, cause, msg); \
893 sgs_tx(sgc, resp); \
894
895/*! Process incoming SGs message (see sgs_server.c)
896 * \param[in] sgc related sgs connection
897 * \param[in] msg received message
898 * \returns 0 in case of success, -EINVAL in case of error. */
899int sgs_iface_rx(struct sgs_connection *sgc, struct msgb *msg)
900{
901 struct msgb *resp;
902 uint8_t msg_type = msg->l2h[0];
903 struct tlv_parsed tp;
904 int rc;
905 char imsi[GSM48_MI_SIZE];
906 char mme_name[SGS_MME_NAME_LEN + 1];
907
908 memset(imsi, 0, sizeof(imsi));
909 memset(mme_name, 0, sizeof(mme_name));
910
911 /* When the receiving entity receives a message that is too short to contain a complete
912 * message type information element, the receiving entity shall ignore that message. */
913 if (msgb_l2len(msg) < 1)
914 goto error;
915
916 /* Parse TLV elements */
917 rc = tlv_parse(&tp, &sgsap_ie_tlvdef, msgb_l2(msg) + 1, msgb_l2len(msg) - 1, 0, 0);
918 if (rc < 0) {
919 TX_STATUS_AND_LOG(sgc, msg_type, SGSAP_SGS_CAUSE_SEMANT_INCORR_MSG, "SGsAP Message %s parsing error\n");
920 goto error;
921 }
922
923 /* Most of the messages contain an IMSI as mandatory IE, parse it right here */
924 if (!TLVP_PRESENT(&tp, SGSAP_IE_IMSI) &&
925 msg_type != SGSAP_MSGT_STATUS && msg_type != SGSAP_MSGT_RESET_IND && msg_type != SGSAP_MSGT_RESET_ACK) {
926 /* reject the message; all but the three above have mandatory IMSI */
927 TX_STATUS_AND_LOG(sgc, msg_type, SGSAP_SGS_CAUSE_MISSING_MAND_IE,
928 "SGsAP Message %s without IMSI, dropping\n");
929 goto error;
930 }
931
932 if (TLVP_PRESENT(&tp, SGSAP_IE_IMSI)) {
933 gsm48_mi_to_string(imsi, sizeof(imsi), TLVP_VAL(&tp, SGSAP_IE_IMSI), TLVP_LEN(&tp, SGSAP_IE_IMSI));
934 if (strlen(imsi) < GSM23003_IMSI_MIN_DIGITS) {
935 TX_STATUS_AND_LOG(sgc, msg_type, SGSAP_SGS_CAUSE_INVALID_MAND_IE,
936 "SGsAP Message %s with short IMSI, dropping\n");
937 goto error;
938 }
939 }
940
941 /* Some messages contain an MME-NAME as mandatore IE, parse it right here. The
942 * MME-NAME is als immediately registered with the sgc, so it will be implicitly
943 * known to all functions that have access to the sgc context. */
944 if (!TLVP_PRESENT(&tp, SGSAP_IE_MME_NAME)
945 && (msg_type == SGSAP_MSGT_RESET_IND || msg_type == SGSAP_MSGT_RESET_ACK
946 || msg_type == SGSAP_MSGT_LOC_UPD_REQ || msg_type == SGSAP_MSGT_IMSI_DET_IND
947 || msg_type == SGSAP_MSGT_EPS_DET_IND)) {
948 TX_STATUS_AND_LOG(sgc, msg_type, SGSAP_SGS_CAUSE_MISSING_MAND_IE,
949 "SGsAP Message %s without MME-Name, dropping\n");
950 goto error;
951 }
952
953 if (TLVP_PRESENT(&tp, SGSAP_IE_MME_NAME)) {
954 if (decode_mme_name(mme_name, &tp) != 0) {
955 TX_STATUS_AND_LOG(sgc, msg_type, SGSAP_SGS_CAUSE_INVALID_MAND_IE,
956 "SGsAP Message %s with invalid MME-Name, dropping\n");
957 goto error;
958 }
959 /* Regsister/check mme_name with sgc */
960 if (sgs_mme_fqdn_received(sgc, mme_name) < 0) {
961 TX_STATUS_AND_LOG(sgc, msg_type, SGSAP_SGS_CAUSE_MSG_INCOMP_STATE,
962 "SGsAP Message %s with invalid MME-Name, dropping\n");
963 goto error;
964 }
965 }
966
967 /* dispatch msg to various handler functions. msgb ownership remains here! */
968 rc = -EINVAL;
969 switch (msg_type) {
970 case SGSAP_MSGT_STATUS:
971 rc = sgs_rx_status(sgc, msg, &tp, imsi);
972 break;
973 case SGSAP_MSGT_RESET_IND:
974 rc = sgs_rx_reset_ind(sgc, msg, &tp);
975 break;
976 case SGSAP_MSGT_RESET_ACK:
977 rc = sgs_rx_reset_ack(sgc, msg, &tp);
978 break;
979 case SGSAP_MSGT_LOC_UPD_REQ:
980 rc = sgs_rx_loc_upd_req(sgc, msg, &tp, imsi);
981 break;
982 case SGSAP_MSGT_IMSI_DET_IND:
983 rc = sgs_rx_imsi_det_ind(sgc, msg, &tp, imsi);
984 break;
985 case SGSAP_MSGT_EPS_DET_IND:
986 rc = sgs_rx_eps_det_ind(sgc, msg, &tp, imsi);
987 break;
988 case SGSAP_MSGT_PAGING_REJ:
989 rc = sgs_rx_pag_rej(sgc, msg, &tp, imsi);
990 break;
991 case SGSAP_MSGT_UE_UNREACHABLE:
992 rc = sgs_rx_ue_unr(sgc, msg, &tp, imsi);
993 break;
994 case SGSAP_MSGT_TMSI_REALL_CMPL:
995 rc = sgs_rx_tmsi_reall_cmpl(sgc, msg, &tp, imsi);
996 break;
997 case SGSAP_MSGT_SERVICE_REQ:
998 rc = sgs_rx_service_req(sgc, msg, &tp, imsi);
999 break;
1000 case SGSAP_MSGT_UL_UD:
1001 rc = sgs_rx_ul_ud(sgc, msg, &tp, imsi);
1002 break;
1003 case SGSAP_MSGT_MO_CSFB_IND:
1004 rc = sgs_rx_csfb_ind(sgc, msg, &tp, imsi);
1005 break;
1006 case SGSAP_MSGT_UE_ACT_IND:
1007 rc = sgs_rx_ue_act_ind(sgc, msg, &tp, imsi);
1008 break;
1009 case SGSAP_MSGT_ALERT_ACK:
1010 case SGSAP_MSGT_ALERT_REJ:
1011 LOGSGC(sgc, LOGL_ERROR, "Rx unmplemented SGsAP %s: %s\n",
1012 sgsap_msg_type_name(msg_type), msgb_hexdump(msg));
1013 resp = gsm29118_create_status(imsi, SGSAP_SGS_CAUSE_MSG_UNKNOWN, msg);
1014 sgs_tx(sgc, resp);
1015 rc = 0;
1016 break;
1017 default:
1018 LOGSGC(sgc, LOGL_ERROR, "Rx unknown SGsAP message type 0x%02x: %s\n", msg_type, msgb_hexdump(msg));
1019 resp = gsm29118_create_status(imsi, SGSAP_SGS_CAUSE_MSG_UNKNOWN, msg);
1020 sgs_tx(sgc, resp);
1021 rc = 0;
1022 break;
1023 }
1024
1025 /* Catch unhandled errors */
1026 if (rc < 0) {
1027 /* Note: Usually the sgs_rx_ should catch errors locally and
1028 * eimit a status message with proper cause code, including
1029 * a suitable log message. If we end up here, something is
1030 * not right and should be fixed */
1031 LOGSGC(sgc, LOGL_ERROR, "Rx unable to decode SGsAP %s: %s\n",
1032 sgsap_msg_type_name(msg_type), msgb_hexdump(msg));
1033 resp = gsm29118_create_status(imsi, SGSAP_SGS_CAUSE_MSG_UNKNOWN, msg);
1034 sgs_tx(sgc, resp);
1035 }
1036
1037error:
1038 msgb_free(msg);
1039 return 0;
1040}
1041
1042/***********************************************************************
1043 * SGs connection "VLR Reset Procedure" FSM
1044 ***********************************************************************/
1045
1046static const struct value_string sgs_vlr_reset_fsm_event_names[] = {
1047 {SGS_VLRR_E_START_RESET, "START-RESET"},
1048 {SGS_VLRR_E_RX_RESET_ACK, "RX-RESET-ACK"},
1049 {0, NULL}
1050};
1051
1052static void sgs_vlr_reset_fsm_null(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1053{
1054 switch (event) {
1055 case SGS_VLRR_E_RX_RESET_ACK:
1056 break;
1057 default:
1058 OSMO_ASSERT(0);
1059 break;
1060 }
1061}
1062
1063static void sgs_vlr_reset_fsm_wait_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1064{
1065 switch (event) {
1066 case SGS_VLRR_E_RX_RESET_ACK:
1067 osmo_fsm_inst_state_chg(fi, SGS_VLRR_ST_COMPLETE, 0, 0);
1068 break;
1069 default:
1070 OSMO_ASSERT(0);
1071 break;
1072 }
1073}
1074
1075static void sgs_vlr_reset_fsm_complete(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1076{
1077 switch (event) {
1078 case SGS_VLRR_E_RX_RESET_ACK:
1079 break;
1080 default:
1081 OSMO_ASSERT(0);
1082 break;
1083 }
1084}
1085
1086static void sgs_vlr_reset_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1087{
1088 struct msgb *reset_ind;
1089 struct gsm29118_reset_msg reset_params;
1090 struct sgs_mme_ctx *mme = (struct sgs_mme_ctx *)fi->priv;
1091 struct sgs_connection *sgc = mme->conn;
1092 struct sgs_state *sgs = mme->sgs;
1093
1094 switch (event) {
1095 case SGS_VLRR_E_START_RESET:
1096 osmo_fsm_inst_state_chg(fi, SGS_VLRR_ST_NULL, 0, 0);
1097 mme->ns11_remaining = sgs->cfg.counter[SGS_STATE_NS11];
1098 /* send a reset message and enter WAIT_ACK state */
1099 memset(&reset_params, 0, sizeof(reset_params));
1100 osmo_strlcpy(reset_params.vlr_name, sgs->cfg.vlr_name, sizeof(reset_params.vlr_name));
1101 reset_params.vlr_name_present = true;
1102 reset_ind = gsm29118_create_reset_ind(&reset_params);
1103 sgs_tx(sgc, reset_ind);
1104 osmo_fsm_inst_state_chg(fi, SGS_VLRR_ST_WAIT_ACK, sgs->cfg.timer[SGS_STATE_TS11], 11);
1105 break;
1106 default:
1107 OSMO_ASSERT(0);
1108 break;
1109 }
1110}
1111
1112static int sgs_vlr_reset_fsm_timer_cb(struct osmo_fsm_inst *fi)
1113{
1114 struct msgb *reset_ind;
1115 struct gsm29118_reset_msg reset_params;
1116 struct sgs_mme_ctx *mme = (struct sgs_mme_ctx *)fi->priv;
1117 struct sgs_connection *sgc = mme->conn;
1118 struct sgs_state *sgs = mme->sgs;
1119
1120 switch (fi->T) {
1121 case 11:
1122 if (mme->ns11_remaining >= 1) {
1123 memset(&reset_params, 0, sizeof(reset_params));
1124 osmo_strlcpy(reset_params.vlr_name, sgs->cfg.vlr_name, sizeof(reset_params.vlr_name));
1125 reset_params.vlr_name_present = true;
1126 reset_ind = gsm29118_create_reset_ind(&reset_params);
1127 sgs_tx(sgc, reset_ind);
1128 osmo_fsm_inst_state_chg(fi, SGS_VLRR_ST_WAIT_ACK, sgs->cfg.timer[SGS_STATE_TS11], 11);
1129 mme->ns11_remaining--;
1130 } else {
1131 LOGMME(mme, LOGL_ERROR, "Ts11 expired more than %u (Ns11) times, giving up\n",
Vadim Yanitskiye9ef7c62019-02-23 16:04:17 +07001132 sgs->cfg.counter[SGS_STATE_NS11]);
Harald Welte0df904d2018-12-03 11:00:04 +01001133 osmo_fsm_inst_state_chg(fi, SGS_VLRR_ST_NULL, 0, 0);
1134 }
1135 break;
1136 default:
1137 OSMO_ASSERT(0);
1138 break;
1139 }
1140 return 0;
1141}
1142
1143static const struct osmo_fsm_state sgs_vlr_reset_fsm_states[] = {
1144 [SGS_VLRR_ST_NULL] = {
1145 /* We haven't even tried yet to send a RESET */
1146 .name = "NULL",
1147 .action = sgs_vlr_reset_fsm_null,
1148 .in_event_mask = S(SGS_VLRR_E_RX_RESET_ACK),
1149 .out_state_mask = S(SGS_VLRR_ST_NULL) | S(SGS_VLRR_ST_WAIT_ACK),
1150 },
1151 [SGS_VLRR_ST_WAIT_ACK] = {
1152 /* We're waiting for a SGsAP_RESET_ACK */
1153 .name = "WAIT-ACK",
1154 .action = sgs_vlr_reset_fsm_wait_ack,
1155 .in_event_mask = S(SGS_VLRR_E_RX_RESET_ACK),
1156 .out_state_mask = S(SGS_VLRR_ST_NULL) |
1157 S(SGS_VLRR_ST_COMPLETE) | S(SGS_VLRR_ST_WAIT_ACK),
1158 },
1159 [SGS_VLRR_ST_COMPLETE] = {
1160 /* Reset procedure to this MME has been completed */
1161 .name = "COMPLETE",
1162 .action = sgs_vlr_reset_fsm_complete,
1163 .in_event_mask = S(SGS_VLRR_E_RX_RESET_ACK),
1164 .out_state_mask = S(SGS_VLRR_ST_NULL) | S(SGS_VLRR_ST_COMPLETE),
1165 },
1166};
1167
1168static struct osmo_fsm sgs_vlr_reset_fsm = {
1169 .name = "SGs-VLR-RESET",
1170 .states = sgs_vlr_reset_fsm_states,
1171 .allstate_event_mask = S(SGS_VLRR_E_START_RESET),
1172 .allstate_action = sgs_vlr_reset_fsm_allstate,
1173 .timer_cb = sgs_vlr_reset_fsm_timer_cb,
1174 .log_subsys = DSGS,
1175 .event_names = sgs_vlr_reset_fsm_event_names,
1176};
1177
1178/*! Send unit-data through SGs interface (see msc_ifaces.c)
1179 * \param[in] msg layer 3 message to send.
1180 * \returns 0 in case of success, -EINVAL in case of error. */
1181int sgs_iface_tx_dtap_ud(struct msgb *msg)
1182{
1183 struct ran_conn *conn;
1184 struct vlr_subscr *vsub;
1185 struct msgb *msg_sgs;
1186 struct sgs_mme_ctx *mme;
1187 int rc = -EINVAL;
1188
1189 /* This function expects a pointer to the related gsm subscriber
1190 * connection (conn) in msg->dst. Also conn->vsub must point to
1191 * the related subscriber */
1192
1193 OSMO_ASSERT(msg->dst);
1194 conn = msg->dst;
1195 OSMO_ASSERT(conn->vsub);
1196 vsub = conn->vsub;
1197
1198 mme = sgs_mme_ctx_by_vsub(vsub, SGSAP_MSGT_DL_UD);
1199 if (!mme)
1200 goto error;
1201
1202 /* Make sure the subscriber has a valid SGs association, otherwise
1203 * don't let unit-data through. */
1204 if (vsub->sgs_fsm->state != SGS_UE_ST_ASSOCIATED) {
1205 LOG_RAN_CONN(conn, LOGL_NOTICE, "Tx %s subscriber not SGs-associated, dropping\n",
1206 sgsap_msg_type_name(SGSAP_MSGT_DL_UD));
1207 goto error;
1208 }
1209
1210 msg_sgs = gsm29118_create_dl_ud(vsub->imsi, msg);
1211 sgs_tx(mme->conn, msg_sgs);
1212 rc = 0;
1213
1214error:
1215 msgb_free(msg);
1216 return rc;
1217}
1218
1219/*! Send a relase message through SGs interface (see msc_ifaces.c)
1220 * \param[in] msg layer 3 message to send.
1221 * \returns 0 in case of success, -EINVAL in case of error. */
1222void sgs_iface_tx_release(struct ran_conn *conn)
1223{
1224 struct msgb *msg_sgs;
1225 struct vlr_subscr *vsub;
1226 struct sgs_mme_ctx *mme;
1227
1228 /*! Use this function to release an SGs connection normally
1229 * (cause code is 0). This function also automatically causes
1230 * the VLR subscriber usage to be balanced. */
1231
1232 OSMO_ASSERT(conn->vsub);
1233 vsub = conn->vsub;
1234
1235 mme = sgs_mme_ctx_by_vsub(vsub, SGSAP_MSGT_DL_UD);
1236 if (!mme)
1237 return;
1238
1239 msg_sgs = gsm29118_create_release_req(vsub->imsi, 0);
1240 sgs_tx(mme->conn, msg_sgs);
1241}
1242
1243/*! initalize SGs new interface
1244 * \param[in] ctx talloc context
1245 * \param[in] network associated gsm network
1246 * \returns returns allocated sgs_stae, NULL in case of error. */
1247struct sgs_state *sgs_iface_init(void *ctx, struct gsm_network *network)
1248{
1249 struct sgs_state *sgs;
1250
1251 gsm_network = network;
1252
1253 sgs = sgs_server_alloc(ctx);
1254 OSMO_ASSERT(sgs);
1255
1256 /* We currently only support one SGs instance */
1257 if (g_sgs)
1258 return NULL;
1259 g_sgs = sgs;
1260
1261 osmo_fsm_register(&sgs_vlr_reset_fsm);
1262 sgs_server_open(sgs);
1263
1264 return sgs;
1265}