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 : #ifndef __included_wg_peer_h__
18 : #define __included_wg_peer_h__
19 :
20 : #include <vlibapi/api_helper_macros.h>
21 :
22 : #include <vnet/ip/ip.h>
23 :
24 : #include <wireguard/wireguard_cookie.h>
25 : #include <wireguard/wireguard_timer.h>
26 : #include <wireguard/wireguard_key.h>
27 : #include <wireguard/wireguard_messages.h>
28 : #include <wireguard/wireguard_if.h>
29 :
30 : typedef struct ip4_udp_header_t_
31 : {
32 : ip4_header_t ip4;
33 : udp_header_t udp;
34 : } __clib_packed ip4_udp_header_t;
35 :
36 : typedef struct ip4_udp_wg_header_t_
37 : {
38 : ip4_header_t ip4;
39 : udp_header_t udp;
40 : message_data_t wg;
41 : } __clib_packed ip4_udp_wg_header_t;
42 :
43 : typedef struct ip6_udp_header_t_
44 : {
45 : ip6_header_t ip6;
46 : udp_header_t udp;
47 : } __clib_packed ip6_udp_header_t;
48 :
49 : typedef struct ip6_udp_wg_header_t_
50 : {
51 : ip6_header_t ip6;
52 : udp_header_t udp;
53 : message_data_t wg;
54 : } __clib_packed ip6_udp_wg_header_t;
55 :
56 : u8 *format_ip4_udp_header (u8 * s, va_list * va);
57 : u8 *format_ip6_udp_header (u8 *s, va_list *va);
58 :
59 : typedef struct wg_peer_endpoint_t_
60 : {
61 : ip46_address_t addr;
62 : u16 port;
63 : } wg_peer_endpoint_t;
64 :
65 : typedef enum
66 : {
67 : WG_PEER_STATUS_DEAD = 0x1,
68 : WG_PEER_ESTABLISHED = 0x2,
69 : } wg_peer_flags;
70 :
71 : typedef struct wg_peer
72 : {
73 : noise_remote_t remote;
74 : cookie_maker_t cookie_maker;
75 :
76 : u32 input_thread_index;
77 : u32 output_thread_index;
78 :
79 : /* Peer addresses */
80 : wg_peer_endpoint_t dst;
81 : wg_peer_endpoint_t src;
82 : u32 table_id;
83 : adj_index_t *adj_indices;
84 :
85 : /* rewrite built from address information */
86 : u8 *rewrite;
87 :
88 : /* Vector of allowed-ips */
89 : fib_prefix_t *allowed_ips;
90 :
91 : /* The WG interface this peer is attached to */
92 : u32 wg_sw_if_index;
93 :
94 : /* API client registered for events */
95 : vpe_client_registration_t *api_clients;
96 : uword *api_client_by_client_index;
97 : wg_peer_flags flags;
98 :
99 : /* Timers */
100 : tw_timer_wheel_16t_2w_512sl_t *timer_wheel;
101 : u32 timers[WG_N_TIMERS];
102 : u8 timers_dispatched[WG_N_TIMERS];
103 : u32 timer_handshake_attempts;
104 : u16 persistent_keepalive_interval;
105 :
106 : /* Timestamps */
107 : f64 last_sent_handshake;
108 : f64 last_sent_packet;
109 : f64 last_received_packet;
110 : f64 session_derived;
111 : f64 rehandshake_started;
112 :
113 : /* Variable intervals */
114 : u32 new_handshake_interval_tick;
115 : u32 rehandshake_interval_tick;
116 :
117 : bool timer_need_another_keepalive;
118 :
119 : /* Handshake is sent to main thread? */
120 : bool handshake_is_sent;
121 : } wg_peer_t;
122 :
123 : typedef struct wg_peer_table_bind_ctx_t_
124 : {
125 : ip_address_family_t af;
126 : u32 new_fib_index;
127 : u32 old_fib_index;
128 : } wg_peer_table_bind_ctx_t;
129 :
130 : int wg_peer_add (u32 tun_sw_if_index,
131 : const u8 public_key_64[NOISE_PUBLIC_KEY_LEN],
132 : u32 table_id,
133 : const ip46_address_t * endpoint,
134 : const fib_prefix_t * allowed_ips,
135 : u16 port, u16 persistent_keepalive, index_t * peer_index);
136 : int wg_peer_remove (u32 peer_index);
137 :
138 : typedef walk_rc_t (*wg_peer_walk_cb_t) (index_t peeri, void *arg);
139 : index_t wg_peer_walk (wg_peer_walk_cb_t fn, void *data);
140 :
141 : u8 *format_wg_peer (u8 * s, va_list * va);
142 :
143 : walk_rc_t wg_peer_if_admin_state_change (index_t peeri, void *data);
144 : walk_rc_t wg_peer_if_delete (index_t peeri, void *data);
145 : walk_rc_t wg_peer_if_adj_change (index_t peeri, void *data);
146 : adj_walk_rc_t wg_peer_adj_walk (adj_index_t ai, void *data);
147 :
148 : void wg_api_peer_event (index_t peeri, wg_peer_flags flags);
149 : void wg_peer_update_flags (index_t peeri, wg_peer_flags flag, bool add_del);
150 : void wg_peer_update_endpoint (index_t peeri, const ip46_address_t *addr,
151 : u16 port);
152 : void wg_peer_update_endpoint_from_mt (index_t peeri,
153 : const ip46_address_t *addr, u16 port);
154 :
155 : static inline bool
156 3990 : wg_peer_is_dead (wg_peer_t *peer)
157 : {
158 3990 : return peer && peer->flags & WG_PEER_STATUS_DEAD;
159 : }
160 :
161 : /*
162 : * Expoed for the data-plane
163 : */
164 : extern index_t *wg_peer_by_adj_index;
165 : extern wg_peer_t *wg_peer_pool;
166 :
167 : static inline wg_peer_t *
168 8930 : wg_peer_get (index_t peeri)
169 : {
170 8930 : return (pool_elt_at_index (wg_peer_pool, peeri));
171 : }
172 :
173 : static inline index_t
174 573 : wg_peer_get_by_adj_index (index_t ai)
175 : {
176 573 : if (ai >= vec_len (wg_peer_by_adj_index))
177 0 : return INDEX_INVALID;
178 573 : return (wg_peer_by_adj_index[ai]);
179 : }
180 :
181 : /*
182 : * Makes choice for thread_id should be assigned.
183 : */
184 : static inline u32
185 79 : wg_peer_assign_thread (u32 thread_id)
186 : {
187 : return ((thread_id) ? thread_id
188 79 : : (vlib_num_workers ()?
189 0 : ((unix_time_now_nsec () % vlib_num_workers ()) +
190 : 1) : thread_id));
191 : }
192 :
193 : static_always_inline bool
194 4990 : fib_prefix_is_cover_addr_46 (const fib_prefix_t *p1, const ip46_address_t *ip)
195 : {
196 4990 : switch (p1->fp_proto)
197 : {
198 3924 : case FIB_PROTOCOL_IP4:
199 3924 : return (ip4_destination_matches_route (&ip4_main, &p1->fp_addr.ip4,
200 3924 : &ip->ip4, p1->fp_len) != 0);
201 1066 : case FIB_PROTOCOL_IP6:
202 1066 : return (ip6_destination_matches_route (&ip6_main, &p1->fp_addr.ip6,
203 1066 : &ip->ip6, p1->fp_len) != 0);
204 0 : case FIB_PROTOCOL_MPLS:
205 0 : break;
206 : }
207 0 : return (false);
208 : }
209 :
210 : static inline bool
211 317 : wg_peer_can_send (wg_peer_t *peer)
212 : {
213 317 : return peer && peer->rewrite;
214 : }
215 :
216 : #endif // __included_wg_peer_h__
217 :
218 : /*
219 : * fd.io coding-style-patch-verification: ON
220 : *
221 : * Local Variables:
222 : * eval: (c-set-style "gnu")
223 : * End:
224 : */
|