move creation of insert subscriber data messages to a common function
Move code to create an Insert Subscriber Data message into a common
function which can be shared by hlr.c and luop.c.
As a consequence, we always encode gsup.cn_domain in the corresponding
msgb and must adjust expected output of the 'gsup' test accordingly.
Change-Id: I6a92ca34cdaadca9eacc774bb1ca386c325ba865
Requested-by: neels
Related: OS#2785
diff --git a/src/gsup_server.c b/src/gsup_server.c
index 07d4feb..4b8a0fa 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/gsm48_ie.h>
#include <osmocom/gsm/apn.h>
#include "gsup_server.h"
@@ -357,3 +358,56 @@
return 0;
}
+
+/**
+ * Populate a gsup message structure with an Insert Subscriber Data Message.
+ * All required memory buffers for data pointed to by pointers in struct omso_gsup_message
+ * must be allocated by the caller and should have the same lifetime as the gsup parameter.
+ *
+ * \param[out] gsup The gsup message to populate.
+ * \param[in] imsi The subscriber's IMSI.
+ * \param[in] msisdn The subscriber's MSISDN.
+ * \param[out] msisdn_enc A buffer large enough to store the MSISDN in encoded form.
+ * \param[in] msisdn_enc_size Size of the buffer (must be >= OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN).
+ * \param[out] apn_buf A buffer large enough to store an APN (required if cn_domain is OSMO_GSUP_CN_DOMAIN_PS).
+ * \param[in] apn_buf_size Size of APN buffer (must be >= APN_MAXLEN).
+ * \param[in] cn_domain The CN Domain of the subscriber connection.
+ * \returns 0 on success, and negative on error.
+ */
+int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
+ uint8_t *msisdn_enc, size_t msisdn_enc_size,
+ uint8_t *apn_buf, size_t apn_buf_size,
+ enum osmo_gsup_cn_domain cn_domain)
+{
+ int len;
+
+ OSMO_ASSERT(gsup);
+
+ gsup->message_type = OSMO_GSUP_MSGT_INSERT_DATA_REQUEST;
+ osmo_strlcpy(gsup->imsi, imsi, sizeof(gsup->imsi));
+
+ if (msisdn_enc_size < OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN)
+ return -ENOSPC;
+
+ OSMO_ASSERT(msisdn_enc);
+ len = gsm48_encode_bcd_number(msisdn_enc, msisdn_enc_size, 0, msisdn);
+ if (len < 1) {
+ LOGP(DLGSUP, LOGL_ERROR, "%s: Error: cannot encode MSISDN '%s'\n", imsi, msisdn);
+ return -ENOSPC;
+ }
+ gsup->msisdn_enc = msisdn_enc;
+ gsup->msisdn_enc_len = len;
+
+ #pragma message "FIXME: deal with encoding the following data: gsup.hlr_enc"
+
+ gsup->cn_domain = cn_domain;
+ if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS) {
+ OSMO_ASSERT(apn_buf_size >= APN_MAXLEN);
+ OSMO_ASSERT(apn_buf);
+ /* FIXME: PDP infos - use more fine-grained access control
+ instead of wildcard APN */
+ osmo_gsup_configure_wildcard_apn(gsup, apn_buf, apn_buf_size);
+ }
+
+ return 0;
+}
diff --git a/src/gsup_server.h b/src/gsup_server.h
index 66c1a9c..e49d283 100644
--- a/src/gsup_server.h
+++ b/src/gsup_server.h
@@ -6,6 +6,10 @@
#include <osmocom/abis/ipaccess.h>
#include <osmocom/gsm/gsup.h>
+#ifndef OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN
+#define OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN 43 /* TS 24.008 10.5.4.7 */
+#endif
+
struct osmo_gsup_conn;
/* Expects message in msg->l2h */
@@ -55,3 +59,7 @@
int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
uint8_t *apn_buf, size_t apn_buf_size);
+int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
+ uint8_t *msisdn_enc, size_t msisdn_enc_size,
+ uint8_t *apn_buf, size_t apn_buf_size,
+ enum osmo_gsup_cn_domain cn_domain);
diff --git a/src/hlr.c b/src/hlr.c
index 1c72f45..4da7b9b 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/gsm48_ie.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/telnet_interface.h>
@@ -62,54 +61,33 @@
return;
llist_for_each_entry(co, &g_hlr->gs->clients, list) {
- struct osmo_gsup_message gsup = {
- .message_type = OSMO_GSUP_MSGT_INSERT_DATA_REQUEST
- };
+ struct osmo_gsup_message gsup = { };
+ uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
+ uint8_t apn[APN_MAXLEN];
+ struct msgb *msg_out;
uint8_t *peer;
int peer_len;
- uint8_t msisdn_enc[43]; /* TODO use constant; TS 24.008 10.5.4.7 */
- uint8_t apn[APN_MAXLEN];
- int len;
- struct msgb *msg_out;
+ enum osmo_gsup_cn_domain cn_domain;
- peer_len = osmo_gsup_conn_ccm_get(co, &peer, IPAC_IDTAG_SERNR);
- if (peer_len < 0) {
+ if (co->supports_ps)
+ cn_domain = OSMO_GSUP_CN_DOMAIN_PS;
+ else if (co->supports_cs)
+ cn_domain = OSMO_GSUP_CN_DOMAIN_CS;
+ else {
+ /* We have not yet received a location update from this subscriber .*/
+ continue;
+ }
+
+ 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(DMAIN, LOGL_ERROR,
- "IMSI='%s': Cannot notify GSUP client, cannot get peer name "
+ "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;
}
- 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 */
- if (osmo_gsup_configure_wildcard_apn(&gsup, apn, sizeof(apn))) {
- LOGP(DMAIN, LOGL_ERROR, "%s: Error: cannot encode wildcard APN\n",
- subscr->imsi);
- continue;
- }
- } 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) {
@@ -120,8 +98,17 @@
co && co->conn && co->conn->server? co->conn->server->port : 0);
continue;
}
-
osmo_gsup_encode(msg_out, &gsup);
+
+ peer_len = osmo_gsup_conn_ccm_get(co, &peer, IPAC_IDTAG_SERNR);
+ if (peer_len < 0) {
+ LOGP(DMAIN, 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;
+ }
+
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 "
diff --git a/src/luop.c b/src/luop.c
index db7b3c9..aff4d81 100644
--- a/src/luop.c
+++ b/src/luop.c
@@ -25,7 +25,6 @@
#include <errno.h>
#include <osmocom/core/logging.h>
-#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/gsm/apn.h>
@@ -52,6 +51,7 @@
struct msgb *msg_out;
msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP LUOP");
+ OSMO_ASSERT(msg_out);
osmo_gsup_encode(msg_out, gsup);
osmo_gsup_addr_send(luop->gsup_server, luop->peer,
@@ -215,40 +215,27 @@
/*! Transmit Insert Subscriber Data to new VLR/SGSN */
void lu_op_tx_insert_subscr_data(struct lu_operation *luop)
{
- struct osmo_gsup_message gsup;
- uint8_t msisdn_enc[43]; /* TODO use constant; TS 24.008 10.5.4.7 */
+ struct hlr_subscriber *subscr = &luop->subscr;
+ struct osmo_gsup_message gsup = { };
+ uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
uint8_t apn[APN_MAXLEN];
- int l;
+ enum osmo_gsup_cn_domain cn_domain;
OSMO_ASSERT(luop->state == LU_S_LU_RECEIVED ||
luop->state == LU_S_CANCEL_ACK_RECEIVED);
- fill_gsup_msg(&gsup, luop, OSMO_GSUP_MSGT_INSERT_DATA_REQUEST);
+ if (luop->is_ps)
+ cn_domain = OSMO_GSUP_CN_DOMAIN_PS;
+ else
+ cn_domain = OSMO_GSUP_CN_DOMAIN_CS;
- l = gsm48_encode_bcd_number(msisdn_enc, sizeof(msisdn_enc), 0,
- luop->subscr.msisdn);
- if (l < 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(DMAIN, LOGL_ERROR,
- "%s: Error: cannot encode MSISDN '%s'\n",
- luop->subscr.imsi, luop->subscr.msisdn);
- lu_op_tx_error(luop, GMM_CAUSE_PROTO_ERR_UNSPEC);
+ "IMSI='%s': Cannot notify GSUP client; could not create gsup message "
+ "for %s\n", subscr->imsi, luop->peer);
return;
}
- gsup.msisdn_enc = msisdn_enc;
- gsup.msisdn_enc_len = l;
-
- #pragma message "FIXME: deal with encoding the following data: gsup.hlr_enc"
-
- if (luop->is_ps) {
- /* FIXME: PDP infos - use more fine-grained access control
- instead of wildcard APN */
- if (osmo_gsup_configure_wildcard_apn(&gsup, apn, sizeof(apn))) {
- LOGP(DMAIN, LOGL_ERROR, "%s: Error: cannot encode wildcard APN\n",
- luop->subscr.imsi);
- lu_op_tx_error(luop, GMM_CAUSE_PROTO_ERR_UNSPEC);
- return;
- }
- }
/* Send ISD to new VLR/SGSN */
_luop_tx_gsup(luop, &gsup);