[PATCH 1/1] wireguard: Add support to bind socket(s) to device

Maximilian Wilhelm max at sdn.clinic
Mon Nov 15 16:04:29 UTC 2021


From: Maximilian Wilhelm <max at sdn.clinic>

   This introduces support for binding Wireguards UDP socket(s) to a
   given interface allowing to send/receive encapsulated packets via
   a VRF.

Signed-off-by: Maximilian Wilhelm <max at sdn.clinic>
---
  drivers/net/wireguard/device.h  |  1 +
  drivers/net/wireguard/netlink.c |  7 ++++++-
  drivers/net/wireguard/socket.c  | 13 +++++++++++++
  include/uapi/linux/wireguard.h  |  2 ++
  4 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireguard/device.h b/drivers/net/wireguard/device.h
index 854bc3d97150..85f9fe687cb8 100644
--- a/drivers/net/wireguard/device.h
+++ b/drivers/net/wireguard/device.h
@@ -56,6 +56,7 @@ struct wg_device {
  	struct list_head device_list, peer_list;
  	unsigned int num_peers, device_update_gen;
  	u32 fwmark;
+	u32 bind_ifindex;
  	u16 incoming_port;
  };

diff --git a/drivers/net/wireguard/netlink.c 
b/drivers/net/wireguard/netlink.c
index d0f3b6d7f408..064402a11eb3 100644
--- a/drivers/net/wireguard/netlink.c
+++ b/drivers/net/wireguard/netlink.c
@@ -27,7 +27,8 @@ static const struct nla_policy 
device_policy[WGDEVICE_A_MAX + 1] = {
  	[WGDEVICE_A_FLAGS]		= { .type = NLA_U32 },
  	[WGDEVICE_A_LISTEN_PORT]	= { .type = NLA_U16 },
  	[WGDEVICE_A_FWMARK]		= { .type = NLA_U32 },
-	[WGDEVICE_A_PEERS]		= { .type = NLA_NESTED }
+	[WGDEVICE_A_PEERS]		= { .type = NLA_NESTED },
+	[WGDEVICE_A_BIND_IFINDEX]	= { .type = NLA_U32 }
  };

  static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = {
@@ -232,6 +233,7 @@ static int wg_get_device_dump(struct sk_buff *skb, 
struct netlink_callback *cb)
  		if (nla_put_u16(skb, WGDEVICE_A_LISTEN_PORT,
  				wg->incoming_port) ||
  		    nla_put_u32(skb, WGDEVICE_A_FWMARK, wg->fwmark) ||
+		    nla_put_u32(skb, WGDEVICE_A_BIND_IFINDEX, wg->bind_ifindex) ||
  		    nla_put_u32(skb, WGDEVICE_A_IFINDEX, wg->dev->ifindex) ||
  		    nla_put_string(skb, WGDEVICE_A_IFNAME, wg->dev->name))
  			goto out;
@@ -531,6 +533,9 @@ static int wg_set_device(struct sk_buff *skb, struct 
genl_info *info)
  			wg_socket_clear_peer_endpoint_src(peer);
  	}

+	if (info->attrs[WGDEVICE_A_BIND_IFINDEX])
+		wg->bind_ifindex = nla_get_u32(info->attrs[WGDEVICE_A_BIND_IFINDEX]);
+
  	if (info->attrs[WGDEVICE_A_LISTEN_PORT]) {
  		ret = set_port(wg,
  			nla_get_u16(info->attrs[WGDEVICE_A_LISTEN_PORT]));
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
index 8c496b747108..d319288a8f3b 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c
@@ -35,6 +35,9 @@ static int send4(struct wg_device *wg, struct sk_buff 
*skb,
  	skb->dev = wg->dev;
  	skb->mark = wg->fwmark;

+	if (wg->bind_ifindex)
+		fl.flowi4_oif = wg->bind_ifindex;
+
  	rcu_read_lock_bh();
  	sock = rcu_dereference_bh(wg->sock4);

@@ -115,6 +118,9 @@ static int send6(struct wg_device *wg, struct 
sk_buff *skb,
  	skb->dev = wg->dev;
  	skb->mark = wg->fwmark;

+	if (wg->bind_ifindex)
+		fl.flowi6_oif = wg->bind_ifindex;
+
  	rcu_read_lock_bh();
  	sock = rcu_dereference_bh(wg->sock6);

@@ -379,6 +385,13 @@ int wg_socket_init(struct wg_device *wg, u16 port)
  	if (unlikely(!net))
  		return -ENONET;

+	if (wg->bind_ifindex) {
+		port4.bind_ifindex = wg->bind_ifindex;
+#if IS_ENABLED(CONFIG_IPV6)
+		port6.bind_ifindex = wg->bind_ifindex;
+#endif
+	}
+
  #if IS_ENABLED(CONFIG_IPV6)
  retry:
  #endif
diff --git a/include/uapi/linux/wireguard.h b/include/uapi/linux/wireguard.h
index ae88be14c947..5c49919596b8 100644
--- a/include/uapi/linux/wireguard.h
+++ b/include/uapi/linux/wireguard.h
@@ -114,6 +114,7 @@
   *        0: NLA_NESTED
   *            ...
   *        ...
+ *    WGDEVICE_A_BIND_IFINDEX: NLA_U32
   *
   * It is possible that the amount of configuration data exceeds that of
   * the maximum message length accepted by the kernel. In that case, 
several
@@ -157,6 +158,7 @@ enum wgdevice_attribute {
  	WGDEVICE_A_LISTEN_PORT,
  	WGDEVICE_A_FWMARK,
  	WGDEVICE_A_PEERS,
+	WGDEVICE_A_BIND_IFINDEX,
  	__WGDEVICE_A_LAST
  };
  #define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1)
-- 
2.20.1



More information about the WireGuard mailing list