osmo-hlr/src/hlr.c

879 lines
27 KiB
C
Raw Normal View History

2016-05-03 16:51:18 +00:00
/* (C) 2016 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <signal.h>
#include <errno.h>
#include <stdbool.h>
#include <getopt.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/application.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/ports.h>
#include <osmocom/vty/cpu_sched_vty.h>
#include <osmocom/ctrl/control_vty.h>
fix luop crash: use buffer for APN that remains valid In osmo_gsup_configure_wildcard_apn(), do not compose APN into a local buffer that becomes invalid as soon as the function exits. Instead, use a caller provided buf. Fixes OS#3231 crash: ==20030==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7fffffffd9c0 at pc 0x7ffff6e9b6c2 bp 0x7fffffffd900 sp 0x7fffffffd0b0 READ of size 2 at 0x7fffffffd9c0 thread T0 #0 0x7ffff6e9b6c1 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x766c1) #1 0x7ffff6314419 in tlv_put ../../../../src/libosmocore/include/osmocom/gsm/tlv.h:107 #2 0x7ffff6314419 in msgb_tlv_put ../../../../src/libosmocore/include/osmocom/gsm/tlv.h:299 #3 0x7ffff6314419 in encode_pdp_info ../../../../src/libosmocore/src/gsm/gsup.c:419 #4 0x7ffff6314419 in osmo_gsup_encode ../../../../src/libosmocore/src/gsm/gsup.c:535 #5 0x555555580016 in _luop_tx_gsup ../../../src/osmo-hlr/src/luop.c:54 #6 0x5555555809d8 in lu_op_tx_insert_subscr_data ../../../src/osmo-hlr/src/luop.c:264 #7 0x55555558b356 in rx_upd_loc_req ../../../src/osmo-hlr/src/hlr.c:306 #8 0x55555558b356 in read_cb ../../../src/osmo-hlr/src/hlr.c:365 #9 0x555555586671 in osmo_gsup_server_read_cb ../../../src/osmo-hlr/src/gsup_server.c:105 #10 0x7ffff5b35911 in ipa_server_conn_read ../../../src/libosmo-abis/src/input/ipa.c:356 #11 0x7ffff5b35911 in ipa_server_conn_cb ../../../src/libosmo-abis/src/input/ipa.c:387 #12 0x7ffff5e5541f in osmo_fd_disp_fds ../../../src/libosmocore/src/select.c:216 #13 0x7ffff5e5541f in osmo_select_main ../../../src/libosmocore/src/select.c:256 #14 0x5555555791b6 in main ../../../src/osmo-hlr/src/hlr.c:600 #15 0x7ffff4707a86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21a86) #16 0x555555579679 in _start (/usr/local/bin/osmo-hlr+0x25679) Address 0x7fffffffd9c0 is located in stack of thread T0 at offset 16 in frame #0 0x7ffff63131ff in osmo_gsup_encode ../../../../src/libosmocore/src/gsm/gsup.c:481 This frame has 1 object(s): [32, 64) 'bcd_buf' <== Memory access at offset 16 underflows this variable Related: OS#3231 Change-Id: I83d9ef2868bbb01e3f1ddb7920fe735aca172b15
2018-05-04 14:02:44 +00:00
#include <osmocom/gsm/apn.h>
#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/gsm_utils.h>
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/mslookup/mslookup_client.h>
#include <osmocom/gsupclient/cni_peer_id.h>
#include <osmocom/hlr/db.h>
#include <osmocom/hlr/hlr.h>
#include <osmocom/hlr/ctrl.h>
#include <osmocom/hlr/logging.h>
#include <osmocom/hlr/gsup_server.h>
#include <osmocom/hlr/gsup_router.h>
#include <osmocom/hlr/rand.h>
#include <osmocom/hlr/hlr_vty.h>
#include <osmocom/hlr/hlr_ussd.h>
#include <osmocom/hlr/dgsm.h>
#include <osmocom/hlr/proxy.h>
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
#include <osmocom/hlr/lu_fsm.h>
#include <osmocom/mslookup/mdns.h>
struct hlr *g_hlr;
static void *hlr_ctx = NULL;
static int quit = 0;
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
struct osmo_tdef g_hlr_tdefs[] = {
/* 4222 is also the OSMO_GSUP_PORT */
{ .T = -4222, .default_val = 30, .desc = "GSUP Update Location timeout" },
{}
};
/* Trigger 'Insert Subscriber Data' messages to all connected GSUP clients.
*
* \param[in] subscr A subscriber we have new data to send for.
*/
void
osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
{
struct osmo_gsup_conn *co;
if (g_hlr->gs == NULL) {
LOGP(DLGSUP, LOGL_DEBUG,
"IMSI %s: NOT Notifying peers of subscriber data change,"
" there is no GSUP server\n",
subscr->imsi);
return;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
/* FIXME: send only to current vlr_number and sgsn_number */
llist_for_each_entry(co, &g_hlr->gs->clients, list) {
struct osmo_gsup_message gsup = { };
uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
fix luop crash: use buffer for APN that remains valid In osmo_gsup_configure_wildcard_apn(), do not compose APN into a local buffer that becomes invalid as soon as the function exits. Instead, use a caller provided buf. Fixes OS#3231 crash: ==20030==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7fffffffd9c0 at pc 0x7ffff6e9b6c2 bp 0x7fffffffd900 sp 0x7fffffffd0b0 READ of size 2 at 0x7fffffffd9c0 thread T0 #0 0x7ffff6e9b6c1 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x766c1) #1 0x7ffff6314419 in tlv_put ../../../../src/libosmocore/include/osmocom/gsm/tlv.h:107 #2 0x7ffff6314419 in msgb_tlv_put ../../../../src/libosmocore/include/osmocom/gsm/tlv.h:299 #3 0x7ffff6314419 in encode_pdp_info ../../../../src/libosmocore/src/gsm/gsup.c:419 #4 0x7ffff6314419 in osmo_gsup_encode ../../../../src/libosmocore/src/gsm/gsup.c:535 #5 0x555555580016 in _luop_tx_gsup ../../../src/osmo-hlr/src/luop.c:54 #6 0x5555555809d8 in lu_op_tx_insert_subscr_data ../../../src/osmo-hlr/src/luop.c:264 #7 0x55555558b356 in rx_upd_loc_req ../../../src/osmo-hlr/src/hlr.c:306 #8 0x55555558b356 in read_cb ../../../src/osmo-hlr/src/hlr.c:365 #9 0x555555586671 in osmo_gsup_server_read_cb ../../../src/osmo-hlr/src/gsup_server.c:105 #10 0x7ffff5b35911 in ipa_server_conn_read ../../../src/libosmo-abis/src/input/ipa.c:356 #11 0x7ffff5b35911 in ipa_server_conn_cb ../../../src/libosmo-abis/src/input/ipa.c:387 #12 0x7ffff5e5541f in osmo_fd_disp_fds ../../../src/libosmocore/src/select.c:216 #13 0x7ffff5e5541f in osmo_select_main ../../../src/libosmocore/src/select.c:256 #14 0x5555555791b6 in main ../../../src/osmo-hlr/src/hlr.c:600 #15 0x7ffff4707a86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21a86) #16 0x555555579679 in _start (/usr/local/bin/osmo-hlr+0x25679) Address 0x7fffffffd9c0 is located in stack of thread T0 at offset 16 in frame #0 0x7ffff63131ff in osmo_gsup_encode ../../../../src/libosmocore/src/gsm/gsup.c:481 This frame has 1 object(s): [32, 64) 'bcd_buf' <== Memory access at offset 16 underflows this variable Related: OS#3231 Change-Id: I83d9ef2868bbb01e3f1ddb7920fe735aca172b15
2018-05-04 14:02:44 +00:00
uint8_t apn[APN_MAXLEN];
struct msgb *msg_out;
uint8_t *peer;
int peer_len;
size_t peer_strlen;
const char *peer_compare;
enum osmo_gsup_cn_domain cn_domain;
if (co->supports_ps) {
cn_domain = OSMO_GSUP_CN_DOMAIN_PS;
peer_compare = subscr->sgsn_number;
} else if (co->supports_cs) {
cn_domain = OSMO_GSUP_CN_DOMAIN_CS;
peer_compare = subscr->vlr_number;
} else {
/* We have not yet received a location update from this GSUP client.*/
continue;
}
peer_len = osmo_gsup_conn_ccm_get(co, &peer, IPAC_IDTAG_SERNR);
if (peer_len < 0) {
LOGP(DLGSUP, LOGL_ERROR,
"IMSI='%s': cannot get peer name for connection %s:%u\n", subscr->imsi,
co && co->conn && co->conn->server? co->conn->server->addr : "unset",
co && co->conn && co->conn->server? co->conn->server->port : 0);
continue;
}
peer_strlen = strnlen((const char*)peer, peer_len);
if (strlen(peer_compare) != peer_strlen || strncmp(peer_compare, (const char *)peer, peer_len)) {
/* Mismatch. The subscriber is not subscribed with this GSUP client. */
/* I hope peer is always nul terminated... */
if (peer_strlen < peer_len)
LOGP(DLGSUP, LOGL_DEBUG,
"IMSI %s: subscriber change: skipping %s peer %s\n",
subscr->imsi, cn_domain == OSMO_GSUP_CN_DOMAIN_PS ? "PS" : "CS",
osmo_quote_str((char*)peer, -1));
continue;
}
LOGP(DLGSUP, LOGL_DEBUG,
"IMSI %s: subscriber change: notifying %s peer %s\n",
subscr->imsi, cn_domain == OSMO_GSUP_CN_DOMAIN_PS ? "PS" : "CS",
osmo_quote_str(peer_compare, -1));
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, msisdn_enc,
sizeof(msisdn_enc), apn, sizeof(apn), cn_domain) != 0) {
LOGP(DLGSUP, LOGL_ERROR,
"IMSI='%s': Cannot notify GSUP client; could not create gsup message "
"for %s:%u\n", subscr->imsi,
co && co->conn && co->conn->server? co->conn->server->addr : "unset",
co && co->conn && co->conn->server? co->conn->server->port : 0);
continue;
}
/* Send ISD to MSC/SGSN */
msg_out = osmo_gsup_msgb_alloc("GSUP ISD UPDATE");
if (msg_out == NULL) {
LOGP(DLGSUP, LOGL_ERROR,
"IMSI='%s': Cannot notify GSUP client; could not allocate msg buffer "
"for %s:%u\n", subscr->imsi,
co && co->conn && co->conn->server? co->conn->server->addr : "unset",
co && co->conn && co->conn->server? co->conn->server->port : 0);
continue;
}
osmo_gsup_encode(msg_out, &gsup);
if (osmo_gsup_addr_send(g_hlr->gs, peer, peer_len, msg_out) < 0) {
LOGP(DMAIN, LOGL_ERROR,
"IMSI='%s': Cannot notify GSUP client; send operation failed "
"for %s:%u\n", subscr->imsi,
co && co->conn && co->conn->server? co->conn->server->addr : "unset",
co && co->conn && co->conn->server? co->conn->server->port : 0);
continue;
}
}
}
static int generate_new_msisdn(char *msisdn, const char *imsi, unsigned int len)
{
int i, j, rc;
uint8_t rand_buf[GSM23003_MSISDN_MAX_DIGITS];
OSMO_ASSERT(len <= sizeof(rand_buf));
/* Generate a random unique MSISDN (with retry) */
for (i = 0; i < 10; i++) {
/* Get a random number (with retry) */
for (j = 0; j < 10; j++) {
rc = osmo_get_rand_id(rand_buf, len);
if (!rc)
break;
}
if (rc) {
LOGP(DMAIN, LOGL_ERROR, "IMSI='%s': Failed to generate new MSISDN, random number generator"
" failed (rc=%d)\n", imsi, rc);
return rc;
}
/* Shift 0x00 ... 0xff range to 30 ... 39 (ASCII numbers) */
for (j = 0; j < len; j++)
msisdn[j] = 48 + (rand_buf[j] % 10);
msisdn[j] = '\0';
/* Ensure there is no subscriber with such MSISDN */
if (db_subscr_exists_by_msisdn(g_hlr->dbc, msisdn) == -ENOENT)
return 0;
}
/* Failure */
LOGP(DMAIN, LOGL_ERROR, "IMSI='%s': Failed to generate a new MSISDN, consider increasing "
"the length for the automatically assigned MSISDNs "
"(see 'subscriber-create-on-demand' command)\n", imsi);
return -1;
}
static int subscr_create_on_demand(const char *imsi)
{
char msisdn[GSM23003_MSISDN_MAX_DIGITS + 1];
int rc;
unsigned int rand_msisdn_len = g_hlr->subscr_create_on_demand_rand_msisdn_len;
if (!g_hlr->subscr_create_on_demand)
return -1;
if (db_subscr_exists_by_imsi(g_hlr->dbc, imsi) == 0)
return -1;
if (rand_msisdn_len && generate_new_msisdn(msisdn, imsi, rand_msisdn_len) != 0)
return -1;
LOGP(DMAIN, LOGL_INFO, "IMSI='%s': Creating subscriber on demand\n", imsi);
rc = db_subscr_create(g_hlr->dbc, imsi, g_hlr->subscr_create_on_demand_flags);
if (rc) {
LOGP(DMAIN, LOGL_ERROR, "Failed to create subscriber on demand (rc=%d): IMSI='%s'\n", rc, imsi);
return rc;
}
if (!rand_msisdn_len)
return 0;
/* Update MSISDN of the new (just allocated) subscriber */
rc = db_subscr_update_msisdn_by_imsi(g_hlr->dbc, imsi, msisdn);
if (rc) {
LOGP(DMAIN, LOGL_ERROR, "IMSI='%s': Failed to assign MSISDN='%s' (rc=%d)\n", imsi, msisdn, rc);
return rc;
}
LOGP(DMAIN, LOGL_INFO, "IMSI='%s': Successfully assigned MSISDN='%s'\n", imsi, msisdn);
return 0;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
/*! Update nam_cs/nam_ps in the db and trigger notifications to GSUP clients.
* \param[in,out] hlr Global hlr context.
* \param[in] subscr Subscriber from a fresh db_subscr_get_by_*() call.
* \param[in] nam_val True to enable CS/PS, false to disable.
* \param[in] is_ps True to enable/disable PS, false for CS.
* \returns 0 on success, ENOEXEC if there is no need to change, a negative
* value on error.
*/
int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val, bool is_ps)
{
int rc;
bool is_val = is_ps? subscr->nam_ps : subscr->nam_cs;
struct osmo_ipa_name vlr_name;
struct osmo_gsup_message gsup_del_data = {
.message_type = OSMO_GSUP_MSGT_DELETE_DATA_REQUEST,
};
OSMO_STRLCPY_ARRAY(gsup_del_data.imsi, subscr->imsi);
if (is_val == nam_val) {
LOGP(DAUC, LOGL_DEBUG, "IMSI-%s: Already has the requested value when asked to %s %s\n",
subscr->imsi, nam_val ? "enable" : "disable", is_ps ? "PS" : "CS");
return ENOEXEC;
}
rc = db_subscr_nam(hlr->dbc, subscr->imsi, nam_val, is_ps);
if (rc)
return rc > 0? -rc : rc;
/* If we're disabling, send a notice out to the GSUP client that is
* responsible. Otherwise no need. */
if (nam_val)
return 0;
if (subscr->vlr_number[0] && !osmo_ipa_name_set_str(&vlr_name, subscr->vlr_number))
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_enc_send_to_ipa_name(g_hlr->gs, &vlr_name, &gsup_del_data);
if (subscr->sgsn_number[0] && !osmo_ipa_name_set_str(&vlr_name, subscr->sgsn_number))
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_enc_send_to_ipa_name(g_hlr->gs, &vlr_name, &gsup_del_data);
return 0;
}
/***********************************************************************
* Send Auth Info handling
***********************************************************************/
/* process an incoming SAI request */
db v6: determine 3G AUC IND from VLR name Each VLR requesting auth tuples should use a distinct IND pool for 3G auth. So far we tied the IND to the GSUP peer connection; MSC and SGSN were always distinct GSUP peers, they ended up using distinct INDs. However, we have implemented a GSUP proxy, so that, in a distributed setup, a remotely roaming subscriber has only one direct GSUP peer proxying for both remote MSC and SGSN. That means as soon as a subscriber roams to a different site, we would use the GSUP proxy name to determine the IND instead of the separate MSC and SGSN. The site's MSC and SGSN appear as the same client, get the same IND bucket, waste SQNs rapidly and cause auth tuple generation load. So instead of using the local client as IND, persistently keep a list of VLR names and assign a different IND to each. Use the gsup_req->source_name as indicator, which reflects the actual remote VLR's name (remote MSC or SGSN). Persist the site <-> IND assignments in the database. Add an IND test to db_test.c There was an earlier patch version that separated the IND pools by cn_domain, but it turned out to add complex semantics, while only solving one aspect of the "adjacent VLR" problem. We need a solution not only for CS vs PS, but also for 2,3G vs 4G, and for sites that are physically adjacent to each other. This patch version does not offer any automatic solution for that -- as soon as more than 2^IND_bitlen (usually 32) VLRs show up, it is the responsibility of the admin to ensure the 'ind' table in the hlr.db does not have unfortunate IND assignments. So far no VTY commands exist for that, they may be added in the future. Related: OS#4319 Change-Id: I6f0a6bbef3a27507605c3b4a0e1a89bdfd468374
2019-12-12 03:04:53 +00:00
static int rx_send_auth_info(struct osmo_gsup_req *req)
{
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
struct osmo_gsup_message gsup_out = {
.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT,
};
bool separation_bit = false;
int num_auth_vectors = OSMO_GSUP_MAX_NUM_AUTH_INFO;
db v6: determine 3G AUC IND from VLR name Each VLR requesting auth tuples should use a distinct IND pool for 3G auth. So far we tied the IND to the GSUP peer connection; MSC and SGSN were always distinct GSUP peers, they ended up using distinct INDs. However, we have implemented a GSUP proxy, so that, in a distributed setup, a remotely roaming subscriber has only one direct GSUP peer proxying for both remote MSC and SGSN. That means as soon as a subscriber roams to a different site, we would use the GSUP proxy name to determine the IND instead of the separate MSC and SGSN. The site's MSC and SGSN appear as the same client, get the same IND bucket, waste SQNs rapidly and cause auth tuple generation load. So instead of using the local client as IND, persistently keep a list of VLR names and assign a different IND to each. Use the gsup_req->source_name as indicator, which reflects the actual remote VLR's name (remote MSC or SGSN). Persist the site <-> IND assignments in the database. Add an IND test to db_test.c There was an earlier patch version that separated the IND pools by cn_domain, but it turned out to add complex semantics, while only solving one aspect of the "adjacent VLR" problem. We need a solution not only for CS vs PS, but also for 2,3G vs 4G, and for sites that are physically adjacent to each other. This patch version does not offer any automatic solution for that -- as soon as more than 2^IND_bitlen (usually 32) VLRs show up, it is the responsibility of the admin to ensure the 'ind' table in the hlr.db does not have unfortunate IND assignments. So far no VTY commands exist for that, they may be added in the future. Related: OS#4319 Change-Id: I6f0a6bbef3a27507605c3b4a0e1a89bdfd468374
2019-12-12 03:04:53 +00:00
unsigned int auc_3g_ind;
int rc;
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
subscr_create_on_demand(req->gsup.imsi);
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
if (req->gsup.current_rat_type == OSMO_RAT_EUTRAN_SGS)
separation_bit = true;
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
if (req->gsup.num_auth_vectors > 0 &&
req->gsup.num_auth_vectors <= OSMO_GSUP_MAX_NUM_AUTH_INFO)
num_auth_vectors = req->gsup.num_auth_vectors;
db v6: determine 3G AUC IND from VLR name Each VLR requesting auth tuples should use a distinct IND pool for 3G auth. So far we tied the IND to the GSUP peer connection; MSC and SGSN were always distinct GSUP peers, they ended up using distinct INDs. However, we have implemented a GSUP proxy, so that, in a distributed setup, a remotely roaming subscriber has only one direct GSUP peer proxying for both remote MSC and SGSN. That means as soon as a subscriber roams to a different site, we would use the GSUP proxy name to determine the IND instead of the separate MSC and SGSN. The site's MSC and SGSN appear as the same client, get the same IND bucket, waste SQNs rapidly and cause auth tuple generation load. So instead of using the local client as IND, persistently keep a list of VLR names and assign a different IND to each. Use the gsup_req->source_name as indicator, which reflects the actual remote VLR's name (remote MSC or SGSN). Persist the site <-> IND assignments in the database. Add an IND test to db_test.c There was an earlier patch version that separated the IND pools by cn_domain, but it turned out to add complex semantics, while only solving one aspect of the "adjacent VLR" problem. We need a solution not only for CS vs PS, but also for 2,3G vs 4G, and for sites that are physically adjacent to each other. This patch version does not offer any automatic solution for that -- as soon as more than 2^IND_bitlen (usually 32) VLRs show up, it is the responsibility of the admin to ensure the 'ind' table in the hlr.db does not have unfortunate IND assignments. So far no VTY commands exist for that, they may be added in the future. Related: OS#4319 Change-Id: I6f0a6bbef3a27507605c3b4a0e1a89bdfd468374
2019-12-12 03:04:53 +00:00
rc = db_ind(g_hlr->dbc, &req->source_name, &auc_3g_ind);
if (rc) {
LOG_GSUP_REQ(req, LOGL_ERROR,
"Unable to determine 3G auth IND for source %s (rc=%d),"
" generating tuples with IND = 0\n",
osmo_cni_peer_id_to_str(&req->source_name), rc);
auc_3g_ind = 0;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
rc = db_get_auc(g_hlr->dbc, req->gsup.imsi, auc_3g_ind,
gsup_out.auth_vectors,
num_auth_vectors,
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
req->gsup.rand, req->gsup.auts, separation_bit);
if (rc <= 0) {
switch (rc) {
case 0:
/* 0 means "0 tuples generated", which shouldn't happen.
* Treat the same as "no auth data". */
case -ENOKEY:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN,
"IMSI known, but has no auth data;"
" Returning slightly inaccurate cause 'IMSI Unknown' via GSUP");
return rc;
case -ENOENT:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "IMSI unknown");
return rc;
default:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_err(req, GMM_CAUSE_NET_FAIL, "failure to look up IMSI in db");
return rc;
}
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
gsup_out.num_auth_vectors = rc;
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond(req, &gsup_out, false, true);
return 0;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
/*! Receive Update Location Request, creates new lu_operation */
static int rx_upd_loc_req(struct osmo_gsup_conn *conn, struct osmo_gsup_req *req)
{
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
switch (req->gsup.cn_domain) {
case OSMO_GSUP_CN_DOMAIN_CS:
conn->supports_cs = true;
break;
default:
/* The client didn't send a CN_DOMAIN IE; assume packet-switched in
* accordance with the GSUP spec in osmo-hlr's user manual (section
* 11.6.15 "CN Domain" says "if no CN Domain IE is present within
* a request, the PS Domain is assumed." */
case OSMO_GSUP_CN_DOMAIN_PS:
conn->supports_ps = true;
break;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
subscr_create_on_demand(req->gsup.imsi);
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
lu_rx_gsup(req);
return 0;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
static int rx_purge_ms_req(struct osmo_gsup_req *req)
{
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
bool is_ps = (req->gsup.cn_domain != OSMO_GSUP_CN_DOMAIN_CS);
int rc;
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
LOG_GSUP_REQ_CAT(req, DAUC, LOGL_INFO, "Purge MS (%s)\n", is_ps ? "PS" : "CS");
/* FIXME: check if the VLR that sends the purge is the same that
* we have on record. Only update if yes */
/* Perform the actual update of the DB */
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
rc = db_subscr_purge(g_hlr->dbc, req->gsup.imsi, true, is_ps);
if (rc == 0)
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_msgt(req, OSMO_GSUP_MSGT_PURGE_MS_RESULT, true);
else if (rc == -ENOENT)
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "IMSI unknown");
else
osmo_gsup_req_respond_err(req, GMM_CAUSE_NET_FAIL, "db error");
return rc;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
static int rx_check_imei_req(struct osmo_gsup_req *req)
{
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
struct osmo_gsup_message gsup_reply;
char imei[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1] = {0};
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
const struct osmo_gsup_message *gsup = &req->gsup;
int rc;
/* Require IMEI */
if (!gsup->imei_enc) {
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO, "missing IMEI");
return -1;
}
/* Decode IMEI (fails if IMEI is too long) */
rc = gsm48_decode_bcd_number2(imei, sizeof(imei), gsup->imei_enc, gsup->imei_enc_len, 0);
if (rc < 0) {
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO,
"failed to decode IMEI %s (rc: %d)",
osmo_hexdump_c(OTC_SELECT, gsup->imei_enc, gsup->imei_enc_len),
rc);
return -1;
}
/* Check if IMEI is too short */
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
if (!osmo_imei_str_valid(imei, false)) {
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO,
"invalid IMEI: %s", osmo_quote_str_c(OTC_SELECT, imei, -1));
return -1;
}
subscr_create_on_demand(gsup->imsi);
/* Save in DB if desired */
if (g_hlr->store_imei) {
LOGP(DAUC, LOGL_DEBUG, "IMSI='%s': storing IMEI = %s\n", gsup->imsi, imei);
if (db_subscr_update_imei_by_imsi(g_hlr->dbc, gsup->imsi, imei) < 0) {
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO, "Failed to store IMEI in HLR db");
return -1;
}
} else {
/* Check if subscriber exists and print IMEI */
LOGP(DMAIN, LOGL_INFO, "IMSI='%s': has IMEI = %s (consider setting 'store-imei')\n", gsup->imsi, imei);
struct hlr_subscriber subscr;
if (db_subscr_get_by_imsi(g_hlr->dbc, gsup->imsi, &subscr) < 0) {
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO, "IMSI unknown");
return -1;
}
}
/* Accept all IMEIs */
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
gsup_reply = (struct osmo_gsup_message){
.message_type = OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,
.imei_result = OSMO_GSUP_IMEI_RESULT_ACK,
};
return osmo_gsup_req_respond(req, &gsup_reply, false, true);
}
static char namebuf[255];
#define LOGP_GSUP_FWD(gsup, level, fmt, args ...) \
LOGP(DMAIN, level, "Forward %s (class=%s, IMSI=%s, %s->%s): " fmt, \
osmo_gsup_message_type_name((gsup)->message_type), \
osmo_gsup_message_class_name((gsup)->message_class), \
(gsup)->imsi, \
osmo_quote_str((const char *)(gsup)->source_name, (gsup)->source_name_len), \
osmo_quote_str_buf2(namebuf, sizeof(namebuf), (const char *)(gsup)->destination_name, (gsup)->destination_name_len), \
## args)
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
static int read_cb_forward(struct osmo_gsup_req *req)
{
int ret = -EINVAL;
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
const struct osmo_gsup_message *gsup = &req->gsup;
struct osmo_gsup_message gsup_err;
struct msgb *forward_msg;
struct osmo_ipa_name destination_name;
/* Check for routing IEs */
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
if (!req->gsup.source_name || !req->gsup.source_name_len
|| !req->gsup.destination_name || !req->gsup.destination_name_len) {
LOGP_GSUP_FWD(&req->gsup, LOGL_ERROR, "missing routing IEs\n");
goto routing_error;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
if (osmo_ipa_name_set(&destination_name, req->gsup.destination_name, req->gsup.destination_name_len)) {
LOGP_GSUP_FWD(&req->gsup, LOGL_ERROR, "invalid destination name\n");
goto routing_error;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
LOG_GSUP_REQ(req, LOGL_INFO, "Forwarding to %s\n", osmo_ipa_name_to_str(&destination_name));
/* Forward message without re-encoding (so we don't remove unknown IEs).
* Copy GSUP part to forward, removing incoming IPA header to be able to prepend an outgoing IPA header */
forward_msg = osmo_gsup_msgb_alloc("GSUP forward");
forward_msg->l2h = msgb_put(forward_msg, msgb_l2len(req->msg));
memcpy(forward_msg->l2h, msgb_l2(req->msg), msgb_l2len(req->msg));
ret = osmo_gsup_send_to_ipa_name(g_hlr->gs, &destination_name, forward_msg);
if (ret) {
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
LOGP_GSUP_FWD(gsup, LOGL_ERROR, "%s (rc=%d)\n",
ret == -ENODEV ? "destination not connected" : "unknown error",
ret);
goto routing_error;
}
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_req_free(req);
return 0;
routing_error:
gsup_err = (struct osmo_gsup_message){
.message_type = OSMO_GSUP_MSGT_ROUTING_ERROR,
.source_name = gsup->destination_name,
.source_name_len = gsup->destination_name_len,
};
osmo_gsup_req_respond(req, &gsup_err, true, true);
return -1;
}
static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
{
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
struct osmo_gsup_req *req = osmo_gsup_conn_rx(conn, msg);
if (!req)
return -EINVAL;
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
/* If the GSUP recipient is other than this HLR, forward. */
if (req->gsup.destination_name_len) {
struct osmo_ipa_name destination_name;
struct osmo_ipa_name my_name;
osmo_ipa_name_set_str(&my_name, g_hlr->gsup_unit_name.serno);
if (!osmo_ipa_name_set(&destination_name, req->gsup.destination_name, req->gsup.destination_name_len)
&& osmo_ipa_name_cmp(&destination_name, &my_name)) {
return read_cb_forward(req);
}
}
/* Distributed GSM: check whether to proxy for / lookup a remote HLR.
* It would require less database hits to do this only if a local-only operation fails with "unknown IMSI", but
* it becomes semantically easier if we do this once-off ahead of time. */
if (osmo_mslookup_client_active(g_hlr->mslookup.client.client)
|| osmo_sockaddr_str_is_nonzero(&g_hlr->mslookup.client.gsup_gateway_proxy)) {
if (dgsm_check_forward_gsup_msg(req))
return 0;
}
/* HLR related messages that are handled at this HLR instance */
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
switch (req->gsup.message_type) {
/* requests sent to us */
case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
db v6: determine 3G AUC IND from VLR name Each VLR requesting auth tuples should use a distinct IND pool for 3G auth. So far we tied the IND to the GSUP peer connection; MSC and SGSN were always distinct GSUP peers, they ended up using distinct INDs. However, we have implemented a GSUP proxy, so that, in a distributed setup, a remotely roaming subscriber has only one direct GSUP peer proxying for both remote MSC and SGSN. That means as soon as a subscriber roams to a different site, we would use the GSUP proxy name to determine the IND instead of the separate MSC and SGSN. The site's MSC and SGSN appear as the same client, get the same IND bucket, waste SQNs rapidly and cause auth tuple generation load. So instead of using the local client as IND, persistently keep a list of VLR names and assign a different IND to each. Use the gsup_req->source_name as indicator, which reflects the actual remote VLR's name (remote MSC or SGSN). Persist the site <-> IND assignments in the database. Add an IND test to db_test.c There was an earlier patch version that separated the IND pools by cn_domain, but it turned out to add complex semantics, while only solving one aspect of the "adjacent VLR" problem. We need a solution not only for CS vs PS, but also for 2,3G vs 4G, and for sites that are physically adjacent to each other. This patch version does not offer any automatic solution for that -- as soon as more than 2^IND_bitlen (usually 32) VLRs show up, it is the responsibility of the admin to ensure the 'ind' table in the hlr.db does not have unfortunate IND assignments. So far no VTY commands exist for that, they may be added in the future. Related: OS#4319 Change-Id: I6f0a6bbef3a27507605c3b4a0e1a89bdfd468374
2019-12-12 03:04:53 +00:00
rx_send_auth_info(req);
break;
case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
rx_upd_loc_req(conn, req);
break;
case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
rx_purge_ms_req(req);
break;
/* responses to requests sent by us */
case OSMO_GSUP_MSGT_DELETE_DATA_ERROR:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
LOG_GSUP_REQ(req, LOGL_ERROR, "Peer responds with: Error while deleting subscriber data\n");
osmo_gsup_req_free(req);
break;
case OSMO_GSUP_MSGT_DELETE_DATA_RESULT:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
LOG_GSUP_REQ(req, LOGL_DEBUG, "Peer responds with: Subscriber data deleted\n");
osmo_gsup_req_free(req);
break;
case OSMO_GSUP_MSGT_PROC_SS_REQUEST:
case OSMO_GSUP_MSGT_PROC_SS_RESULT:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
rx_proc_ss_req(req);
break;
case OSMO_GSUP_MSGT_PROC_SS_ERROR:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
rx_proc_ss_error(req);
break;
case OSMO_GSUP_MSGT_INSERT_DATA_ERROR:
case OSMO_GSUP_MSGT_INSERT_DATA_RESULT:
case OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR:
case OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
lu_rx_gsup(req);
break;
case OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST:
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
rx_check_imei_req(req);
break;
default:
LOGP(DMAIN, LOGL_DEBUG, "Unhandled GSUP message type %s\n",
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_gsup_message_type_name(req->gsup.message_type));
osmo_gsup_req_free(req);
break;
}
return 0;
}
static void print_usage()
{
printf("Usage: osmo-hlr\n");
}
static void print_help()
{
printf(" -h --help This text.\n");
printf(" -c --config-file filename The config file to use.\n");
printf(" -l --database db-name The database to use.\n");
printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM Enable debugging.\n");
printf(" -D --daemonize Fork the process into a background daemon.\n");
printf(" -s --disable-color Do not print ANSI colors in the log\n");
printf(" -T --timestamp Prefix every log line with a timestamp.\n");
printf(" -e --log-level number Set a global loglevel.\n");
printf(" -U --db-upgrade Allow HLR database schema upgrades.\n");
printf(" -C --db-check Quit after opening (and upgrading) the database.\n");
printf(" -V --version Print the version of OsmoHLR.\n");
printf("\nVTY reference generation:\n");
printf(" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n");
printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
}
static struct {
const char *config_file;
const char *db_file;
bool daemonize;
bool db_upgrade;
bool db_check;
} cmdline_opts = {
.config_file = "osmo-hlr.cfg",
.db_file = NULL,
.daemonize = false,
.db_upgrade = false,
};
static void handle_long_options(const char *prog_name, const int long_option)
{
static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
switch (long_option) {
case 1:
vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
if (vty_ref_mode < 0) {
fprintf(stderr, "%s: Unknown VTY reference generation "
"mode '%s'\n", prog_name, optarg);
exit(2);
}
break;
case 2:
fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
exit(0);
default:
fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
exit(2);
}
}
static void handle_options(int argc, char **argv)
{
while (1) {
int option_index = 0, c;
static int long_option = 0;
static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"config-file", 1, 0, 'c'},
{"database", 1, 0, 'l'},
{"debug", 1, 0, 'd'},
{"daemonize", 0, 0, 'D'},
{"disable-color", 0, 0, 's'},
{"log-level", 1, 0, 'e'},
{"timestamp", 0, 0, 'T'},
{"db-upgrade", 0, 0, 'U' },
{"db-check", 0, 0, 'C' },
{"version", 0, 0, 'V' },
{"vty-ref-mode", 1, &long_option, 1},
{"vty-ref-xml", 0, &long_option, 2},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hc:l:d:Dse:TUV",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
handle_long_options(argv[0], long_option);
break;
case 'h':
print_usage();
print_help();
exit(0);
case 'c':
cmdline_opts.config_file = optarg;
break;
case 'l':
cmdline_opts.db_file = optarg;
break;
case 'd':
log_parse_category_mask(osmo_stderr_target, optarg);
break;
case 'D':
cmdline_opts.daemonize = 1;
break;
case 's':
log_set_use_color(osmo_stderr_target, 0);
break;
case 'e':
log_set_log_level(osmo_stderr_target, atoi(optarg));
break;
case 'T':
log_set_print_timestamp(osmo_stderr_target, 1);
break;
case 'U':
cmdline_opts.db_upgrade = true;
break;
case 'C':
cmdline_opts.db_check = true;
break;
case 'V':
print_version(1);
exit(0);
break;
default:
/* catch unknown options *as well as* missing arguments. */
fprintf(stderr, "Error in command line options. Exiting.\n");
exit(-1);
break;
}
}
if (argc > optind) {
fprintf(stderr, "Unsupported positional arguments on command line\n");
exit(2);
}
}
static void signal_hdlr(int signal)
{
switch (signal) {
case SIGTERM:
case SIGINT:
LOGP(DMAIN, LOGL_NOTICE, "Terminating due to signal=%d\n", signal);
quit++;
break;
case SIGUSR1:
LOGP(DMAIN, LOGL_DEBUG, "Talloc Report due to SIGUSR1\n");
talloc_report_full(hlr_ctx, stderr);
break;
}
}
static const char vlr_copyright[] =
"Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
"This is free software: you are free to change and redistribute it.\r\n"
"There is NO WARRANTY, to the extent permitted by law.\r\n";
static struct vty_app_info vty_info = {
.name = "OsmoHLR",
.version = PACKAGE_VERSION,
.copyright = vlr_copyright,
.is_config_node = hlr_vty_is_config_node,
.go_parent_cb = hlr_vty_go_parent,
};
int main(int argc, char **argv)
{
int rc;
/* Track the use of talloc NULL memory contexts */
talloc_enable_null_tracking();
hlr_ctx = talloc_named_const(NULL, 1, "OsmoHLR");
msgb_talloc_ctx_init(hlr_ctx, 0);
vty_info.tall_ctx = hlr_ctx;
g_hlr = talloc_zero(hlr_ctx, struct hlr);
INIT_LLIST_HEAD(&g_hlr->euse_list);
INIT_LLIST_HEAD(&g_hlr->ss_sessions);
INIT_LLIST_HEAD(&g_hlr->ussd_routes);
INIT_LLIST_HEAD(&g_hlr->mslookup.server.local_site_services);
g_hlr->db_file_path = talloc_strdup(g_hlr, HLR_DEFAULT_DB_FILE_PATH);
g_hlr->mslookup.server.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT);
g_hlr->mslookup.client.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT);
/* Init default (call independent) SS session guard timeout value */
g_hlr->ncss_guard_timeout = NCSS_GUARD_TIMEOUT_DEFAULT;
rc = osmo_init_logging2(hlr_ctx, &hlr_log_info);
if (rc < 0) {
fprintf(stderr, "Error initializing logging\n");
exit(1);
}
/* Set up llists and objects, startup is happening from VTY commands. */
dgsm_init(hlr_ctx);
osmo_stats_init(hlr_ctx);
vty_init(&vty_info);
ctrl_vty_init(hlr_ctx);
hlr_vty_init();
dgsm_vty_init();
osmo_cpu_sched_vty_init(hlr_ctx);
handle_options(argc, argv);
rc = vty_read_config_file(cmdline_opts.config_file, NULL);
if (rc < 0) {
LOGP(DMAIN, LOGL_FATAL,
"Failed to parse the config file: '%s'\n",
cmdline_opts.config_file);
return rc;
}
LOGP(DMAIN, LOGL_NOTICE, "hlr starting\n");
rc = rand_init();
if (rc < 0) {
LOGP(DMAIN, LOGL_FATAL, "Error initializing random source\n");
exit(1);
}
if (cmdline_opts.db_file)
osmo_talloc_replace_string(g_hlr, &g_hlr->db_file_path, cmdline_opts.db_file);
g_hlr->dbc = db_open(hlr_ctx, g_hlr->db_file_path, true, cmdline_opts.db_upgrade);
if (!g_hlr->dbc) {
LOGP(DMAIN, LOGL_FATAL, "Error opening database %s\n", osmo_quote_str(g_hlr->db_file_path, -1));
exit(1);
}
if (cmdline_opts.db_check) {
LOGP(DMAIN, LOGL_NOTICE, "Cmdline option --db-check: Database was opened successfully, quitting.\n");
db_close(g_hlr->dbc);
log_fini();
talloc_free(hlr_ctx);
talloc_free(tall_vty_ctx);
talloc_disable_null_tracking();
exit(0);
}
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(hlr_ctx, NULL, vty_get_bind_addr(),
OSMO_VTY_PORT_HLR);
if (rc < 0)
return rc;
g_hlr->gs = osmo_gsup_server_create(hlr_ctx, g_hlr->gsup_bind_addr, OSMO_GSUP_PORT,
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
read_cb, g_hlr);
if (!g_hlr->gs) {
LOGP(DMAIN, LOGL_FATAL, "Error starting GSUP server\n");
exit(1);
}
proxy_init(g_hlr->gs);
g_hlr->ctrl_bind_addr = ctrl_vty_get_bind_addr();
g_hlr->ctrl = hlr_controlif_setup(g_hlr);
dgsm_start(hlr_ctx);
osmo_init_ignore_signals();
signal(SIGINT, &signal_hdlr);
signal(SIGTERM, &signal_hdlr);
signal(SIGUSR1, &signal_hdlr);
if (cmdline_opts.daemonize) {
rc = osmo_daemonize();
if (rc < 0) {
perror("Error during daemonize");
exit(1);
}
}
while (!quit)
1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name These are seemingly orthogonal changes in one patch, because they are in fact sufficiently intertwined that we are not willing to spend the time to separate them. They are also refactoring changes, unlikely to make sense on their own. ** lu_fsm: Attempting to make luop.c keep state about incoming GSUP requests made me find shortcomings in several places: - since it predates osmo_fsm, it is a state machine that does not strictly enforce the order of state transitions or the right sequence of incoming events. - several places OSMO_ASSERT() on data received from the network. - modifies the subscriber state before a LU is accepted. - dead code about canceling a subscriber in a previous VLR. That would be a good thing to actually do, which should also be trivial now that we record vlr_name and sgsn_name, but I decided to remove the dead code for now. To both step up the LU game *and* make it easier for me to integrate osmo_gsup_req handling, I decided to create a lu_fsm, drawing from my, by now, ample experience of writing osmo_fsms. ** osmo_gsup_req: Prepare for D-GSM, where osmo-hlr will do proxy routing for remote HLRs / communicate with remote MSCs via a proxy: a) It is important that a response that osmo-hlr generates and that is sent back to a requesting MSC contains all IEs that are needed to route it back to the requester. Particularly source_name must become destination_name in the response to be able to even reach the requesting MSC. Other fields are also necessary to match, which were so far taken care of in individual numerous code paths. b) For some operations, the response to a GSUP request is generated asynchronously (like Update Location Request -> Response, or taking the response from an EUSE, or the upcoming proxying to a remote HLR). To be able to feed a request message's information back into the response, we must thus keep the request data around. Since struct osmo_gsup_message references a lot of external data, usually with pointers directly into the received msgb, it is not so trivial to pass GSUP message data around asynchronously, on its own. osmo_gsup_req is the combined solution for both a and b: it keeps all data for a GSUP message by taking ownership of the incoming msgb, and it provides an explicit API "forcing" callers to respond with osmo_gsup_req_respond(), so that all code paths trivially are definitely responding with the correct IEs set to match the request's routing (by using osmo_gsup_make_response() recently added to libosmocore). Adjust all osmo-hlr code paths to use *only* osmo_gsup_req to respond to incoming requests received on the GSUP server (above LU code being one of them). In fact, the same should be done on the client side. Hence osmo_gsup_req is implemented in a server/client agnostic way, and is placed in libosmo-gsupclient. As soon as we see routing errors in complex GSUP setups, using osmo_gsup_req in the related GSUP client is likely to resolve those problems without much thinking required beyond making all code paths use it. libosmo-gsupclient is hence added to osmo-hlr binary's own library dependencies. It would have been added by the D-GSM proxy routing anyway, we are just doing it a little sooner. ** cni_peer_id.c / osmo_ipa_name: We so far handle an IPA unit name as pointer + size, or as just pointer with implicit talloc size. To ease working with GSUP peer identification data, I require: - a non-allocated storage of an IPA Name. It brings the drawback of being size limited, but our current implementation is anyway only able to handle MSC and SGSN names of 31 characters (see struct hlr_subscriber). - a single-argument handle for IPA Name, - easy to use utility functions like osmo_ipa_name_to_str(), osmo_ipa_name_cmp(), and copying by simple assignment, a = b. Hence this patch adds a osmo_ipa_name in cni_peer_id.h and cni_peer_id.c. Heavily used in LU and osmo_gsup_req. Depends: libosmocore Id9692880079ea0f219f52d81b1923a76fc640566 Change-Id: I3a8dff3d4a1cbe10d6ab08257a0138d6b2a082d9
2019-11-20 01:36:45 +00:00
osmo_select_main_ctx(0);
dgsm_stop();
osmo_gsup_server_destroy(g_hlr->gs);
db_close(g_hlr->dbc);
log_fini();
/**
* Report the heap state of root context, then free,
* so both ASAN and Valgrind are happy...
*/
talloc_report_full(hlr_ctx, stderr);
talloc_free(hlr_ctx);
/* FIXME: VTY code still uses NULL-context */
talloc_free(tall_vty_ctx);
/**
* Report the heap state of NULL context, then free,
* so both ASAN and Valgrind are happy...
*/
talloc_report_full(NULL, stderr);
talloc_disable_null_tracking();
return 0;
}