From ca2361c23717fd13e33088d6dfe4e2370b714097 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 3 Dec 2015 14:12:44 +0100 Subject: gtphub: implement sgsn_use_sender for NAT. If an SGSN is behind NAT, we cannot rely on the default ports. Specifically, if a GGSN sends a message, the forwarding to the SGSN should go to whichever port the SGSN last sent from (whether sequence nr is known or not). Add sgsn_use_sender config and VTY command, and store the sender instead of the GSN Address IE and default port if set. Sponsored-by: On-Waves ehi --- openbsc/include/openbsc/gtphub.h | 3 +++ openbsc/src/gprs/gtphub.c | 23 +++++++++++++++++++++-- openbsc/src/gprs/gtphub_vty.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h index c98603b4e..1bff68127 100644 --- a/openbsc/include/openbsc/gtphub.h +++ b/openbsc/include/openbsc/gtphub.h @@ -361,6 +361,7 @@ struct gtphub_cfg_bind { struct gtphub_cfg { struct gtphub_cfg_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N]; struct gtphub_cfg_addr proxy[GTPH_SIDE_N][GTPH_PLANE_N]; + int sgsn_use_sender; /* Use sender, not GSN addr IE with std ports */ }; @@ -454,6 +455,8 @@ struct gtphub { struct expiry expire_slowly; uint8_t restart_counter; + + int sgsn_use_sender; }; struct gtp_packet_desc; diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index e96088c74..676282575 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -1502,9 +1502,27 @@ static int gtphub_handle_create_pdp_ctx(struct gtphub *hub, tei_from_ie = ntoh32(p->ie[ie_idx]->tv4.v); /* Make sure an entry for this peer address with default port - * exists. */ + * exists. + * + * Exception: if sgsn_use_sender is set, instead use the + * sender's address and port for Ctrl -- the User port is not + * known until the first User packet arrives. + * + * Note: doing this here is just an optimization, because + * gtphub_handle_buf() has code to replace the tunnel + * endpoints' addresses with the sender (needed for User + * plane). We could just ignore sgsn_use_sender here. But if we + * set up a default port here and replace it in + * gtphub_handle_buf(), we'd be creating a peer port just to + * expire it right away. */ + if (hub->sgsn_use_sender && (side_idx == GTPH_SIDE_SGSN)) { + gsn_addr_from_sockaddr(&use_addr, &use_port, &from_ctrl->sa); + } else { + use_port = gtphub_plane_idx_default_port[plane_idx]; + + } + struct gtphub_peer_port *peer_from_ie; - use_port = gtphub_plane_idx_default_port[plane_idx]; peer_from_ie = gtphub_port_have(hub, &hub->to_gsns[side_idx][plane_idx], &use_addr, use_port); @@ -2417,6 +2435,7 @@ int gtphub_start(struct gtphub *hub, struct gtphub_cfg *cfg, gtphub_init(hub); hub->restart_counter = restart_counter; + hub->sgsn_use_sender = cfg->sgsn_use_sender? 1 : 0; /* If a Ctrl plane proxy is configured, ares will never be used. */ if (!cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str) { diff --git a/openbsc/src/gprs/gtphub_vty.c b/openbsc/src/gprs/gtphub_vty.c index 204d1deeb..324d155b9 100644 --- a/openbsc/src/gprs/gtphub_vty.c +++ b/openbsc/src/gprs/gtphub_vty.c @@ -87,6 +87,10 @@ static int config_write_gtphub(struct vty *vty) &g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].bind, &g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].bind); + if (g_cfg->sgsn_use_sender) { + vty_out(vty, "sgsn-use-sender%s", VTY_NEWLINE); + } + if (g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].addr_str) { write_addrs(vty, "sgsn-proxy", &g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL], @@ -237,6 +241,28 @@ DEFUN(cfg_gtphub_sgsn_proxy, cfg_gtphub_sgsn_proxy_cmd, } +#define SGSN_USE_SENDER_STR \ + "Ignore SGSN's Address IEs, use sender address and port (useful over NAT)\n" + +DEFUN(cfg_gtphub_sgsn_use_sender, + cfg_gtphub_sgsn_use_sender_cmd, + "sgsn-use-sender", + SGSN_USE_SENDER_STR) +{ + g_cfg->sgsn_use_sender = 1; + return CMD_SUCCESS; +} + +DEFUN(cfg_gtphub_no_sgsn_use_sender, + cfg_gtphub_no_sgsn_use_sender_cmd, + "no sgsn-use-sender", + NO_STR SGSN_USE_SENDER_STR) +{ + g_cfg->sgsn_use_sender = 0; + return CMD_SUCCESS; +} + + /* Copied from sgsn_vty.h */ DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd, "grx-dns-add A.B.C.D", @@ -425,6 +451,8 @@ int gtphub_vty_init(struct gtphub *global_hub, struct gtphub_cfg *global_cfg) install_element(GTPHUB_NODE, &cfg_gtphub_ggsn_proxy_cmd); install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_short_cmd); install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_cmd); + install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_use_sender_cmd); + install_element(GTPHUB_NODE, &cfg_gtphub_no_sgsn_use_sender_cmd); install_element(GTPHUB_NODE, &cfg_grx_ggsn_cmd); return 0; -- cgit v1.2.3