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, "dst-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 rv = wg_peer_add (tun_sw_if_index, public_key, table_id, &ip_addr_46 (&ip),
217 allowed_ips, portDst, persistent_keepalive, &peer_index);
221 case VNET_API_ERROR_KEY_LENGTH:
222 error = clib_error_return (0, "Error parsing public key");
224 case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
225 error = clib_error_return (0, "Peer already exist");
227 case VNET_API_ERROR_INVALID_SW_IF_INDEX:
228 error = clib_error_return (0, "Tunnel is not specified");
230 case VNET_API_ERROR_LIMIT_EXCEEDED:
231 error = clib_error_return (0, "Max peers limit");
233 case VNET_API_ERROR_INIT_FAILED:
234 error = clib_error_return (0, "wireguard device parameters is not set");
236 case VNET_API_ERROR_INVALID_PROTOCOL:
237 error = clib_error_return (0, "ipv6 not supported yet");
242 vec_free (public_key_64);
243 vec_free (allowed_ips);
244 unformat_free (line_input);
249 VLIB_CLI_COMMAND (wg_peer_add_command, static) = {
250 .path = "wireguard peer add",
252 "wireguard peer add <wg_int> public-key <pub_key_other> "
253 "endpoint <ip4_dst> allowed-ip <prefix> "
254 "dst-port [port_dst] persistent-keepalive [keepalive_interval]",
255 .function = wg_peer_add_command_fn,
259 static clib_error_t *
260 wg_peer_remove_command_fn (vlib_main_t * vm,
261 unformat_input_t * input, vlib_cli_command_t * cmd)
263 wg_main_t *wmp = &wg_main;
264 clib_error_t *error = NULL;
268 unformat_input_t _line_input, *line_input = &_line_input;
269 if (!unformat_user (input, unformat_line_input, line_input))
272 wg_feature_init (wmp);
274 if (unformat (line_input, "%d", &peer_index))
278 error = clib_error_return (0, "Input error");
282 rv = wg_peer_remove (peer_index);
286 case VNET_API_ERROR_KEY_LENGTH:
287 error = clib_error_return (0, "Error parsing public key");
292 unformat_free (line_input);
297 VLIB_CLI_COMMAND (wg_peer_remove_command, static) =
299 .path = "wireguard peer remove",
300 .short_help = "wireguard peer remove <index>",
301 .function = wg_peer_remove_command_fn,
306 wg_peer_show_one (index_t peeri, void *arg)
308 vlib_cli_output (arg, "%U", format_wg_peer, peeri);
310 return (WALK_CONTINUE);
313 static clib_error_t *
314 wg_show_peer_command_fn (vlib_main_t * vm,
315 unformat_input_t * input, vlib_cli_command_t * cmd)
317 wg_peer_walk (wg_peer_show_one, vm);
323 VLIB_CLI_COMMAND (wg_show_peers_command, static) =
325 .path = "show wireguard peer",
326 .short_help = "show wireguard peer",
327 .function = wg_show_peer_command_fn,
332 wg_if_show_one (index_t itfi, void *arg)
334 vlib_cli_output (arg, "%U", format_wg_if, itfi);
336 return (WALK_CONTINUE);
339 static clib_error_t *
340 wg_show_if_command_fn (vlib_main_t * vm,
341 unformat_input_t * input, vlib_cli_command_t * cmd)
343 wg_main_t *wmp = &wg_main;
345 wg_feature_init (wmp);
347 wg_if_walk (wg_if_show_one, vm);
353 VLIB_CLI_COMMAND (wg_show_itfs_command, static) =
355 .path = "show wireguard interface",
356 .short_help = "show wireguard",
357 .function = wg_show_if_command_fn,
360 static clib_error_t *
361 wg_set_async_mode_command_fn (vlib_main_t *vm, unformat_input_t *input,
362 vlib_cli_command_t *cmd)
364 unformat_input_t _line_input, *line_input = &_line_input;
365 int async_enable = 0;
367 if (!unformat_user (input, unformat_line_input, line_input))
370 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
372 if (unformat (line_input, "on"))
374 else if (unformat (line_input, "off"))
377 return (clib_error_return (0, "unknown input '%U'",
378 format_unformat_error, line_input));
381 wg_set_async_mode (async_enable);
383 unformat_free (line_input);
387 VLIB_CLI_COMMAND (wg_set_async_mode_command, static) = {
388 .path = "set wireguard async mode",
389 .short_help = "set wireguard async mode on|off",
390 .function = wg_set_async_mode_command_fn,
393 static clib_error_t *
394 wg_show_mode_command_fn (vlib_main_t *vm, unformat_input_t *input,
395 vlib_cli_command_t *cmd)
397 vlib_cli_output (vm, "Wireguard mode");
400 vlib_cli_output (vm, "\t%s: %s", s, \
401 (wg_op_mode_is_set_##f () ? "enabled" : "disabled"));
402 foreach_wg_op_mode_flags
408 VLIB_CLI_COMMAND (wg_show_modemode_command, static) = {
409 .path = "show wireguard mode",
410 .short_help = "show wireguard mode",
411 .function = wg_show_mode_command_fn,
417 * fd.io coding-style-patch-verification: ON
420 * eval: (c-set-style "gnu")