Add network configuration for the 'vs' interface
authorJagger <robert@swiecki.net>
Mon, 29 Feb 2016 01:51:55 +0000 (02:51 +0100)
committerJagger <robert@swiecki.net>
Mon, 29 Feb 2016 01:51:55 +0000 (02:51 +0100)
cmdline.c
common.h
contain.c
net.c
net.h

index c245f068e482ab07d59eec5b92a390ea75f2ce64..a5af039f95f3a5b1467e85bbc8242319842bd337 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -283,7 +283,10 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                .tmpfs_size = 4 * (1024 * 1024),
                .mount_proc = true,
                .iface = NULL,
-               .iface_lo_up = false,
+               .iface_no_lo = false,
+               .iface_vs_ip = "192.168.255.2",
+               .iface_vs_nm = "255.255.255.0",
+               .iface_vs_gw = "192.168.255.1",
                .sbinip_fd = -1,
        };
        /*  *INDENT-OFF* */
@@ -346,10 +349,13 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                {{"bindmount_ro", required_argument, NULL, 'R'}, "List of mountpoints to be mounted --bind (ro) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
                {{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
                {{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"},
-               {{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVTAP) and put inside the subprocess' namespace"},
-               {{"iface_lo_up", no_argument, NULL, 0x700}, "Bring up the 'lo' interface"},
                {{"tmpfs_size", required_argument, NULL, 0x0602}, "Number of bytes to allocate for tmpfsmounts (default: 4194304)"},
                {{"disable_proc", no_argument, NULL, 0x0603}, "Disable mounting /proc in the jail"},
+               {{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVTAP) and put inside the subprocess' namespace as 'vs'"},
+               {{"iface_no_lo", no_argument, NULL, 0x700}, "Don't Bring up the 'lo' interface"},
+               {{"iface_vs_ip", required_argument, NULL, 0x701}, "IP of the 'vs' interface"},
+               {{"iface_vs_nm", required_argument, NULL, 0x702}, "Netmask of the 'vs' interface"},
+               {{"iface_vs_gw", required_argument, NULL, 0x703}, "Default GW for the 'vs' interface"},
                {{0, 0, 0, 0}, NULL},
        };
         /*  *INDENT-ON* */
@@ -558,7 +564,16 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                        nsjconf->iface = optarg;
                        break;
                case 0x700:
-                       nsjconf->iface_lo_up = true;
+                       nsjconf->iface_no_lo = true;
+                       break;
+               case 0x701:
+                       nsjconf->iface_vs_ip = optarg;
+                       break;
+               case 0x702:
+                       nsjconf->iface_vs_nm = optarg;
+                       break;
+               case 0x703:
+                       nsjconf->iface_vs_gw = optarg;
                        break;
                default:
                        cmdlineUsage(argv[0], custom_opts);
index 311cba71bc54045649679b709c664694a602a73f..2be3814c069fb35a43da1f4eba217fba6e0103ff 100644 (file)
--- a/common.h
+++ b/common.h
@@ -99,7 +99,10 @@ struct nsjconf_t {
        size_t tmpfs_size;
        bool mount_proc;
        char *iface;
-       bool iface_lo_up;
+       bool iface_no_lo;
+       const char *iface_vs_ip;
+       const char *iface_vs_nm;
+       const char *iface_vs_gw;
        int sbinip_fd;
         TAILQ_HEAD(envlist, charptr_t) envs;
         TAILQ_HEAD(pidslist, pids_t) pids;
index 082f41424f5e705ed63bcb101f91b9d189e11a63..5d64e96f8add520cb86622db54c8797ebaa966d5 100644 (file)
--- a/contain.c
+++ b/contain.c
 
 bool containInitNetNs(struct nsjconf_t * nsjconf)
 {
-       if (nsjconf->iface_lo_up) {
+       if (nsjconf->iface_no_lo == false) {
                if (netIfaceUp("lo") == false) {
                        return false;
                }
        }
+       if (nsjconf->iface) {
+               if (netConfigureVs(nsjconf) == false) {
+                       return false;
+               }
+       }
+
        return true;
 }
 
diff --git a/net.c b/net.c
index f24d4b05ec5fe6aab8e5f60d67096953e380aebd..8e5b1ee3cbfec9c21a88a712686c5d1f28ee692a 100644 (file)
--- a/net.c
+++ b/net.c
 #include <arpa/inet.h>
 #include <errno.h>
 #include <net/if.h>
+#include <net/route.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
 #include <sched.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
 #include <sys/ioctl.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
@@ -85,7 +86,8 @@ static bool netSystemSbinIp(struct nsjconf_t *nsjconf, char *const *argv)
        }
 }
 
-bool netCloneMacVtapAndNS(struct nsjconf_t * nsjconf, int pid)
+#define IFACE_NAME "vs"
+bool netCloneMacVtapAndNS(struct nsjconf_t *nsjconf, int pid)
 {
        if (nsjconf->iface == NULL) {
                return true;
@@ -104,7 +106,7 @@ bool netCloneMacVtapAndNS(struct nsjconf_t * nsjconf, int pid)
        char pid_str[256];
        snprintf(pid_str, sizeof(pid_str), "%d", pid);
        char *const argv_netns[] =
-           { "ip", "link", "set", "dev", iface, "netns", pid_str, "name", "virt.ns",
+           { "ip", "link", "set", "dev", iface, "netns", pid_str, "name", IFACE_NAME,
                NULL
        };
        if (netSystemSbinIp(nsjconf, argv_netns) == false) {
@@ -274,7 +276,7 @@ bool netIfaceUp(const char *ifacename)
        snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename);
 
        if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
-               PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP", ifacename);
+               PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename);
                close(sock);
                return false;
        }
@@ -282,7 +284,81 @@ bool netIfaceUp(const char *ifacename)
        ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
 
        if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
-               PLOG_E("ioctl(iface='%s', SIOCSIFFLAGS, IFF_UP", ifacename);
+               PLOG_E("ioctl(iface='%s', SIOCSIFFLAGS, IFF_UP)", ifacename);
+               close(sock);
+               return false;
+       }
+
+       close(sock);
+       return true;
+}
+
+bool netConfigureVs(struct nsjconf_t * nsjconf)
+{
+       struct ifreq ifr;
+       snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", IFACE_NAME);
+       struct in_addr addr;
+
+       int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+       if (sock == -1) {
+               PLOG_E("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)");
+               return false;
+       }
+
+       if (inet_pton(AF_INET, nsjconf->iface_vs_ip, &addr) != 1) {
+               PLOG_E("Cannot convert '%s' into an IPv4 address", nsjconf->iface_vs_ip);
+               close(sock);
+               return false;
+       }
+       struct sockaddr_in *sa = (struct sockaddr_in *)(&ifr.ifr_addr);
+       sa->sin_family = AF_INET;
+       sa->sin_addr = addr;
+       if (ioctl(sock, SIOCSIFADDR, &ifr) == -1) {
+               PLOG_E("ioctl(iface='%s', SIOCSIFADDR, '%s')", IFACE_NAME, nsjconf->iface_vs_ip);
+               close(sock);
+               return false;
+       }
+
+       if (inet_pton(AF_INET, nsjconf->iface_vs_nm, &addr) != 1) {
+               PLOG_E("Cannot convert '%s' into an IPv4 netmask", nsjconf->iface_vs_nm);
+               close(sock);
+               return false;
+       }
+       sa->sin_family = AF_INET;
+       sa->sin_addr = addr;
+       if (ioctl(sock, SIOCSIFNETMASK, &ifr) == -1) {
+               PLOG_E("ioctl(iface='%s', SIOCSIFNETMASK, '%s')", IFACE_NAME, nsjconf->iface_vs_nm);
+               close(sock);
+               return false;
+       }
+
+       if (netIfaceUp(IFACE_NAME) == false) {
+               return false;
+       }
+
+       if (inet_pton(AF_INET, nsjconf->iface_vs_gw, &addr) != 1) {
+               PLOG_E("Cannot convert '%s' into an IPv4 GW address", nsjconf->iface_vs_gw);
+               close(sock);
+               return false;
+       }
+
+       struct rtentry rt;
+       memset(&rt, '\0', sizeof(rt));
+
+       struct sockaddr_in *sdest = (struct sockaddr_in *)(&rt.rt_dst);
+       struct sockaddr_in *smask = (struct sockaddr_in *)(&rt.rt_genmask);
+       struct sockaddr_in *sgate = (struct sockaddr_in *)(&rt.rt_gateway);
+       sdest->sin_family = AF_INET;
+       sdest->sin_addr.s_addr = INADDR_ANY;
+       smask->sin_family = AF_INET;
+       smask->sin_addr.s_addr = INADDR_ANY;
+       sgate->sin_family = AF_INET;
+       sgate->sin_addr = addr;
+
+       rt.rt_flags = RTF_UP | RTF_GATEWAY;
+
+       if (ioctl(sock, SIOCADDRT, &rt) == -1) {
+               PLOG_E("ioctl(SIOCADDRT, '%s')", nsjconf->iface_vs_gw);
                close(sock);
                return false;
        }
diff --git a/net.h b/net.h
index 77b1df4bdbe89a8516eeadb6f2576284890f86c1..edb54045eabe65816b18555345da0e46adf23c37 100644 (file)
--- a/net.h
+++ b/net.h
@@ -32,5 +32,6 @@ int netGetRecvSocket(const char *bindhost, int port);
 int netAcceptConn(int listenfd);
 void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6 *addr_or_null);
 bool netIfaceUp(const char *ifacename);
+bool netConfigureVs(struct nsjconf_t *nsjconf);
 
 #endif                         /* _NET_H */