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 unformat_input_t _line_input, *line_input = &_line_input;
27 u8 private_key[NOISE_PUBLIC_KEY_LEN];
28 u32 instance, sw_if_index;
32 u32 port, generate_key = 0;
36 instance = sw_if_index = ~0;
40 if (unformat_user (input, unformat_line_input, line_input))
42 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
44 if (unformat (line_input, "instance %d", &instance))
46 else if (unformat (line_input, "private-key %s", &private_key_64))
48 if (!(key_from_base64 (private_key_64,
49 NOISE_KEY_LEN_BASE64, private_key)))
51 error = clib_error_return (0, "Error parsing private key");
55 else if (unformat (line_input, "listen-port %d", &port))
57 else if (unformat (line_input, "port %d", &port))
59 else if (unformat (line_input, "generate-key"))
62 if (unformat (line_input, "src %U", unformat_ip_address, &src_ip))
66 error = clib_error_return (0, "unknown input: %U",
67 format_unformat_error, line_input);
72 unformat_free (line_input);
79 curve25519_gen_secret (private_key);
81 rv = wg_if_create (instance, private_key, port, &src_ip, &sw_if_index);
84 return clib_error_return (0, "wireguard interface create failed");
86 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
92 * Create a Wireguard interface.
95 VLIB_CLI_COMMAND (wg_if_create_command, static) = {
96 .path = "wireguard create",
97 .short_help = "wireguard create listen-port <port> "
98 "private-key <key> src <IP> [generate-key]",
99 .function = wg_if_create_cli,
103 static clib_error_t *
104 wg_if_delete_cli (vlib_main_t * vm,
105 unformat_input_t * input, vlib_cli_command_t * cmd)
111 vnm = vnet_get_main ();
114 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
117 (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
123 if (~0 != sw_if_index)
125 rv = wg_if_delete (sw_if_index);
128 return clib_error_return (0, "wireguard interface delete failed");
131 return clib_error_return (0, "no such interface: %U",
132 format_unformat_error, input);
138 * Delete a Wireguard interface.
141 VLIB_CLI_COMMAND (wg_if_delete_command, static) = {
142 .path = "wireguard delete",
143 .short_help = "wireguard delete <interface>",
144 .function = wg_if_delete_cli,
149 static clib_error_t *
150 wg_peer_add_command_fn (vlib_main_t * vm,
151 unformat_input_t * input, vlib_cli_command_t * cmd)
153 vnet_main_t *vnm = vnet_get_main ();
154 clib_error_t *error = NULL;
155 unformat_input_t _line_input, *line_input = &_line_input;
157 u8 *public_key_64 = 0;
158 u8 public_key[NOISE_PUBLIC_KEY_LEN];
159 fib_prefix_t allowed_ip, *allowed_ips = NULL;
162 u32 portDst = 0, table_id = 0;
163 u32 persistent_keepalive = 0;
164 u32 tun_sw_if_index = ~0;
168 if (!unformat_user (input, unformat_line_input, line_input))
171 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
173 if (unformat (line_input, "public-key %s", &public_key_64))
175 if (!(key_from_base64 (public_key_64,
176 NOISE_KEY_LEN_BASE64, public_key)))
178 error = clib_error_return (0, "Error parsing private key");
182 else if (unformat (line_input, "endpoint %U", unformat_ip_address, &ip))
184 else if (unformat (line_input, "table-id %d", &table_id))
186 else if (unformat (line_input, "port %d", &portDst))
188 else if (unformat (line_input, "persistent-keepalive %d",
189 &persistent_keepalive))
191 else if (unformat (line_input, "allowed-ip %U",
192 unformat_ip_prefix, &pfx))
194 ip_prefix_to_fib_prefix (&pfx, &allowed_ip);
195 vec_add1 (allowed_ips, allowed_ip);
197 else if (unformat (line_input, "%U",
198 unformat_vnet_sw_interface, vnm, &tun_sw_if_index))
202 error = clib_error_return (0, "Input error");
207 if (AF_IP6 == ip_addr_version (&ip) ||
208 FIB_PROTOCOL_IP6 == allowed_ip.fp_proto)
209 rv = VNET_API_ERROR_INVALID_PROTOCOL;
211 rv = wg_peer_add (tun_sw_if_index,
216 portDst, persistent_keepalive, &peer_index);
220 case VNET_API_ERROR_KEY_LENGTH:
221 error = clib_error_return (0, "Error parsing public key");
223 case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
224 error = clib_error_return (0, "Peer already exist");
226 case VNET_API_ERROR_INVALID_SW_IF_INDEX:
227 error = clib_error_return (0, "Tunnel is not specified");
229 case VNET_API_ERROR_LIMIT_EXCEEDED:
230 error = clib_error_return (0, "Max peers limit");
232 case VNET_API_ERROR_INIT_FAILED:
233 error = clib_error_return (0, "wireguard device parameters is not set");
235 case VNET_API_ERROR_INVALID_PROTOCOL:
236 error = clib_error_return (0, "ipv6 not supported yet");
241 vec_free (public_key_64);
242 vec_free (allowed_ips);
243 unformat_free (line_input);
248 VLIB_CLI_COMMAND (wg_peer_add_command, static) =
250 .path = "wireguard peer add",
251 .short_help = "wireguard peer add <wg_int> public-key <pub_key_other>"
252 "endpoint <ip4_dst> allowed-ip <prefix>"
253 "dst-port [port_dst] persistent-keepalive [keepalive_interval]",
254 .function = wg_peer_add_command_fn,
258 static clib_error_t *
259 wg_peer_remove_command_fn (vlib_main_t * vm,
260 unformat_input_t * input, vlib_cli_command_t * cmd)
262 clib_error_t *error = NULL;
266 unformat_input_t _line_input, *line_input = &_line_input;
267 if (!unformat_user (input, unformat_line_input, line_input))
270 if (unformat (line_input, "%d", &peer_index))
274 error = clib_error_return (0, "Input error");
278 rv = wg_peer_remove (peer_index);
282 case VNET_API_ERROR_KEY_LENGTH:
283 error = clib_error_return (0, "Error parsing public key");
288 unformat_free (line_input);
293 VLIB_CLI_COMMAND (wg_peer_remove_command, static) =
295 .path = "wireguard peer remove",
296 .short_help = "wireguard peer remove <index>",
297 .function = wg_peer_remove_command_fn,
302 wg_peer_show_one (index_t peeri, void *arg)
304 vlib_cli_output (arg, "%U", format_wg_peer, peeri);
306 return (WALK_CONTINUE);
309 static clib_error_t *
310 wg_show_peer_command_fn (vlib_main_t * vm,
311 unformat_input_t * input, vlib_cli_command_t * cmd)
313 wg_peer_walk (wg_peer_show_one, vm);
319 VLIB_CLI_COMMAND (wg_show_peers_command, static) =
321 .path = "show wireguard peer",
322 .short_help = "show wireguard peer",
323 .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_if_walk (wg_if_show_one, vm);
345 VLIB_CLI_COMMAND (wg_show_itfs_command, static) =
347 .path = "show wireguard interface",
348 .short_help = "show wireguard",
349 .function = wg_show_if_command_fn,
354 * fd.io coding-style-patch-verification: ON
357 * eval: (c-set-style "gnu")