From 98146776dddb986fda78b5f028e79f041460ee4c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 5 Sep 2017 17:41:20 +0200 Subject: [PATCH] ggsn: Add ability to specify local IP addresses for GTP-C and GTP-U In case the GGSN is behind some kind of DNAT, the public GTP-C and GTP-U IP addresses as exposed inside the GTP payload information elements are different from the (internal, behind-nat) IP address to which it listens/binds. Change-Id: I548c9011c9abd66d46f963b1def61575f3dabb89 --- ggsn/ggsn.c | 8 ++++++++ ggsn/ggsn.h | 4 ++++ ggsn/ggsn_vty.c | 42 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c index 0b877cf..46850a6 100644 --- a/ggsn/ggsn.c +++ b/ggsn/ggsn.c @@ -693,6 +693,14 @@ int ggsn_start(struct ggsn_ctx *ggsn) } ggsn->gsn->priv = ggsn; + /* patch in different addresses to use (in case we're behind NAT, the listen + * address is different from what we advertise externally) */ + if (ggsn->cfg.gtpc_addr.v4.s_addr) + ggsn->gsn->gsnc = ggsn->cfg.gtpc_addr.v4; + + if (ggsn->cfg.gtpu_addr.v4.s_addr) + ggsn->gsn->gsnu = ggsn->cfg.gtpu_addr.v4; + /* Register File Descriptors */ osmo_fd_setup(&ggsn->gtp_fd0, ggsn->gsn->fd0, BSC_FD_READ, ggsn_gtp_fd_cb, ggsn, 0); rc = osmo_fd_register(&ggsn->gtp_fd0); diff --git a/ggsn/ggsn.h b/ggsn/ggsn.h index bab6cf7..2dd963c 100644 --- a/ggsn/ggsn.h +++ b/ggsn/ggsn.h @@ -99,6 +99,10 @@ struct ggsn_ctx { struct apn_ctx *default_apn; /* ADdress to which we listen for GTP */ struct in46_addr listen_addr; + /* Local GTP-C address advertised in GTP */ + struct in46_addr gtpc_addr; + /* Local GTP-U address advertised in GTP */ + struct in46_addr gtpu_addr; /* directory for state file */ char *state_dir; /* administratively shut-down (true) or not (false) */ diff --git a/ggsn/ggsn_vty.c b/ggsn/ggsn_vty.c index 4a3e753..d7bd9a7 100644 --- a/ggsn/ggsn_vty.c +++ b/ggsn/ggsn_vty.c @@ -165,8 +165,8 @@ DEFUN(cfg_no_ggsn, cfg_no_ggsn_cmd, return CMD_SUCCESS; } -DEFUN(cfg_ggsn_local_ip, cfg_ggsn_local_ip_cmd, - "gtp local-ip A.B.C.D", +DEFUN(cfg_ggsn_bind_ip, cfg_ggsn_bind_ip_cmd, + "gtp bind-ip A.B.C.D", "GTP Parameters\n" "Set the IP address for the local GTP bind\n" "IPv4 Address\n") @@ -179,6 +179,34 @@ DEFUN(cfg_ggsn_local_ip, cfg_ggsn_local_ip_cmd, return CMD_SUCCESS; } +DEFUN(cfg_ggsn_gtpc_ip, cfg_ggsn_gtpc_ip_cmd, + "gtp control-ip A.B.C.D", + "GTP Parameters\n" + "Set the IP address states as local IP in GTP-C messages\n" + "IPv4 Address\n") +{ + struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index; + size_t t; + + ippool_aton(&ggsn->cfg.gtpc_addr, &t, argv[0], 0); + + return CMD_SUCCESS; +} + +DEFUN(cfg_ggsn_gtpu_ip, cfg_ggsn_gtpu_ip_cmd, + "gtp user-ip A.B.C.D", + "GTP Parameters\n" + "Set the IP address states as local IP in GTP-U messages\n" + "IPv4 Address\n") +{ + struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index; + size_t t; + + ippool_aton(&ggsn->cfg.gtpu_addr, &t, argv[0], 0); + + return CMD_SUCCESS; +} + DEFUN(cfg_ggsn_state_dir, cfg_ggsn_state_dir_cmd, "gtp state-dir PATH", "GTP Parameters\n" @@ -633,7 +661,11 @@ static int config_write_ggsn(struct vty *vty) if (ggsn->cfg.description) vty_out(vty, " description %s%s", ggsn->cfg.description, VTY_NEWLINE); vty_out(vty, " gtp state-dir %s%s", ggsn->cfg.state_dir, VTY_NEWLINE); - vty_out(vty, " gtp local-ip %s%s", in46a_ntoa(&ggsn->cfg.listen_addr), VTY_NEWLINE); + vty_out(vty, " gtp bind-ip %s%s", in46a_ntoa(&ggsn->cfg.listen_addr), VTY_NEWLINE); + if (ggsn->cfg.gtpc_addr.v4.s_addr) + vty_out(vty, " gtp control-ip %s%s", in46a_ntoa(&ggsn->cfg.gtpc_addr), VTY_NEWLINE); + if (ggsn->cfg.gtpu_addr.v4.s_addr) + vty_out(vty, " gtp user-ip %s%s", in46a_ntoa(&ggsn->cfg.gtpu_addr), VTY_NEWLINE); llist_for_each_entry(apn, &ggsn->apn_list, list) config_write_apn(vty, apn); if (ggsn->cfg.default_apn) @@ -806,7 +838,9 @@ int ggsn_vty_init(void) install_element(GGSN_NODE, &cfg_no_description_cmd); install_element(GGSN_NODE, &cfg_ggsn_shutdown_cmd); install_element(GGSN_NODE, &cfg_ggsn_no_shutdown_cmd); - install_element(GGSN_NODE, &cfg_ggsn_local_ip_cmd); + install_element(GGSN_NODE, &cfg_ggsn_bind_ip_cmd); + install_element(GGSN_NODE, &cfg_ggsn_gtpc_ip_cmd); + install_element(GGSN_NODE, &cfg_ggsn_gtpu_ip_cmd); install_element(GGSN_NODE, &cfg_ggsn_state_dir_cmd); install_element(GGSN_NODE, &cfg_ggsn_apn_cmd); install_element(GGSN_NODE, &cfg_ggsn_no_apn_cmd);