diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-09-25 04:22:09 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-10-02 02:45:53 +0200 |
commit | f129bdab552d21ae3cd77412342b94b5f23587b2 (patch) | |
tree | 4cb9ebc3ed181a9fd463ac00dbca0274c647a79c /src/uapi | |
parent | tools: uapi: only make sure socket file is socket (diff) | |
download | wireguard-monolithic-historical-f129bdab552d21ae3cd77412342b94b5f23587b2.tar.xz wireguard-monolithic-historical-f129bdab552d21ae3cd77412342b94b5f23587b2.zip |
netlink: switch from ioctl to netlink for configuration
Diffstat (limited to '')
-rw-r--r-- | src/uapi.h | 166 | ||||
-rw-r--r-- | src/uapi/wireguard.h | 199 |
2 files changed, 199 insertions, 166 deletions
diff --git a/src/uapi.h b/src/uapi.h deleted file mode 100644 index e699025..0000000 --- a/src/uapi.h +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. - * - * Userspace API for WireGuard - * --------------------------- - * - * ioctl(WG_GET_DEVICE, { .ifr_name: "wg0", .ifr_data: NULL }): - * - * Returns the number of bytes required to hold the peers of a device (`ret_peers_size`). - * - * ioctl(WG_GET_DEVICE, { .ifr_name: "wg0", .ifr_data: user_pointer }): - * - * Retrevies device info, peer info, and ipmask info. - * - * `user_pointer` must point to a region of memory of size `sizeof(struct wgdevice) + ret_peers_size` - * and containing the structure `struct wgdevice { .peers_size: ret_peers_size }`. - * - * Writes to `user_pointer` a succession of structs: - * - * struct wgdevice { .num_peers = 3 } - * struct wgpeer { .num_ipmasks = 4 } - * struct wgipmask - * struct wgipmask - * struct wgipmask - * struct wgipmask - * struct wgpeer { .num_ipmasks = 2 } - * struct wgipmask - * struct wgipmask - * struct wgpeer { .num_ipmasks = 0 } - * - * Returns 0 on success. Returns -EMSGSIZE if there is too much data for the size of passed-in - * memory, in which case, this should be recalculated using the call above. Returns -errno if - * another error occured. - * - * ioctl(WG_SET_DEVICE, { .ifr_name: "wg0", .ifr_data: user_pointer }): - * - * Sets device info, peer info, and ipmask info. - * - * `user_pointer` must point to a region of memory containing a succession of structs: - * - * struct wgdevice { .num_peers = 3 } - * struct wgpeer { .num_ipmasks = 4 } - * struct wgipmask - * struct wgipmask - * struct wgipmask - * struct wgipmask - * struct wgpeer { .num_ipmasks = 2 } - * struct wgipmask - * struct wgipmask - * struct wgpeer { .num_ipmasks = 0 } - * - * If `wgdevice->flags & WGDEVICE_REPLACE_PEERS` is true, removes all peers of device before adding new ones. - * If `wgpeer->flags & WGPEER_REMOVE_ME` is true, the peer identified by `wgpeer->public_key` is removed. - * If `wgpeer->flags & WGPEER_REPLACE_IPMASKS` is true, removes all ipmasks before adding new ones. - * If `wgdevice->private_key` is filled with zeros, no action is taken on the private key. - * If `wgdevice->preshared_key` is filled with zeros, no action is taken on the preshared key. - * If `wgdevice->flags & WGDEVICE_REMOVE_PRIVATE_KEY` is true, the private key is removed. - * If `wgdevice->flags & WGDEVICE_REMOVE_PRESHARED_KEY` is true, the preshared key is removed. - * - * Returns 0 on success, or -errno if an error occurred. - */ - - -#ifndef WGUAPI_H -#define WGUAPI_H - -#ifdef __linux__ -#include <linux/types.h> -#else -#include <stdint.h> -typedef uint8_t __u8; -typedef uint16_t __u16; -typedef uint32_t __u32; -typedef uint64_t __u64; -typedef int32_t __s32; -#endif -#ifdef __KERNEL__ -#include <linux/time.h> -#include <linux/socket.h> -#else -#include <net/if.h> -#include <netinet/in.h> -#include <sys/time.h> -#include <sys/socket.h> -#endif - -#define WG_GET_DEVICE (SIOCDEVPRIVATE + 0) -#define WG_SET_DEVICE (SIOCDEVPRIVATE + 1) - -#define WG_KEY_LEN 32 - -struct wgipmask { - __s32 family; - union { - struct in_addr ip4; - struct in6_addr ip6; - }; - __u8 cidr; -}; - -enum { - WGPEER_REMOVE_ME = (1 << 0), - WGPEER_REPLACE_IPMASKS = (1 << 1), - WGPEER_REMOVE_PRESHARED_KEY = (1 << 2) -}; - -struct wgpeer { - __u8 public_key[WG_KEY_LEN]; /* Get/Set */ - __u8 preshared_key[WG_KEY_LEN]; /* Get/Set */ - __u32 flags; /* Set */ - - union { - struct sockaddr addr; - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - } endpoint; /* Get/Set */ - - struct timeval last_handshake_time; /* Get */ - __u64 rx_bytes, tx_bytes; /* Get */ - __u16 persistent_keepalive_interval; /* Get/Set -- 0 = off, 0xffff = unset */ - - __u16 num_ipmasks; /* Get/Set */ -}; - -enum { - WGDEVICE_REPLACE_PEERS = (1 << 0), - WGDEVICE_REMOVE_PRIVATE_KEY = (1 << 1), - WGDEVICE_REMOVE_FWMARK = (1 << 2) -}; - -enum { - WG_API_VERSION_MAGIC = 0xbeef0003 -}; - -struct wgdevice { - __u32 version_magic; /* Must be value of WG_API_VERSION_MAGIC */ - char interface[IFNAMSIZ]; /* Get */ - __u32 flags; /* Set */ - - __u8 public_key[WG_KEY_LEN]; /* Get */ - __u8 private_key[WG_KEY_LEN]; /* Get/Set */ - __u32 fwmark; /* Get/Set */ - __u16 port; /* Get/Set */ - - union { - __u32 num_peers; /* Get/Set */ - __u32 peers_size; /* Get */ - }; -}; - -/* These are simply for convenience in iterating. It allows you to write something like: - * - * for_each_wgpeer(device, peer, i) { - * for_each_wgipmask(peer, ipmask, j) { - * do_something_with_ipmask(ipmask); - * } - * } - */ -#define for_each_wgpeer(__dev, __peer, __i) for ((__i) = 0, (__peer) = (struct wgpeer *)((uint8_t *)(__dev) + sizeof(struct wgdevice)); \ - (__i) < (__dev)->num_peers; \ - ++(__i), (__peer) = (struct wgpeer *)((uint8_t *)(__peer) + sizeof(struct wgpeer) + (sizeof(struct wgipmask) * (__peer)->num_ipmasks))) - -#define for_each_wgipmask(__peer, __ipmask, __i) for ((__i) = 0, (__ipmask) = (struct wgipmask *)((uint8_t *)(__peer) + sizeof(struct wgpeer)); \ - (__i) < (__peer)->num_ipmasks; \ - ++(__i), (__ipmask) = (struct wgipmask *)((uint8_t *)(__ipmask) + sizeof(struct wgipmask))) - -#endif diff --git a/src/uapi/wireguard.h b/src/uapi/wireguard.h new file mode 100644 index 0000000..9c260be --- /dev/null +++ b/src/uapi/wireguard.h @@ -0,0 +1,199 @@ +/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + * + * The following MIT license applies only to this file: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this file, to deal in this file without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of this file, and to permit persons to + * whom this file is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of this file. + * + * THIS FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THIS FILE OR THE USE OR OTHER DEALINGS IN THIS + * FILE. + * + * Documentation + * ============= + * + * The below enums and macros are for interfacing with WireGuard, using generic + * netlink, with family WG_GENL_NAME and version WG_GENL_VERSION. It defines two + * methods: get and set. Note that while they share many common attributes, these + * two functions actually accept a slightly different set of inputs and outputs. + * + * WG_CMD_GET_DEVICE + * ----------------- + * + * May only be called via NLM_F_REQUEST | NLM_F_DUMP. The command should contain + * one but not both of: + * + * WGDEVICE_A_IFINDEX: NLA_U32 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * + * The kernel will then return several messages (NLM_F_MULTI) containing the following + * tree of nested items: + * + * WGDEVICE_A_IFINDEX: NLA_U32 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN + * WGDEVICE_A_PUBLIC_KEY: len WG_KEY_LEN + * WGDEVICE_A_LISTEN_PORT: NLA_U16 + * WGDEVICE_A_FWMARK: NLA_U32 + * WGDEVICE_A_PEERS: NLA_NESTED + * 0: NLA_NESTED + * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN + * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN + * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 + * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16 + * WGPEER_A_LAST_HANDSHAKE_TIME: struct timeval + * WGPEER_A_RX_BYTES: NLA_U64 + * WGPEER_A_TX_BYTES: NLA_U64 + * WGPEER_A_ALLOWEDIPS: NLA_NESTED + * 0: NLA_NESTED + * WGALLOWEDIP_A_FAMILY: NLA_U16 + * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr + * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 + * 1: NLA_NESTED + * ... + * 2: NLA_NESTED + * ... + * ... + * 1: NLA_NESTED + * ... + * ... + * + * It is possible that all of the allowed IPs of a single peer will not + * fit within a single netlink message. In that case, the same peer will + * be written in the following message, except it will only contain + * WGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several + * times in a row for the same peer. It is then up to the receiver to + * coalesce adjacent peers. Likewise, it is possible that all peers will + * not fit within a single message. So, subsequent peers will be sent + * in following messages, except those will only contain WGDEVICE_A_IFNAME + * and WGDEVICE_A_PEERS. It is then up to the receiver to coalesce these + * messages to form the complete list of peers. + * + * Since this is an NLA_F_DUMP command, the final message will always be + * NLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message + * contains an integer error code. It is either zero or a negative error + * code corresponding to the errno. + * + * WG_CMD_SET_DEVICE + * ----------------- + * + * May only be called via NLM_F_REQUEST. The command should contain the following + * tree of nested items, containing one but not both of WGDEVICE_A_IFINDEX + * and WGDEVICE_A_IFNAME: + * + * WGDEVICE_A_IFINDEX: NLA_U32 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * WGDEVICE_A_FLAGS: NLA_U32, 0 or WGDEVICE_F_REPLACE_PEERS if all current + * peers should be removed prior to adding the list below. + * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove + * WGDEVICE_A_LISTEN_PORT: NLA_U16, 0 to choose randomly + * WGDEVICE_A_FWMARK: NLA_U32, 0 to disable + * WGDEVICE_A_PEERS: NLA_NESTED + * 0: NLA_NESTED + * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN + * WGPEER_A_FLAGS: NLA_U32, 0 and/or WGPEER_F_REMOVE_ME if the specified peer + * should be removed rather than added/updated and/or + * WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs of + * this peer should be removed prior to adding the list below. + * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN, all zeros to remove + * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 + * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16, 0 to disable + * WGPEER_A_ALLOWEDIPS: NLA_NESTED + * 0: NLA_NESTED + * WGALLOWEDIP_A_FAMILY: NLA_U16 + * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr + * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 + * 1: NLA_NESTED + * ... + * 2: NLA_NESTED + * ... + * ... + * 1: NLA_NESTED + * ... + * ... + * + * It is possible that the amount of configuration data exceeds that of + * the maximum message length accepted by the kernel. In that case, + * several messages should be sent one after another, with each + * successive one filling in information not contained in the prior. Note + * that if WGDEVICE_F_REPLACE_PEERS is specified in the first message, it + * probably should not be specified in fragments that come after, so that + * the list of peers is only cleared the first time but appened after. + * Likewise for peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in the + * first message of a peer, it likely should not be specified in subsequent + * fragments. + * + * If an error occurs, NLMSG_ERROR will reply containing an errno. + */ + +#ifndef UAPI_WIREGUARD_H +#define UAPI_WIREGUARD_H + +#define WG_GENL_NAME "wireguard" +#define WG_GENL_VERSION 1 + +#define WG_KEY_LEN 32 + +enum wg_cmd { + WG_CMD_GET_DEVICE, + WG_CMD_SET_DEVICE, + __WG_CMD_MAX +}; +#define WG_CMD_MAX (__WG_CMD_MAX - 1) + +enum wgdevice_flag { + WGDEVICE_F_REPLACE_PEERS = (1 << 0) +}; +enum wgdevice_attribute { + WGDEVICE_A_UNSPEC, + WGDEVICE_A_IFINDEX, + WGDEVICE_A_IFNAME, + WGDEVICE_A_PRIVATE_KEY, + WGDEVICE_A_PUBLIC_KEY, + WGDEVICE_A_FLAGS, + WGDEVICE_A_LISTEN_PORT, + WGDEVICE_A_FWMARK, + WGDEVICE_A_PEERS, + __WGDEVICE_A_LAST +}; +#define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1) + +enum wgpeer_flag { + WGPEER_F_REMOVE_ME = (1 << 0), + WGPEER_F_REPLACE_ALLOWEDIPS = (1 << 1) +}; +enum wgpeer_attribute { + WGPEER_A_UNSPEC, + WGPEER_A_PUBLIC_KEY, + WGPEER_A_PRESHARED_KEY, + WGPEER_A_FLAGS, + WGPEER_A_ENDPOINT, + WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, + WGPEER_A_LAST_HANDSHAKE_TIME, + WGPEER_A_RX_BYTES, + WGPEER_A_TX_BYTES, + WGPEER_A_ALLOWEDIPS, + __WGPEER_A_LAST +}; +#define WGPEER_A_MAX (__WGPEER_A_LAST - 1) + +enum wgallowedip_attribute { + WGALLOWEDIP_A_UNSPEC, + WGALLOWEDIP_A_FAMILY, + WGALLOWEDIP_A_IPADDR, + WGALLOWEDIP_A_CIDR_MASK, + __WGALLOWEDIP_A_LAST +}; +#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1) + +#endif |