aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/netns.c142
-rw-r--r--lib/netns.h4
-rw-r--r--sgsnemu/sgsnemu.c51
3 files changed, 132 insertions, 65 deletions
diff --git a/lib/netns.c b/lib/netns.c
index 6734b5d..bd2076b 100644
--- a/lib/netns.c
+++ b/lib/netns.c
@@ -49,99 +49,133 @@ static int default_nsfd;
int switch_ns(int nsfd, sigset_t *oldmask)
{
sigset_t intmask;
+ int rc;
- sigfillset(&intmask);
- sigprocmask(SIG_BLOCK, &intmask, oldmask);
+ if (sigfillset(&intmask) < 0)
+ return -errno;
+ if ((rc = sigprocmask(SIG_BLOCK, &intmask, oldmask)) != 0)
+ return -rc;
- return setns(nsfd, CLONE_NEWNET);
+ if (setns(nsfd, CLONE_NEWNET) < 0)
+ return -errno;
+ return 0;
}
-void restore_ns(sigset_t *oldmask)
+int restore_ns(sigset_t *oldmask)
{
- setns(default_nsfd, CLONE_NEWNET);
+ int rc;
+ if (setns(default_nsfd, CLONE_NEWNET) < 0)
+ return -errno;
- sigprocmask(SIG_SETMASK, oldmask, NULL);
+ if ((rc = sigprocmask(SIG_SETMASK, oldmask, NULL)) != 0)
+ return -rc;
+ return 0;
}
int open_ns(int nsfd, const char *pathname, int flags)
{
sigset_t intmask, oldmask;
int fd;
- int errsv;
-
- sigfillset(&intmask);
- sigprocmask(SIG_BLOCK, &intmask, &oldmask);
-
- setns(nsfd, CLONE_NEWNET);
- fd = open(pathname, flags);
- errsv = errno;
- setns(default_nsfd, CLONE_NEWNET);
-
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ int rc;
+
+ if (sigfillset(&intmask) < 0)
+ return -errno;
+ if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
+ return -rc;
+
+ if (setns(nsfd, CLONE_NEWNET) < 0)
+ return -errno;
+ if ((fd = open(pathname, flags)) < 0)
+ return -errno;
+ if (setns(default_nsfd, CLONE_NEWNET) < 0) {
+ close(fd);
+ return -errno;
+ }
+ if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) {
+ close(fd);
+ return -rc;
+ }
- errno = errsv;
- return fd;
+ return 0;
}
int socket_ns(int nsfd, int domain, int type, int protocol)
{
sigset_t intmask, oldmask;
int sk;
- int errsv;
-
- sigfillset(&intmask);
- sigprocmask(SIG_BLOCK, &intmask, &oldmask);
-
- setns(nsfd, CLONE_NEWNET);
- sk = socket(domain, type, protocol);
- errsv = errno;
- setns(default_nsfd, CLONE_NEWNET);
-
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ int rc;
+
+ if (sigfillset(&intmask) < 0)
+ return -errno;
+ if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
+ return -rc;
+
+ if (setns(nsfd, CLONE_NEWNET) < 0)
+ return -errno;
+ if ((sk = socket(domain, type, protocol)) < 0)
+ return -errno;
+ if (setns(default_nsfd, CLONE_NEWNET) < 0) {
+ close(sk);
+ return -errno;
+ }
- errno = errsv;
+ if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) {
+ close(sk);
+ return -rc;
+ }
return sk;
}
-void init_netns()
+int init_netns()
{
- if ((default_nsfd = open("/proc/self/ns/net", O_RDONLY)) < 0) {
- perror("init_netns");
- exit(EXIT_FAILURE);
- }
+ if ((default_nsfd = open("/proc/self/ns/net", O_RDONLY)) < 0)
+ return -errno;
+ return 0;
}
int get_nsfd(const char *name)
{
- int r;
+ int rc;
+ int fd;
sigset_t intmask, oldmask;
char path[MAXPATHLEN] = NETNS_PATH;
- r = mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
- if (r < 0 && errno != EEXIST)
- return r;
+ rc = mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+ if (rc < 0 && errno != EEXIST)
+ return rc;
snprintf(path, sizeof(path), "%s/%s", NETNS_PATH, name);
- r = open(path, O_RDONLY|O_CREAT|O_EXCL, 0);
- if (r < 0) {
- if (errno == EEXIST)
- return open(path, O_RDONLY);
-
- return r;
+ fd = open(path, O_RDONLY|O_CREAT|O_EXCL, 0);
+ if (fd < 0) {
+ if (errno == EEXIST) {
+ if ((fd = open(path, O_RDONLY)) < 0)
+ return -errno;
+ return fd;
+ }
+ return -errno;
}
- close(r);
+ if (close(fd) < 0)
+ return -errno;
- sigfillset(&intmask);
- sigprocmask(SIG_BLOCK, &intmask, &oldmask);
+ if (sigfillset(&intmask) < 0)
+ return -errno;
+ if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
+ return -rc;
- unshare(CLONE_NEWNET);
- mount("/proc/self/ns/net", path, "none", MS_BIND, NULL);
+ if (unshare(CLONE_NEWNET) < 0)
+ return -errno;
+ if (mount("/proc/self/ns/net", path, "none", MS_BIND, NULL) < 0)
+ return -errno;
- setns(default_nsfd, CLONE_NEWNET);
+ if (setns(default_nsfd, CLONE_NEWNET) < 0)
+ return -errno;
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0)
+ return -rc;
- return open(path, O_RDONLY);
+ if ((fd = open(path, O_RDONLY)) < 0)
+ return -errno;
+ return fd;
}
#endif
diff --git a/lib/netns.h b/lib/netns.h
index 168e44f..3b91ba3 100644
--- a/lib/netns.h
+++ b/lib/netns.h
@@ -21,10 +21,10 @@
#if defined(__linux__)
-void init_netns(void);
+int init_netns(void);
int switch_ns(int nsfd, sigset_t *oldmask);
-void restore_ns(sigset_t *oldmask);
+int restore_ns(sigset_t *oldmask);
int open_ns(int nsfd, const char *pathname, int flags);
int socket_ns(int nsfd, int domain, int type, int protocol);
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 2c0ce1b..fce5059 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -1323,19 +1323,29 @@ static int create_ping(void *gsn, struct pdp_t *pdp,
static int delete_context(struct pdp_t *pdp)
{
+ int rc;
+
if (tun && options.ipdown) {
#if defined(__linux__)
sigset_t oldmask;
if ((options.netns)) {
- switch_ns(netns, &oldmask);
+ if ((rc = switch_ns(netns, &oldmask)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0,
+ "Failed to switch to netns %s: %s\n",
+ options.netns, strerror(-rc));
+ }
}
#endif
tun_runscript(tun, options.ipdown);
#if defined(__linux__)
if ((options.netns)) {
- restore_ns(&oldmask);
+ if ((rc = restore_ns(&oldmask)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0,
+ "Failed to switch to original netns: %s\n",
+ strerror(-rc));
+ }
}
#endif
}
@@ -1399,6 +1409,7 @@ 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)
{
+ int rc;
struct in46_addr addr;
#if defined(__linux__)
sigset_t oldmask;
@@ -1458,7 +1469,11 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
#if defined(__linux__)
if ((options.createif) && (options.netns)) {
- switch_ns(netns, &oldmask);
+ if ((rc = switch_ns(netns, &oldmask)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0,
+ "Failed to switch to netns %s: %s\n",
+ options.netns, strerror(-rc));
+ }
}
#endif
@@ -1504,7 +1519,10 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
#if defined(__linux__)
if ((options.createif) && (options.netns)) {
- restore_ns(&oldmask);
+ if ((rc = restore_ns(&oldmask)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to switch to original netns: %s\n",
+ strerror(-rc));
+ }
}
#endif
@@ -1572,7 +1590,7 @@ int main(int argc, char **argv)
fd_set fds; /* For select() */
struct timeval idleTime; /* How long to select() */
struct pdp_t *pdp;
- int n;
+ int n, rc;
int starttime = time(NULL); /* Time program was started */
int stoptime = 0; /* Time to exit */
int pingtimeout = 0; /* Time to print ping statistics */
@@ -1594,7 +1612,10 @@ int main(int argc, char **argv)
osmo_init_logging2(tall_sgsnemu_ctx, &log_info);
#if defined(__linux__)
- init_netns();
+ if ((rc = init_netns()) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to initialize netns: %s", strerror(-rc));
+ exit(1);
+ }
#endif
/* Process options given in configuration file and command line */
@@ -1622,8 +1643,16 @@ int main(int argc, char **argv)
#if defined(__linux__)
if ((options.createif) && (options.netns)) {
- netns = get_nsfd(options.netns);
- switch_ns(netns, &oldmask);
+ if ((netns = get_nsfd(options.netns)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to obtain fd for netns %s: %s\n",
+ options.netns, strerror(-netns));
+ exit(1);
+ }
+ if ((rc = switch_ns(netns, &oldmask)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to switch to netns %s: %s\n",
+ options.netns, strerror(-rc));
+ exit(1);
+ }
}
#endif
@@ -1654,7 +1683,11 @@ int main(int argc, char **argv)
#if defined(__linux__)
if ((options.createif) && (options.netns)) {
- restore_ns(&oldmask);
+ if ((rc = restore_ns(&oldmask)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to switch to original netns: %s\n",
+ strerror(-rc));
+ exit(1);
+ }
}
#endif