LCOV - code coverage report
Current view: top level - plugins/wireguard - wireguard_cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 22 162 13.6 %
Date: 2023-10-26 01:39:38 Functions: 20 26 76.9 %

          Line data    Source code
       1             : /*
       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:
       7             :  *
       8             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      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.
      15             :  */
      16             : 
      17             : #include <wireguard/wireguard.h>
      18             : #include <wireguard/wireguard_key.h>
      19             : #include <wireguard/wireguard_peer.h>
      20             : #include <wireguard/wireguard_if.h>
      21             : 
      22             : static clib_error_t *
      23           0 : wg_if_create_cli (vlib_main_t * vm,
      24             :                   unformat_input_t * input, vlib_cli_command_t * cmd)
      25             : {
      26           0 :   wg_main_t *wmp = &wg_main;
      27           0 :   unformat_input_t _line_input, *line_input = &_line_input;
      28             :   u8 private_key[NOISE_PUBLIC_KEY_LEN + 1];
      29             :   u32 instance, sw_if_index;
      30             :   ip_address_t src_ip;
      31             :   clib_error_t *error;
      32             :   u8 *private_key_64;
      33           0 :   u32 port, generate_key = 0;
      34             :   int rv;
      35             : 
      36           0 :   error = NULL;
      37           0 :   instance = sw_if_index = ~0;
      38           0 :   private_key_64 = 0;
      39           0 :   port = 0;
      40             : 
      41           0 :   wg_feature_init (wmp);
      42             : 
      43           0 :   if (unformat_user (input, unformat_line_input, line_input))
      44             :     {
      45           0 :       while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
      46             :         {
      47           0 :           if (unformat (line_input, "instance %d", &instance))
      48             :             ;
      49           0 :           else if (unformat (line_input, "private-key %s", &private_key_64))
      50             :             {
      51           0 :               if (!(key_from_base64 (private_key_64,
      52             :                                      NOISE_KEY_LEN_BASE64, private_key)))
      53             :                 {
      54           0 :                   error = clib_error_return (0, "Error parsing private key");
      55           0 :                   break;
      56             :                 }
      57             :             }
      58           0 :           else if (unformat (line_input, "listen-port %d", &port))
      59             :             ;
      60           0 :           else if (unformat (line_input, "port %d", &port))
      61             :             ;
      62           0 :           else if (unformat (line_input, "generate-key"))
      63           0 :             generate_key = 1;
      64             :           else
      65           0 :             if (unformat (line_input, "src %U", unformat_ip_address, &src_ip))
      66             :             ;
      67             :           else
      68             :             {
      69           0 :               error = clib_error_return (0, "unknown input: %U",
      70             :                                          format_unformat_error, line_input);
      71           0 :               break;
      72             :             }
      73             :         }
      74             : 
      75           0 :       unformat_free (line_input);
      76             : 
      77           0 :       if (error)
      78           0 :         return error;
      79             :     }
      80             : 
      81           0 :   if (generate_key)
      82           0 :     curve25519_gen_secret (private_key);
      83             : 
      84           0 :   rv = wg_if_create (instance, private_key, port, &src_ip, &sw_if_index);
      85             : 
      86           0 :   if (rv)
      87           0 :     return clib_error_return (0, "wireguard interface create failed");
      88             : 
      89           0 :   vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
      90             :                    sw_if_index);
      91           0 :   return 0;
      92             : }
      93             : 
      94             : /*?
      95             :  * Create a Wireguard interface.
      96             : ?*/
      97             : /* *INDENT-OFF* */
      98        1151 : 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,
     103             : };
     104             : /* *INDENT-ON* */
     105             : 
     106             : static clib_error_t *
     107           0 : wg_if_delete_cli (vlib_main_t * vm,
     108             :                   unformat_input_t * input, vlib_cli_command_t * cmd)
     109             : {
     110           0 :   wg_main_t *wmp = &wg_main;
     111             :   vnet_main_t *vnm;
     112             :   u32 sw_if_index;
     113             :   int rv;
     114             : 
     115           0 :   wg_feature_init (wmp);
     116             : 
     117           0 :   vnm = vnet_get_main ();
     118           0 :   sw_if_index = ~0;
     119             : 
     120           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     121             :     {
     122           0 :       if (unformat
     123             :           (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
     124             :         ;
     125             :       else
     126           0 :         break;
     127             :     }
     128             : 
     129           0 :   if (~0 != sw_if_index)
     130             :     {
     131           0 :       rv = wg_if_delete (sw_if_index);
     132             : 
     133           0 :       if (rv)
     134           0 :         return clib_error_return (0, "wireguard interface delete failed");
     135             :     }
     136             :   else
     137           0 :     return clib_error_return (0, "no such interface: %U",
     138             :                               format_unformat_error, input);
     139             : 
     140           0 :   return 0;
     141             : }
     142             : 
     143             : /*?
     144             :  * Delete a Wireguard interface.
     145             : ?*/
     146             : /* *INDENT-OFF* */
     147        1151 : VLIB_CLI_COMMAND (wg_if_delete_command, static) = {
     148             :   .path = "wireguard delete",
     149             :   .short_help = "wireguard delete <interface>",
     150             :   .function = wg_if_delete_cli,
     151             : };
     152             : /* *INDENT-ON* */
     153             : 
     154             : 
     155             : static clib_error_t *
     156           0 : wg_peer_add_command_fn (vlib_main_t * vm,
     157             :                         unformat_input_t * input, vlib_cli_command_t * cmd)
     158             : {
     159           0 :   vnet_main_t *vnm = vnet_get_main ();
     160           0 :   wg_main_t *wmp = &wg_main;
     161           0 :   clib_error_t *error = NULL;
     162           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     163             : 
     164           0 :   u8 *public_key_64 = 0;
     165             :   u8 public_key[NOISE_PUBLIC_KEY_LEN + 1];
     166           0 :   fib_prefix_t allowed_ip, *allowed_ips = NULL;
     167             :   ip_prefix_t pfx;
     168           0 :   ip_address_t ip = ip_address_initializer;
     169           0 :   u32 portDst = 0, table_id = 0;
     170           0 :   u32 persistent_keepalive = 0;
     171           0 :   u32 tun_sw_if_index = ~0;
     172             :   u32 peer_index;
     173             :   int rv;
     174             : 
     175           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     176           0 :     return 0;
     177             : 
     178           0 :   wg_feature_init (wmp);
     179             : 
     180           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     181             :     {
     182           0 :       if (unformat (line_input, "public-key %s", &public_key_64))
     183             :         {
     184           0 :           if (!(key_from_base64 (public_key_64,
     185             :                                  NOISE_KEY_LEN_BASE64, public_key)))
     186             :             {
     187           0 :               error = clib_error_return (0, "Error parsing private key");
     188           0 :               goto done;
     189             :             }
     190             :         }
     191           0 :       else if (unformat (line_input, "endpoint %U", unformat_ip_address, &ip))
     192             :         ;
     193           0 :       else if (unformat (line_input, "table-id %d", &table_id))
     194             :         ;
     195           0 :       else if (unformat (line_input, "dst-port %d", &portDst))
     196             :         ;
     197           0 :       else if (unformat (line_input, "persistent-keepalive %d",
     198             :                          &persistent_keepalive))
     199             :         ;
     200           0 :       else if (unformat (line_input, "allowed-ip %U",
     201             :                          unformat_ip_prefix, &pfx))
     202             :         {
     203           0 :           ip_prefix_to_fib_prefix (&pfx, &allowed_ip);
     204           0 :           vec_add1 (allowed_ips, allowed_ip);
     205             :         }
     206           0 :       else if (unformat (line_input, "%U",
     207             :                          unformat_vnet_sw_interface, vnm, &tun_sw_if_index))
     208             :         ;
     209             :       else
     210             :         {
     211           0 :           error = clib_error_return (0, "Input error");
     212           0 :           goto done;
     213             :         }
     214             :     }
     215             : 
     216           0 :   if (0 == vec_len (allowed_ips))
     217             :     {
     218           0 :       error = clib_error_return (0, "Allowed IPs are not specified");
     219           0 :       goto done;
     220             :     }
     221             : 
     222           0 :   rv = wg_peer_add (tun_sw_if_index, public_key, table_id, &ip_addr_46 (&ip),
     223             :                     allowed_ips, portDst, persistent_keepalive, &peer_index);
     224             : 
     225           0 :   switch (rv)
     226             :     {
     227           0 :     case VNET_API_ERROR_KEY_LENGTH:
     228           0 :       error = clib_error_return (0, "Error parsing public key");
     229           0 :       break;
     230           0 :     case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
     231           0 :       error = clib_error_return (0, "Peer already exist");
     232           0 :       break;
     233           0 :     case VNET_API_ERROR_INVALID_SW_IF_INDEX:
     234           0 :       error = clib_error_return (0, "Tunnel is not specified");
     235           0 :       break;
     236           0 :     case VNET_API_ERROR_LIMIT_EXCEEDED:
     237           0 :       error = clib_error_return (0, "Max peers limit");
     238           0 :       break;
     239           0 :     case VNET_API_ERROR_INIT_FAILED:
     240           0 :       error = clib_error_return (0, "wireguard device parameters is not set");
     241           0 :       break;
     242           0 :     case VNET_API_ERROR_INVALID_PROTOCOL:
     243           0 :       error = clib_error_return (0, "ipv6 not supported yet");
     244           0 :       break;
     245             :     }
     246             : 
     247           0 : done:
     248           0 :   vec_free (public_key_64);
     249           0 :   vec_free (allowed_ips);
     250           0 :   unformat_free (line_input);
     251           0 :   return error;
     252             : }
     253             : 
     254             : /* *INDENT-OFF* */
     255        1151 : VLIB_CLI_COMMAND (wg_peer_add_command, static) = {
     256             :   .path = "wireguard peer add",
     257             :   .short_help =
     258             :     "wireguard peer add <wg_int> public-key <pub_key_other> "
     259             :     "endpoint <ip4_dst> allowed-ip <prefix> "
     260             :     "dst-port [port_dst] persistent-keepalive [keepalive_interval]",
     261             :   .function = wg_peer_add_command_fn,
     262             : };
     263             : /* *INDENT-ON* */
     264             : 
     265             : static clib_error_t *
     266           0 : wg_peer_remove_command_fn (vlib_main_t * vm,
     267             :                            unformat_input_t * input, vlib_cli_command_t * cmd)
     268             : {
     269           0 :   wg_main_t *wmp = &wg_main;
     270           0 :   clib_error_t *error = NULL;
     271             :   u32 peer_index;
     272             :   int rv;
     273             : 
     274           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     275           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     276           0 :     return 0;
     277             : 
     278           0 :   wg_feature_init (wmp);
     279             : 
     280           0 :   if (unformat (line_input, "%d", &peer_index))
     281             :     ;
     282             :   else
     283             :     {
     284           0 :       error = clib_error_return (0, "Input error");
     285           0 :       goto done;
     286             :     }
     287             : 
     288           0 :   rv = wg_peer_remove (peer_index);
     289             : 
     290           0 :   switch (rv)
     291             :     {
     292           0 :     case VNET_API_ERROR_KEY_LENGTH:
     293           0 :       error = clib_error_return (0, "Error parsing public key");
     294           0 :       break;
     295             :     }
     296             : 
     297           0 : done:
     298           0 :   unformat_free (line_input);
     299           0 :   return error;
     300             : }
     301             : 
     302             : /* *INDENT-OFF* */
     303        1151 : VLIB_CLI_COMMAND (wg_peer_remove_command, static) =
     304             : {
     305             :   .path = "wireguard peer remove",
     306             :   .short_help = "wireguard peer remove <index>",
     307             :   .function = wg_peer_remove_command_fn,
     308             : };
     309             : /* *INDENT-ON* */
     310             : 
     311             : static walk_rc_t
     312          64 : wg_peer_show_one (index_t peeri, void *arg)
     313             : {
     314          64 :   vlib_cli_output (arg, "%U", format_wg_peer, peeri);
     315             : 
     316          64 :   return (WALK_CONTINUE);
     317             : }
     318             : 
     319             : static clib_error_t *
     320           2 : wg_show_peer_command_fn (vlib_main_t * vm,
     321             :                          unformat_input_t * input, vlib_cli_command_t * cmd)
     322             : {
     323           2 :   wg_peer_walk (wg_peer_show_one, vm);
     324             : 
     325           2 :   return NULL;
     326             : }
     327             : 
     328             : /* *INDENT-OFF* */
     329        1151 : VLIB_CLI_COMMAND (wg_show_peers_command, static) =
     330             : {
     331             :   .path = "show wireguard peer",
     332             :   .short_help = "show wireguard peer",
     333             :   .function = wg_show_peer_command_fn,
     334             : };
     335             : /* *INDENT-ON* */
     336             : 
     337             : static walk_rc_t
     338           4 : wg_if_show_one (index_t itfi, void *arg)
     339             : {
     340           4 :   vlib_cli_output (arg, "%U", format_wg_if, itfi);
     341             : 
     342           4 :   return (WALK_CONTINUE);
     343             : }
     344             : 
     345             : static clib_error_t *
     346           2 : wg_show_if_command_fn (vlib_main_t * vm,
     347             :                        unformat_input_t * input, vlib_cli_command_t * cmd)
     348             : {
     349           2 :   wg_main_t *wmp = &wg_main;
     350             : 
     351           2 :   wg_feature_init (wmp);
     352             : 
     353           2 :   wg_if_walk (wg_if_show_one, vm);
     354             : 
     355           2 :   return NULL;
     356             : }
     357             : 
     358             : /* *INDENT-OFF* */
     359        1151 : VLIB_CLI_COMMAND (wg_show_itfs_command, static) =
     360             : {
     361             :   .path = "show wireguard interface",
     362             :   .short_help = "show wireguard",
     363             :   .function = wg_show_if_command_fn,
     364             : };
     365             : 
     366             : static clib_error_t *
     367           0 : wg_set_async_mode_command_fn (vlib_main_t *vm, unformat_input_t *input,
     368             :                               vlib_cli_command_t *cmd)
     369             : {
     370           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     371           0 :   int async_enable = 0;
     372             : 
     373           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     374           0 :     return 0;
     375             : 
     376           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     377             :     {
     378           0 :       if (unformat (line_input, "on"))
     379           0 :         async_enable = 1;
     380           0 :       else if (unformat (line_input, "off"))
     381           0 :         async_enable = 0;
     382             :       else
     383           0 :         return (clib_error_return (0, "unknown input '%U'",
     384             :                                    format_unformat_error, line_input));
     385             :     }
     386             : 
     387           0 :   wg_set_async_mode (async_enable);
     388             : 
     389           0 :   unformat_free (line_input);
     390           0 :   return (NULL);
     391             : }
     392             : 
     393        1151 : VLIB_CLI_COMMAND (wg_set_async_mode_command, static) = {
     394             :   .path = "set wireguard async mode",
     395             :   .short_help = "set wireguard async mode on|off",
     396             :   .function = wg_set_async_mode_command_fn,
     397             : };
     398             : 
     399             : static clib_error_t *
     400           0 : wg_show_mode_command_fn (vlib_main_t *vm, unformat_input_t *input,
     401             :                          vlib_cli_command_t *cmd)
     402             : {
     403           0 :   vlib_cli_output (vm, "Wireguard mode");
     404             : 
     405             : #define _(v, f, s)                                                            \
     406             :   vlib_cli_output (vm, "\t%s: %s", s,                                         \
     407             :                    (wg_op_mode_is_set_##f () ? "enabled" : "disabled"));
     408           0 :   foreach_wg_op_mode_flags
     409             : #undef _
     410             : 
     411           0 :     return (NULL);
     412             : }
     413             : 
     414        1151 : VLIB_CLI_COMMAND (wg_show_modemode_command, static) = {
     415             :   .path = "show wireguard mode",
     416             :   .short_help = "show wireguard mode",
     417             :   .function = wg_show_mode_command_fn,
     418             : };
     419             : 
     420             : /* *INDENT-ON* */
     421             : 
     422             : /*
     423             :  * fd.io coding-style-patch-verification: ON
     424             :  *
     425             :  * Local Variables:
     426             :  * eval: (c-set-style "gnu")
     427             :  * End:
     428             :  */

Generated by: LCOV version 1.14