]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
netdev_move_by_index: support wlan
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 15 Oct 2014 14:20:45 +0000 (16:20 +0200)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 15 Oct 2014 21:22:41 +0000 (23:22 +0200)
The python lxc-device supported adding wlan devices, so add that
support as well.  Since the python one did not support 'del',
I didn't try adding that support, though it should be trivial to
add.

We should be able to do the wlan adding using netlink, but I
went ahead and used 'iw' as the netlink path looked more
complicated than it does for other nics.  Patches to switch that
over would be very welcome.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
src/lxc/lxccontainer.c
src/lxc/network.c

index 8cafdae5083b1f51a3fe74a0ee18c10065a66826..1f1f9ea904a80698b158ce03fd84c62fd3b1bd97 100644 (file)
@@ -3442,11 +3442,9 @@ static bool lxcapi_attach_interface(struct lxc_container *c, const char *ifname,
        }
 
        ret = lxc_netdev_isup(ifname);
-       if (ret < 0)
-               goto err;
 
-       /* netdev of ifname is up. */
-       if (ret) {
+       if (ret > 0) {
+               /* netdev of ifname is up. */
                ret = lxc_netdev_down(ifname);
                if (ret)
                        goto err;
@@ -3457,11 +3455,8 @@ static bool lxcapi_attach_interface(struct lxc_container *c, const char *ifname,
                goto err;
 
        return true;
+
 err:
-       /* -EINVAL means there is no netdev named as ifanme. */
-       if (ret == -EINVAL) {
-               ERROR("No network device named as %s.", ifname);
-       }
        return false;
 }
 
index 941cb35e466fa52d9f8ad8045f8617dfaeb7096e..136e4e06da89923d2e40da39bca24f3ade268e43 100644 (file)
@@ -141,9 +141,116 @@ out:
        return err;
 }
 
+/*
+ * If we are asked to move a wireless interface, then
+ * we must actually move its phyN device.  Detect
+ * that condition and return the physname here.  The
+ * physname will be passed to lxc_netdev_move_wlan()
+ * which will free it when done
+ */
+#define PHYSNAME "/sys/class/net/%s/phy80211/name"
+static char * is_wlan(const char *ifname)
+{
+       char *path, *physname = NULL;
+       size_t len = strlen(ifname) + strlen(PHYSNAME) - 1;
+       struct stat sb;
+       long physlen;
+       FILE *f;
+       int ret, i;
+
+       path = alloca(len+1);
+       ret = snprintf(path, len, PHYSNAME, ifname);
+       if (ret < 0 || ret >= len)
+               goto bad;
+       ret = stat(path, &sb);
+       if (ret)
+               goto bad;
+       if (!(f = fopen(path, "r")))
+               goto bad;
+       // feh - sb.st_size is always 4096
+       fseek(f, 0, SEEK_END);
+       physlen = ftell(f);
+       fseek(f, 0, SEEK_SET);
+       physname = malloc(physlen+1);
+       if (!physname)
+               goto bad;
+       memset(physname, 0, physlen+1);
+       ret = fread(physname, 1, physlen, f);
+       fclose(f);
+       if (ret < 0)
+               goto bad;
+
+       for (i = 0;  i < physlen; i++) {
+               if (physname[i] == '\n')
+                       physname[i] = '\0';
+               if (physname[i] == '\0')
+                       break;
+       }
+
+       return physname;
+
+bad:
+       if (physname)
+               free(physname);
+       return NULL;
+}
+
+static int
+lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old, const char *new)
+{
+       pid_t fpid = fork();
+
+       if (fpid < 0)
+               return -1;
+       if (fpid != 0)
+               return wait_for_pid(fpid);
+       if (!switch_to_ns(pid, "net"))
+               return -1;
+       exit(lxc_netdev_rename_by_name(old, new));
+}
+
+static int
+lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid, const char* newname)
+{
+       int err = -1;
+       pid_t fpid;
+       char *cmd;
+
+       /* Move phyN into the container.  TODO - do this using netlink.
+        * However, IIUC this involves a bit more complicated work to
+        * talk to the 80211 module, so for now just call out to iw
+        */
+       cmd = on_path("iw", NULL);
+       if (!cmd)
+               goto out1;
+       free(cmd);
+
+       fpid = fork();
+       if (fpid < 0)
+               goto out1;
+       if (fpid == 0) {
+               char pidstr[30];
+               sprintf(pidstr, "%d", pid);
+               if (execlp("iw", "iw", "phy", physname, "set", "netns", pidstr, NULL))
+                       exit(1);
+               exit(0); // notreached
+       }
+       if (wait_for_pid(fpid))
+               goto out1;
+
+       err = 0;
+       if (newname)
+               err = lxc_netdev_rename_by_name_in_netns(pid, ifname, newname);
+
+out1:
+       free(physname);
+       return err;
+}
+
 int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname)
 {
        int index;
+       char *physname;
 
        if (!ifname)
                return -EINVAL;
@@ -152,6 +259,9 @@ int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname)
        if (!index)
                return -EINVAL;
 
+       if ((physname = is_wlan(ifname)))
+               return lxc_netdev_move_wlan(physname, ifname, pid, newname);
+
        return lxc_netdev_move_by_index(index, pid, newname);
 }