aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */