summaryrefslogtreecommitdiffhomepage
path: root/src/uapi.h
blob: b139d43dd08c40884594952c6b47c0fc100a38cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* Copyright (C) 2015-2016 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->replace_peer_list` is true, removes all peers of device before adding new ones.
 *     If `wgpeer->remove_me` is true, the peer identified by `wgpeer->public_key` is removed.
 *     If `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 pre-shared key.
 *     If `wgdevice->remove_private_key` is true, the private key is removed.
 *     If `wgdevice->remove_preshared_key` is true, the pre-shared 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 <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;
};

struct wgpeer {
	__u8 public_key[WG_KEY_LEN]; /* Get/Set */

	struct sockaddr_storage endpoint; /* Get/Set */

	struct timeval last_handshake_time; /* Get */
	__u64 rx_bytes, tx_bytes; /* Get */

	__u32 remove_me : 1; /* Set */
	__u32 replace_ipmasks : 1; /* Set */

	__u16 num_ipmasks; /* Get/Set */
	__u16 persistent_keepalive_interval; /* Get/Set -- 0 = off, 0xffff = unset */
};

struct wgdevice {
	char interface[IFNAMSIZ]; /* Get */

	__u8 public_key[WG_KEY_LEN]; /* Get */
	__u8 private_key[WG_KEY_LEN]; /* Get/Set */
	__u8 preshared_key[WG_KEY_LEN]; /* Get/Set */

	__u16 port; /* Get/Set */

	__u32 replace_peer_list : 1; /* Set */
	__u32 remove_private_key : 1; /* Set */
	__u32 remove_preshared_key : 1; /* Set */

	union {
		__u16 num_peers; /* Get/Set */
		__u64 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