Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include "netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include "device.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "peer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include "socket.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include "queueing.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "messages.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <uapi/linux/wireguard.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/if.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <crypto/algapi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) static struct genl_family genl_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	[WGDEVICE_A_IFINDEX]		= { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	[WGDEVICE_A_IFNAME]		= { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	[WGDEVICE_A_PRIVATE_KEY]	= NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	[WGDEVICE_A_PUBLIC_KEY]		= NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	[WGDEVICE_A_FLAGS]		= { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	[WGDEVICE_A_LISTEN_PORT]	= { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	[WGDEVICE_A_FWMARK]		= { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	[WGDEVICE_A_PEERS]		= { .type = NLA_NESTED }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	[WGPEER_A_PUBLIC_KEY]				= NLA_POLICY_EXACT_LEN(NOISE_PUBLIC_KEY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	[WGPEER_A_PRESHARED_KEY]			= NLA_POLICY_EXACT_LEN(NOISE_SYMMETRIC_KEY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	[WGPEER_A_FLAGS]				= { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	[WGPEER_A_ENDPOINT]				= NLA_POLICY_MIN_LEN(sizeof(struct sockaddr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]	= { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	[WGPEER_A_LAST_HANDSHAKE_TIME]			= NLA_POLICY_EXACT_LEN(sizeof(struct __kernel_timespec)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	[WGPEER_A_RX_BYTES]				= { .type = NLA_U64 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	[WGPEER_A_TX_BYTES]				= { .type = NLA_U64 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	[WGPEER_A_ALLOWEDIPS]				= { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	[WGPEER_A_PROTOCOL_VERSION]			= { .type = NLA_U32 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static const struct nla_policy allowedip_policy[WGALLOWEDIP_A_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	[WGALLOWEDIP_A_FAMILY]		= { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	[WGALLOWEDIP_A_IPADDR]		= NLA_POLICY_MIN_LEN(sizeof(struct in_addr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	[WGALLOWEDIP_A_CIDR_MASK]	= { .type = NLA_U8 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) static struct wg_device *lookup_interface(struct nlattr **attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 					  struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	if (!attrs[WGDEVICE_A_IFINDEX] == !attrs[WGDEVICE_A_IFNAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		return ERR_PTR(-EBADR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	if (attrs[WGDEVICE_A_IFINDEX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		dev = dev_get_by_index(sock_net(skb->sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 				       nla_get_u32(attrs[WGDEVICE_A_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	else if (attrs[WGDEVICE_A_IFNAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		dev = dev_get_by_name(sock_net(skb->sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 				      nla_data(attrs[WGDEVICE_A_IFNAME]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (!dev->rtnl_link_ops || !dev->rtnl_link_ops->kind ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	    strcmp(dev->rtnl_link_ops->kind, KBUILD_MODNAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return ERR_PTR(-EOPNOTSUPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static int get_allowedips(struct sk_buff *skb, const u8 *ip, u8 cidr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 			  int family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	struct nlattr *allowedip_nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	allowedip_nest = nla_nest_start(skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (!allowedip_nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	if (nla_put_u8(skb, WGALLOWEDIP_A_CIDR_MASK, cidr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	    nla_put_u16(skb, WGALLOWEDIP_A_FAMILY, family) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	    nla_put(skb, WGALLOWEDIP_A_IPADDR, family == AF_INET6 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		    sizeof(struct in6_addr) : sizeof(struct in_addr), ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		nla_nest_cancel(skb, allowedip_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	nla_nest_end(skb, allowedip_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) struct dump_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	struct wg_device *wg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct wg_peer *next_peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	u64 allowedips_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	struct allowedips_node *next_allowedip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define DUMP_CTX(cb) ((struct dump_ctx *)(cb)->args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) get_peer(struct wg_peer *peer, struct sk_buff *skb, struct dump_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	struct nlattr *allowedips_nest, *peer_nest = nla_nest_start(skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	struct allowedips_node *allowedips_node = ctx->next_allowedip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	bool fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	if (!peer_nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	down_read(&peer->handshake.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	fail = nla_put(skb, WGPEER_A_PUBLIC_KEY, NOISE_PUBLIC_KEY_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		       peer->handshake.remote_static);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	up_read(&peer->handshake.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	if (fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (!allowedips_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		const struct __kernel_timespec last_handshake = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			.tv_sec = peer->walltime_last_handshake.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			.tv_nsec = peer->walltime_last_handshake.tv_nsec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		down_read(&peer->handshake.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		fail = nla_put(skb, WGPEER_A_PRESHARED_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			       NOISE_SYMMETRIC_KEY_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			       peer->handshake.preshared_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		up_read(&peer->handshake.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		if (fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		if (nla_put(skb, WGPEER_A_LAST_HANDSHAKE_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			    sizeof(last_handshake), &last_handshake) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		    nla_put_u16(skb, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 				peer->persistent_keepalive_interval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		    nla_put_u64_64bit(skb, WGPEER_A_TX_BYTES, peer->tx_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 				      WGPEER_A_UNSPEC) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		    nla_put_u64_64bit(skb, WGPEER_A_RX_BYTES, peer->rx_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 				      WGPEER_A_UNSPEC) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		    nla_put_u32(skb, WGPEER_A_PROTOCOL_VERSION, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		read_lock_bh(&peer->endpoint_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		if (peer->endpoint.addr.sa_family == AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			fail = nla_put(skb, WGPEER_A_ENDPOINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 				       sizeof(peer->endpoint.addr4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 				       &peer->endpoint.addr4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		else if (peer->endpoint.addr.sa_family == AF_INET6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			fail = nla_put(skb, WGPEER_A_ENDPOINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 				       sizeof(peer->endpoint.addr6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 				       &peer->endpoint.addr6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		read_unlock_bh(&peer->endpoint_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		if (fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		allowedips_node =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			list_first_entry_or_null(&peer->allowedips_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 					struct allowedips_node, peer_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (!allowedips_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		goto no_allowedips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	if (!ctx->allowedips_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		ctx->allowedips_seq = peer->device->peer_allowedips.seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	else if (ctx->allowedips_seq != peer->device->peer_allowedips.seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		goto no_allowedips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	allowedips_nest = nla_nest_start(skb, WGPEER_A_ALLOWEDIPS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	if (!allowedips_nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	list_for_each_entry_from(allowedips_node, &peer->allowedips_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 				 peer_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		u8 cidr, ip[16] __aligned(__alignof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		int family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		family = wg_allowedips_read_node(allowedips_node, ip, &cidr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		if (get_allowedips(skb, ip, cidr, family)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			nla_nest_end(skb, allowedips_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			nla_nest_end(skb, peer_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			ctx->next_allowedip = allowedips_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	nla_nest_end(skb, allowedips_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) no_allowedips:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	nla_nest_end(skb, peer_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	ctx->next_allowedip = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	ctx->allowedips_seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	nla_nest_cancel(skb, peer_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int wg_get_device_start(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	struct wg_device *wg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	wg = lookup_interface(genl_dumpit_info(cb)->attrs, cb->skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (IS_ERR(wg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		return PTR_ERR(wg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	DUMP_CTX(cb)->wg = wg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int wg_get_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	struct wg_peer *peer, *next_peer_cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	struct dump_ctx *ctx = DUMP_CTX(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	struct wg_device *wg = ctx->wg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	struct nlattr *peers_nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	int ret = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	bool done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	mutex_lock(&wg->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	cb->seq = wg->device_update_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	next_peer_cursor = ctx->next_peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			  &genl_family, NLM_F_MULTI, WG_CMD_GET_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	genl_dump_check_consistent(cb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (!ctx->next_peer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		if (nla_put_u16(skb, WGDEVICE_A_LISTEN_PORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 				wg->incoming_port) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		    nla_put_u32(skb, WGDEVICE_A_FWMARK, wg->fwmark) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		    nla_put_u32(skb, WGDEVICE_A_IFINDEX, wg->dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		    nla_put_string(skb, WGDEVICE_A_IFNAME, wg->dev->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		down_read(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		if (wg->static_identity.has_identity) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			if (nla_put(skb, WGDEVICE_A_PRIVATE_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 				    NOISE_PUBLIC_KEY_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 				    wg->static_identity.static_private) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			    nla_put(skb, WGDEVICE_A_PUBLIC_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 				    NOISE_PUBLIC_KEY_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 				    wg->static_identity.static_public)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 				up_read(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		up_read(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	peers_nest = nla_nest_start(skb, WGDEVICE_A_PEERS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	if (!peers_nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	/* If the last cursor was removed via list_del_init in peer_remove, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	 * we just treat this the same as there being no more peers left. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	 * reason is that seq_nr should indicate to userspace that this isn't a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	 * coherent dump anyway, so they'll try again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	if (list_empty(&wg->peer_list) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	    (ctx->next_peer && list_empty(&ctx->next_peer->peer_list))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		nla_nest_cancel(skb, peers_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	lockdep_assert_held(&wg->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	peer = list_prepare_entry(ctx->next_peer, &wg->peer_list, peer_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	list_for_each_entry_continue(peer, &wg->peer_list, peer_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		if (get_peer(peer, skb, ctx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			done = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		next_peer_cursor = peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	nla_nest_end(skb, peers_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	if (!ret && !done && next_peer_cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		wg_peer_get(next_peer_cursor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	wg_peer_put(ctx->next_peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	mutex_unlock(&wg->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	if (done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		ctx->next_peer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	ctx->next_peer = next_peer_cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	/* At this point, we can't really deal ourselves with safely zeroing out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	 * the private key material after usage. This will need an additional API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	 * in the kernel for marking skbs as zero_on_free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int wg_get_device_done(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	struct dump_ctx *ctx = DUMP_CTX(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	if (ctx->wg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		dev_put(ctx->wg->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	wg_peer_put(ctx->next_peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static int set_port(struct wg_device *wg, u16 port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	struct wg_peer *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	if (wg->incoming_port == port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	list_for_each_entry(peer, &wg->peer_list, peer_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		wg_socket_clear_peer_endpoint_src(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	if (!netif_running(wg->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		wg->incoming_port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	return wg_socket_init(wg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static int set_allowedip(struct wg_peer *peer, struct nlattr **attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	u16 family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	u8 cidr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	if (!attrs[WGALLOWEDIP_A_FAMILY] || !attrs[WGALLOWEDIP_A_IPADDR] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	    !attrs[WGALLOWEDIP_A_CIDR_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	family = nla_get_u16(attrs[WGALLOWEDIP_A_FAMILY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	cidr = nla_get_u8(attrs[WGALLOWEDIP_A_CIDR_MASK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	if (family == AF_INET && cidr <= 32 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	    nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		ret = wg_allowedips_insert_v4(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 			&peer->device->peer_allowedips,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 			nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			&peer->device->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	else if (family == AF_INET6 && cidr <= 128 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		 nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in6_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		ret = wg_allowedips_insert_v6(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			&peer->device->peer_allowedips,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 			&peer->device->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int set_peer(struct wg_device *wg, struct nlattr **attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	u8 *public_key = NULL, *preshared_key = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	struct wg_peer *peer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	u32 flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	if (attrs[WGPEER_A_PUBLIC_KEY] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	    nla_len(attrs[WGPEER_A_PUBLIC_KEY]) == NOISE_PUBLIC_KEY_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		public_key = nla_data(attrs[WGPEER_A_PUBLIC_KEY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (attrs[WGPEER_A_PRESHARED_KEY] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	    nla_len(attrs[WGPEER_A_PRESHARED_KEY]) == NOISE_SYMMETRIC_KEY_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		preshared_key = nla_data(attrs[WGPEER_A_PRESHARED_KEY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	if (attrs[WGPEER_A_FLAGS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		flags = nla_get_u32(attrs[WGPEER_A_FLAGS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	if (flags & ~__WGPEER_F_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	ret = -EPFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (attrs[WGPEER_A_PROTOCOL_VERSION]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		if (nla_get_u32(attrs[WGPEER_A_PROTOCOL_VERSION]) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	peer = wg_pubkey_hashtable_lookup(wg->peer_hashtable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 					  nla_data(attrs[WGPEER_A_PUBLIC_KEY]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	if (!peer) { /* Peer doesn't exist yet. Add a new one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		if (flags & (WGPEER_F_REMOVE_ME | WGPEER_F_UPDATE_ONLY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		/* The peer is new, so there aren't allowed IPs to remove. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		flags &= ~WGPEER_F_REPLACE_ALLOWEDIPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		down_read(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		if (wg->static_identity.has_identity &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		    !memcmp(nla_data(attrs[WGPEER_A_PUBLIC_KEY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 			    wg->static_identity.static_public,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 			    NOISE_PUBLIC_KEY_LEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			/* We silently ignore peers that have the same public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 			 * key as the device. The reason we do it silently is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 			 * that we'd like for people to be able to reuse the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 			 * same set of API calls across peers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 			up_read(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		up_read(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		peer = wg_peer_create(wg, public_key, preshared_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		if (IS_ERR(peer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			ret = PTR_ERR(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			peer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		/* Take additional reference, as though we've just been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		 * looked up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		wg_peer_get(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	if (flags & WGPEER_F_REMOVE_ME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		wg_peer_remove(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	if (preshared_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		down_write(&peer->handshake.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		memcpy(&peer->handshake.preshared_key, preshared_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		       NOISE_SYMMETRIC_KEY_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		up_write(&peer->handshake.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	if (attrs[WGPEER_A_ENDPOINT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		struct sockaddr *addr = nla_data(attrs[WGPEER_A_ENDPOINT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		size_t len = nla_len(attrs[WGPEER_A_ENDPOINT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		if ((len == sizeof(struct sockaddr_in) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		     addr->sa_family == AF_INET) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		    (len == sizeof(struct sockaddr_in6) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		     addr->sa_family == AF_INET6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 			struct endpoint endpoint = { { { 0 } } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			memcpy(&endpoint.addr, addr, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			wg_socket_set_peer_endpoint(peer, &endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	if (flags & WGPEER_F_REPLACE_ALLOWEDIPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		wg_allowedips_remove_by_peer(&wg->peer_allowedips, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 					     &wg->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	if (attrs[WGPEER_A_ALLOWEDIPS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		struct nlattr *attr, *allowedip[WGALLOWEDIP_A_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		int rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		nla_for_each_nested(attr, attrs[WGPEER_A_ALLOWEDIPS], rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 			ret = nla_parse_nested(allowedip, WGALLOWEDIP_A_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 					       attr, allowedip_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 			ret = set_allowedip(peer, allowedip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	if (attrs[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		const u16 persistent_keepalive_interval = nla_get_u16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 				attrs[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		const bool send_keepalive =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 			!peer->persistent_keepalive_interval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			persistent_keepalive_interval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 			netif_running(wg->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		peer->persistent_keepalive_interval = persistent_keepalive_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		if (send_keepalive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 			wg_packet_send_keepalive(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	if (netif_running(wg->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		wg_packet_send_staged_packets(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	wg_peer_put(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	if (attrs[WGPEER_A_PRESHARED_KEY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		memzero_explicit(nla_data(attrs[WGPEER_A_PRESHARED_KEY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 				 nla_len(attrs[WGPEER_A_PRESHARED_KEY]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	struct wg_device *wg = lookup_interface(info->attrs, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	u32 flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	if (IS_ERR(wg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		ret = PTR_ERR(wg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		goto out_nodev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	mutex_lock(&wg->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	if (info->attrs[WGDEVICE_A_FLAGS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		flags = nla_get_u32(info->attrs[WGDEVICE_A_FLAGS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	if (flags & ~__WGDEVICE_F_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	if (info->attrs[WGDEVICE_A_LISTEN_PORT] || info->attrs[WGDEVICE_A_FWMARK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		net = rcu_dereference(wg->creating_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		ret = !net || !ns_capable(net->user_ns, CAP_NET_ADMIN) ? -EPERM : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	++wg->device_update_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	if (info->attrs[WGDEVICE_A_FWMARK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		struct wg_peer *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		wg->fwmark = nla_get_u32(info->attrs[WGDEVICE_A_FWMARK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		list_for_each_entry(peer, &wg->peer_list, peer_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 			wg_socket_clear_peer_endpoint_src(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	if (info->attrs[WGDEVICE_A_LISTEN_PORT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		ret = set_port(wg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			nla_get_u16(info->attrs[WGDEVICE_A_LISTEN_PORT]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	if (flags & WGDEVICE_F_REPLACE_PEERS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		wg_peer_remove_all(wg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (info->attrs[WGDEVICE_A_PRIVATE_KEY] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	    nla_len(info->attrs[WGDEVICE_A_PRIVATE_KEY]) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		    NOISE_PUBLIC_KEY_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		u8 *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		u8 public_key[NOISE_PUBLIC_KEY_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		struct wg_peer *peer, *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		if (!crypto_memneq(wg->static_identity.static_private,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 				   private_key, NOISE_PUBLIC_KEY_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 			goto skip_set_private_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		/* We remove before setting, to prevent race, which means doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		 * two 25519-genpub ops.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		if (curve25519_generate_public(public_key, private_key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 			peer = wg_pubkey_hashtable_lookup(wg->peer_hashtable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 							  public_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 			if (peer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 				wg_peer_put(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 				wg_peer_remove(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		down_write(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		wg_noise_set_static_identity_private_key(&wg->static_identity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 							 private_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 		list_for_each_entry_safe(peer, temp, &wg->peer_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 					 peer_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 			wg_noise_precompute_static_static(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 			wg_noise_expire_current_peer_keypairs(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		wg_cookie_checker_precompute_device_keys(&wg->cookie_checker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		up_write(&wg->static_identity.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) skip_set_private_key:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	if (info->attrs[WGDEVICE_A_PEERS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		struct nlattr *attr, *peer[WGPEER_A_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		int rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		nla_for_each_nested(attr, info->attrs[WGDEVICE_A_PEERS], rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 			ret = nla_parse_nested(peer, WGPEER_A_MAX, attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 					       peer_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 			ret = set_peer(wg, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	mutex_unlock(&wg->device_update_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	dev_put(wg->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) out_nodev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	if (info->attrs[WGDEVICE_A_PRIVATE_KEY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		memzero_explicit(nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 				 nla_len(info->attrs[WGDEVICE_A_PRIVATE_KEY]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static const struct genl_ops genl_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		.cmd = WG_CMD_GET_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		.start = wg_get_device_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		.dumpit = wg_get_device_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		.done = wg_get_device_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		.flags = GENL_UNS_ADMIN_PERM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		.cmd = WG_CMD_SET_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		.doit = wg_set_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		.flags = GENL_UNS_ADMIN_PERM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static struct genl_family genl_family __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	.ops = genl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	.n_ops = ARRAY_SIZE(genl_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	.name = WG_GENL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	.version = WG_GENL_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	.maxattr = WGDEVICE_A_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	.module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	.policy = device_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	.netnsok = true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int __init wg_genetlink_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	return genl_register_family(&genl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) void __exit wg_genetlink_uninit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	genl_unregister_family(&genl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }