diff options
author | Julian Orth <ju.orth@gmail.com> | 2018-09-11 20:14:55 +0200 |
---|---|---|
committer | Julian Orth <ju.orth@gmail.com> | 2018-12-17 15:39:45 +0100 |
commit | 21e5f1bcc352af8a2ed8b4212872688d214ae464 (patch) | |
tree | 6e2a9c46e38e5829f49fc7be39943b5cffc6e2e2 /src/tools/ipc.c | |
parent | tools: add framework for shared options (diff) | |
download | wireguard-monolithic-historical-21e5f1bcc352af8a2ed8b4212872688d214ae464.tar.xz wireguard-monolithic-historical-21e5f1bcc352af8a2ed8b4212872688d214ae464.zip |
tools: allow specifying the device namespace
The user can now use
wg --netns <pid|file-path> <subcommand>
to specify the network namespace in which wg should act. This sets the
attribute WGDEVICE_A_DEV_NETNS_PID or WGDEVICE_A_DEV_NETNS_FD.
In the case of
wg --netns <pid|file-path> show all
we have to try to enter the network namespace because the kernel
interface does not allow us to list devices in a network namespace
referenced by pid or fd. Since entering a network namespace requires
CAP_SYS_ADMIN in the current user namespace and the target user
namespace, this is almost useless. TODO: Add the missing functionality
to the kernel.
Diffstat (limited to 'src/tools/ipc.c')
-rw-r--r-- | src/tools/ipc.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/src/tools/ipc.c b/src/tools/ipc.c index 5879109..2c16897 100644 --- a/src/tools/ipc.c +++ b/src/tools/ipc.c @@ -551,7 +551,7 @@ cleanup: return ret; } -static int kernel_set_device(struct wgdevice *dev) +static int kernel_set_device(struct wgnetns *dev_netns, struct wgdevice *dev) { int ret = 0; struct wgpeer *peer = NULL; @@ -579,6 +579,10 @@ again: mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark); if (dev->flags & WGDEVICE_REPLACE_PEERS) flags |= WGDEVICE_F_REPLACE_PEERS; + if (dev_netns->flags & WGNETNS_HAS_PID) + mnl_attr_put_u32(nlh, WGDEVICE_A_DEV_NETNS_PID, dev_netns->pid); + if (dev_netns->flags & WGNETNS_HAS_FD) + mnl_attr_put_u32(nlh, WGDEVICE_A_DEV_NETNS_FD, (uint32_t)dev_netns->fd); if (flags) mnl_attr_put_u32(nlh, WGDEVICE_A_FLAGS, flags); } @@ -885,7 +889,8 @@ static void coalesce_peers(struct wgdevice *device) } } -static int kernel_get_device(struct wgdevice **device, const char *interface) +static int kernel_get_device(struct wgnetns *dev_netns, + struct wgdevice **device, const char *interface) { int ret = 0; struct nlmsghdr *nlh; @@ -905,6 +910,10 @@ try_again: nlh = mnlg_msg_prepare(nlg, WG_CMD_GET_DEVICE, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, interface); + if (dev_netns->flags & WGNETNS_HAS_PID) + mnl_attr_put_u32(nlh, WGDEVICE_A_DEV_NETNS_PID, dev_netns->pid); + if (dev_netns->flags & WGNETNS_HAS_FD) + mnl_attr_put_u32(nlh, WGDEVICE_A_DEV_NETNS_FD, (uint32_t)dev_netns->fd); if (mnlg_socket_send(nlg, nlh) < 0) { ret = -errno; goto out; @@ -959,23 +968,24 @@ cleanup: return buffer.buffer; } -int ipc_get_device(struct wgdevice **dev, const char *interface) +int ipc_get_device(struct wgnetns *dev_netns, struct wgdevice **dev, + const char *interface) { #ifdef __linux__ if (userspace_has_wireguard_interface(interface)) return userspace_get_device(dev, interface); - return kernel_get_device(dev, interface); + return kernel_get_device(dev_netns, dev, interface); #else return userspace_get_device(dev, interface); #endif } -int ipc_set_device(struct wgdevice *dev) +int ipc_set_device(struct wgnetns *dev_netns, struct wgdevice *dev) { #ifdef __linux__ if (userspace_has_wireguard_interface(dev->name)) return userspace_set_device(dev); - return kernel_set_device(dev); + return kernel_set_device(dev_netns, dev); #else return userspace_set_device(dev); #endif |