LCOV - code coverage report
Current view: top level - plugins/wireguard - wireguard_peer.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 230 266 86.5 %
Date: 2023-07-05 22:20:52 Functions: 22 25 88.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2020 Doc.ai and/or its affiliates.
       3             :  * Copyright (c) 2020 Cisco 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 <vnet/adj/adj_midchain.h>
      18             : #include <vnet/fib/fib_table.h>
      19             : #include <wireguard/wireguard_peer.h>
      20             : #include <wireguard/wireguard_if.h>
      21             : #include <wireguard/wireguard_messages.h>
      22             : #include <wireguard/wireguard_key.h>
      23             : #include <wireguard/wireguard_send.h>
      24             : #include <wireguard/wireguard.h>
      25             : #include <vnet/tunnel/tunnel_dp.h>
      26             : 
      27             : wg_peer_t *wg_peer_pool;
      28             : 
      29             : index_t *wg_peer_by_adj_index;
      30             : 
      31             : static void
      32         584 : wg_peer_endpoint_reset (wg_peer_endpoint_t * ep)
      33             : {
      34         584 :   ip46_address_reset (&ep->addr);
      35         584 :   ep->port = 0;
      36         584 : }
      37             : 
      38             : static void
      39         162 : wg_peer_endpoint_init (wg_peer_endpoint_t *ep, const ip46_address_t *addr,
      40             :                        u16 port)
      41             : {
      42         162 :   ip46_address_copy (&ep->addr, addr);
      43         162 :   ep->port = port;
      44         162 : }
      45             : 
      46             : static void
      47         292 : wg_peer_clear (vlib_main_t * vm, wg_peer_t * peer)
      48             : {
      49         292 :   index_t perri = peer - wg_peer_pool;
      50         292 :   wg_timers_stop (peer);
      51         292 :   wg_peer_update_flags (perri, WG_PEER_ESTABLISHED, false);
      52         292 :   wg_peer_update_flags (perri, WG_PEER_STATUS_DEAD, true);
      53        1752 :   for (int i = 0; i < WG_N_TIMERS; i++)
      54             :     {
      55        1460 :       peer->timers[i] = ~0;
      56        1460 :       peer->timers_dispatched[i] = 0;
      57             :     }
      58             : 
      59         292 :   peer->last_sent_handshake = vlib_time_now (vm) - (REKEY_TIMEOUT + 1);
      60             : 
      61         292 :   clib_memset (&peer->cookie_maker, 0, sizeof (peer->cookie_maker));
      62             : 
      63         292 :   wg_peer_endpoint_reset (&peer->src);
      64         292 :   wg_peer_endpoint_reset (&peer->dst);
      65             : 
      66             :   adj_index_t *adj_index;
      67         332 :   vec_foreach (adj_index, peer->adj_indices)
      68             :     {
      69          40 :       wg_peer_by_adj_index[*adj_index] = INDEX_INVALID;
      70             : 
      71          40 :       if (adj_is_valid (*adj_index))
      72           2 :         adj_midchain_delegate_unstack (*adj_index);
      73             :     }
      74         292 :   peer->input_thread_index = ~0;
      75         292 :   peer->output_thread_index = ~0;
      76         292 :   peer->timer_wheel = 0;
      77         292 :   peer->persistent_keepalive_interval = 0;
      78         292 :   peer->timer_handshake_attempts = 0;
      79         292 :   peer->last_sent_packet = 0;
      80         292 :   peer->last_received_packet = 0;
      81         292 :   peer->session_derived = 0;
      82         292 :   peer->rehandshake_started = 0;
      83         292 :   peer->new_handshake_interval_tick = 0;
      84         292 :   peer->rehandshake_interval_tick = 0;
      85         292 :   peer->timer_need_another_keepalive = false;
      86         292 :   peer->handshake_is_sent = false;
      87         292 :   vec_free (peer->rewrite);
      88         292 :   vec_free (peer->allowed_ips);
      89         292 :   vec_free (peer->adj_indices);
      90         292 : }
      91             : 
      92             : static void
      93         146 : wg_peer_init (vlib_main_t * vm, wg_peer_t * peer)
      94             : {
      95         146 :   peer->api_client_by_client_index = hash_create (0, sizeof (u32));
      96         146 :   peer->api_clients = NULL;
      97         146 :   wg_peer_clear (vm, peer);
      98         146 : }
      99             : 
     100             : static void
     101          52 : wg_peer_adj_stack (wg_peer_t *peer, adj_index_t ai)
     102             : {
     103             :   ip_adjacency_t *adj;
     104             :   u32 sw_if_index;
     105             :   wg_if_t *wgi;
     106             :   fib_protocol_t fib_proto;
     107             : 
     108          52 :   if (!adj_is_valid (ai))
     109           0 :     return;
     110             : 
     111          52 :   adj = adj_get (ai);
     112          52 :   sw_if_index = adj->rewrite_header.sw_if_index;
     113          52 :   u8 is_ip4 = ip46_address_is_ip4 (&peer->src.addr);
     114          52 :   fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
     115             : 
     116          52 :   wgi = wg_if_get (wg_if_find_by_sw_if_index (sw_if_index));
     117             : 
     118          52 :   if (!wgi)
     119           0 :     return;
     120             : 
     121          52 :   if (!vnet_sw_interface_is_admin_up (vnet_get_main (), wgi->sw_if_index) ||
     122          50 :       !wg_peer_can_send (peer))
     123             :     {
     124           2 :       adj_midchain_delegate_unstack (ai);
     125             :     }
     126             :   else
     127             :     {
     128             :       /* *INDENT-OFF* */
     129          50 :       fib_prefix_t dst = {
     130             :         .fp_len = is_ip4 ? 32 : 128,
     131             :         .fp_proto = fib_proto,
     132             :         .fp_addr = peer->dst.addr,
     133             :       };
     134             :       /* *INDENT-ON* */
     135             :       u32 fib_index;
     136             : 
     137          50 :       fib_index = fib_table_find (fib_proto, peer->table_id);
     138             : 
     139          50 :       adj_midchain_delegate_stack (ai, fib_index, &dst);
     140             :     }
     141             : }
     142             : 
     143             : static void
     144           8 : wg_peer_adj_reset_stacking (adj_index_t ai)
     145             : {
     146           8 :   adj_midchain_delegate_remove (ai);
     147           8 : }
     148             : 
     149             : static void
     150           0 : wg_peer_66_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b,
     151             :                   const void *data)
     152             : {
     153           0 :   u8 iph_offset = 0;
     154             :   ip6_header_t *ip6_out;
     155             :   ip6_header_t *ip6_in;
     156             : 
     157             :   /* Must set locally originated otherwise we're not allowed to
     158             :      fragment the packet later */
     159           0 :   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
     160             : 
     161           0 :   ip6_out = vlib_buffer_get_current (b);
     162           0 :   iph_offset = vnet_buffer (b)->ip.save_rewrite_length;
     163           0 :   ip6_in = vlib_buffer_get_current (b) + iph_offset;
     164             : 
     165           0 :   ip6_out->ip_version_traffic_class_and_flow_label =
     166           0 :     ip6_in->ip_version_traffic_class_and_flow_label;
     167           0 : }
     168             : 
     169             : static void
     170           0 : wg_peer_46_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b,
     171             :                   const void *data)
     172             : {
     173           0 :   u8 iph_offset = 0;
     174             :   ip6_header_t *ip6_out;
     175             :   ip4_header_t *ip4_in;
     176             : 
     177             :   /* Must set locally originated otherwise we're not allowed to
     178             :      fragment the packet later */
     179           0 :   b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
     180             : 
     181           0 :   ip6_out = vlib_buffer_get_current (b);
     182           0 :   iph_offset = vnet_buffer (b)->ip.save_rewrite_length;
     183           0 :   ip4_in = vlib_buffer_get_current (b) + iph_offset;
     184             : 
     185           0 :   u32 vtcfl = 0x6 << 28;
     186           0 :   vtcfl |= ip4_in->tos << 20;
     187           0 :   vtcfl |= vnet_buffer (b)->ip.flow_hash & 0x000fffff;
     188             : 
     189           0 :   ip6_out->ip_version_traffic_class_and_flow_label =
     190           0 :     clib_host_to_net_u32 (vtcfl);
     191           0 : }
     192             : 
     193             : static adj_midchain_fixup_t
     194          48 : wg_peer_get_fixup (wg_peer_t *peer, vnet_link_t lt)
     195             : {
     196          48 :   if (!ip46_address_is_ip4 (&peer->dst.addr))
     197             :     {
     198          22 :       if (lt == VNET_LINK_IP4)
     199           6 :         return (wg_peer_46_fixup);
     200          16 :       if (lt == VNET_LINK_IP6)
     201          16 :         return (wg_peer_66_fixup);
     202             :     }
     203          26 :   return (NULL);
     204             : }
     205             : 
     206             : static void
     207           4 : wg_peer_disable (vlib_main_t *vm, wg_peer_t *peer)
     208             : {
     209           4 :   index_t peeri = peer - wg_peer_pool;
     210             : 
     211           4 :   wg_timers_stop (peer);
     212           4 :   wg_peer_update_flags (peeri, WG_PEER_ESTABLISHED, false);
     213             : 
     214          24 :   for (int i = 0; i < WG_N_TIMERS; i++)
     215             :     {
     216          20 :       peer->timers[i] = ~0;
     217          20 :       peer->timers_dispatched[i] = 0;
     218             :     }
     219           4 :   peer->timer_handshake_attempts = 0;
     220             : 
     221           4 :   peer->last_sent_handshake = vlib_time_now (vm) - (REKEY_TIMEOUT + 1);
     222           4 :   peer->last_sent_packet = 0;
     223           4 :   peer->last_received_packet = 0;
     224           4 :   peer->session_derived = 0;
     225           4 :   peer->rehandshake_started = 0;
     226             : 
     227           4 :   peer->new_handshake_interval_tick = 0;
     228           4 :   peer->rehandshake_interval_tick = 0;
     229             : 
     230           4 :   peer->timer_need_another_keepalive = false;
     231             : 
     232           4 :   noise_remote_clear (vm, &peer->remote);
     233           4 : }
     234             : 
     235             : static void
     236           4 : wg_peer_enable (vlib_main_t *vm, wg_peer_t *peer)
     237             : {
     238           4 :   index_t peeri = peer - wg_peer_pool;
     239             :   wg_if_t *wg_if;
     240             :   u8 public_key[NOISE_PUBLIC_KEY_LEN];
     241             : 
     242           4 :   wg_if = wg_if_get (wg_if_find_by_sw_if_index (peer->wg_sw_if_index));
     243           4 :   clib_memcpy (public_key, peer->remote.r_public, NOISE_PUBLIC_KEY_LEN);
     244             : 
     245           4 :   noise_remote_init (vm, &peer->remote, peeri, public_key, wg_if->local_idx);
     246             : 
     247           4 :   wg_timers_send_first_handshake (peer);
     248           4 : }
     249             : 
     250             : walk_rc_t
     251           8 : wg_peer_if_admin_state_change (index_t peeri, void *data)
     252             : {
     253             :   wg_peer_t *peer;
     254             :   adj_index_t *adj_index;
     255           8 :   vlib_main_t *vm = vlib_get_main ();
     256             : 
     257           8 :   peer = wg_peer_get (peeri);
     258          12 :   vec_foreach (adj_index, peer->adj_indices)
     259             :     {
     260           4 :       wg_peer_adj_stack (peer, *adj_index);
     261             :     }
     262             : 
     263           8 :   if (vnet_sw_interface_is_admin_up (vnet_get_main (), peer->wg_sw_if_index))
     264             :     {
     265           4 :       wg_peer_enable (vm, peer);
     266             :     }
     267             :   else
     268             :     {
     269           4 :       wg_peer_disable (vm, peer);
     270             :     }
     271             : 
     272           8 :   return (WALK_CONTINUE);
     273             : }
     274             : 
     275             : walk_rc_t
     276        1109 : wg_peer_if_adj_change (index_t peeri, void *data)
     277             : {
     278        1109 :   adj_index_t *adj_index = data;
     279             :   adj_midchain_fixup_t fixup;
     280             :   ip_adjacency_t *adj;
     281             :   wg_peer_t *peer;
     282             :   fib_prefix_t *allowed_ip;
     283             : 
     284        1109 :   adj = adj_get (*adj_index);
     285             : 
     286        1109 :   peer = wg_peer_get (peeri);
     287        2179 :   vec_foreach (allowed_ip, peer->allowed_ips)
     288             :     {
     289        1110 :       if (fib_prefix_is_cover_addr_46 (allowed_ip,
     290        1110 :                                        &adj->sub_type.nbr.next_hop))
     291             :         {
     292          40 :           vec_add1 (peer->adj_indices, *adj_index);
     293             : 
     294         222 :           vec_validate_init_empty (wg_peer_by_adj_index, *adj_index,
     295             :                                    INDEX_INVALID);
     296          40 :           wg_peer_by_adj_index[*adj_index] = peeri;
     297             : 
     298          40 :           fixup = wg_peer_get_fixup (peer, adj_get_link_type (*adj_index));
     299          40 :           adj_nbr_midchain_update_rewrite (*adj_index, fixup, NULL,
     300             :                                            ADJ_FLAG_MIDCHAIN_IP_STACK,
     301          40 :                                            vec_dup (peer->rewrite));
     302             : 
     303          40 :           wg_peer_adj_stack (peer, *adj_index);
     304          40 :           return (WALK_STOP);
     305             :         }
     306             :     }
     307             : 
     308        1069 :   return (WALK_CONTINUE);
     309             : }
     310             : 
     311             : adj_walk_rc_t
     312         509 : wg_peer_adj_walk (adj_index_t ai, void *data)
     313             : {
     314         509 :   return wg_peer_if_adj_change ((*(index_t *) (data)), &ai) == WALK_CONTINUE ?
     315         509 :            ADJ_WALK_RC_CONTINUE :
     316             :            ADJ_WALK_RC_STOP;
     317             : }
     318             : 
     319             : walk_rc_t
     320           0 : wg_peer_if_delete (index_t peeri, void *data)
     321             : {
     322           0 :   wg_peer_remove (peeri);
     323           0 :   return (WALK_CONTINUE);
     324             : }
     325             : 
     326             : static int
     327         146 : wg_peer_fill (vlib_main_t *vm, wg_peer_t *peer, u32 table_id,
     328             :               const ip46_address_t *dst, u16 port,
     329             :               u16 persistent_keepalive_interval,
     330             :               const fib_prefix_t *allowed_ips, u32 wg_sw_if_index)
     331             : {
     332         146 :   index_t perri = peer - wg_peer_pool;
     333         146 :   wg_peer_endpoint_init (&peer->dst, dst, port);
     334             : 
     335         146 :   peer->table_id = table_id;
     336         146 :   peer->wg_sw_if_index = wg_sw_if_index;
     337         146 :   peer->timer_wheel = &wg_main.timer_wheel;
     338         146 :   peer->persistent_keepalive_interval = persistent_keepalive_interval;
     339         146 :   peer->last_sent_handshake = vlib_time_now (vm) - (REKEY_TIMEOUT + 1);
     340         146 :   wg_peer_update_flags (perri, WG_PEER_STATUS_DEAD, false);
     341             : 
     342         146 :   const wg_if_t *wgi = wg_if_get (wg_if_find_by_sw_if_index (wg_sw_if_index));
     343             : 
     344         146 :   if (NULL == wgi)
     345           0 :     return (VNET_API_ERROR_INVALID_INTERFACE);
     346             : 
     347         146 :   ip_address_to_46 (&wgi->src_ip, &peer->src.addr);
     348         146 :   peer->src.port = wgi->port;
     349             : 
     350         146 :   u8 is_ip4 = ip46_address_is_ip4 (&peer->dst.addr);
     351         292 :   peer->rewrite = wg_build_rewrite (&peer->src.addr, peer->src.port,
     352         146 :                                     &peer->dst.addr, peer->dst.port, is_ip4);
     353             : 
     354             :   u32 ii;
     355         146 :   vec_validate (peer->allowed_ips, vec_len (allowed_ips) - 1);
     356         293 :   vec_foreach_index (ii, allowed_ips)
     357             :   {
     358         147 :     peer->allowed_ips[ii] = allowed_ips[ii];
     359             :   }
     360             : 
     361             :   fib_protocol_t proto;
     362         438 :   FOR_EACH_FIB_IP_PROTOCOL (proto)
     363             :   {
     364         292 :     adj_nbr_walk (wg_sw_if_index, proto, wg_peer_adj_walk, &perri);
     365             :   }
     366         146 :   return (0);
     367             : }
     368             : 
     369             : void
     370         823 : wg_peer_update_flags (index_t peeri, wg_peer_flags flag, bool add_del)
     371             : {
     372         823 :   wg_peer_t *peer = wg_peer_get (peeri);
     373         823 :   if ((add_del && (peer->flags & flag)) || (!add_del && !(peer->flags & flag)))
     374             :     {
     375         273 :       return;
     376             :     }
     377             : 
     378         550 :   peer->flags ^= flag;
     379         550 :   wg_api_peer_event (peeri, peer->flags);
     380             : }
     381             : 
     382             : void
     383         102 : wg_peer_update_endpoint (index_t peeri, const ip46_address_t *addr, u16 port)
     384             : {
     385         102 :   wg_peer_t *peer = wg_peer_get (peeri);
     386             : 
     387         102 :   if (ip46_address_is_equal (&peer->dst.addr, addr) && peer->dst.port == port)
     388          86 :     return;
     389             : 
     390          16 :   wg_peer_endpoint_init (&peer->dst, addr, port);
     391             : 
     392          16 :   u8 is_ip4 = ip46_address_is_ip4 (&peer->dst.addr);
     393          16 :   vec_free (peer->rewrite);
     394          32 :   peer->rewrite = wg_build_rewrite (&peer->src.addr, peer->src.port,
     395          16 :                                     &peer->dst.addr, peer->dst.port, is_ip4);
     396             : 
     397             :   adj_index_t *adj_index;
     398          24 :   vec_foreach (adj_index, peer->adj_indices)
     399             :     {
     400           8 :       if (adj_is_valid (*adj_index))
     401             :         {
     402             :           adj_midchain_fixup_t fixup =
     403           8 :             wg_peer_get_fixup (peer, adj_get_link_type (*adj_index));
     404           8 :           adj_nbr_midchain_update_rewrite (*adj_index, fixup, NULL,
     405             :                                            ADJ_FLAG_MIDCHAIN_IP_STACK,
     406           8 :                                            vec_dup (peer->rewrite));
     407             : 
     408           8 :           wg_peer_adj_reset_stacking (*adj_index);
     409           8 :           wg_peer_adj_stack (peer, *adj_index);
     410             :         }
     411             :     }
     412             : }
     413             : 
     414             : typedef struct wg_peer_upd_ep_args_t_
     415             : {
     416             :   index_t peeri;
     417             :   ip46_address_t addr;
     418             :   u16 port;
     419             : } wg_peer_upd_ep_args_t;
     420             : 
     421             : static void
     422           8 : wg_peer_update_endpoint_thread_fn (wg_peer_upd_ep_args_t *args)
     423             : {
     424           8 :   wg_peer_update_endpoint (args->peeri, &args->addr, args->port);
     425           8 : }
     426             : 
     427             : void
     428           8 : wg_peer_update_endpoint_from_mt (index_t peeri, const ip46_address_t *addr,
     429             :                                  u16 port)
     430             : {
     431           8 :   wg_peer_upd_ep_args_t args = {
     432             :     .peeri = peeri,
     433             :     .port = port,
     434             :   };
     435             : 
     436           8 :   ip46_address_copy (&args.addr, addr);
     437           8 :   vlib_rpc_call_main_thread (wg_peer_update_endpoint_thread_fn, (u8 *) &args,
     438             :                              sizeof (args));
     439           8 : }
     440             : 
     441             : int
     442         146 : wg_peer_add (u32 tun_sw_if_index, const u8 public_key[NOISE_PUBLIC_KEY_LEN],
     443             :              u32 table_id, const ip46_address_t *endpoint,
     444             :              const fib_prefix_t *allowed_ips, u16 port,
     445             :              u16 persistent_keepalive, u32 *peer_index)
     446             : {
     447             :   wg_if_t *wg_if;
     448             :   wg_peer_t *peer;
     449             :   int rv;
     450             : 
     451         146 :   vlib_main_t *vm = vlib_get_main ();
     452             : 
     453         146 :   if (tun_sw_if_index == ~0)
     454           0 :     return (VNET_API_ERROR_INVALID_SW_IF_INDEX);
     455             : 
     456         146 :   wg_if = wg_if_get (wg_if_find_by_sw_if_index (tun_sw_if_index));
     457         146 :   if (!wg_if)
     458           0 :     return (VNET_API_ERROR_INVALID_SW_IF_INDEX);
     459             : 
     460             :   /* *INDENT-OFF* */
     461        1158 :   pool_foreach (peer, wg_peer_pool)
     462             :    {
     463        1012 :     if (!memcmp (peer->remote.r_public, public_key, NOISE_PUBLIC_KEY_LEN))
     464             :     {
     465           0 :       return (VNET_API_ERROR_ENTRY_ALREADY_EXISTS);
     466             :     }
     467             :   }
     468             :   /* *INDENT-ON* */
     469             : 
     470         146 :   if (pool_elts (wg_peer_pool) > MAX_PEERS)
     471           0 :     return (VNET_API_ERROR_LIMIT_EXCEEDED);
     472             : 
     473         146 :   pool_get_zero (wg_peer_pool, peer);
     474             : 
     475         146 :   wg_peer_init (vm, peer);
     476             : 
     477         146 :   rv = wg_peer_fill (vm, peer, table_id, endpoint, (u16) port,
     478             :                      persistent_keepalive, allowed_ips, tun_sw_if_index);
     479             : 
     480         146 :   if (rv)
     481             :     {
     482           0 :       wg_peer_clear (vm, peer);
     483           0 :       pool_put (wg_peer_pool, peer);
     484           0 :       return (rv);
     485             :     }
     486             : 
     487         146 :   noise_remote_init (vm, &peer->remote, peer - wg_peer_pool, public_key,
     488             :                      wg_if->local_idx);
     489         146 :   cookie_maker_init (&peer->cookie_maker, public_key);
     490             : 
     491         146 :   if (vnet_sw_interface_is_admin_up (vnet_get_main (), tun_sw_if_index))
     492             :     {
     493         144 :       wg_timers_send_first_handshake (peer);
     494             :     }
     495             : 
     496         146 :   *peer_index = peer - wg_peer_pool;
     497         146 :   wg_if_peer_add (wg_if, *peer_index);
     498             : 
     499         146 :   return (0);
     500             : }
     501             : 
     502             : int
     503         146 : wg_peer_remove (index_t peeri)
     504             : {
     505         146 :   wg_main_t *wmp = &wg_main;
     506         146 :   wg_peer_t *peer = NULL;
     507             :   wg_if_t *wgi;
     508             : 
     509         146 :   if (pool_is_free_index (wg_peer_pool, peeri))
     510           0 :     return VNET_API_ERROR_NO_SUCH_ENTRY;
     511             : 
     512         146 :   peer = pool_elt_at_index (wg_peer_pool, peeri);
     513             : 
     514         146 :   wgi = wg_if_get (wg_if_find_by_sw_if_index (peer->wg_sw_if_index));
     515         146 :   wg_if_peer_remove (wgi, peeri);
     516             : 
     517         146 :   noise_remote_clear (wmp->vlib_main, &peer->remote);
     518         146 :   wg_peer_clear (wmp->vlib_main, peer);
     519         146 :   pool_put (wg_peer_pool, peer);
     520             : 
     521         146 :   return (0);
     522             : }
     523             : 
     524             : index_t
     525         942 : wg_peer_walk (wg_peer_walk_cb_t fn, void *data)
     526             : {
     527             :   index_t peeri;
     528             : 
     529             :   /* *INDENT-OFF* */
     530        2438 :   pool_foreach_index (peeri, wg_peer_pool)
     531             :   {
     532        2123 :     if (WALK_STOP == fn(peeri, data))
     533         627 :       return peeri;
     534             :   }
     535             :   /* *INDENT-ON* */
     536         315 :   return INDEX_INVALID;
     537             : }
     538             : 
     539             : static u8 *
     540         128 : format_wg_peer_endpoint (u8 * s, va_list * args)
     541             : {
     542         128 :   wg_peer_endpoint_t *ep = va_arg (*args, wg_peer_endpoint_t *);
     543             : 
     544         128 :   s = format (s, "%U:%d", format_ip46_address, &ep->addr, IP46_TYPE_ANY,
     545         128 :               ep->port);
     546             : 
     547         128 :   return (s);
     548             : }
     549             : 
     550             : u8 *
     551          64 : format_wg_peer (u8 * s, va_list * va)
     552             : {
     553          64 :   index_t peeri = va_arg (*va, index_t);
     554             :   fib_prefix_t *allowed_ip;
     555             :   adj_index_t *adj_index;
     556             :   u8 key[NOISE_KEY_LEN_BASE64];
     557             :   wg_peer_t *peer;
     558             : 
     559          64 :   peer = wg_peer_get (peeri);
     560          64 :   key_to_base64 (peer->remote.r_public, NOISE_PUBLIC_KEY_LEN, key);
     561             : 
     562          64 :   s = format (
     563             :     s,
     564             :     "[%d] endpoint:[%U->%U] %U keep-alive:%d flags: %d, api-clients count: %d",
     565             :     peeri, format_wg_peer_endpoint, &peer->src, format_wg_peer_endpoint,
     566             :     &peer->dst, format_vnet_sw_if_index_name, vnet_get_main (),
     567          64 :     peer->wg_sw_if_index, peer->persistent_keepalive_interval, peer->flags,
     568          64 :     pool_elts (peer->api_clients));
     569          64 :   s = format (s, "\n  adj:");
     570          64 :   vec_foreach (adj_index, peer->adj_indices)
     571             :     {
     572           0 :       s = format (s, " %d", *adj_index);
     573             :     }
     574          64 :   s = format (s, "\n  key:%=s %U", key, format_hex_bytes,
     575          64 :               peer->remote.r_public, NOISE_PUBLIC_KEY_LEN);
     576          64 :   s = format (s, "\n  allowed-ips:");
     577         128 :   vec_foreach (allowed_ip, peer->allowed_ips)
     578             :   {
     579          64 :     s = format (s, " %U", format_fib_prefix, allowed_ip);
     580             :   }
     581             : 
     582          64 :   return s;
     583             : }
     584             : 
     585             : /*
     586             :  * fd.io coding-style-patch-verification: ON
     587             :  *
     588             :  * Local Variables:
     589             :  * eval: (c-set-style "gnu")
     590             :  * End:
     591             :  */

Generated by: LCOV version 1.14