From 39f040d62b16b2d99352f5facd83ce098fa2f462 Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Thu, 18 Dec 2014 12:46:47 +0100 Subject: [PATCH] sgsn: Integrate the GSUP client into the SGSN This commit adds GSUP client configuration (via VTY), connection set up, and real message sending. The following configuration commands are added: - gsup remote-ip A.B.C.D set server IP address - gsup remote-port PORT set server TCP port Ticket: OW#1338 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gprs_sgsn.h | 2 +- openbsc/include/openbsc/sgsn.h | 7 ++++ openbsc/src/gprs/gprs_subscriber.c | 52 ++++++++++++++++++++++++++--- openbsc/src/gprs/sgsn_main.c | 6 ++++ openbsc/src/gprs/sgsn_vty.c | 31 +++++++++++++++++ openbsc/tests/sgsn/Makefile.am | 2 ++ 6 files changed, 94 insertions(+), 6 deletions(-) diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h index 8019ad1ca..84307a5cc 100644 --- a/openbsc/include/openbsc/gprs_sgsn.h +++ b/openbsc/include/openbsc/gprs_sgsn.h @@ -305,7 +305,7 @@ struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx, GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \ ) -void gprs_subscr_init(struct sgsn_instance *sgi); +int gprs_subscr_init(struct sgsn_instance *sgi); int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx); int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx); void gprs_subscr_delete(struct gsm_subscriber *subscr); diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h index 6b83337d0..71be1ce2a 100644 --- a/openbsc/include/openbsc/sgsn.h +++ b/openbsc/include/openbsc/sgsn.h @@ -7,6 +7,8 @@ #include #include +struct gprs_gsup_client; + enum sgsn_auth_policy { SGSN_AUTH_POLICY_OPEN, SGSN_AUTH_POLICY_CLOSED, @@ -25,6 +27,9 @@ struct sgsn_config { enum sgsn_auth_policy auth_policy; struct llist_head imsi_acl; + + struct sockaddr_in gsup_server_addr; + int gsup_server_port; }; struct sgsn_instance { @@ -38,6 +43,8 @@ struct sgsn_instance { struct osmo_timer_list gtp_timer; /* GSN instance for libgtp */ struct gsn_t *gsn; + /* Subscriber */ + struct gprs_gsup_client *gsup_client; }; extern struct sgsn_instance *sgsn; diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 461b3a573..04debff24 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -20,6 +20,7 @@ */ #include +#include #include #include @@ -28,10 +29,47 @@ #include +#include +#include + extern void *tall_bsc_ctx; -void gprs_subscr_init(struct sgsn_instance *sgi) +static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg); + +/* TODO: Some functions are specific to the SGSN, but this file is more general + * (it has gprs_* name). Either move these functions elsewhere, split them and + * move a part, or replace the gprs_ prefix by sgsn_. The applies to + * gprs_subscr_init, gsup_read_cb, and gprs_subscr_tx_gsup_message. + */ + +int gprs_subscr_init(struct sgsn_instance *sgi) { + const char *addr_str; + + if (!sgi->cfg.gsup_server_addr.sin_addr.s_addr) + return 0; + + addr_str = inet_ntoa(sgi->cfg.gsup_server_addr.sin_addr); + + sgi->gsup_client = gprs_gsup_client_create( + addr_str, sgi->cfg.gsup_server_port, + &gsup_read_cb); + + if (!sgi->gsup_client) + return -1; + + return 1; +} + +static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg) +{ + int rc; + + rc = gprs_subscr_rx_gsup_message(msg); + if (rc < 0) + return -1; + + return rc; } static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx) @@ -96,17 +134,21 @@ void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr) static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr, struct gprs_gsup_message *gsup_msg) { - struct msgb *msg = msgb_alloc(4096, __func__); + struct msgb *msg = gprs_gsup_msgb_alloc(); strncpy(gsup_msg->imsi, subscr->imsi, sizeof(gsup_msg->imsi) - 1); gprs_gsup_encode(msg, gsup_msg); LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm, - "Sending GSUP NYI, would send: %s\n", msgb_hexdump(msg)); - msgb_free(msg); + "Sending GSUP, will send: %s\n", msgb_hexdump(msg)); - return -ENOTSUP; + if (!sgsn->gsup_client) { + msgb_free(msg); + return -ENOTSUP; + } + + return gprs_gsup_client_send(sgsn->gsup_client, msg); } static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr, diff --git a/openbsc/src/gprs/sgsn_main.c b/openbsc/src/gprs/sgsn_main.c index 141eacf94..f26b812a8 100644 --- a/openbsc/src/gprs/sgsn_main.c +++ b/openbsc/src/gprs/sgsn_main.c @@ -357,6 +357,12 @@ int main(int argc, char **argv) exit(2); } + rc = gprs_subscr_init(&sgsn_inst); + if (rc < 0) { + LOGP(DGPRS, LOGL_FATAL, "Cannot set up subscriber management\n"); + exit(2); + } + rc = gprs_ns_nsip_listen(sgsn_nsi); if (rc < 0) { LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n"); diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index b15de75c7..e9333f562 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -139,6 +139,12 @@ static int config_write_sgsn(struct vty *vty) vty_out(vty, " auth-policy %s%s", get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy), VTY_NEWLINE); + if (g_cfg->gsup_server_addr.sin_addr.s_addr) + vty_out(vty, " gsup remote-ip %s%s", + inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE); + if (g_cfg->gsup_server_port) + vty_out(vty, " gsup remote-port %d%s", + g_cfg->gsup_server_port, VTY_NEWLINE); llist_for_each_entry(acl, &g_cfg->imsi_acl, list) vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE); @@ -650,6 +656,29 @@ DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd, return CMD_SUCCESS; } +DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd, + "gsup remote-ip A.B.C.D", + "GSUP Parameters\n" + "Set the IP address of the remote GSUP server\n" + "IPv4 Address\n") +{ + inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr); + + return CMD_SUCCESS; +} + +DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd, + "gsup remote-port <0-65535>", + "GSUP Parameters\n" + "Set the TCP port of the remote GSUP server\n" + "Remote TCP port\n") +{ + g_cfg->gsup_server_port = atoi(argv[0]); + + return CMD_SUCCESS; +} + + int sgsn_vty_init(void) { @@ -676,6 +705,8 @@ int sgsn_vty_init(void) install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd); install_element(SGSN_NODE, &cfg_imsi_acl_cmd); install_element(SGSN_NODE, &cfg_auth_policy_cmd); + install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd); + install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd); return 0; } diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index c8dccfe07..70e0924f2 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -22,9 +22,11 @@ sgsn_test_LDADD = \ $(top_builddir)/src/gprs/sgsn_libgtp.o \ $(top_builddir)/src/gprs/sgsn_auth.o \ $(top_builddir)/src/gprs/gprs_gsup_messages.o \ + $(top_builddir)/src/gprs/gprs_gsup_client.o \ $(top_builddir)/src/gprs/gprs_utils.o \ $(top_builddir)/src/gprs/gprs_subscriber.o \ $(top_builddir)/src/libcommon/libcommon.a \ + $(LIBOSMOABIS_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOGB_LIBS) \