diff options
author | Matt Macy <mmacy@FreeBSD.org> | 2020-11-29 19:38:03 +0000 |
---|---|---|
committer | Matt Macy <mmacy@FreeBSD.org> | 2020-11-29 19:38:03 +0000 |
commit | 2338da0373f19b511fb4625438565d26307243e4 (patch) | |
tree | d79d2eac83c9964c97cd939f08e9b4fb6d112ff3 /sys/dev/if_wg/include/sys/if_wg_session_vars.h | |
parent | baa2cd58a6d29c84450982b1c04cda5991e499ee (diff) | |
download | src-2338da0373f19b511fb4625438565d26307243e4.tar.gz src-2338da0373f19b511fb4625438565d26307243e4.zip |
Import kernel WireGuard support
Data path largely shared with the OpenBSD implementation by
Matt Dunwoodie <ncon@nconroy.net>
Reviewed by: grehan@freebsd.org
MFC after: 1 month
Sponsored by: Rubicon LLC, (Netgate)
Differential Revision: https://reviews.freebsd.org/D26137
Notes
Notes:
svn path=/head/; revision=368163
Diffstat (limited to 'sys/dev/if_wg/include/sys/if_wg_session_vars.h')
-rw-r--r-- | sys/dev/if_wg/include/sys/if_wg_session_vars.h | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/sys/dev/if_wg/include/sys/if_wg_session_vars.h b/sys/dev/if_wg/include/sys/if_wg_session_vars.h new file mode 100644 index 000000000000..e9261c079456 --- /dev/null +++ b/sys/dev/if_wg/include/sys/if_wg_session_vars.h @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2019 Matt Dunwoodie <ncon@noconroy.net> + * Copyright (c) 2019-2020 Rubicon Communications, LLC (Netgate) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _IF_WG_VARS_H_ +#define _IF_WG_VARS_H_ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> + +#include <sys/lock.h> +#include <sys/mutex.h> +#include <crypto/siphash/siphash.h> + + +#include <net/if.h> +#include <net/if_var.h> +#include <net/if_types.h> +#include <net/ethernet.h> +#include <net/pfvar.h> +#include <net/iflib.h> + +#include <sys/wg_noise.h> +#include <sys/wg_cookie.h> +/* This is only needed for wg_keypair. */ +#include <sys/if_wg_session.h> + +#define UNIMPLEMENTED() panic("%s not implemented\n", __func__) + +#define WG_KEY_SIZE 32 +#define WG_MSG_PADDING_SIZE 16 + + +/* Constant for session */ +#define REKEY_TIMEOUT 5 +#define REKEY_TIMEOUT_JITTER 500 /* TODO ok? jason */ +#define REJECT_AFTER_TIME 180 +#define KEEPALIVE_TIMEOUT 10 +#define MAX_TIMER_HANDSHAKES (90 / REKEY_TIMEOUT) +#define NEW_HANDSHAKE_TIMEOUT (REKEY_TIMEOUT + KEEPALIVE_TIMEOUT) + +#define MAX_QUEUED_INCOMING_HANDSHAKES 4096 /* TODO: replace this with DQL */ +#define MAX_QUEUED_PACKETS 1024 /* TODO: replace this with DQL */ + +#define HASHTABLE_PEER_SIZE (1 << 6) //1 << 11 +#define HASHTABLE_INDEX_SIZE (HASHTABLE_PEER_SIZE * 3) //1 << 13 + +#define PEER_MAGIC1 0xCAFEBABEB00FDADDULL +#define PEER_MAGIC2 0xCAAFD0D0D00DBABEULL +#define PEER_MAGIC3 0xD00DBABEF00DFADEULL + + +enum message_type { + MESSAGE_INVALID = 0, + MESSAGE_HANDSHAKE_INITIATION = 1, + MESSAGE_HANDSHAKE_RESPONSE = 2, + MESSAGE_HANDSHAKE_COOKIE = 3, + MESSAGE_DATA = 4 +}; + +struct wg_softc; + +#if __FreeBSD_version > 1300000 +typedef void timeout_t (void *); +#endif + +/* Socket */ +struct wg_endpoint { + union wg_remote { + struct sockaddr r_sa; + struct sockaddr_in r_sin; + struct sockaddr_in6 r_sin6; + } e_remote; + union wg_source { + struct in_addr l_in; + struct in6_pktinfo l_pktinfo6; +#define l_in6 l_pktinfo6.ipi6_addr + } e_local; +}; + +struct wg_socket { + struct mtx so_mtx; + in_port_t so_port; + struct socket *so_so4; + struct socket *so_so6; +}; + +struct wg_queue { + struct mtx q_mtx; + struct mbufq q; +}; + +struct wg_index { + LIST_ENTRY(wg_index) i_entry; + SLIST_ENTRY(wg_index) i_unused_entry; + uint32_t i_key; + struct noise_remote *i_value; +}; + +struct wg_timers { + /* t_lock is for blocking wg_timers_event_* when setting t_disabled. */ + struct rwlock t_lock; + + int t_disabled; + int t_need_another_keepalive; + uint16_t t_persistent_keepalive_interval; + struct callout t_new_handshake; + struct callout t_send_keepalive; + struct callout t_retry_handshake; + struct callout t_zero_key_material; + struct callout t_persistent_keepalive; + + struct mtx t_handshake_mtx; + struct timespec t_handshake_last_sent; + struct timespec t_handshake_complete; + volatile int t_handshake_retries; + +}; + +struct wg_peer { + uint64_t p_magic_1; + CK_LIST_ENTRY(wg_peer) p_hash_entry; + CK_LIST_ENTRY(wg_peer) p_entry; + uint64_t p_id; + struct wg_softc *p_sc; + + struct noise_remote p_remote; + struct cookie_maker p_cookie; + struct wg_timers p_timers; + + struct rwlock p_endpoint_lock; + struct wg_endpoint p_endpoint; + + uint64_t p_magic_2; + + SLIST_HEAD(,wg_index) p_unused_index; + struct wg_index p_index[3]; + + struct wg_queue p_encap_queue; + struct wg_queue p_decap_queue; + + struct grouptask p_clear_secrets; + struct grouptask p_send_initiation; + struct grouptask p_send_keepalive; + struct grouptask p_send; + struct grouptask p_recv; + + counter_u64_t p_tx_bytes; + counter_u64_t p_rx_bytes; + + CK_LIST_HEAD(, wg_route) p_routes; + uint64_t p_magic_3; + struct mtx p_lock; + struct epoch_context p_ctx; +}; + + + +/* Packet */ + +void wg_softc_decrypt(struct wg_softc *); +void wg_softc_encrypt(struct wg_softc *); + +/* Queue */ +void wg_queue_init(struct wg_queue *, const char *); +void wg_queue_deinit(struct wg_queue *); + +/* Counter */ + +/* Timers */ + +/* Route */ +enum route_direction { + IN, + OUT, +}; + +struct wg_route_table { + size_t t_count; + struct radix_node_head *t_ip; + struct radix_node_head *t_ip6; +}; +struct wg_peer; + +struct wg_route { + struct radix_node r_nodes[2]; + struct wg_allowedip r_cidr; + CK_LIST_ENTRY(wg_route) r_entry; + struct wg_peer *r_peer; +}; + + +int wg_route_add(struct wg_route_table *, struct wg_peer *, + const struct wg_allowedip *); +int wg_route_delete(struct wg_route_table *, struct wg_peer *); + +/* Noise */ + +/* + * Peer + * + * + * + */ + +struct wg_softc; + +struct wg_hashtable { + struct mtx h_mtx; + SIPHASH_KEY h_secret; + CK_LIST_HEAD(, wg_peer) h_peers_list; + CK_LIST_HEAD(, wg_peer) *h_peers; + u_long h_peers_mask; + size_t h_num_peers; + LIST_HEAD(, noise_keypair) *h_keys; + u_long h_keys_mask; + size_t h_num_keys; +}; + +/* Softc */ +struct wg_softc { + if_softc_ctx_t shared; + if_ctx_t wg_ctx; + struct ifnet *sc_ifp; + uint16_t sc_incoming_port; + uint32_t sc_user_cookie; + + struct wg_socket sc_socket; + struct wg_hashtable sc_hashtable; + struct wg_route_table sc_routes; + + struct mbufq sc_handshake_queue; + struct grouptask sc_handshake; + + struct noise_local sc_local; + struct cookie_checker sc_cookie; + + struct buf_ring *sc_encap_ring; + struct buf_ring *sc_decap_ring; + + struct grouptask *sc_encrypt; + struct grouptask *sc_decrypt; + + struct rwlock sc_index_lock; + LIST_HEAD(,wg_index) *sc_index; + u_long sc_index_mask; + + struct mtx sc_mtx; +}; + +struct wg_tag { + struct m_tag wt_tag; + struct wg_endpoint t_endpoint; + struct wg_peer *t_peer; + struct mbuf *t_mbuf; + sa_family_t t_family; + int t_done; + int t_mtu; +}; + +int wg_route_add(struct wg_route_table *tbl, struct wg_peer *peer, + const struct wg_allowedip *cidr_); + +struct wg_peer *wg_route_lookup(struct wg_route_table *, struct mbuf *, + enum route_direction); + +void wg_peer_remove_all(struct wg_softc *); +struct wg_peer *wg_peer_alloc(struct wg_softc *); +void wg_peer_destroy(struct wg_peer *); + +void wg_hashtable_init(struct wg_hashtable *); +void wg_hashtable_destroy(struct wg_hashtable *); +void wg_hashtable_peer_insert(struct wg_hashtable *, struct wg_peer *); +struct wg_peer *wg_peer_lookup(struct wg_softc *, + const uint8_t [WG_KEY_SIZE]); +void wg_hashtable_peer_remove(struct wg_hashtable *, struct wg_peer *); + + +int wg_queue_out(struct wg_peer *peer, struct mbuf *m); + +int wg_route_init(struct wg_route_table *); +void wg_route_destroy(struct wg_route_table *); + +int wg_socket_init(struct wg_softc *sc); +void wg_socket_reinit(struct wg_softc *, struct socket *so4, + struct socket *so6); +int wg_socket_close(struct wg_socket *so); + +void wg_softc_handshake_receive(struct wg_softc *sc); + +int wg_timers_get_persistent_keepalive(struct wg_timers *, uint16_t *); +void wg_timers_set_persistent_keepalive(struct wg_timers *t, uint16_t); +void wg_timers_get_last_handshake(struct wg_timers *, struct timespec *); + + +struct noise_remote *wg_remote_get(struct wg_softc *, uint8_t [NOISE_KEY_SIZE]); +uint32_t wg_index_set(struct wg_softc *, struct noise_remote *); +struct noise_remote *wg_index_get(struct wg_softc *, uint32_t); +void wg_index_drop(struct wg_softc *, uint32_t); +void wg_encrypt_dispatch(struct wg_softc *); +void wg_decrypt_dispatch(struct wg_softc *); + +struct wg_tag *wg_tag_get(struct mbuf *m); + + +#endif /* _IF_WG_VARS_H_ */ |