^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) }