aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/uapi
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-09-25 04:22:09 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2017-10-02 02:45:53 +0200
commitf129bdab552d21ae3cd77412342b94b5f23587b2 (patch)
tree4cb9ebc3ed181a9fd463ac00dbca0274c647a79c /src/uapi
parenttools: uapi: only make sure socket file is socket (diff)
downloadwireguard-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.h166
-rw-r--r--src/uapi/wireguard.h199
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