netdev_move_by_index: support wlan

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>
This commit is contained in:
Serge Hallyn 2014-10-15 16:20:45 +02:00
parent e0f5918984
commit e5848d395c
2 changed files with 113 additions and 8 deletions

View 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;
}

View 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);
}