pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-uecups/+/42442?usp=email )


Change subject: Use libosmocore netns API
......................................................................

Use libosmocore netns API

Change-Id: Ia8617765d4c14483e2ad0ea09a8f2276fd7aaebf
---
M daemon/Makefile.am
M daemon/cups_client.c
M daemon/internal.h
M daemon/main.c
D daemon/netns.c
D daemon/netns.h
M daemon/tun_device.c
7 files changed, 10 insertions(+), 324 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-uecups refs/changes/42/42442/1

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 2d62f11..1c680a6 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -27,7 +27,6 @@

 noinst_HEADERS = \
        gtp.h \
-       netns.h \
        internal.h \
        $(NULL)

@@ -39,7 +38,6 @@
        cups_client.c \
        utility.c \
        netdev.c \
-       netns.c \
        tun_device.c \
        gtp_daemon.c \
        gtp_endpoint.c \
diff --git a/daemon/cups_client.c b/daemon/cups_client.c
index e2bae46..578719b 100644
--- a/daemon/cups_client.c
+++ b/daemon/cups_client.c
@@ -13,6 +13,7 @@
 #include <osmocom/core/talloc.h>
 #include <osmocom/core/logging.h>
 #include <osmocom/core/exec.h>
+#include <osmocom/core/netns.h>

 #include "internal.h"
 #include "gtp.h"
@@ -405,7 +406,7 @@
        struct gtp_daemon *d = cc->d;
        const char *cmd, *user;
        char **addl_env = NULL;
-       sigset_t oldmask;
+       struct osmo_netns_switch_state switch_state;
        int nsfd = -1, rc;

        juser = json_object_get(sprog, "run_as_user");
@@ -447,7 +448,7 @@
        }

        if (jnetns) {
-               rc = switch_ns(nsfd, &oldmask);
+               rc = osmo_netns_switch_enter(nsfd, &switch_state);
                if (rc < 0) {
                        talloc_free(addl_env);
                        return -EIO;
@@ -457,7 +458,7 @@
        rc = osmo_system_nowait2(cmd, osmo_environment_whitelist, addl_env, 
user);

        if (jnetns) {
-               OSMO_ASSERT(restore_ns(&oldmask) == 0);
+               OSMO_ASSERT(osmo_netns_switch_exit(&switch_state) == 0);
        }

        talloc_free(addl_env);
diff --git a/daemon/internal.h b/daemon/internal.h
index d431add..7a016fa 100644
--- a/daemon/internal.h
+++ b/daemon/internal.h
@@ -1,8 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #pragma once

-#include "netns.h"
-
 #include <stdint.h>
 #include <stdbool.h>
 #include <pthread.h>
diff --git a/daemon/main.c b/daemon/main.c
index c023351..b00e5d3 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -36,7 +36,6 @@
 #include <jansson.h>

 #include "internal.h"
-#include "netns.h"
 #include "gtp.h"

 static void *g_tall_ctx;
@@ -226,8 +225,6 @@

        handle_options(argc, argv);

-       init_netns();
-
        rc = vty_read_config_file(g_config_file, NULL);
        if (rc < 0) {
                fprintf(stderr, "Failed to open config file: '%s'\n", 
g_config_file);
diff --git a/daemon/netns.c b/daemon/netns.c
deleted file mode 100644
index b0ec254..0000000
--- a/daemon/netns.c
+++ /dev/null
@@ -1,273 +0,0 @@
-#warning "Merge netns.c from osmo-ggsn and osmo-gtpu-daemon"
-/*
- * Copyright (C) 2014-2017, Travelping GmbH <[email protected]>
- * Copyright (C) 2020, Harald Welte <[email protected]>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#if defined(__linux__)
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sched.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/mount.h>
-#include <sys/param.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <osmocom/core/utils.h>
-
-#include "netns.h"
-
-#define NETNS_PATH "/var/run/netns"
-
-/*! default namespace of the GGSN process */
-static int default_nsfd = -1;
-
-/*! switch to a (non-default) namespace, store existing signal mask in oldmask.
- *  \param[in] nsfd file descriptor representing the namespace to whch we 
shall switch
- *  \param[out] oldmaks caller-provided memory location to which old signal 
mask is stored
- *  \ returns 0 on success or negative (errno) in case of error */
-int switch_ns(int nsfd, sigset_t *oldmask)
-{
-       sigset_t intmask;
-       int rc;
-
-       OSMO_ASSERT(default_nsfd >= 0);
-
-       if (sigfillset(&intmask) < 0)
-               return -errno;
-       if ((rc = sigprocmask(SIG_BLOCK, &intmask, oldmask)) != 0)
-               return -rc;
-
-       if (setns(nsfd, CLONE_NEWNET) < 0) {
-               /* restore old mask if we couldn't switch the netns */
-               sigprocmask(SIG_SETMASK, oldmask, NULL);
-               return -errno;
-       }
-       return 0;
-}
-
-/*! switch back to the default namespace, restoring signal mask.
- *  \param[in] oldmask signal mask to restore after returning to default 
namespace
- *  \returns 0 on successs; negative errno value in case of error */
-int restore_ns(sigset_t *oldmask)
-{
-       OSMO_ASSERT(default_nsfd >= 0);
-
-       int rc;
-       if (setns(default_nsfd, CLONE_NEWNET) < 0)
-               return -errno;
-
-       if ((rc = sigprocmask(SIG_SETMASK, oldmask, NULL)) != 0)
-               return -rc;
-       return 0;
-}
-
-/*! open a file from within specified network namespace */
-int open_ns(int nsfd, const char *pathname, int flags)
-{
-       sigset_t intmask, oldmask;
-       int ret;
-       int fd = -1;
-       int rc;
-
-       OSMO_ASSERT(default_nsfd >= 0);
-
-       /* mask off all signals, store old signal mask */
-       if (sigfillset(&intmask) < 0)
-               return -errno;
-       if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
-               return -rc;
-
-       /* associate the calling thread with namespace file descriptor */
-       if (setns(nsfd, CLONE_NEWNET) < 0) {
-               ret = -errno;
-               goto restore_sigmask;
-       }
-       /* open the requested file/path */
-       if ((fd = open(pathname, flags)) < 0) {
-               ret = -errno;
-               goto restore_defaultns;
-       }
-       ret = fd;
-
-restore_defaultns:
-       /* return back to default namespace */
-       if (setns(default_nsfd, CLONE_NEWNET) < 0) {
-               if (fd >= 0)
-                       close(fd);
-               return -errno;
-       }
-
-restore_sigmask:
-       /* restore process mask */
-       if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) {
-               if (fd >= 0)
-                       close(fd);
-               return -rc;
-       }
-
-       return ret;
-}
-
-/*! create a socket in another namespace.
- *  Switches temporarily to namespace indicated by nsfd, creates a socket in
- *  that namespace and then returns to the default namespace.
- *  \param[in] nsfd File descriptor of the namspace in which to create socket
- *  \param[in] domain Domain of the socket (AF_INET, ...)
- *  \param[in] type Type of the socket (SOCK_STREAM, ...)
- *  \param[in] protocol Protocol of the socket (IPPROTO_TCP, ...)
- *  \returns 0 on success; negative errno in case of error */
-int socket_ns(int nsfd, int domain, int type, int protocol)
-{
-       sigset_t intmask, oldmask;
-       int ret;
-       int sk = -1;
-       int rc;
-
-       OSMO_ASSERT(default_nsfd >= 0);
-
-       /* mask off all signals, store old signal mask */
-       if (sigfillset(&intmask) < 0)
-               return -errno;
-       if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
-               return -rc;
-
-       /* associate the calling thread with namespace file descriptor */
-       if (setns(nsfd, CLONE_NEWNET) < 0) {
-               ret = -errno;
-               goto restore_sigmask;
-       }
-
-       /* create socket of requested domain/type/proto */
-       if ((sk = socket(domain, type, protocol)) < 0) {
-               ret = -errno;
-               goto restore_defaultns;
-       }
-       ret = sk;
-
-restore_defaultns:
-       /* return back to default namespace */
-       if (setns(default_nsfd, CLONE_NEWNET) < 0) {
-               if (sk >= 0)
-                       close(sk);
-               return -errno;
-       }
-
-restore_sigmask:
-       /* restore process mask */
-       if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) {
-               if (sk >= 0)
-                       close(sk);
-               return -rc;
-       }
-       return ret;
-}
-
-/*! initialize this network namespace helper module.
- *  Must be called before using any other functions of this file.
- *  \returns 0 on success; negative errno in case of error */
-int init_netns()
-{
-       /* store the default namespace for later reference */
-       if ((default_nsfd = open("/proc/self/ns/net", O_RDONLY)) < 0)
-               return -errno;
-       return 0;
-}
-
-/*! create obtain file descriptor for network namespace of give name.
- *  Creates /var/run/netns  if it doesn't exist already.
- *  \param[in] name Name of the network namespace (in /var/run/netns/)
- *  \returns File descriptor of network namespace; negative errno in case of 
error */
-int get_nsfd(const char *name)
-{
-       int ret = 0;
-       int rc;
-       int fd;
-       sigset_t intmask, oldmask;
-       char path[MAXPATHLEN] = NETNS_PATH;
-
-       OSMO_ASSERT(default_nsfd >= 0);
-
-       /* create /var/run/netns, if it doesn't exist already */
-       rc = mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-       if (rc < 0 && errno != EEXIST)
-               return rc;
-
-       /* create /var/run/netns/[name], if it doesn't exist already */
-       snprintf(path, sizeof(path), "%s/%s", NETNS_PATH, name);
-       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;
-       }
-       if (close(fd) < 0)
-               return -errno;
-
-       /* mask off all signals, store old signal mask */
-       if (sigfillset(&intmask) < 0)
-               return -errno;
-       if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
-               return -rc;
-
-       /* create a new network namespace */
-       if (unshare(CLONE_NEWNET) < 0) {
-               ret = -errno;
-               goto restore_sigmask;
-       }
-       if (mount("/proc/self/ns/net", path, "none", MS_BIND, NULL) < 0)
-               ret = -errno;
-
-       /* switch back to default namespace */
-       if (setns(default_nsfd, CLONE_NEWNET) < 0)
-               return -errno;
-
-restore_sigmask:
-       /* restore process mask */
-       if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0)
-               return -rc;
-
-       /* might have been set above in case mount fails */
-       if (ret < 0)
-               return ret;
-
-       /* finally, open the created namespace file descriptor from default ns 
*/
-       if ((fd = open(path, O_RDONLY)) < 0)
-               return -errno;
-
-       return fd;
-}
-
-#endif
diff --git a/daemon/netns.h b/daemon/netns.h
deleted file mode 100644
index 3b91ba3..0000000
--- a/daemon/netns.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2014-2017, Travelping GmbH <[email protected]>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef __NETNS_H
-#define __NETNS_H
-
-#if defined(__linux__)
-
-int init_netns(void);
-
-int switch_ns(int nsfd, 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);
-int get_nsfd(const char *name);
-
-#endif
-
-#endif
diff --git a/daemon/tun_device.c b/daemon/tun_device.c
index bc41db9..837fd9d 100644
--- a/daemon/tun_device.c
+++ b/daemon/tun_device.c
@@ -33,11 +33,11 @@
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/talloc.h>
 #include <osmocom/core/logging.h>
+#include <osmocom/core/netns.h>
 #include <osmocom/core/utils.h>

 #include "gtp.h"
 #include "internal.h"
-#include "netns.h"

 /***********************************************************************
  * TUN Device
@@ -320,7 +320,7 @@
 {
        struct rtnl_link *link;
        struct tun_device *tun;
-       sigset_t oldmask;
+       struct osmo_netns_switch_state switch_state;
        int rc;

        tun = talloc_zero(d, struct tun_device);
@@ -333,7 +333,7 @@

        if (netns_name) {
                tun->netns_name = talloc_strdup(tun, netns_name);
-               tun->netns_fd = get_nsfd(tun->netns_name);
+               tun->netns_fd = osmo_netns_open_fd(tun->netns_name);
                if (tun->netns_fd < 0) {
                        LOGTUN(tun, LOGL_ERROR, "Cannot obtain netns file 
descriptor: %s\n",
                                strerror(errno));
@@ -343,7 +343,7 @@

        /* temporarily switch to specified namespace to create tun device */
        if (tun->netns_name) {
-               rc = switch_ns(tun->netns_fd, &oldmask);
+               rc = osmo_netns_switch_enter(tun->netns_fd, &switch_state);
                if (rc < 0) {
                        LOGTUN(tun, LOGL_ERROR, "Cannot switch to netns '%s': 
%s\n",
                                tun->netns_name, strerror(errno));
@@ -374,7 +374,7 @@

        /* switch back to default namespace before creating new thread */
        if (tun->netns_name)
-               OSMO_ASSERT(restore_ns(&oldmask) == 0);
+               OSMO_ASSERT(osmo_netns_switch_exit(&switch_state) == 0);

        /* bring the network device up */
        rc = netdev_set_link(tun->nl, tun->ifindex, true);
@@ -413,7 +413,7 @@
        close(tun->fd);
 err_restore_ns:
        if (tun->netns_name)
-               OSMO_ASSERT(restore_ns(&oldmask) == 0);
+               OSMO_ASSERT(osmo_netns_switch_exit(&switch_state) == 0);
 err_close_ns:
        if (tun->netns_name)
                close(tun->netns_fd);

--
To view, visit https://gerrit.osmocom.org/c/osmo-uecups/+/42442?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmo-uecups
Gerrit-Branch: master
Gerrit-Change-Id: Ia8617765d4c14483e2ad0ea09a8f2276fd7aaebf
Gerrit-Change-Number: 42442
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>

Reply via email to