1/*-
2 * Copyright (c) 2016 Yandex LLC
3 * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: stable/11/sys/net/if_ipsec.c 365277 2020-09-02 20:36:33Z jhb $");
30
31#include "opt_inet.h"
32#include "opt_inet6.h"
33#include "opt_ipsec.h"
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/fnv_hash.h>
39#include <sys/jail.h>
40#include <sys/lock.h>
41#include <sys/malloc.h>
42#include <sys/mbuf.h>
43#include <sys/module.h>
44#include <sys/rmlock.h>
45#include <sys/socket.h>
46#include <sys/sockio.h>
47#include <sys/sx.h>
48#include <sys/errno.h>
49#include <sys/sysctl.h>
50#include <sys/priv.h>
51#include <sys/proc.h>
52#include <sys/conf.h>
53
54#include <net/if.h>
55#include <net/if_var.h>
56#include <net/if_clone.h>
57#include <net/if_types.h>
58#include <net/bpf.h>
59#include <net/route.h>
60#include <net/vnet.h>
61
62#include <netinet/in.h>
63#include <netinet/in_var.h>
64#include <netinet/ip.h>
65
66#include <netinet/ip6.h>
67#include <netinet6/in6_var.h>
68#include <netinet6/scope6_var.h>
69
70#include <netipsec/ipsec.h>
71#ifdef INET6
72#include <netipsec/ipsec6.h>
73#endif
74
75#include <net/if_ipsec.h>
76#include <netipsec/key.h>
77
78#include <security/mac/mac_framework.h>
79
80static MALLOC_DEFINE(M_IPSEC, "ipsec", "IPsec Virtual Tunnel Interface");
81static const char ipsecname[] = "ipsec";
82
83#if defined(INET) && defined(INET6)
84#define	IPSEC_SPCOUNT		4
85#else
86#define	IPSEC_SPCOUNT		2
87#endif
88
89struct ipsec_softc {
90	struct ifnet		*ifp;
91
92	struct rmlock		lock;
93	struct secpolicy	*sp[IPSEC_SPCOUNT];
94
95	uint32_t		reqid;
96	u_int			family;
97	u_int			fibnum;
98	LIST_ENTRY(ipsec_softc)	chain;
99	LIST_ENTRY(ipsec_softc) hash;
100};
101
102#define	IPSEC_LOCK_INIT(sc)	rm_init(&(sc)->lock, "if_ipsec softc")
103#define	IPSEC_LOCK_DESTROY(sc)	rm_destroy(&(sc)->lock)
104#define	IPSEC_RLOCK_TRACKER	struct rm_priotracker ipsec_tracker
105#define	IPSEC_RLOCK(sc)		rm_rlock(&(sc)->lock, &ipsec_tracker)
106#define	IPSEC_RUNLOCK(sc)	rm_runlock(&(sc)->lock, &ipsec_tracker)
107#define	IPSEC_RLOCK_ASSERT(sc)	rm_assert(&(sc)->lock, RA_RLOCKED)
108#define	IPSEC_WLOCK(sc)		rm_wlock(&(sc)->lock)
109#define	IPSEC_WUNLOCK(sc)	rm_wunlock(&(sc)->lock)
110#define	IPSEC_WLOCK_ASSERT(sc)	rm_assert(&(sc)->lock, RA_WLOCKED)
111
112static struct rmlock ipsec_sc_lock;
113RM_SYSINIT(ipsec_sc_lock, &ipsec_sc_lock, "if_ipsec softc list");
114
115#define	IPSEC_SC_RLOCK_TRACKER	struct rm_priotracker ipsec_sc_tracker
116#define	IPSEC_SC_RLOCK()	rm_rlock(&ipsec_sc_lock, &ipsec_sc_tracker)
117#define	IPSEC_SC_RUNLOCK()	rm_runlock(&ipsec_sc_lock, &ipsec_sc_tracker)
118#define	IPSEC_SC_RLOCK_ASSERT()	rm_assert(&ipsec_sc_lock, RA_RLOCKED)
119#define	IPSEC_SC_WLOCK()	rm_wlock(&ipsec_sc_lock)
120#define	IPSEC_SC_WUNLOCK()	rm_wunlock(&ipsec_sc_lock)
121#define	IPSEC_SC_WLOCK_ASSERT()	rm_assert(&ipsec_sc_lock, RA_WLOCKED)
122
123LIST_HEAD(ipsec_iflist, ipsec_softc);
124static VNET_DEFINE(struct ipsec_iflist, ipsec_sc_list);
125static VNET_DEFINE(struct ipsec_iflist *, ipsec_sc_htbl);
126static VNET_DEFINE(u_long, ipsec_sc_hmask);
127#define	V_ipsec_sc_list		VNET(ipsec_sc_list)
128#define	V_ipsec_sc_htbl		VNET(ipsec_sc_htbl)
129#define	V_ipsec_sc_hmask	VNET(ipsec_sc_hmask)
130
131static uint32_t
132ipsec_hash(uint32_t id)
133{
134
135	return (fnv_32_buf(&id, sizeof(id), FNV1_32_INIT));
136}
137
138#define	SCHASH_NHASH_LOG2	5
139#define	SCHASH_NHASH		(1 << SCHASH_NHASH_LOG2)
140#define	SCHASH_HASHVAL(id)	(ipsec_hash((id)) & V_ipsec_sc_hmask)
141#define	SCHASH_HASH(id)		&V_ipsec_sc_htbl[SCHASH_HASHVAL(id)]
142
143/*
144 * ipsec_ioctl_sx protects from concurrent ioctls.
145 */
146static struct sx ipsec_ioctl_sx;
147SX_SYSINIT(ipsec_ioctl_sx, &ipsec_ioctl_sx, "ipsec_ioctl");
148
149static int	ipsec_init_reqid(struct ipsec_softc *);
150static int	ipsec_set_tunnel(struct ipsec_softc *, struct sockaddr *,
151    struct sockaddr *, uint32_t);
152static void	ipsec_delete_tunnel(struct ifnet *, int);
153
154static int	ipsec_set_addresses(struct ifnet *, struct sockaddr *,
155    struct sockaddr *);
156static int	ipsec_set_reqid(struct ifnet *, uint32_t);
157
158static int	ipsec_ioctl(struct ifnet *, u_long, caddr_t);
159static int	ipsec_transmit(struct ifnet *, struct mbuf *);
160static int	ipsec_output(struct ifnet *, struct mbuf *,
161    const struct sockaddr *, struct route *);
162static void	ipsec_qflush(struct ifnet *);
163static int	ipsec_clone_create(struct if_clone *, int, caddr_t);
164static void	ipsec_clone_destroy(struct ifnet *);
165
166static VNET_DEFINE(struct if_clone *, ipsec_cloner);
167#define	V_ipsec_cloner		VNET(ipsec_cloner)
168
169static int
170ipsec_clone_create(struct if_clone *ifc, int unit, caddr_t params)
171{
172	struct ipsec_softc *sc;
173	struct ifnet *ifp;
174
175	sc = malloc(sizeof(*sc), M_IPSEC, M_WAITOK | M_ZERO);
176	sc->fibnum = curthread->td_proc->p_fibnum;
177	sc->ifp = ifp = if_alloc(IFT_TUNNEL);
178	IPSEC_LOCK_INIT(sc);
179	ifp->if_softc = sc;
180	if_initname(ifp, ipsecname, unit);
181
182	ifp->if_addrlen = 0;
183	ifp->if_mtu = IPSEC_MTU;
184	ifp->if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
185	ifp->if_ioctl  = ipsec_ioctl;
186	ifp->if_transmit  = ipsec_transmit;
187	ifp->if_qflush  = ipsec_qflush;
188	ifp->if_output = ipsec_output;
189	if_attach(ifp);
190	bpfattach(ifp, DLT_NULL, sizeof(uint32_t));
191
192	IPSEC_SC_WLOCK();
193	LIST_INSERT_HEAD(&V_ipsec_sc_list, sc, chain);
194	IPSEC_SC_WUNLOCK();
195	return (0);
196}
197
198static void
199ipsec_clone_destroy(struct ifnet *ifp)
200{
201	struct ipsec_softc *sc;
202
203	sx_xlock(&ipsec_ioctl_sx);
204	sc = ifp->if_softc;
205
206	IPSEC_SC_WLOCK();
207	ipsec_delete_tunnel(ifp, 1);
208	LIST_REMOVE(sc, chain);
209	IPSEC_SC_WUNLOCK();
210
211	bpfdetach(ifp);
212	if_detach(ifp);
213	ifp->if_softc = NULL;
214	sx_xunlock(&ipsec_ioctl_sx);
215
216	if_free(ifp);
217	IPSEC_LOCK_DESTROY(sc);
218	free(sc, M_IPSEC);
219}
220
221static void
222vnet_ipsec_init(const void *unused __unused)
223{
224
225	LIST_INIT(&V_ipsec_sc_list);
226	V_ipsec_sc_htbl = hashinit(SCHASH_NHASH, M_IPSEC, &V_ipsec_sc_hmask);
227	V_ipsec_cloner = if_clone_simple(ipsecname, ipsec_clone_create,
228	    ipsec_clone_destroy, 0);
229}
230VNET_SYSINIT(vnet_ipsec_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
231    vnet_ipsec_init, NULL);
232
233static void
234vnet_ipsec_uninit(const void *unused __unused)
235{
236
237	if_clone_detach(V_ipsec_cloner);
238	hashdestroy(V_ipsec_sc_htbl, M_IPSEC, V_ipsec_sc_hmask);
239}
240VNET_SYSUNINIT(vnet_ipsec_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
241    vnet_ipsec_uninit, NULL);
242
243static struct secpolicy *
244ipsec_getpolicy(struct ipsec_softc *sc, int dir, sa_family_t af)
245{
246
247	switch (af) {
248#ifdef INET
249	case AF_INET:
250		return (sc->sp[(dir == IPSEC_DIR_INBOUND ? 0: 1)]);
251#endif
252#ifdef INET6
253	case AF_INET6:
254		return (sc->sp[(dir == IPSEC_DIR_INBOUND ? 0: 1)
255#ifdef INET
256			+ 2
257#endif
258		]);
259#endif
260	}
261	return (NULL);
262}
263
264static struct secasindex *
265ipsec_getsaidx(struct ipsec_softc *sc, int dir, sa_family_t af)
266{
267	struct secpolicy *sp;
268
269	sp = ipsec_getpolicy(sc, dir, af);
270	if (sp == NULL)
271		return (NULL);
272	return (&sp->req[0]->saidx);
273}
274
275static int
276ipsec_transmit(struct ifnet *ifp, struct mbuf *m)
277{
278	IPSEC_RLOCK_TRACKER;
279	struct ipsec_softc *sc;
280	struct secpolicy *sp;
281	struct ip *ip;
282	uint32_t af;
283	int error;
284
285#ifdef MAC
286	error = mac_ifnet_check_transmit(ifp, m);
287	if (error) {
288		m_freem(m);
289		goto err;
290	}
291#endif
292	error = ENETDOWN;
293	sc = ifp->if_softc;
294	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
295	    (ifp->if_flags & IFF_MONITOR) != 0 ||
296	    (ifp->if_flags & IFF_UP) == 0) {
297		m_freem(m);
298		goto err;
299	}
300
301	/* Determine address family to correctly handle packet in BPF */
302	ip = mtod(m, struct ip *);
303	switch (ip->ip_v) {
304#ifdef INET
305	case IPVERSION:
306		af = AF_INET;
307		break;
308#endif
309#ifdef INET6
310	case (IPV6_VERSION >> 4):
311		af = AF_INET6;
312		break;
313#endif
314	default:
315		error = EAFNOSUPPORT;
316		m_freem(m);
317		goto err;
318	}
319
320	/*
321	 * Loop prevention.
322	 * XXX: for now just check presence of IPSEC_OUT_DONE mbuf tag.
323	 *      We can read full chain and compare destination address,
324	 *      proto and mode from xform_history with values from softc.
325	 */
326	if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) {
327		m_freem(m);
328		goto err;
329	}
330
331	IPSEC_RLOCK(sc);
332	if (sc->family == 0) {
333		IPSEC_RUNLOCK(sc);
334		m_freem(m);
335		goto err;
336	}
337	sp = ipsec_getpolicy(sc, IPSEC_DIR_OUTBOUND, af);
338	key_addref(sp);
339	M_SETFIB(m, sc->fibnum);
340	IPSEC_RUNLOCK(sc);
341
342	BPF_MTAP2(ifp, &af, sizeof(af), m);
343	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
344	if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
345
346	switch (af) {
347#ifdef INET
348	case AF_INET:
349		error = ipsec4_process_packet(m, sp, NULL);
350		break;
351#endif
352#ifdef INET6
353	case AF_INET6:
354		error = ipsec6_process_packet(m, sp, NULL);
355		break;
356#endif
357	default:
358		panic("%s: unknown address family\n", __func__);
359	}
360err:
361	if (error != 0)
362		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
363	return (error);
364}
365
366static void
367ipsec_qflush(struct ifnet *ifp __unused)
368{
369
370}
371
372static int
373ipsec_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
374	struct route *ro)
375{
376
377	return (ifp->if_transmit(ifp, m));
378}
379
380int
381ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af)
382{
383	IPSEC_SC_RLOCK_TRACKER;
384	struct secasindex *saidx;
385	struct ipsec_softc *sc;
386	struct ifnet *ifp;
387
388	if (sav->state != SADB_SASTATE_MATURE &&
389	    sav->state != SADB_SASTATE_DYING) {
390		m_freem(m);
391		return (ENETDOWN);
392	}
393
394	if (sav->sah->saidx.mode != IPSEC_MODE_TUNNEL ||
395	    sav->sah->saidx.proto != IPPROTO_ESP)
396		return (0);
397
398	IPSEC_SC_RLOCK();
399	/*
400	 * We only acquire SC_RLOCK() while we are doing search in
401	 * ipsec_sc_htbl. It is safe, because removing softc or changing
402	 * of reqid/addresses requires removing from hash table.
403	 */
404	LIST_FOREACH(sc, SCHASH_HASH(sav->sah->saidx.reqid), hash) {
405		saidx = ipsec_getsaidx(sc, IPSEC_DIR_INBOUND,
406		    sav->sah->saidx.src.sa.sa_family);
407		/* SA's reqid should match reqid in SP */
408		if (saidx == NULL ||
409		    sav->sah->saidx.reqid != saidx->reqid)
410			continue;
411		/* SAH's addresses should match tunnel endpoints. */
412		if (key_sockaddrcmp(&sav->sah->saidx.dst.sa,
413		    &saidx->dst.sa, 0) != 0)
414			continue;
415		if (key_sockaddrcmp(&sav->sah->saidx.src.sa,
416		    &saidx->src.sa, 0) == 0)
417			break;
418	}
419	if (sc == NULL) {
420		IPSEC_SC_RUNLOCK();
421		/* Tunnel was not found. Nothing to do. */
422		return (0);
423	}
424	ifp = sc->ifp;
425	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
426	    (ifp->if_flags & IFF_UP) == 0) {
427		IPSEC_SC_RUNLOCK();
428		m_freem(m);
429		return (ENETDOWN);
430	}
431	/*
432	 * We found matching and working tunnel.
433	 * Set its ifnet as receiving interface.
434	 */
435	m->m_pkthdr.rcvif = ifp;
436	IPSEC_SC_RUNLOCK();
437
438	m_clrprotoflags(m);
439	M_SETFIB(m, ifp->if_fib);
440	BPF_MTAP2(ifp, &af, sizeof(af), m);
441	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
442	if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
443	if ((ifp->if_flags & IFF_MONITOR) != 0) {
444		m_freem(m);
445		return (ENETDOWN);
446	}
447	return (0);
448}
449
450/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
451int
452ipsec_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
453{
454	IPSEC_RLOCK_TRACKER;
455	struct ifreq *ifr = (struct ifreq*)data;
456	struct sockaddr *dst, *src;
457	struct ipsec_softc *sc;
458	struct secasindex *saidx;
459#ifdef INET
460	struct sockaddr_in *sin = NULL;
461#endif
462#ifdef INET6
463	struct sockaddr_in6 *sin6 = NULL;
464#endif
465	uint32_t reqid;
466	int error;
467
468	switch (cmd) {
469	case SIOCSIFADDR:
470		ifp->if_flags |= IFF_UP;
471	case SIOCADDMULTI:
472	case SIOCDELMULTI:
473	case SIOCGIFMTU:
474	case SIOCSIFFLAGS:
475		return (0);
476	case SIOCSIFMTU:
477		if (ifr->ifr_mtu < IPSEC_MTU_MIN ||
478		    ifr->ifr_mtu > IPSEC_MTU_MAX)
479			return (EINVAL);
480		else
481			ifp->if_mtu = ifr->ifr_mtu;
482		return (0);
483	}
484	sx_xlock(&ipsec_ioctl_sx);
485	sc = ifp->if_softc;
486	/* Check that softc is still here */
487	if (sc == NULL) {
488		error = ENXIO;
489		goto bad;
490	}
491	error = 0;
492	switch (cmd) {
493	case SIOCSIFPHYADDR:
494#ifdef INET6
495	case SIOCSIFPHYADDR_IN6:
496#endif
497		error = EINVAL;
498		switch (cmd) {
499#ifdef INET
500		case SIOCSIFPHYADDR:
501			src = (struct sockaddr *)
502				&(((struct in_aliasreq *)data)->ifra_addr);
503			dst = (struct sockaddr *)
504				&(((struct in_aliasreq *)data)->ifra_dstaddr);
505			break;
506#endif
507#ifdef INET6
508		case SIOCSIFPHYADDR_IN6:
509			src = (struct sockaddr *)
510				&(((struct in6_aliasreq *)data)->ifra_addr);
511			dst = (struct sockaddr *)
512				&(((struct in6_aliasreq *)data)->ifra_dstaddr);
513			break;
514#endif
515		default:
516			goto bad;
517		}
518		/* sa_family must be equal */
519		if (src->sa_family != dst->sa_family ||
520		    src->sa_len != dst->sa_len)
521			goto bad;
522
523		/* validate sa_len */
524		switch (src->sa_family) {
525#ifdef INET
526		case AF_INET:
527			if (src->sa_len != sizeof(struct sockaddr_in))
528				goto bad;
529			break;
530#endif
531#ifdef INET6
532		case AF_INET6:
533			if (src->sa_len != sizeof(struct sockaddr_in6))
534				goto bad;
535			break;
536#endif
537		default:
538			error = EAFNOSUPPORT;
539			goto bad;
540		}
541		/* check sa_family looks sane for the cmd */
542		error = EAFNOSUPPORT;
543		switch (cmd) {
544#ifdef INET
545		case SIOCSIFPHYADDR:
546			if (src->sa_family == AF_INET)
547				break;
548			goto bad;
549#endif
550#ifdef INET6
551		case SIOCSIFPHYADDR_IN6:
552			if (src->sa_family == AF_INET6)
553				break;
554			goto bad;
555#endif
556		}
557		error = EADDRNOTAVAIL;
558		switch (src->sa_family) {
559#ifdef INET
560		case AF_INET:
561			if (satosin(src)->sin_addr.s_addr == INADDR_ANY ||
562			    satosin(dst)->sin_addr.s_addr == INADDR_ANY)
563				goto bad;
564			break;
565#endif
566#ifdef INET6
567		case AF_INET6:
568			if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)
569			    ||
570			    IN6_IS_ADDR_UNSPECIFIED(&satosin6(dst)->sin6_addr))
571				goto bad;
572			/*
573			 * Check validity of the scope zone ID of the
574			 * addresses, and convert it into the kernel
575			 * internal form if necessary.
576			 */
577			error = sa6_embedscope(satosin6(src), 0);
578			if (error != 0)
579				goto bad;
580			error = sa6_embedscope(satosin6(dst), 0);
581			if (error != 0)
582				goto bad;
583#endif
584		};
585		error = ipsec_set_addresses(ifp, src, dst);
586		break;
587	case SIOCDIFPHYADDR:
588		ipsec_delete_tunnel(ifp, 0);
589		break;
590	case SIOCGIFPSRCADDR:
591	case SIOCGIFPDSTADDR:
592#ifdef INET6
593	case SIOCGIFPSRCADDR_IN6:
594	case SIOCGIFPDSTADDR_IN6:
595#endif
596		IPSEC_RLOCK(sc);
597		if (sc->family == 0) {
598			IPSEC_RUNLOCK(sc);
599			error = EADDRNOTAVAIL;
600			break;
601		}
602		saidx = ipsec_getsaidx(sc, IPSEC_DIR_OUTBOUND, sc->family);
603		switch (cmd) {
604#ifdef INET
605		case SIOCGIFPSRCADDR:
606		case SIOCGIFPDSTADDR:
607			if (saidx->src.sa.sa_family != AF_INET) {
608				error = EADDRNOTAVAIL;
609				break;
610			}
611			sin = (struct sockaddr_in *)&ifr->ifr_addr;
612			memset(sin, 0, sizeof(*sin));
613			sin->sin_family = AF_INET;
614			sin->sin_len = sizeof(*sin);
615			break;
616#endif
617#ifdef INET6
618		case SIOCGIFPSRCADDR_IN6:
619		case SIOCGIFPDSTADDR_IN6:
620			if (saidx->src.sa.sa_family != AF_INET6) {
621				error = EADDRNOTAVAIL;
622				break;
623			}
624			sin6 = (struct sockaddr_in6 *)
625				&(((struct in6_ifreq *)data)->ifr_addr);
626			memset(sin6, 0, sizeof(*sin6));
627			sin6->sin6_family = AF_INET6;
628			sin6->sin6_len = sizeof(*sin6);
629			break;
630#endif
631		default:
632			error = EAFNOSUPPORT;
633		}
634		if (error == 0) {
635			switch (cmd) {
636#ifdef INET
637			case SIOCGIFPSRCADDR:
638				sin->sin_addr = saidx->src.sin.sin_addr;
639				break;
640			case SIOCGIFPDSTADDR:
641				sin->sin_addr = saidx->dst.sin.sin_addr;
642				break;
643#endif
644#ifdef INET6
645			case SIOCGIFPSRCADDR_IN6:
646				sin6->sin6_addr = saidx->src.sin6.sin6_addr;
647				break;
648			case SIOCGIFPDSTADDR_IN6:
649				sin6->sin6_addr = saidx->dst.sin6.sin6_addr;
650				break;
651#endif
652			}
653		}
654		IPSEC_RUNLOCK(sc);
655		if (error != 0)
656			break;
657		switch (cmd) {
658#ifdef INET
659		case SIOCGIFPSRCADDR:
660		case SIOCGIFPDSTADDR:
661			error = prison_if(curthread->td_ucred,
662			    (struct sockaddr *)sin);
663			if (error != 0)
664				memset(sin, 0, sizeof(*sin));
665			break;
666#endif
667#ifdef INET6
668		case SIOCGIFPSRCADDR_IN6:
669		case SIOCGIFPDSTADDR_IN6:
670			error = prison_if(curthread->td_ucred,
671			    (struct sockaddr *)sin6);
672			if (error == 0)
673				error = sa6_recoverscope(sin6);
674			if (error != 0)
675				memset(sin6, 0, sizeof(*sin6));
676#endif
677		}
678		break;
679	case SIOCGTUNFIB:
680		ifr->ifr_fib = sc->fibnum;
681		break;
682	case SIOCSTUNFIB:
683		if ((error = priv_check(curthread, PRIV_NET_SETIFFIB)) != 0)
684			break;
685		if (ifr->ifr_fib >= rt_numfibs)
686			error = EINVAL;
687		else
688			sc->fibnum = ifr->ifr_fib;
689		break;
690	case IPSECGREQID:
691		reqid = sc->reqid;
692		error = copyout(&reqid, ifr_data_get_ptr(ifr), sizeof(reqid));
693		break;
694	case IPSECSREQID:
695		if ((error = priv_check(curthread, PRIV_NET_SETIFCAP)) != 0)
696			break;
697		error = copyin(ifr_data_get_ptr(ifr), &reqid, sizeof(reqid));
698		if (error != 0)
699			break;
700		error = ipsec_set_reqid(ifp, reqid);
701		break;
702	default:
703		error = EINVAL;
704		break;
705	}
706bad:
707	sx_xunlock(&ipsec_ioctl_sx);
708	return (error);
709}
710
711/*
712 * Allocate new private security policies for tunneling interface.
713 * Each tunneling interface has following security policies for
714 * both AF:
715 *   0.0.0.0/0[any] 0.0.0.0/0[any] -P in \
716 *	ipsec esp/tunnel/RemoteIP-LocalIP/unique:reqid
717 *   0.0.0.0/0[any] 0.0.0.0/0[any] -P out \
718 *	ipsec esp/tunnel/LocalIP-RemoteIP/unique:reqid
719 */
720static int
721ipsec_newpolicies(struct ipsec_softc *sc, struct secpolicy *sp[IPSEC_SPCOUNT],
722    const struct sockaddr *src, const struct sockaddr *dst, uint32_t reqid)
723{
724	struct ipsecrequest *isr;
725	int i;
726
727	memset(sp, 0, sizeof(struct secpolicy *) * IPSEC_SPCOUNT);
728	for (i = 0; i < IPSEC_SPCOUNT; i++) {
729		if ((sp[i] = key_newsp()) == NULL)
730			goto fail;
731		if ((isr = ipsec_newisr()) == NULL)
732			goto fail;
733
734		sp[i]->policy = IPSEC_POLICY_IPSEC;
735		sp[i]->state = IPSEC_SPSTATE_DEAD;
736		sp[i]->req[sp[i]->tcount++] = isr;
737		sp[i]->created = time_second;
738		/* Use priority field to store if_index */
739		sp[i]->priority = sc->ifp->if_index;
740		isr->level = IPSEC_LEVEL_UNIQUE;
741		isr->saidx.proto = IPPROTO_ESP;
742		isr->saidx.mode = IPSEC_MODE_TUNNEL;
743		isr->saidx.reqid = reqid;
744		if (i % 2 == 0) {
745			sp[i]->spidx.dir = IPSEC_DIR_INBOUND;
746			bcopy(src, &isr->saidx.dst, src->sa_len);
747			bcopy(dst, &isr->saidx.src, dst->sa_len);
748		} else {
749			sp[i]->spidx.dir = IPSEC_DIR_OUTBOUND;
750			bcopy(src, &isr->saidx.src, src->sa_len);
751			bcopy(dst, &isr->saidx.dst, dst->sa_len);
752		}
753		sp[i]->spidx.ul_proto = IPSEC_ULPROTO_ANY;
754#ifdef INET
755		if (i < 2) {
756			sp[i]->spidx.src.sa.sa_family =
757			    sp[i]->spidx.dst.sa.sa_family = AF_INET;
758			sp[i]->spidx.src.sa.sa_len =
759			    sp[i]->spidx.dst.sa.sa_len =
760			    sizeof(struct sockaddr_in);
761			continue;
762		}
763#endif
764#ifdef INET6
765		sp[i]->spidx.src.sa.sa_family =
766		    sp[i]->spidx.dst.sa.sa_family = AF_INET6;
767		sp[i]->spidx.src.sa.sa_len =
768		    sp[i]->spidx.dst.sa.sa_len = sizeof(struct sockaddr_in6);
769#endif
770	}
771	return (0);
772fail:
773	for (i = 0; i < IPSEC_SPCOUNT; i++)
774		key_freesp(&sp[i]);
775	return (ENOMEM);
776}
777
778static int
779ipsec_check_reqid(uint32_t reqid)
780{
781	struct ipsec_softc *sc;
782
783	IPSEC_SC_RLOCK_ASSERT();
784	LIST_FOREACH(sc, &V_ipsec_sc_list, chain) {
785		if (sc->reqid == reqid)
786			return (EEXIST);
787	}
788	return (0);
789}
790
791/*
792 * We use key_newreqid() to automatically obtain unique reqid.
793 * Then we check that given id is unique, i.e. it is not used by
794 * another if_ipsec(4) interface. This macro limits the number of
795 * tries to get unique id.
796 */
797#define	IPSEC_REQID_TRYCNT	64
798static int
799ipsec_init_reqid(struct ipsec_softc *sc)
800{
801	uint32_t reqid;
802	int trycount;
803
804	IPSEC_SC_RLOCK_ASSERT();
805
806	if (sc->reqid != 0) /* already initialized */
807		return (0);
808
809	trycount = IPSEC_REQID_TRYCNT;
810	while (--trycount > 0) {
811		reqid = key_newreqid();
812		if (ipsec_check_reqid(reqid) == 0)
813			break;
814	}
815	if (trycount == 0)
816		return (EEXIST);
817	sc->reqid = reqid;
818	return (0);
819}
820
821/*
822 * Set or update reqid for given tunneling interface.
823 * When specified reqid is zero, generate new one.
824 * We are protected by ioctl_sx lock from concurrent id generation.
825 * Also softc would not disappear while we hold ioctl_sx lock.
826 */
827static int
828ipsec_set_reqid(struct ifnet *ifp, uint32_t reqid)
829{
830	IPSEC_SC_RLOCK_TRACKER;
831	struct ipsec_softc *sc;
832	struct secasindex *saidx;
833
834	sx_assert(&ipsec_ioctl_sx, SA_XLOCKED);
835
836	sc = ifp->if_softc;
837	if (sc->reqid == reqid && reqid != 0)
838		return (0);
839
840	IPSEC_SC_RLOCK();
841	if (reqid != 0) {
842		/* Check that specified reqid doesn't exist */
843		if (ipsec_check_reqid(reqid) != 0) {
844			IPSEC_SC_RUNLOCK();
845			return (EEXIST);
846		}
847		sc->reqid = reqid;
848	} else {
849		/* Generate new reqid */
850		if (ipsec_init_reqid(sc) != 0) {
851			IPSEC_SC_RUNLOCK();
852			return (EEXIST);
853		}
854	}
855	IPSEC_SC_RUNLOCK();
856
857	/* Tunnel isn't fully configured, just return. */
858	if (sc->family == 0)
859		return (0);
860
861	saidx = ipsec_getsaidx(sc, IPSEC_DIR_OUTBOUND, sc->family);
862	KASSERT(saidx != NULL,
863	    ("saidx is NULL, but family is %d", sc->family));
864	return (ipsec_set_tunnel(sc, &saidx->src.sa, &saidx->dst.sa,
865	    sc->reqid));
866}
867
868/*
869 * Set tunnel endpoints addresses.
870 */
871static int
872ipsec_set_addresses(struct ifnet *ifp, struct sockaddr *src,
873    struct sockaddr *dst)
874{
875	IPSEC_SC_RLOCK_TRACKER;
876	struct ipsec_softc *sc, *tsc;
877	struct secasindex *saidx;
878
879	sx_assert(&ipsec_ioctl_sx, SA_XLOCKED);
880
881	sc = ifp->if_softc;
882	if (sc->family != 0) {
883		saidx = ipsec_getsaidx(sc, IPSEC_DIR_OUTBOUND,
884		    src->sa_family);
885		if (saidx != NULL && saidx->reqid == sc->reqid &&
886		    key_sockaddrcmp(&saidx->src.sa, src, 0) == 0 &&
887		    key_sockaddrcmp(&saidx->dst.sa, dst, 0) == 0)
888			return (0); /* Nothing has been changed. */
889
890	}
891	/*
892	 * We cannot service IPsec tunnel when source address is
893	 * not our own.
894	 */
895#ifdef INET
896	if (src->sa_family == AF_INET &&
897	    in_localip(satosin(src)->sin_addr) == 0)
898		return (EADDRNOTAVAIL);
899#endif
900#ifdef INET6
901	/*
902	 * NOTE: IPv6 addresses are in kernel internal form with
903	 * embedded scope zone id.
904	 */
905	if (src->sa_family == AF_INET6 &&
906	    in6_localip(&satosin6(src)->sin6_addr) == 0)
907		return (EADDRNOTAVAIL);
908#endif
909	/* Check that given addresses aren't already configured */
910	IPSEC_SC_RLOCK();
911	LIST_FOREACH(tsc, &V_ipsec_sc_list, chain) {
912		if (tsc == sc || tsc->family != src->sa_family)
913			continue;
914		saidx = ipsec_getsaidx(tsc, IPSEC_DIR_OUTBOUND, tsc->family);
915		if (key_sockaddrcmp(&saidx->src.sa, src, 0) == 0 &&
916		    key_sockaddrcmp(&saidx->dst.sa, dst, 0) == 0) {
917			/* We already have tunnel with such addresses */
918			IPSEC_SC_RUNLOCK();
919			return (EADDRNOTAVAIL);
920		}
921	}
922	/* If reqid is not set, generate new one. */
923	if (ipsec_init_reqid(sc) != 0) {
924		IPSEC_SC_RUNLOCK();
925		return (EEXIST);
926	}
927	IPSEC_SC_RUNLOCK();
928	return (ipsec_set_tunnel(sc, src, dst, sc->reqid));
929}
930
931static int
932ipsec_set_tunnel(struct ipsec_softc *sc, struct sockaddr *src,
933    struct sockaddr *dst, uint32_t reqid)
934{
935	struct secpolicy *sp[IPSEC_SPCOUNT];
936	struct secpolicy *oldsp[IPSEC_SPCOUNT];
937	int i, f;
938
939	sx_assert(&ipsec_ioctl_sx, SA_XLOCKED);
940
941	/* Allocate SP with new addresses. */
942	if (ipsec_newpolicies(sc, sp, src, dst, reqid) == 0) {
943		/* Add new policies to SPDB */
944		if (key_register_ifnet(sp, IPSEC_SPCOUNT) != 0) {
945			for (i = 0; i < IPSEC_SPCOUNT; i++)
946				key_freesp(&sp[i]);
947			return (EAGAIN);
948		}
949		IPSEC_SC_WLOCK();
950		if ((f = sc->family) != 0)
951			LIST_REMOVE(sc, hash);
952		IPSEC_WLOCK(sc);
953		for (i = 0; i < IPSEC_SPCOUNT; i++) {
954			oldsp[i] = sc->sp[i];
955			sc->sp[i] = sp[i];
956		}
957		sc->family = src->sa_family;
958		IPSEC_WUNLOCK(sc);
959		LIST_INSERT_HEAD(SCHASH_HASH(sc->reqid), sc, hash);
960		IPSEC_SC_WUNLOCK();
961	} else {
962		sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
963		return (ENOMEM);
964	}
965
966	sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
967	if (f != 0) {
968		key_unregister_ifnet(oldsp, IPSEC_SPCOUNT);
969		for (i = 0; i < IPSEC_SPCOUNT; i++)
970			key_freesp(&oldsp[i]);
971	}
972	return (0);
973}
974
975static void
976ipsec_delete_tunnel(struct ifnet *ifp, int locked)
977{
978	struct ipsec_softc *sc = ifp->if_softc;
979	struct secpolicy *oldsp[IPSEC_SPCOUNT];
980	int i;
981
982	sx_assert(&ipsec_ioctl_sx, SA_XLOCKED);
983
984	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
985	if (sc->family != 0) {
986		if (!locked)
987			IPSEC_SC_WLOCK();
988		/* Remove from hash table */
989		LIST_REMOVE(sc, hash);
990		IPSEC_WLOCK(sc);
991		for (i = 0; i < IPSEC_SPCOUNT; i++) {
992			oldsp[i] = sc->sp[i];
993			sc->sp[i] = NULL;
994		}
995		sc->family = 0;
996		IPSEC_WUNLOCK(sc);
997		if (!locked)
998			IPSEC_SC_WUNLOCK();
999		key_unregister_ifnet(oldsp, IPSEC_SPCOUNT);
1000		for (i = 0; i < IPSEC_SPCOUNT; i++)
1001			key_freesp(&oldsp[i]);
1002	}
1003}
1004