10fb6ad5ae/*-
2ec17826ae * Copyright (c) 2016-2018 Yandex LLC
3ec17826ae * Copyright (c) 2016-2018 Andrey V. Elsukov <ae@FreeBSD.org>
40fb6ad5ae * All rights reserved.
50fb6ad5ae *
60fb6ad5ae * Redistribution and use in source and binary forms, with or without
70fb6ad5ae * modification, are permitted provided that the following conditions
80fb6ad5ae * are met:
90fb6ad5ae *
100fb6ad5ae * 1. Redistributions of source code must retain the above copyright
110fb6ad5ae *    notice, this list of conditions and the following disclaimer.
120fb6ad5ae * 2. Redistributions in binary form must reproduce the above copyright
130fb6ad5ae *    notice, this list of conditions and the following disclaimer in the
140fb6ad5ae *    documentation and/or other materials provided with the distribution.
150fb6ad5ae *
160fb6ad5ae * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
170fb6ad5ae * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
180fb6ad5ae * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
190fb6ad5ae * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
200fb6ad5ae * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
210fb6ad5ae * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
220fb6ad5ae * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
230fb6ad5ae * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
240fb6ad5ae * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
250fb6ad5ae * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260fb6ad5ae */
270fb6ad5ae
280fb6ad5ae#include <sys/cdefs.h>
290fb6ad5ae__FBSDID("$FreeBSD$");
300fb6ad5ae
310fb6ad5ae#include "opt_inet.h"
320fb6ad5ae#include "opt_inet6.h"
33006ae8bjhb#include "opt_ipsec.h"
340fb6ad5ae
350fb6ad5ae#include <sys/param.h>
360fb6ad5ae#include <sys/systm.h>
370fb6ad5ae#include <sys/kernel.h>
380fb6ad5ae#include <sys/fnv_hash.h>
390fb6ad5ae#include <sys/jail.h>
400fb6ad5ae#include <sys/lock.h>
410fb6ad5ae#include <sys/malloc.h>
420fb6ad5ae#include <sys/mbuf.h>
430fb6ad5ae#include <sys/module.h>
440fb6ad5ae#include <sys/socket.h>
450fb6ad5ae#include <sys/sockio.h>
460fb6ad5ae#include <sys/sx.h>
470fb6ad5ae#include <sys/errno.h>
480fb6ad5ae#include <sys/sysctl.h>
490fb6ad5ae#include <sys/priv.h>
500fb6ad5ae#include <sys/proc.h>
510fb6ad5ae#include <sys/conf.h>
520fb6ad5ae
530fb6ad5ae#include <net/if.h>
540fb6ad5ae#include <net/if_var.h>
550fb6ad5ae#include <net/if_clone.h>
560fb6ad5ae#include <net/if_types.h>
570fb6ad5ae#include <net/bpf.h>
580fb6ad5ae#include <net/route.h>
590fb6ad5ae#include <net/vnet.h>
600fb6ad5ae
610fb6ad5ae#include <netinet/in.h>
620fb6ad5ae#include <netinet/in_var.h>
630fb6ad5ae#include <netinet/ip.h>
64ec17826ae#include <netinet/ip_encap.h>
650fb6ad5ae
660fb6ad5ae#include <netinet/ip6.h>
670fb6ad5ae#include <netinet6/in6_var.h>
680fb6ad5ae#include <netinet6/scope6_var.h>
690fb6ad5ae
700fb6ad5ae#include <netipsec/ipsec.h>
710fb6ad5ae#ifdef INET6
720fb6ad5ae#include <netipsec/ipsec6.h>
730fb6ad5ae#endif
740fb6ad5ae
750fb6ad5ae#include <net/if_ipsec.h>
760fb6ad5ae#include <netipsec/key.h>
770fb6ad5ae
780fb6ad5ae#include <security/mac/mac_framework.h>
790fb6ad5ae
800fb6ad5aestatic MALLOC_DEFINE(M_IPSEC, "ipsec", "IPsec Virtual Tunnel Interface");
810fb6ad5aestatic const char ipsecname[] = "ipsec";
820fb6ad5ae
830fb6ad5ae#if defined(INET) && defined(INET6)
840fb6ad5ae#define	IPSEC_SPCOUNT		4
850fb6ad5ae#else
860fb6ad5ae#define	IPSEC_SPCOUNT		2
870fb6ad5ae#endif
880fb6ad5ae
890fb6ad5aestruct ipsec_softc {
900fb6ad5ae	struct ifnet		*ifp;
910fb6ad5ae	struct secpolicy	*sp[IPSEC_SPCOUNT];
920fb6ad5ae	uint32_t		reqid;
930fb6ad5ae	u_int			family;
940fb6ad5ae	u_int			fibnum;
95ec17826ae
96ec17826ae	CK_LIST_ENTRY(ipsec_softc) idhash;
97ec17826ae	CK_LIST_ENTRY(ipsec_softc) srchash;
980fb6ad5ae};
990fb6ad5ae
100ec17826ae#define	IPSEC_RLOCK_TRACKER	struct epoch_tracker ipsec_et
101ec17826ae#define	IPSEC_RLOCK()	epoch_enter_preempt(net_epoch_preempt, &ipsec_et)
102ec17826ae#define	IPSEC_RUNLOCK()	epoch_exit_preempt(net_epoch_preempt, &ipsec_et)
103ec17826ae#define	IPSEC_WAIT()	epoch_wait_preempt(net_epoch_preempt)
104ec17826ae
105ec17826ae#ifndef IPSEC_HASH_SIZE
106ec17826ae#define	IPSEC_HASH_SIZE	(1 << 5)
107ec17826ae#endif
108ec17826ae
109ec17826aeCK_LIST_HEAD(ipsec_iflist, ipsec_softc);
110ec17826aeVNET_DEFINE_STATIC(struct ipsec_iflist *, ipsec_idhtbl) = NULL;
111ec17826ae#define	V_ipsec_idhtbl		VNET(ipsec_idhtbl)
112ec17826ae
113ec17826ae#ifdef INET
114ec17826aeVNET_DEFINE_STATIC(struct ipsec_iflist *, ipsec4_srchtbl) = NULL;
115ec17826ae#define	V_ipsec4_srchtbl	VNET(ipsec4_srchtbl)
116ec17826aestatic const struct srcaddrtab *ipsec4_srctab = NULL;
117ec17826ae#endif
118ec17826ae
119ec17826ae#ifdef INET6
120ec17826aeVNET_DEFINE_STATIC(struct ipsec_iflist *, ipsec6_srchtbl) = NULL;
121ec17826ae#define	V_ipsec6_srchtbl	VNET(ipsec6_srchtbl)
122ec17826aestatic const struct srcaddrtab *ipsec6_srctab = NULL;
123ec17826ae#endif
124ec17826ae
125ec17826aestatic struct ipsec_iflist *
126ec17826aeipsec_idhash(uint32_t id)
1270fb6ad5ae{
1280fb6ad5ae
129ec17826ae	return (&V_ipsec_idhtbl[fnv_32_buf(&id, sizeof(id),
130ec17826ae	    FNV1_32_INIT) & (IPSEC_HASH_SIZE - 1)]);
1310fb6ad5ae}
1320fb6ad5ae
133ec17826aestatic struct ipsec_iflist *
134ec17826aeipsec_srchash(const struct sockaddr *sa)
135ec17826ae{
136ec17826ae	uint32_t hval;
137ec17826ae
138ec17826ae	switch (sa->sa_family) {
139ec17826ae#ifdef INET
140ec17826ae	case AF_INET:
141ec17826ae		hval = fnv_32_buf(
142ec17826ae		    &((const struct sockaddr_in *)sa)->sin_addr.s_addr,
143ec17826ae		    sizeof(in_addr_t), FNV1_32_INIT);
144ec17826ae		return (&V_ipsec4_srchtbl[hval & (IPSEC_HASH_SIZE - 1)]);
145ec17826ae#endif
146ec17826ae#ifdef INET6
147ec17826ae	case AF_INET6:
148ec17826ae		hval = fnv_32_buf(
149ec17826ae		    &((const struct sockaddr_in6 *)sa)->sin6_addr,
150ec17826ae		    sizeof(struct in6_addr), FNV1_32_INIT);
151ec17826ae		return (&V_ipsec6_srchtbl[hval & (IPSEC_HASH_SIZE - 1)]);
152ec17826ae#endif
153ec17826ae	}
154ec17826ae	return (NULL);
155ec17826ae}
1560fb6ad5ae
1570fb6ad5ae/*
1580fb6ad5ae * ipsec_ioctl_sx protects from concurrent ioctls.
1590fb6ad5ae */
1600fb6ad5aestatic struct sx ipsec_ioctl_sx;
1610fb6ad5aeSX_SYSINIT(ipsec_ioctl_sx, &ipsec_ioctl_sx, "ipsec_ioctl");
1620fb6ad5ae
1630fb6ad5aestatic int	ipsec_init_reqid(struct ipsec_softc *);
1640fb6ad5aestatic int	ipsec_set_tunnel(struct ipsec_softc *, struct sockaddr *,
1650fb6ad5ae    struct sockaddr *, uint32_t);
166ec17826aestatic void	ipsec_delete_tunnel(struct ipsec_softc *);
1670fb6ad5ae
1680fb6ad5aestatic int	ipsec_set_addresses(struct ifnet *, struct sockaddr *,
1690fb6ad5ae    struct sockaddr *);
170ec17826aestatic int	ipsec_set_reqid(struct ipsec_softc *, uint32_t);
171ec17826aestatic void	ipsec_set_running(struct ipsec_softc *);
1720fb6ad5ae
173ba20cd0ae#ifdef VIMAGE
174ba20cd0aestatic void	ipsec_reassign(struct ifnet *, struct vnet *, char *);
175ba20cd0ae#endif
176ec17826aestatic void	ipsec_srcaddr(void *, const struct sockaddr *, int);
1770fb6ad5aestatic int	ipsec_ioctl(struct ifnet *, u_long, caddr_t);
1780fb6ad5aestatic int	ipsec_transmit(struct ifnet *, struct mbuf *);
1790fb6ad5aestatic int	ipsec_output(struct ifnet *, struct mbuf *,
1800fb6ad5ae    const struct sockaddr *, struct route *);
1810fb6ad5aestatic void	ipsec_qflush(struct ifnet *);
1820fb6ad5aestatic int	ipsec_clone_create(struct if_clone *, int, caddr_t);
1830fb6ad5aestatic void	ipsec_clone_destroy(struct ifnet *);
184