2 * Copyright (c) 2020 Cisco and/or its affiliates.
3 * Copyright (c) 2020 Doc.ai and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <wireguard/wireguard.h>
18 #include <wireguard/wireguard_key.h>
19 #include <wireguard/wireguard_peer.h>
20 #include <wireguard/wireguard_if.h>
23 wg_if_create_cli (vlib_main_t * vm,
24 unformat_input_t * input, vlib_cli_command_t * cmd)
26 wg_main_t *wmp = &wg_main;
27 unformat_input_t _line_input, *line_input = &_line_input;
28 u8 private_key[NOISE_PUBLIC_KEY_LEN];
29 u32 instance, sw_if_index;
33 u32 port, generate_key = 0;
37 instance = sw_if_index = ~0;
41 wg_feature_init (wmp);
43 if (unformat_user (input, unformat_line_input, line_input))
45 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
47 if (unformat (line_input, "instance %d", &instance))
49 else if (unformat (line_input, "private-key %s", &private_key_64))
51 if (!(key_from_base64 (private_key_64,
52 NOISE_KEY_LEN_BASE64, private_key)))
54 error = clib_error_return (0, "Error parsing private key");
58 else if (unformat (line_input, "listen-port %d", &port))
60 else if (unformat (line_input, "port %d", &port))
62 else if (unformat (line_input, "generate-key"))
65 if (unformat (line_input, "src %U", unformat_ip_address, &src_ip))
69 error = clib_error_return (0, "unknown input: %U",
70 format_unformat_error, line_input);
75 unformat_free (line_input);
82 curve25519_gen_secret (private_key);
84 rv = wg_if_create (instance, private_key, port, &src_ip, &sw_if_index);
87 return clib_error_return (0, "wireguard interface create failed");
89 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
95 * Create a Wireguard interface.
98 VLIB_CLI_COMMAND (wg_if_create_command, static) = {
99 .path = "wireguard create",
100 .short_help = "wireguard create listen-port <port> "
101 "private-key <key> src <IP> [generate-key]",
102 .function = wg_if_create_cli,
106 static clib_error_t *
107 wg_if_delete_cli (vlib_main_t * vm,
108 unformat_input_t * input, vlib_cli_command_t * cmd)
110 wg_main_t *wmp = &wg_main;
115 wg_feature_init (wmp);
117 vnm = vnet_get_main ();
120 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
123 (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
129 if (~0 != sw_if_index)
131 rv = wg_if_delete (sw_if_index);
134 return clib_error_return (0, "wireguard interface delete failed");
137 return clib_error_return (0, "no such interface: %U",
138 format_unformat_error, input);
144 * Delete a Wireguard interface.
147 VLIB_CLI_COMMAND (wg_if_delete_command, static) = {
148 .path = "wireguard delete",
149 .short_help = "wireguard delete <interface>",
150 .function = wg_if_delete_cli,
155 static clib_error_t *
156 wg_peer_add_command_fn (vlib_main_t * vm,
157 unformat_input_t * input, vlib_cli_command_t * cmd)
159 vnet_main_t *vnm = vnet_get_main ();
160 wg_main_t *wmp = &wg_main;
161 clib_error_t *error = NULL;
162 unformat_input_t _line_input, *line_input = &_line_input;
164 u8 *public_key_64 = 0;
165 u8 public_key[NOISE_PUBLIC_KEY_LEN];
166 fib_prefix_t allowed_ip, *allowed_ips = NULL;
169 u32 portDst = 0, table_id = 0;
170 u32 persistent_keepalive = 0;
171 u32 tun_sw_if_index = ~0;
175 if (!unformat_user (input, unformat_line_input, line_input))
178 wg_feature_init (wmp);
180 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
182 if (unformat (line_input, "public-key %s", &public_key_64))
184 if (!(key_from_base64 (public_key_64,
185 NOISE_KEY_LEN_BASE64, public_key)))
187 error = clib_error_return (0, "Error parsing private key");
191 else if (unformat (line_input, "endpoint %U", unformat_ip_address, &ip))
193 else if (unformat (line_input, "table-id %d", &table_id))
195 else if (unformat (line_input, "port %d", &portDst))
197 else if (unformat (line_input, "persistent-keepalive %d",
198 &persistent_keepalive))
200 else if (unformat (line_input, "allowed-ip %U",
201 unformat_ip_prefix, &pfx))
203 ip_prefix_to_fib_prefix (&pfx, &allowed_ip);
204 vec_add1 (allowed_ips, allowed_ip);
206 else if (unformat (line_input, "%U",
207 unformat_vnet_sw_interface, vnm, &tun_sw_if_index))
211 error = clib_error_return (0, "Input error");
216 if (AF_IP6 == ip_addr_version (&ip) ||
217 FIB_PROTOCOL_IP6 == allowed_ip.fp_proto)
218 rv = VNET_API_ERROR_INVALID_PROTOCOL;
220 rv = wg_peer_add (tun_sw_if_index,
225 portDst, persistent_keepalive, &peer_index);
229 case VNET_API_ERROR_KEY_LENGTH:
230 error = clib_error_return (0, "Error parsing public key");
232 case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
233 error = clib_error_return (0, "Peer already exist");
235 case VNET_API_ERROR_INVALID_SW_IF_INDEX:
236 error = clib_error_return (0, "Tunnel is not specified");
238 case VNET_API_ERROR_LIMIT_EXCEEDED:
239 error = clib_error_return (0, "Max peers limit");
241 case VNET_API_ERROR_INIT_FAILED:
242 error = clib_error_return (0, "wireguard device parameters is not set");
244 case VNET_API_ERROR_INVALID_PROTOCOL:
245 error = clib_error_return (0, "ipv6 not supported yet");
250 vec_free (public_key_64);
251 vec_free (allowed_ips);
252 unformat_free (line_input);
257 VLIB_CLI_COMMAND (wg_peer_add_command, static) =
259 .path = "wireguard peer add",
260 .short_help = "wireguard peer add <wg_int> public-key <pub_key_other>"
261 "endpoint <ip4_dst> allowed-ip <prefix>"
262 "dst-port [port_dst] persistent-keepalive [keepalive_interval]",
263 .function = wg_peer_add_command_fn,
267 static clib_error_t *
268 wg_peer_remove_command_fn (vlib_main_t * vm,
269 unformat_input_t * input, vlib_cli_command_t * cmd)
271 wg_main_t *wmp = &wg_main;
272 clib_error_t *error = NULL;
276 unformat_input_t _line_input, *line_input = &_line_input;
277 if (!unformat_user (input, unformat_line_input, line_input))
280 wg_feature_init (wmp);
282 if (unformat (line_input, "%d", &peer_index))
286 error = clib_error_return (0, "Input error");
290 rv = wg_peer_remove (peer_index);
294 case VNET_API_ERROR_KEY_LENGTH:
295 error = clib_error_return (0, "Error parsing public key");
300 unformat_free (line_input);
305 VLIB_CLI_COMMAND (wg_peer_remove_command, static) =
307 .path = "wireguard peer remove",
308 .short_help = "wireguard peer remove <index>",
309 .function = wg_peer_remove_command_fn,
314 wg_peer_show_one (index_t peeri, void *arg)
316 vlib_cli_output (arg, "%U", format_wg_peer, peeri);
318 return (WALK_CONTINUE);
321 static clib_error_t *
322 wg_show_peer_command_fn (vlib_main_t * vm,
323 unformat_input_t * input, vlib_cli_command_t * cmd)
325 wg_peer_walk (wg_peer_show_one, vm);
331 VLIB_CLI_COMMAND (wg_show_peers_command, static) =
333 .path = "show wireguard peer",
334 .short_help = "show wireguard peer",
335 .function = wg_show_peer_command_fn,
340 wg_if_show_one (index_t itfi, void *arg)
342 vlib_cli_output (arg, "%U", format_wg_if, itfi);
344 return (WALK_CONTINUE);
347 static clib_error_t *
348 wg_show_if_command_fn (vlib_main_t * vm,
349 unformat_input_t * input, vlib_cli_command_t * cmd)
351 wg_main_t *wmp = &wg_main;
353 wg_feature_init (wmp);
355 wg_if_walk (wg_if_show_one, vm);
361 VLIB_CLI_COMMAND (wg_show_itfs_command, static) =
363 .path = "show wireguard interface",
364 .short_help = "show wireguard",
365 .function = wg_show_if_command_fn,
370 * fd.io coding-style-patch-verification: ON
373 * eval: (c-set-style "gnu")