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 + 1];
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.
97 VLIB_CLI_COMMAND (wg_if_create_command, static) = {
98 .path = "wireguard create",
99 .short_help = "wireguard create listen-port <port> "
100 "private-key <key> src <IP> [generate-key]",
101 .function = wg_if_create_cli,
104 static clib_error_t *
105 wg_if_delete_cli (vlib_main_t * vm,
106 unformat_input_t * input, vlib_cli_command_t * cmd)
108 wg_main_t *wmp = &wg_main;
113 wg_feature_init (wmp);
115 vnm = vnet_get_main ();
118 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
121 (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
127 if (~0 != sw_if_index)
129 rv = wg_if_delete (sw_if_index);
132 return clib_error_return (0, "wireguard interface delete failed");
135 return clib_error_return (0, "no such interface: %U",
136 format_unformat_error, input);
142 * Delete a Wireguard interface.
144 VLIB_CLI_COMMAND (wg_if_delete_command, static) = {
145 .path = "wireguard delete",
146 .short_help = "wireguard delete <interface>",
147 .function = wg_if_delete_cli,
151 static clib_error_t *
152 wg_peer_add_command_fn (vlib_main_t * vm,
153 unformat_input_t * input, vlib_cli_command_t * cmd)
155 vnet_main_t *vnm = vnet_get_main ();
156 wg_main_t *wmp = &wg_main;
157 clib_error_t *error = NULL;
158 unformat_input_t _line_input, *line_input = &_line_input;
160 u8 *public_key_64 = 0;
161 u8 public_key[NOISE_PUBLIC_KEY_LEN + 1];
162 fib_prefix_t allowed_ip, *allowed_ips = NULL;
164 ip_address_t ip = ip_address_initializer;
165 u32 portDst = 0, table_id = 0;
166 u32 persistent_keepalive = 0;
167 u32 tun_sw_if_index = ~0;
171 if (!unformat_user (input, unformat_line_input, line_input))
174 wg_feature_init (wmp);
176 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
178 if (unformat (line_input, "public-key %s", &public_key_64))
180 if (!(key_from_base64 (public_key_64,
181 NOISE_KEY_LEN_BASE64, public_key)))
183 error = clib_error_return (0, "Error parsing private key");
187 else if (unformat (line_input, "endpoint %U", unformat_ip_address, &ip))
189 else if (unformat (line_input, "table-id %d", &table_id))
191 else if (unformat (line_input, "dst-port %d", &portDst))
193 else if (unformat (line_input, "persistent-keepalive %d",
194 &persistent_keepalive))
196 else if (unformat (line_input, "allowed-ip %U",
197 unformat_ip_prefix, &pfx))
199 ip_prefix_to_fib_prefix (&pfx, &allowed_ip);
200 vec_add1 (allowed_ips, allowed_ip);
202 else if (unformat (line_input, "%U",
203 unformat_vnet_sw_interface, vnm, &tun_sw_if_index))
207 error = clib_error_return (0, "Input error");
212 if (0 == vec_len (allowed_ips))
214 error = clib_error_return (0, "Allowed IPs are not specified");
218 rv = wg_peer_add (tun_sw_if_index, public_key, table_id, &ip_addr_46 (&ip),
219 allowed_ips, portDst, persistent_keepalive, &peer_index);
223 case VNET_API_ERROR_KEY_LENGTH:
224 error = clib_error_return (0, "Error parsing public key");
226 case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
227 error = clib_error_return (0, "Peer already exist");
229 case VNET_API_ERROR_INVALID_SW_IF_INDEX:
230 error = clib_error_return (0, "Tunnel is not specified");
232 case VNET_API_ERROR_LIMIT_EXCEEDED:
233 error = clib_error_return (0, "Max peers limit");
235 case VNET_API_ERROR_INIT_FAILED:
236 error = clib_error_return (0, "wireguard device parameters is not set");
238 case VNET_API_ERROR_INVALID_PROTOCOL:
239 error = clib_error_return (0, "ipv6 not supported yet");
244 vec_free (public_key_64);
245 vec_free (allowed_ips);
246 unformat_free (line_input);
250 VLIB_CLI_COMMAND (wg_peer_add_command, static) = {
251 .path = "wireguard peer add",
253 "wireguard peer add <wg_int> public-key <pub_key_other> "
254 "endpoint <ip4_dst> allowed-ip <prefix> "
255 "dst-port [port_dst] persistent-keepalive [keepalive_interval]",
256 .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);
296 VLIB_CLI_COMMAND (wg_peer_remove_command, static) =
298 .path = "wireguard peer remove",
299 .short_help = "wireguard peer remove <index>",
300 .function = wg_peer_remove_command_fn,
304 wg_peer_show_one (index_t peeri, void *arg)
306 vlib_cli_output (arg, "%U", format_wg_peer, peeri);
308 return (WALK_CONTINUE);
311 static clib_error_t *
312 wg_show_peer_command_fn (vlib_main_t * vm,
313 unformat_input_t * input, vlib_cli_command_t * cmd)
315 wg_peer_walk (wg_peer_show_one, vm);
320 VLIB_CLI_COMMAND (wg_show_peers_command, static) =
322 .path = "show wireguard peer",
323 .short_help = "show wireguard peer",
324 .function = wg_show_peer_command_fn,
328 wg_if_show_one (index_t itfi, void *arg)
330 vlib_cli_output (arg, "%U", format_wg_if, itfi);
332 return (WALK_CONTINUE);
335 static clib_error_t *
336 wg_show_if_command_fn (vlib_main_t * vm,
337 unformat_input_t * input, vlib_cli_command_t * cmd)
339 wg_main_t *wmp = &wg_main;
341 wg_feature_init (wmp);
343 wg_if_walk (wg_if_show_one, vm);
348 VLIB_CLI_COMMAND (wg_show_itfs_command, static) =
350 .path = "show wireguard interface",
351 .short_help = "show wireguard",
352 .function = wg_show_if_command_fn,
355 static clib_error_t *
356 wg_set_async_mode_command_fn (vlib_main_t *vm, unformat_input_t *input,
357 vlib_cli_command_t *cmd)
359 unformat_input_t _line_input, *line_input = &_line_input;
360 int async_enable = 0;
362 if (!unformat_user (input, unformat_line_input, line_input))
365 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
367 if (unformat (line_input, "on"))
369 else if (unformat (line_input, "off"))
372 return (clib_error_return (0, "unknown input '%U'",
373 format_unformat_error, line_input));
376 wg_set_async_mode (async_enable);
378 unformat_free (line_input);
382 VLIB_CLI_COMMAND (wg_set_async_mode_command, static) = {
383 .path = "set wireguard async mode",
384 .short_help = "set wireguard async mode on|off",
385 .function = wg_set_async_mode_command_fn,
388 static clib_error_t *
389 wg_show_mode_command_fn (vlib_main_t *vm, unformat_input_t *input,
390 vlib_cli_command_t *cmd)
392 vlib_cli_output (vm, "Wireguard mode");
395 vlib_cli_output (vm, "\t%s: %s", s, \
396 (wg_op_mode_is_set_##f () ? "enabled" : "disabled"));
397 foreach_wg_op_mode_flags
403 VLIB_CLI_COMMAND (wg_show_modemode_command, static) = {
404 .path = "show wireguard mode",
405 .short_help = "show wireguard mode",
406 .function = wg_show_mode_command_fn,
411 * fd.io coding-style-patch-verification: ON
414 * eval: (c-set-style "gnu")