diff options
-rw-r--r-- | src/gsup_server.c | 18 | ||||
-rw-r--r-- | src/gsup_server.h | 6 | ||||
-rw-r--r-- | src/hlr.c | 79 | ||||
-rw-r--r-- | src/luop.c | 12 |
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); @@ -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 */ @@ -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 */ |