aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Sperling <ssperling@sysmocom.de>2018-04-10 19:26:14 +0200
committerStefan Sperling <ssperling@sysmocom.de>2018-05-02 13:34:38 +0200
commit93c5b10310a41f7d7b190d4fc98c859f5fb8584b (patch)
tree0f0b586f7eb46052d4080ffe8515e9d060d13eb9
parentec9440f1bc371fc9b95166e051be642ca3ac1274 (diff)
rewrite subscriber_update_notify() without calls into luop
This function relied on implementation details of the luop code. Port what is necessary for an independent Insert Subscriber Data Tx operation from the luop code into this function. A next possible step would be to try to merge both of these into a common implementation. This will be addressed in a follow-up change as soon as this change is merged. The TTCN3 test TC_vty_msisdn_isd is still passing (it currently triggers the "circuit switched domain" case because it does not advertise itself as an SGSN in the IPA unit name). Change-Id: I06c43ece2b48dc63d599000eb6d6d51e08963067 Related: OS#2785
-rw-r--r--src/gsup_server.c18
-rw-r--r--src/gsup_server.h6
-rw-r--r--src/hlr.c79
-rw-r--r--src/luop.c12
4 files changed, 94 insertions, 21 deletions
diff --git a/src/gsup_server.c b/src/gsup_server.c
index b382c86..24ba738 100644
--- a/src/gsup_server.c
+++ b/src/gsup_server.c
@@ -24,6 +24,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/abis/ipa.h>
#include <osmocom/abis/ipaccess.h>
+#include <osmocom/gsm/apn.h>
#include "gsup_server.h"
#include "gsup_router.h"
@@ -333,3 +334,20 @@ void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups)
}
talloc_free(gsups);
}
+
+void osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup)
+{
+ int l;
+ uint8_t apn[APN_MAXLEN];
+
+ l = osmo_apn_from_str(apn, sizeof(apn), "*");
+ if (l <= 0)
+ return;
+
+ gsup->pdp_infos[0].apn_enc = apn;
+ gsup->pdp_infos[0].apn_enc_len = l;
+ gsup->pdp_infos[0].have_info = 1;
+ gsup->num_pdp_infos = 1;
+ /* FIXME: use real value: */
+ gsup->pdp_infos[0].context_id = 1;
+}
diff --git a/src/gsup_server.h b/src/gsup_server.h
index 74062d4..3d36bff 100644
--- a/src/gsup_server.h
+++ b/src/gsup_server.h
@@ -4,6 +4,7 @@
#include <osmocom/core/msgb.h>
#include <osmocom/abis/ipa.h>
#include <osmocom/abis/ipaccess.h>
+#include <osmocom/gsm/gsup.h>
struct osmo_gsup_conn;
@@ -33,6 +34,10 @@ struct osmo_gsup_conn {
struct tlv_parsed ccm;
unsigned int auc_3g_ind; /*!< IND index used for UMTS AKA SQN */
+
+ /* Set when Location Update is received: */
+ bool supports_cs; /* client supports OSMO_GSUP_CN_DOMAIN_CS */
+ bool supports_ps; /* client supports OSMO_GSUP_CN_DOMAIN_PS */
};
@@ -48,3 +53,4 @@ struct osmo_gsup_server *osmo_gsup_server_create(void *ctx,
void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups);
+void osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup);
diff --git a/src/hlr.c b/src/hlr.c
index 3845993..479b5cf 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -26,7 +26,6 @@
#include <osmocom/core/logging.h>
#include <osmocom/core/application.h>
#include <osmocom/gsm/gsup.h>
-#include <osmocom/gsm/apn.h>
#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
@@ -62,19 +61,69 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
return;
llist_for_each_entry(co, &g_hlr->gs->clients, list) {
- struct lu_operation *luop = lu_op_alloc_conn(co);
- if (!luop) {
+ struct osmo_gsup_message gsup = {
+ .message_type = OSMO_GSUP_MSGT_INSERT_DATA_REQUEST
+ };
+ uint8_t *peer;
+ int peer_len;
+ uint8_t msisdn_enc[43]; /* TODO use constant; TS 24.008 10.5.4.7 */
+ int len;
+ struct msgb *msg_out;
+
+ peer_len = osmo_gsup_conn_ccm_get(co, &peer, IPAC_IDTAG_SERNR);
+ if (peer_len < 0) {
LOGP(DMAIN, LOGL_ERROR,
- "IMSI='%s': Cannot notify GSUP client, cannot allocate lu_operation,"
- " for %s:%u\n", subscr->imsi,
+ "IMSI='%s': Cannot notify GSUP client, cannot get peer name "
+ "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_strlcpy(gsup.imsi, subscr->imsi, GSM23003_IMSI_MAX_DIGITS + 1);
+
+ len = gsm48_encode_bcd_number(msisdn_enc, sizeof(msisdn_enc), 0, subscr->msisdn);
+ if (len < 1) {
+ LOGP(DMAIN, LOGL_ERROR, "%s: Error: cannot encode MSISDN '%s'\n",
+ subscr->imsi, subscr->msisdn);
+ continue;
+ }
+ gsup.msisdn_enc = msisdn_enc;
+ gsup.msisdn_enc_len = len;
+
+ if (co->supports_ps) {
+ gsup.cn_domain = OSMO_GSUP_CN_DOMAIN_PS;
+
+ /* FIXME: PDP infos - use more fine-grained access control
+ instead of wildcard APN */
+ osmo_gsup_configure_wildcard_apn(&gsup);
+ } else if (co->supports_cs) {
+ gsup.cn_domain = OSMO_GSUP_CN_DOMAIN_CS;
+ } else {
+ /* We have not yet received a location update from this subscriber .*/
+ continue;
+ }
+
+ /* Send ISD to MSC/SGSN */
+ msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP ISD UPDATE");
+ if (msg_out == NULL) {
+ LOGP(DMAIN, 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;
}
- luop->subscr = *subscr;
- luop->state = LU_S_LU_RECEIVED; /* Pretend we received a location update. */
- lu_op_tx_insert_subscr_data(luop);
- lu_op_free(luop);
}
}
@@ -202,8 +251,18 @@ static int rx_upd_loc_req(struct osmo_gsup_conn *conn,
lu_op_statechg(luop, LU_S_LU_RECEIVED);
- if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS)
+ if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_CS)
+ conn->supports_cs = true;
+ if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS) {
+ conn->supports_ps = true;
luop->is_ps = true;
+ } else {
+ /* 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." */
+ conn->supports_ps = true;
+ }
llist_add(&luop->list, &g_lu_ops);
/* Roughly follwing "Process Update_Location_HLR" of TS 09.02 */
diff --git a/src/luop.c b/src/luop.c
index 02c41d0..7150b64 100644
--- a/src/luop.c
+++ b/src/luop.c
@@ -27,7 +27,6 @@
#include <osmocom/core/logging.h>
#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/gsup.h>
-#include <osmocom/gsm/apn.h>
#include "gsup_server.h"
#include "gsup_router.h"
@@ -233,7 +232,6 @@ void lu_op_tx_cancel_old(struct lu_operation *luop)
void lu_op_tx_insert_subscr_data(struct lu_operation *luop)
{
struct osmo_gsup_message gsup;
- uint8_t apn[APN_MAXLEN];
uint8_t msisdn_enc[43]; /* TODO use constant; TS 24.008 10.5.4.7 */
int l;
@@ -259,15 +257,7 @@ void lu_op_tx_insert_subscr_data(struct lu_operation *luop)
if (luop->is_ps) {
/* FIXME: PDP infos - use more fine-grained access control
instead of wildcard APN */
- l = osmo_apn_from_str(apn, sizeof(apn), "*");
- if (l > 0) {
- gsup.pdp_infos[0].apn_enc = apn;
- gsup.pdp_infos[0].apn_enc_len = l;
- gsup.pdp_infos[0].have_info = 1;
- gsup.num_pdp_infos = 1;
- /* FIXME: use real value: */
- gsup.pdp_infos[0].context_id = 1;
- }
+ osmo_gsup_configure_wildcard_apn(&gsup);
}
/* Send ISD to new VLR/SGSN */