<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ggsn/+/17253">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add Linux network namespace support for TUN device<br><br>Change-Id: Idd0ad8fa9c8e7ba0aeec1b52947598d4d297b620<br>---<br>M lib/Makefile.am<br>A lib/netns.c<br>A lib/netns.h<br>M sgsnemu/cmdline.c<br>M sgsnemu/cmdline.ggo<br>M sgsnemu/cmdline.h<br>M sgsnemu/sgsnemu.c<br>7 files changed, 294 insertions(+), 12 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-ggsn refs/changes/53/17253/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/lib/Makefile.am b/lib/Makefile.am</span><br><span>index 533d777..f2c5dc9 100644</span><br><span>--- a/lib/Makefile.am</span><br><span>+++ b/lib/Makefile.am</span><br><span>@@ -1,10 +1,10 @@</span><br><span> noinst_LIBRARIES = libmisc.a</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h in46_addr.h netdev.h gtp-kernel.h util.h</span><br><span style="color: hsl(120, 100%, 40%);">+noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h in46_addr.h netdev.h gtp-kernel.h netns.h util.h</span><br><span> </span><br><span> AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c debug.c in46_addr.c netdev.c util.c</span><br><span style="color: hsl(120, 100%, 40%);">+libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c debug.c in46_addr.c netdev.c netns.c util.c</span><br><span> </span><br><span> if ENABLE_GTP_KERNEL</span><br><span> AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)</span><br><span>diff --git a/lib/netns.c b/lib/netns.c</span><br><span>new file mode 100644</span><br><span>index 0000000..6734b5d</span><br><span>--- /dev/null</span><br><span>+++ b/lib/netns.c</span><br><span>@@ -0,0 +1,147 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2014-2017, Travelping GmbH <info@travelping.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software: you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation, either version 3 of the</span><br><span style="color: hsl(120, 100%, 40%);">+ * License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU Affero General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Affero General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_CONFIG_H</span><br><span style="color: hsl(120, 100%, 40%);">+# include "config.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _GNU_SOURCE</span><br><span style="color: hsl(120, 100%, 40%);">+# define _GNU_SOURCE</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sched.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <signal.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/stat.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/socket.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/mount.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/param.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <fcntl.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "netns.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define NETNS_PATH "/var/run/netns"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int default_nsfd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int switch_ns(int nsfd, sigset_t *oldmask)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ sigset_t intmask;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   sigfillset(&intmask);</span><br><span style="color: hsl(120, 100%, 40%);">+     sigprocmask(SIG_BLOCK, &intmask, oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return setns(nsfd, CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void restore_ns(sigset_t *oldmask)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ setns(default_nsfd, CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  sigprocmask(SIG_SETMASK, oldmask, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int open_ns(int nsfd, const char *pathname, int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      sigset_t intmask, oldmask;</span><br><span style="color: hsl(120, 100%, 40%);">+    int fd;</span><br><span style="color: hsl(120, 100%, 40%);">+       int errsv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  sigfillset(&intmask);</span><br><span style="color: hsl(120, 100%, 40%);">+     sigprocmask(SIG_BLOCK, &intmask, &oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ setns(nsfd, CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+    fd = open(pathname, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+   errsv = errno;</span><br><span style="color: hsl(120, 100%, 40%);">+        setns(default_nsfd, CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  sigprocmask(SIG_SETMASK, &oldmask, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       errno = errsv;</span><br><span style="color: hsl(120, 100%, 40%);">+        return fd;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int socket_ns(int nsfd, int domain, int type, int protocol)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       sigset_t intmask, oldmask;</span><br><span style="color: hsl(120, 100%, 40%);">+    int sk;</span><br><span style="color: hsl(120, 100%, 40%);">+       int errsv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  sigfillset(&intmask);</span><br><span style="color: hsl(120, 100%, 40%);">+     sigprocmask(SIG_BLOCK, &intmask, &oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ setns(nsfd, CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+    sk = socket(domain, type, protocol);</span><br><span style="color: hsl(120, 100%, 40%);">+  errsv = errno;</span><br><span style="color: hsl(120, 100%, 40%);">+        setns(default_nsfd, CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  sigprocmask(SIG_SETMASK, &oldmask, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       errno = errsv;</span><br><span style="color: hsl(120, 100%, 40%);">+        return sk;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void init_netns()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((default_nsfd = open("/proc/self/ns/net", O_RDONLY)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          perror("init_netns");</span><br><span style="color: hsl(120, 100%, 40%);">+               exit(EXIT_FAILURE);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int get_nsfd(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int r;</span><br><span style="color: hsl(120, 100%, 40%);">+        sigset_t intmask, oldmask;</span><br><span style="color: hsl(120, 100%, 40%);">+    char path[MAXPATHLEN] = NETNS_PATH;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ r = mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (r < 0 && errno != EEXIST)</span><br><span style="color: hsl(120, 100%, 40%);">+              return r;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   snprintf(path, sizeof(path), "%s/%s", NETNS_PATH, name);</span><br><span style="color: hsl(120, 100%, 40%);">+    r = open(path, O_RDONLY|O_CREAT|O_EXCL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (r < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (errno == EEXIST)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return open(path, O_RDONLY);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                return r;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     close(r);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   sigfillset(&intmask);</span><br><span style="color: hsl(120, 100%, 40%);">+     sigprocmask(SIG_BLOCK, &intmask, &oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ unshare(CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+        mount("/proc/self/ns/net", path, "none", MS_BIND, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        setns(default_nsfd, CLONE_NEWNET);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  sigprocmask(SIG_SETMASK, &oldmask, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return open(path, O_RDONLY);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>diff --git a/lib/netns.h b/lib/netns.h</span><br><span>new file mode 100644</span><br><span>index 0000000..168e44f</span><br><span>--- /dev/null</span><br><span>+++ b/lib/netns.h</span><br><span>@@ -0,0 +1,35 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2014-2017, Travelping GmbH <info@travelping.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software: you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation, either version 3 of the</span><br><span style="color: hsl(120, 100%, 40%);">+ * License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU Affero General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Affero General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __NETNS_H</span><br><span style="color: hsl(120, 100%, 40%);">+#define __NETNS_H</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void init_netns(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int switch_ns(int nsfd, sigset_t *oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+void restore_ns(sigset_t *oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int open_ns(int nsfd, const char *pathname, int flags);</span><br><span style="color: hsl(120, 100%, 40%);">+int socket_ns(int nsfd, int domain, int type, int protocol);</span><br><span style="color: hsl(120, 100%, 40%);">+int get_nsfd(const char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>diff --git a/sgsnemu/cmdline.c b/sgsnemu/cmdline.c</span><br><span>index b062533..13d0295 100644</span><br><span>--- a/sgsnemu/cmdline.c</span><br><span>+++ b/sgsnemu/cmdline.c</span><br><span>@@ -72,6 +72,7 @@</span><br><span>  "      --ipup=STRING             Script to run after link-up",</span><br><span>     "      --ipdown=STRING           Script to run after link-down",</span><br><span>   "      --tun-device=STRING       Name of the local network interface",</span><br><span style="color: hsl(120, 100%, 40%);">+      "      --netns=STRING            Network namespace to use",</span><br><span>        "\n Mode: pinghost\n  generate ICMP payload inside G-PDU without setting up tun interface",</span><br><span>        "      --pinghost=STRING         Ping remote host",</span><br><span>        "      --pingrate=INT            Number of ping req per second  (default=`1')",</span><br><span>@@ -163,6 +164,7 @@</span><br><span>  args_info->ipup_given = 0;</span><br><span>        args_info->ipdown_given = 0;</span><br><span>      args_info->tun_device_given = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   args_info->netns_given = 0;</span><br><span>       args_info->pinghost_given = 0;</span><br><span>    args_info->pingrate_given = 0;</span><br><span>    args_info->pingsize_given = 0;</span><br><span>@@ -244,6 +246,8 @@</span><br><span>      args_info->ipdown_orig = NULL;</span><br><span>    args_info->tun_device_arg = NULL;</span><br><span>         args_info->tun_device_orig = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ args_info->netns_arg = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       args_info->netns_orig = NULL;</span><br><span>     args_info->pinghost_arg = NULL;</span><br><span>   args_info->pinghost_orig = NULL;</span><br><span>  args_info->pingrate_arg = 1;</span><br><span>@@ -300,13 +304,14 @@</span><br><span>      args_info->ipup_help = gengetopt_args_info_help[35];</span><br><span>      args_info->ipdown_help = gengetopt_args_info_help[36];</span><br><span>    args_info->tun_device_help = gengetopt_args_info_help[37];</span><br><span style="color: hsl(0, 100%, 40%);">-   args_info->pinghost_help = gengetopt_args_info_help[39];</span><br><span style="color: hsl(0, 100%, 40%);">-     args_info->pingrate_help = gengetopt_args_info_help[40];</span><br><span style="color: hsl(0, 100%, 40%);">-     args_info->pingsize_help = gengetopt_args_info_help[41];</span><br><span style="color: hsl(0, 100%, 40%);">-     args_info->pingcount_help = gengetopt_args_info_help[42];</span><br><span style="color: hsl(0, 100%, 40%);">-    args_info->pingquiet_help = gengetopt_args_info_help[43];</span><br><span style="color: hsl(0, 100%, 40%);">-    args_info->no_tx_gpdu_seq_help = gengetopt_args_info_help[44];</span><br><span style="color: hsl(0, 100%, 40%);">-       args_info->pdp_type_help = gengetopt_args_info_help[45];</span><br><span style="color: hsl(120, 100%, 40%);">+   args_info->netns_help = gengetopt_args_info_help[38];</span><br><span style="color: hsl(120, 100%, 40%);">+      args_info->pinghost_help = gengetopt_args_info_help[40];</span><br><span style="color: hsl(120, 100%, 40%);">+   args_info->pingrate_help = gengetopt_args_info_help[41];</span><br><span style="color: hsl(120, 100%, 40%);">+   args_info->pingsize_help = gengetopt_args_info_help[42];</span><br><span style="color: hsl(120, 100%, 40%);">+   args_info->pingcount_help = gengetopt_args_info_help[43];</span><br><span style="color: hsl(120, 100%, 40%);">+  args_info->pingquiet_help = gengetopt_args_info_help[44];</span><br><span style="color: hsl(120, 100%, 40%);">+  args_info->no_tx_gpdu_seq_help = gengetopt_args_info_help[45];</span><br><span style="color: hsl(120, 100%, 40%);">+     args_info->pdp_type_help = gengetopt_args_info_help[46];</span><br><span> </span><br><span> }</span><br><span> </span><br><span>@@ -432,6 +437,8 @@</span><br><span>       free_string_field(&(args_info->ipdown_orig));</span><br><span>         free_string_field(&(args_info->tun_device_arg));</span><br><span>      free_string_field(&(args_info->tun_device_orig));</span><br><span style="color: hsl(120, 100%, 40%);">+      free_string_field(&(args_info->netns_arg));</span><br><span style="color: hsl(120, 100%, 40%);">+    free_string_field(&(args_info->netns_orig));</span><br><span>  free_string_field(&(args_info->pinghost_arg));</span><br><span>        free_string_field(&(args_info->pinghost_orig));</span><br><span>       free_string_field(&(args_info->pingrate_orig));</span><br><span>@@ -545,6 +552,8 @@</span><br><span>         if (args_info->tun_device_given)</span><br><span>          write_into_file(outfile, "tun-device",</span><br><span>                             args_info->tun_device_orig, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (args_info->netns_given)</span><br><span style="color: hsl(120, 100%, 40%);">+                write_into_file(outfile, "netns", args_info->netns_orig, 0);</span><br><span>    if (args_info->pinghost_given)</span><br><span>            write_into_file(outfile, "pinghost", args_info->pinghost_orig,</span><br><span>                          0);</span><br><span>@@ -709,6 +718,12 @@</span><br><span>                   prog_name, (additional_error ? additional_error : ""));</span><br><span>            error_occurred = 1;</span><br><span>  }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (args_info->netns_given && !args_info->createif_given) {</span><br><span style="color: hsl(120, 100%, 40%);">+             fprintf(stderr,</span><br><span style="color: hsl(120, 100%, 40%);">+                       "%s: '--netns' option depends on option 'createif'%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                    prog_name, (additional_error ? additional_error : ""));</span><br><span style="color: hsl(120, 100%, 40%);">+             error_occurred = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span>    if (args_info->pingrate_given && !args_info->pinghost_given) {</span><br><span>                 fprintf(stderr,</span><br><span>                      "%s: '--pingrate' option depends on option 'pinghost'%s\n",</span><br><span>@@ -954,6 +969,7 @@</span><br><span>                  {"ipup", 1, NULL, 0},</span><br><span>                      {"ipdown", 1, NULL, 0},</span><br><span>                    {"tun-device", 1, NULL, 0},</span><br><span style="color: hsl(120, 100%, 40%);">+                 {"netns", 1, NULL, 0},</span><br><span>                     {"pinghost", 1, NULL, 0},</span><br><span>                  {"pingrate", 1, NULL, 0},</span><br><span>                  {"pingsize", 1, NULL, 0},</span><br><span>@@ -1494,6 +1510,22 @@</span><br><span>                                         goto failure;</span><br><span> </span><br><span>                    }</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Network namespace to use.  */</span><br><span style="color: hsl(120, 100%, 40%);">+                      else if (strcmp</span><br><span style="color: hsl(120, 100%, 40%);">+                                (long_options[option_index].name,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "netns") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          args_info->createif_mode_counter += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                           if (update_arg((void *)&(args_info->netns_arg),</span><br><span style="color: hsl(120, 100%, 40%);">+                                               &(args_info->netns_orig),</span><br><span style="color: hsl(120, 100%, 40%);">+                                              &(args_info->netns_given),</span><br><span style="color: hsl(120, 100%, 40%);">+                                             &(local_args_info.netns_given),</span><br><span style="color: hsl(120, 100%, 40%);">+                                           optarg, 0, 0, ARG_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             check_ambiguity, override, 0, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              "netns", '-', additional_error))</span><br><span style="color: hsl(120, 100%, 40%);">+                                     goto failure;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span>                    /* Ping remote host.  */</span><br><span>                     else if (strcmp</span><br><span>                               (long_options[option_index].name,</span><br><span>@@ -1609,11 +1641,12 @@</span><br><span>                 int createif_given[] =</span><br><span>                   { args_info->createif_given, args_info->net_given,</span><br><span>                         args_info->defaultroute_given, args_info->ipup_given,</span><br><span style="color: hsl(0, 100%, 40%);">-                     args_info->ipdown_given, args_info->tun_device_given, -1</span><br><span style="color: hsl(120, 100%, 40%);">+                        args_info->ipdown_given, args_info->tun_device_given,</span><br><span style="color: hsl(120, 100%, 40%);">+                   args_info->netns_given, -1</span><br><span>                };</span><br><span>           const char *createif_desc[] =</span><br><span>                    { "--createif", "--net", "--defaultroute", "--ipup",</span><br><span style="color: hsl(0, 100%, 40%);">-                        "--ipdown", "--tun-device", 0</span><br><span style="color: hsl(120, 100%, 40%);">+                     "--ipdown", "--tun-device", "--netns", 0</span><br><span>               };</span><br><span>           int pinghost_given[] =</span><br><span>                   { args_info->pinghost_given, args_info->pingrate_given,</span><br><span>diff --git a/sgsnemu/cmdline.ggo b/sgsnemu/cmdline.ggo</span><br><span>index 0f415f5..0d074aa 100644</span><br><span>--- a/sgsnemu/cmdline.ggo</span><br><span>+++ b/sgsnemu/cmdline.ggo</span><br><span>@@ -59,6 +59,7 @@</span><br><span> modeoption   "ipup"         - "Script to run after link-up"    string dependon="createif" no        mode="createif"</span><br><span> modeoption   "ipdown"       - "Script to run after link-down"  string dependon="createif" no        mode="createif"</span><br><span> modeoption   "tun-device"   - "Name of the local network interface" string dependon="createif" no   mode="createif"</span><br><span style="color: hsl(120, 100%, 40%);">+modeoption   "netns"        - "Network namespace to use"       string dependon="createif" no        mode="createif"</span><br><span> </span><br><span> modeoption   "pinghost"     - "Ping remote host"               string no                                mode="pinghost"</span><br><span> modeoption   "pingrate"     - "Number of ping req per second"  int default="1" dependon="pinghost" no   mode="pinghost"</span><br><span>diff --git a/sgsnemu/cmdline.h b/sgsnemu/cmdline.h</span><br><span>index 24f772b..c7c8521 100644</span><br><span>--- a/sgsnemu/cmdline.h</span><br><span>+++ b/sgsnemu/cmdline.h</span><br><span>@@ -242,6 +242,12 @@</span><br><span>                           /**< @brief Name of the local network interface original value given at command line.  */</span><br><span>                 const char *tun_device_help;</span><br><span>                                /**< @brief Name of the local network interface help description.  */</span><br><span style="color: hsl(120, 100%, 40%);">+               char *netns_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+                      /**< @brief Network namespace to use.  */</span><br><span style="color: hsl(120, 100%, 40%);">+          char *netns_orig;</span><br><span style="color: hsl(120, 100%, 40%);">+                     /**< @brief Network namespace to use original value given at command line.  */</span><br><span style="color: hsl(120, 100%, 40%);">+             const char *netns_help;</span><br><span style="color: hsl(120, 100%, 40%);">+                         /**< @brief Network namespace to use help description.  */</span><br><span>              char *pinghost_arg;</span><br><span>                  /**< @brief Ping remote host.  */</span><br><span>                 char *pinghost_orig;</span><br><span>@@ -355,6 +361,8 @@</span><br><span>                           /**< @brief Whether ipdown was given.  */</span><br><span>                 unsigned int tun_device_given;</span><br><span>                                       /**< @brief Whether tun-device was given.  */</span><br><span style="color: hsl(120, 100%, 40%);">+              unsigned int netns_given;</span><br><span style="color: hsl(120, 100%, 40%);">+                             /**< @brief Whether netns was given.  */</span><br><span>          unsigned int pinghost_given;</span><br><span>                                 /**< @brief Whether pinghost was given.  */</span><br><span>               unsigned int pingrate_given;</span><br><span>diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c</span><br><span>index 7904c49..2c0ce1b 100644</span><br><span>--- a/sgsnemu/sgsnemu.c</span><br><span>+++ b/sgsnemu/sgsnemu.c</span><br><span>@@ -50,6 +50,7 @@</span><br><span> #include "../lib/tun.h"</span><br><span> #include "../lib/ippool.h"</span><br><span> #include "../lib/syserr.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "../lib/netns.h"</span><br><span> #include "../gtp/pdp.h"</span><br><span> #include "../gtp/gtp.h"</span><br><span> #include "cmdline.h"</span><br><span>@@ -81,12 +82,16 @@</span><br><span> int maxfd = 0;                 /* For select() */</span><br><span> int echoversion = 1;              /* First try this version */</span><br><span> void *tall_sgsnemu_ctx;         /* root talloc ctx */</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+int netns = -1;                  /* network namespace */</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span> /* Struct with local versions of gengetopt options */</span><br><span> struct {</span><br><span>     int debug;              /* Print debug messages */</span><br><span>   int createif;           /* Create local network interface */</span><br><span>         char *tun_dev_name;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *netns;</span><br><span>         struct in46_addr netaddr, destaddr, net;        /* Network interface  */</span><br><span>     size_t prefixlen;</span><br><span>    char *ipup, *ipdown;    /* Filename of scripts */</span><br><span>@@ -294,6 +299,8 @@</span><br><span>              printf("createif: %d\n", args_info.createif_flag);</span><br><span>                 if (args_info.tun_device_arg)</span><br><span>                        printf("tun-device: %s\n", args_info.tun_device_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (args_info.netns_arg)</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("netns: %s\n", args_info.netns_arg);</span><br><span>                if (args_info.ipup_arg)</span><br><span>                      printf("ipup: %s\n", args_info.ipup_arg);</span><br><span>          if (args_info.ipdown_arg)</span><br><span>@@ -352,6 +359,8 @@</span><br><span>                      printf("createif: %d\n", args_info.createif_flag);</span><br><span>                         if (args_info.tun_device_arg)</span><br><span>                                printf("tun-device: %s\n", args_info.tun_device_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (args_info.netns_arg)</span><br><span style="color: hsl(120, 100%, 40%);">+                              printf("netns: %s\n", args_info.netns_arg);</span><br><span>                        if (args_info.ipup_arg)</span><br><span>                              printf("ipup: %s\n", args_info.ipup_arg);</span><br><span>                  if (args_info.ipdown_arg)</span><br><span>@@ -870,6 +879,7 @@</span><br><span>      /* createif */</span><br><span>       options.createif = args_info.createif_flag;</span><br><span>  options.tun_dev_name = args_info.tun_device_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+      options.netns = args_info.netns_arg;</span><br><span> </span><br><span>     /* net                                                          */</span><br><span>   /* Store net as in_addr net and mask                            */</span><br><span>@@ -1313,10 +1323,23 @@</span><br><span> </span><br><span> static int delete_context(struct pdp_t *pdp)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tun && options.ipdown) {</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+          sigset_t oldmask;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (tun && options.ipdown)</span><br><span style="color: hsl(120, 100%, 40%);">+            if ((options.netns)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        switch_ns(netns, &oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>            tun_runscript(tun, options.ipdown);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+               if ((options.netns)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        restore_ns(&oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  ipdel((struct iphash_t *)pdp->peer[0]);</span><br><span>   memset(pdp->peer[0], 0, sizeof(struct iphash_t));    /* To be sure */</span><br><span> </span><br><span>@@ -1377,6 +1400,9 @@</span><br><span> static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)</span><br><span> {</span><br><span>     struct in46_addr addr;</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+        sigset_t oldmask;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>        struct iphash_t *iph = (struct iphash_t *)cbp;</span><br><span> </span><br><span>@@ -1430,6 +1456,12 @@</span><br><span>          break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((options.createif) && (options.netns)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          switch_ns(netns, &oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if ((options.createif) && (!options.net.len)) {</span><br><span>              size_t prefixlen = 32;</span><br><span>               if (addr.len == 16)</span><br><span>@@ -1470,6 +1502,12 @@</span><br><span>                 free(forwarding);</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((options.createif) && (options.netns)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          restore_ns(&oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  ipset(iph, &addr);</span><br><span> </span><br><span>   state = 2;              /* Connected */</span><br><span>@@ -1543,6 +1581,9 @@</span><br><span>      struct timezone tz;     /* Used for calculating ping times */</span><br><span>        struct timeval tv;</span><br><span>   int diff;</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+     sigset_t oldmask;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>        signal(SIGTERM, signal_handler);</span><br><span>     signal(SIGHUP,  signal_handler);</span><br><span>@@ -1552,6 +1593,10 @@</span><br><span>    msgb_talloc_ctx_init(tall_sgsnemu_ctx, 0);</span><br><span>   osmo_init_logging2(tall_sgsnemu_ctx, &log_info);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+      init_netns();</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /* Process options given in configuration file and command line */</span><br><span>   if (process_options(argc, argv))</span><br><span>             exit(1);</span><br><span>@@ -1575,6 +1620,13 @@</span><br><span>    else</span><br><span>                 gtp_set_cb_data_ind(gsn, encaps_ping);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((options.createif) && (options.netns)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          netns = get_nsfd(options.netns);</span><br><span style="color: hsl(120, 100%, 40%);">+              switch_ns(netns, &oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (options.createif) {</span><br><span>              printf("Setting up interface\n");</span><br><span>          /* Create a tunnel interface */</span><br><span>@@ -1600,6 +1652,12 @@</span><br><span>                     tun_runscript(tun, options.ipup);</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__linux__)</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((options.createif) && (options.netns)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          restore_ns(&oldmask);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* Initialise hash tables */</span><br><span>         memset(&iphash, 0, sizeof(iphash));</span><br><span>      memset(&iparr, 0, sizeof(iparr));</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ggsn/+/17253">change 17253</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-ggsn/+/17253"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-ggsn </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Idd0ad8fa9c8e7ba0aeec1b52947598d4d297b620 </div>
<div style="display:none"> Gerrit-Change-Number: 17253 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>