FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
wireguard_api.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Doc.ai and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vnet/vnet.h>
17 #include <vlibmemory/api.h>
18 
19 #include <vnet/format_fns.h>
20 #include <vnet/ip/ip_types_api.h>
21 #include <vlibapi/api.h>
22 
23 #include <wireguard/wireguard.api_enum.h>
24 #include <wireguard/wireguard.api_types.h>
25 
27 #include <wireguard/wireguard.h>
28 #include <wireguard/wireguard_if.h>
30 
31 #define REPLY_MSG_ID_BASE wmp->msg_id_base
33 
34 static void
37 {
39  wg_main_t *wmp = &wg_main;
42  u32 sw_if_index = ~0;
43  int rv = 0;
44 
45  ip_address_decode2 (&mp->interface.src_ip, &src);
46 
47  if (AF_IP6 == ip_addr_version (&src))
48  rv = VNET_API_ERROR_INVALID_PROTOCOL;
49  else
50  {
51  if (mp->generate_key)
52  curve25519_gen_secret (private_key);
53  else
54  clib_memcpy (private_key, mp->interface.private_key,
56 
57  rv = wg_if_create (ntohl (mp->interface.user_instance), private_key,
58  ntohs (mp->interface.port), &src, &sw_if_index);
59  }
60 
61  /* *INDENT-OFF* */
62  REPLY_MACRO2(VL_API_WIREGUARD_INTERFACE_CREATE_REPLY,
63  {
64  rmp->sw_if_index = htonl(sw_if_index);
65  });
66  /* *INDENT-ON* */
67 }
68 
69 static void
72 {
73  vl_api_wireguard_interface_delete_reply_t *rmp;
74  wg_main_t *wmp = &wg_main;
75  int rv = 0;
76 
78 
79  rv = wg_if_delete (ntohl (mp->sw_if_index));
80 
82 
83  /* *INDENT-OFF* */
84  REPLY_MACRO(VL_API_WIREGUARD_INTERFACE_DELETE_REPLY);
85  /* *INDENT-ON* */
86 }
87 
88 typedef struct wg_deatils_walk_t_
89 {
93 
94 static walk_rc_t
96 {
99  const wg_if_t *wgi;
100  const noise_local_t *local;
101 
102  wgi = wg_if_get (wgii);
103  local = noise_local_get (wgi->local_idx);
104 
105  rmp = vl_msg_api_alloc_zero (sizeof (*rmp));
106  rmp->_vl_msg_id = htons (VL_API_WIREGUARD_INTERFACE_DETAILS +
108 
109  clib_memcpy (rmp->interface.private_key,
111  rmp->interface.sw_if_index = htonl (wgi->sw_if_index);
112  rmp->interface.port = htons (wgi->port);
113  ip_address_encode2 (&wgi->src_ip, &rmp->interface.src_ip);
114 
115  rmp->context = ctx->context;
116 
117  vl_api_send_msg (ctx->reg, (u8 *) rmp);
118 
119  return (WALK_CONTINUE);
120 }
121 
122 static void
124  mp)
125 {
127 
129  if (reg == 0)
130  return;
131 
133  .reg = reg,
134  .context = mp->context,
135  };
136 
138 }
139 
140 static void
142 {
144  wg_main_t *wmp = &wg_main;
145  index_t peeri = INDEX_INVALID;
146  int ii, rv = 0;
147 
149  fib_prefix_t *allowed_ips = NULL;
150 
151  VALIDATE_SW_IF_INDEX (&(mp->peer));
152 
153  if (0 == mp->peer.n_allowed_ips)
154  {
155  rv = VNET_API_ERROR_INVALID_VALUE;
156  goto done;
157  }
158 
159  vec_validate (allowed_ips, mp->peer.n_allowed_ips - 1);
160  ip_address_decode2 (&mp->peer.endpoint, &endpoint);
161 
162  for (ii = 0; ii < mp->peer.n_allowed_ips; ii++)
163  ip_prefix_decode (&mp->peer.allowed_ips[ii], &allowed_ips[ii]);
164 
165  if (AF_IP6 == ip_addr_version (&endpoint) ||
166  FIB_PROTOCOL_IP6 == allowed_ips[0].fp_proto)
167  /* ip6 currently not supported, but the API needs to support it
168  * else we'll need to change it later, and that's a PITA */
169  rv = VNET_API_ERROR_INVALID_PROTOCOL;
170  else
171  rv = wg_peer_add (ntohl (mp->peer.sw_if_index),
172  mp->peer.public_key,
173  ntohl (mp->peer.table_id),
174  &ip_addr_46 (&endpoint),
175  allowed_ips,
176  ntohs (mp->peer.port),
177  ntohs (mp->peer.persistent_keepalive), &peeri);
178 
179  vec_free (allowed_ips);
180 done:
182  /* *INDENT-OFF* */
183  REPLY_MACRO2(VL_API_WIREGUARD_PEER_ADD_REPLY,
184  {
185  rmp->peer_index = ntohl (peeri);
186  });
187  /* *INDENT-ON* */
188 }
189 
190 static void
192 {
193  vl_api_wireguard_peer_remove_reply_t *rmp;
194  wg_main_t *wmp = &wg_main;
195  int rv = 0;
196 
197  rv = wg_peer_remove (ntohl (mp->peer_index));
198 
199  /* *INDENT-OFF* */
200  REPLY_MACRO(VL_API_WIREGUARD_PEER_REMOVE_REPLY);
201  /* *INDENT-ON* */
202 }
203 
204 static walk_rc_t
206 {
209  const wg_peer_t *peer;
211  size_t ss;
212 
213  peer = wg_peer_get (peeri);
214  n_allowed_ips = vec_len (peer->allowed_ips);
215 
216  ss = (sizeof (*rmp) + (n_allowed_ips * sizeof (rmp->peer.allowed_ips[0])));
217 
218  rmp = vl_msg_api_alloc_zero (ss);
219 
220  rmp->_vl_msg_id = htons (VL_API_WIREGUARD_PEERS_DETAILS +
222 
223  if (peer->is_dead)
224  rmp->peer.flags = WIREGUARD_PEER_STATUS_DEAD;
225  clib_memcpy (rmp->peer.public_key,
227 
228  ip_address_encode (&peer->dst.addr, IP46_TYPE_ANY, &rmp->peer.endpoint);
229  rmp->peer.port = htons (peer->dst.port);
230  rmp->peer.n_allowed_ips = n_allowed_ips;
231  rmp->peer.sw_if_index = htonl (peer->wg_sw_if_index);
232 
233  int ii;
234  for (ii = 0; ii < n_allowed_ips; ii++)
235  ip_prefix_encode (&peer->allowed_ips[ii].prefix,
236  &rmp->peer.allowed_ips[ii]);
237 
238  rmp->context = ctx->context;
239 
240  vl_api_send_msg (ctx->reg, (u8 *) rmp);
241 
242  return (WALK_CONTINUE);
243 }
244 
245 static void
247 {
249 
251  if (reg == NULL)
252  return;
253 
255  .reg = reg,
256  .context = mp->context,
257  };
258 
260 }
261 
262 /* set tup the API message handling tables */
263 #include <wireguard/wireguard.api.c>
264 static clib_error_t *
266 {
267  wg_main_t *wmp = &wg_main;
269  return 0;
270 }
271 
273 
274 /*
275  * fd.io coding-style-patch-verification: ON
276  *
277  * Local Variables:
278  * eval: (c-set-style "gnu")
279  * End:
280  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
Add Wireguard interface interface response.
Definition: wireguard.api:53
wg_peer_allowed_ip_t * allowed_ips
#define ip_addr_46(_a)
Definition: ip_types.h:57
VLIB_API_INIT_FUNCTION(wg_api_hookup)
void ip_address_encode2(const ip_address_t *in, vl_api_address_t *out)
Definition: ip_types_api.c:216
void ip_prefix_decode(const vl_api_prefix_t *in, fib_prefix_t *out)
Definition: ip_types_api.c:233
#define ntohs(x)
Definition: af_xdp.bpf.c:29
static_always_inline wg_if_t * wg_if_get(index_t wgii)
Definition: wireguard_if.h:67
Create an Wireguard interface.
Definition: wireguard.api:41
#define REPLY_MACRO2(t, body)
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:35
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:57
index_t wg_peer_walk(wg_peer_walk_cb_t fn, void *data)
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
vl_api_address_t src
Definition: gre.api:54
vlib_main_t * vm
Definition: in2out_ed.c:1582
vl_api_wireguard_interface_t interface
Definition: wireguard.api:78
int wg_peer_add(u32 tun_sw_if_index, const u8 public_key[NOISE_PUBLIC_KEY_LEN], u32 table_id, const ip46_address_t *endpoint, const fib_prefix_t *allowed_ips, u16 port, u16 persistent_keepalive, u32 *peer_index)
#define ip_addr_version(_a)
Definition: ip_types.h:60
void * vl_msg_api_alloc_zero(int nbytes)
uint8_t r_public[NOISE_PUBLIC_KEY_LEN]
static walk_rc_t wireguard_if_send_details(index_t wgii, void *data)
Definition: wireguard_api.c:95
unsigned char u8
Definition: types.h:56
u8 data[128]
Definition: ipsec_types.api:89
#define clib_memcpy(d, s, n)
Definition: string.h:180
Dump peers response.
Definition: wireguard.api:153
enum walk_rc_t_ walk_rc_t
Walk return code.
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:64
vl_api_registration_t * reg
Definition: wireguard_api.c:90
u8 n_allowed_ips
Definition: wireguard.api:104
noise_remote_t remote
vl_api_prefix_t allowed_ips[n_allowed_ips]
Definition: wireguard.api:105
Aggregate type for a prefix.
Definition: fib_types.h:203
int wg_if_delete(u32 sw_if_index)
Definition: wireguard_if.c:300
unsigned int u32
Definition: types.h:88
u32 local_idx
Definition: wireguard_if.h:29
#define NOISE_PUBLIC_KEY_LEN
u8 private_key[32]
Definition: wireguard.api:34
long ctx[MAX_CONNS]
Definition: main.c:144
u16 msg_id_base
Definition: wireguard.h:36
static void vl_api_wireguard_peers_dump_t_handler(vl_api_wireguard_peers_dump_t *mp)
#define REPLY_MACRO(t)
vl_api_address_t peer
Definition: teib.api:28
void ip_address_decode2(const vl_api_address_t *in, ip_address_t *out)
Definition: ip_types_api.c:166
An API client registration, only in vpp/vlib.
Definition: api_common.h:47
#define BAD_SW_IF_INDEX_LABEL
vl_api_address_t endpoint
Definition: wireguard.api:101
wg_peer_endpoint_t dst
ip_address_t src_ip
Definition: wireguard_if.h:36
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:79
struct wg_deatils_walk_t_ wg_deatils_walk_t
Remove peer by public_key.
Definition: wireguard.api:131
bool is_dead
static void vl_api_wireguard_interface_delete_t_handler(vl_api_wireguard_interface_delete_t *mp)
Definition: wireguard_api.c:71
wg_main_t wg_main
Definition: wireguard.c:27
static void vl_api_wireguard_peer_add_t_handler(vl_api_wireguard_peer_add_t *mp)
static void vl_api_wireguard_interface_create_t_handler(vl_api_wireguard_interface_create_t *mp)
Definition: wireguard_api.c:36
bool curve25519_gen_secret(u8 secret_key[CURVE25519_KEY_SIZE])
Definition: wireguard_key.c:85
vl_api_wireguard_peer_t peer
Definition: wireguard.api:155
vl_api_wireguard_interface_t interface
Definition: wireguard.api:44
void wg_if_walk(wg_if_walk_cb_t fn, void *data)
Definition: wireguard_if.c:349
static void vl_api_wireguard_peer_remove_t_handler(vl_api_wireguard_peer_remove_t *mp)
u32 wg_sw_if_index
void ip_prefix_encode(const fib_prefix_t *in, vl_api_prefix_t *out)
Definition: ip_types_api.c:261
uint8_t l_private[NOISE_PUBLIC_KEY_LEN]
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
void ip_address_encode(const ip46_address_t *in, ip46_type_t type, vl_api_address_t *out)
Definition: ip_types_api.c:194
ip46_address_t addr
static_always_inline noise_local_t * noise_local_get(uint32_t locali)
int wg_peer_remove(index_t peeri)
static clib_error_t * wg_api_hookup(vlib_main_t *vm)
static void setup_message_id_table(snat_main_t *sm, api_main_t *am)
Definition: nat_api.c:2804
int wg_if_create(u32 user_instance, const u8 private_key[NOISE_PUBLIC_KEY_LEN], u16 port, const ip_address_t *src_ip, u32 *sw_if_indexp)
Definition: wireguard_if.c:224
static void vl_api_wireguard_interface_dump_t_handler(vl_api_wireguard_interface_dump_t *mp)
vl_api_wireguard_peer_t peer
Definition: wireguard.api:117
static wg_peer_t * wg_peer_get(index_t peeri)
u32 sw_if_index
Definition: wireguard_if.h:25
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
#define VALIDATE_SW_IF_INDEX(mp)
static walk_rc_t send_wg_peers_details(index_t peeri, void *data)