aboutsummaryrefslogtreecommitdiffstats
path: root/sgsnemu/sgsnemu.c
diff options
context:
space:
mode:
Diffstat (limited to 'sgsnemu/sgsnemu.c')
-rw-r--r--sgsnemu/sgsnemu.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 7904c49..2c0ce1b 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -50,6 +50,7 @@
#include "../lib/tun.h"
#include "../lib/ippool.h"
#include "../lib/syserr.h"
+#include "../lib/netns.h"
#include "../gtp/pdp.h"
#include "../gtp/gtp.h"
#include "cmdline.h"
@@ -81,12 +82,16 @@ struct tun_t *tun = NULL; /* TUN instance */
int maxfd = 0; /* For select() */
int echoversion = 1; /* First try this version */
void *tall_sgsnemu_ctx; /* root talloc ctx */
+#if defined(__linux__)
+int netns = -1; /* network namespace */
+#endif
/* Struct with local versions of gengetopt options */
struct {
int debug; /* Print debug messages */
int createif; /* Create local network interface */
char *tun_dev_name;
+ char *netns;
struct in46_addr netaddr, destaddr, net; /* Network interface */
size_t prefixlen;
char *ipup, *ipdown; /* Filename of scripts */
@@ -294,6 +299,8 @@ static int process_options(int argc, char **argv)
printf("createif: %d\n", args_info.createif_flag);
if (args_info.tun_device_arg)
printf("tun-device: %s\n", args_info.tun_device_arg);
+ if (args_info.netns_arg)
+ printf("netns: %s\n", args_info.netns_arg);
if (args_info.ipup_arg)
printf("ipup: %s\n", args_info.ipup_arg);
if (args_info.ipdown_arg)
@@ -352,6 +359,8 @@ static int process_options(int argc, char **argv)
printf("createif: %d\n", args_info.createif_flag);
if (args_info.tun_device_arg)
printf("tun-device: %s\n", args_info.tun_device_arg);
+ if (args_info.netns_arg)
+ printf("netns: %s\n", args_info.netns_arg);
if (args_info.ipup_arg)
printf("ipup: %s\n", args_info.ipup_arg);
if (args_info.ipdown_arg)
@@ -870,6 +879,7 @@ static int process_options(int argc, char **argv)
/* createif */
options.createif = args_info.createif_flag;
options.tun_dev_name = args_info.tun_device_arg;
+ options.netns = args_info.netns_arg;
/* net */
/* Store net as in_addr net and mask */
@@ -1313,10 +1323,23 @@ static int create_ping(void *gsn, struct pdp_t *pdp,
static int delete_context(struct pdp_t *pdp)
{
+ if (tun && options.ipdown) {
+#if defined(__linux__)
+ sigset_t oldmask;
- if (tun && options.ipdown)
+ if ((options.netns)) {
+ switch_ns(netns, &oldmask);
+ }
+#endif
tun_runscript(tun, options.ipdown);
+#if defined(__linux__)
+ if ((options.netns)) {
+ restore_ns(&oldmask);
+ }
+#endif
+ }
+
ipdel((struct iphash_t *)pdp->peer[0]);
memset(pdp->peer[0], 0, sizeof(struct iphash_t)); /* To be sure */
@@ -1377,6 +1400,9 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
{
struct in46_addr addr;
+#if defined(__linux__)
+ sigset_t oldmask;
+#endif
struct iphash_t *iph = (struct iphash_t *)cbp;
@@ -1430,6 +1456,12 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
break;
}
+#if defined(__linux__)
+ if ((options.createif) && (options.netns)) {
+ switch_ns(netns, &oldmask);
+ }
+#endif
+
if ((options.createif) && (!options.net.len)) {
size_t prefixlen = 32;
if (addr.len == 16)
@@ -1470,6 +1502,12 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
free(forwarding);
}
+#if defined(__linux__)
+ if ((options.createif) && (options.netns)) {
+ restore_ns(&oldmask);
+ }
+#endif
+
ipset(iph, &addr);
state = 2; /* Connected */
@@ -1543,6 +1581,9 @@ int main(int argc, char **argv)
struct timezone tz; /* Used for calculating ping times */
struct timeval tv;
int diff;
+#if defined(__linux__)
+ sigset_t oldmask;
+#endif
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
@@ -1552,6 +1593,10 @@ int main(int argc, char **argv)
msgb_talloc_ctx_init(tall_sgsnemu_ctx, 0);
osmo_init_logging2(tall_sgsnemu_ctx, &log_info);
+#if defined(__linux__)
+ init_netns();
+#endif
+
/* Process options given in configuration file and command line */
if (process_options(argc, argv))
exit(1);
@@ -1575,6 +1620,13 @@ int main(int argc, char **argv)
else
gtp_set_cb_data_ind(gsn, encaps_ping);
+#if defined(__linux__)
+ if ((options.createif) && (options.netns)) {
+ netns = get_nsfd(options.netns);
+ switch_ns(netns, &oldmask);
+ }
+#endif
+
if (options.createif) {
printf("Setting up interface\n");
/* Create a tunnel interface */
@@ -1600,6 +1652,12 @@ int main(int argc, char **argv)
tun_runscript(tun, options.ipup);
}
+#if defined(__linux__)
+ if ((options.createif) && (options.netns)) {
+ restore_ns(&oldmask);
+ }
+#endif
+
/* Initialise hash tables */
memset(&iphash, 0, sizeof(iphash));
memset(&iparr, 0, sizeof(iparr));