2 * Copyright (c) 2016-2018 Yandex LLC
3 * Copyright (c) 2016-2018 Andrey V. Elsukov <ae@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
28 #include <sys/cdefs.h>
30 #include "opt_inet6.h"
31 #include "opt_ipsec.h"
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/fnv_hash.h>
39 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/socket.h>
43 #include <sys/sockio.h>
45 #include <sys/errno.h>
46 #include <sys/sysctl.h>
52 #include <net/if_var.h>
53 #include <net/if_private.h>
54 #include <net/if_clone.h>
55 #include <net/if_types.h>
57 #include <net/route.h>
60 #include <netinet/in.h>
61 #include <netinet/in_var.h>
62 #include <netinet/ip.h>
63 #include <netinet/ip_encap.h>
65 #include <netinet/ip6.h>
66 #include <netinet6/in6_var.h>
67 #include <netinet6/scope6_var.h>
69 #include <netipsec/ipsec.h>
71 #include <netipsec/ipsec6.h>
74 #include <net/if_ipsec.h>
75 #include <netipsec/key.h>
77 #include <security/mac/mac_framework.h>
79 static MALLOC_DEFINE(M_IPSEC
, "ipsec", "IPsec Virtual Tunnel Interface");
80 static const char ipsecname
[] = "ipsec";
82 #if defined(INET) && defined(INET6)
83 #define IPSEC_SPCOUNT 4
85 #define IPSEC_SPCOUNT 2
90 struct secpolicy
*sp
[IPSEC_SPCOUNT
];
95 CK_LIST_ENTRY(ipsec_softc
) idhash
;
96 CK_LIST_ENTRY(ipsec_softc
) srchash
;
99 #define IPSEC_RLOCK_TRACKER struct epoch_tracker ipsec_et
100 #define IPSEC_RLOCK() epoch_enter_preempt(net_epoch_preempt, &ipsec_et)
101 #define IPSEC_RUNLOCK() epoch_exit_preempt(net_epoch_preempt, &ipsec_et)
102 #define IPSEC_WAIT() epoch_wait_preempt(net_epoch_preempt)
104 #ifndef IPSEC_HASH_SIZE
105 #define IPSEC_HASH_SIZE (1 << 5)
108 CK_LIST_HEAD(ipsec_iflist
, ipsec_softc
);
109 VNET_DEFINE_STATIC(struct ipsec_iflist
*, ipsec_idhtbl
) = NULL
;
110 #define V_ipsec_idhtbl VNET(ipsec_idhtbl)
113 VNET_DEFINE_STATIC(struct ipsec_iflist
*, ipsec4_srchtbl
) = NULL
;
114 #define V_ipsec4_srchtbl VNET(ipsec4_srchtbl)
115 static const struct srcaddrtab
*ipsec4_srctab
= NULL
;
119 VNET_DEFINE_STATIC(struct ipsec_iflist
*, ipsec6_srchtbl
) = NULL
;
120 #define V_ipsec6_srchtbl VNET(ipsec6_srchtbl)
121 static const struct srcaddrtab
*ipsec6_srctab
= NULL
;
124 static struct ipsec_iflist
*
125 ipsec_idhash(uint32_t id
)
128 return (&V_ipsec_idhtbl
[fnv_32_buf(&id
, sizeof(id
),
129 FNV1_32_INIT
) & (IPSEC_HASH_SIZE
- 1)]);
132 static struct ipsec_iflist
*
133 ipsec_srchash(const struct sockaddr
*sa
)
137 switch (sa
->sa_family
) {
141 &((const struct sockaddr_in
*)sa
)->sin_addr
.s_addr
,
142 sizeof(in_addr_t
), FNV1_32_INIT
);
143 return (&V_ipsec4_srchtbl
[hval
& (IPSEC_HASH_SIZE
- 1)]);
148 &((const struct sockaddr_in6
*)sa
)->sin6_addr
,
149 sizeof(struct in6_addr
), FNV1_32_INIT
);
150 return (&V_ipsec6_srchtbl
[hval
& (IPSEC_HASH_SIZE
- 1)]);
157 * ipsec_ioctl_sx protects from concurrent ioctls.
159 static struct sx ipsec_ioctl_sx
;
160 SX_SYSINIT(ipsec_ioctl_sx
, &ipsec_ioctl_sx
, "ipsec_ioctl");
162 static int ipsec_init_reqid(struct ipsec_softc
*);
163 static int ipsec_set_tunnel(struct ipsec_softc
*, struct sockaddr
*,
164 struct sockaddr
*, uint32_t);
165 static void ipsec_delete_tunnel(struct ipsec_softc
*);
167 static int ipsec_set_addresses(struct ifnet
*, struct sockaddr
*,
169 static int ipsec_set_reqid(struct ipsec_softc
*, uint32_t);
170 static void ipsec_set_running(struct ipsec_softc
*);
173 static void ipsec_reassign(struct ifnet
*, struct vnet
*, char *);
175 static void ipsec_srcaddr(void *, const struct sockaddr
*, int);
176 static int ipsec_ioctl(struct ifnet
*, u_long
, caddr_t
);
177 static int ipsec_transmit(struct ifnet
*, struct mbuf
*);
178 static int ipsec_output(struct ifnet
*, struct mbuf
*,
179 const struct sockaddr
*, struct route
*);
180 static void ipsec_qflush(struct ifnet
*);
181 static int ipsec_clone_create(struct if_clone
*, int, caddr_t
);
182 static void ipsec_clone_destroy(struct ifnet
*);
184 VNET_DEFINE_STATIC(struct if_clone
*, ipsec_cloner
);
185 #define V_ipsec_cloner VNET(ipsec_cloner)
188 ipsec_clone_create(struct if_clone
*ifc
, int unit
, caddr_t params
)
190 struct ipsec_softc
*sc
;
193 sc
= malloc(sizeof(*sc
), M_IPSEC
, M_WAITOK
| M_ZERO
);
194 sc
->fibnum
= curthread
->td_proc
->p_fibnum
;
195 sc
->ifp
= ifp
= if_alloc(IFT_TUNNEL
);
197 if_initname(ifp
, ipsecname
, unit
);
200 ifp
->if_mtu
= IPSEC_MTU
;
201 ifp
->if_flags
= IFF_POINTOPOINT
| IFF_MULTICAST
;
202 ifp
->if_ioctl
= ipsec_ioctl
;
203 ifp
->if_transmit
= ipsec_transmit
;
204 ifp
->if_qflush
= ipsec_qflush
;
205 ifp
->if_output
= ipsec_output
;
207 ifp
->if_reassign
= ipsec_reassign
;
210 bpfattach(ifp
, DLT_NULL
, sizeof(uint32_t));
217 ipsec_reassign(struct ifnet
*ifp
, struct vnet
*new_vnet __unused
,
218 char *unused __unused
)
220 struct ipsec_softc
*sc
;
222 sx_xlock(&ipsec_ioctl_sx
);
225 ipsec_delete_tunnel(sc
);
226 sx_xunlock(&ipsec_ioctl_sx
);
231 ipsec_clone_destroy(struct ifnet
*ifp
)
233 struct ipsec_softc
*sc
;
235 sx_xlock(&ipsec_ioctl_sx
);
237 ipsec_delete_tunnel(sc
);
239 * Delete softc from idhash on interface destroy, since
240 * ipsec_delete_tunnel() keeps reqid unchanged.
243 CK_LIST_REMOVE(sc
, idhash
);
246 ifp
->if_softc
= NULL
;
247 sx_xunlock(&ipsec_ioctl_sx
);
254 static struct ipsec_iflist
*
257 struct ipsec_iflist
*hash
;
260 hash
= malloc(sizeof(struct ipsec_iflist
) * IPSEC_HASH_SIZE
,
262 for (i
= 0; i
< IPSEC_HASH_SIZE
; i
++)
263 CK_LIST_INIT(&hash
[i
]);
269 vnet_ipsec_init(const void *unused __unused
)
272 V_ipsec_idhtbl
= ipsec_hashinit();
274 V_ipsec4_srchtbl
= ipsec_hashinit();
275 if (IS_DEFAULT_VNET(curvnet
))
276 ipsec4_srctab
= ip_encap_register_srcaddr(ipsec_srcaddr
,
280 V_ipsec6_srchtbl
= ipsec_hashinit();
281 if (IS_DEFAULT_VNET(curvnet
))
282 ipsec6_srctab
= ip6_encap_register_srcaddr(ipsec_srcaddr
,
285 V_ipsec_cloner
= if_clone_simple(ipsecname
, ipsec_clone_create
,
286 ipsec_clone_destroy
, 0);
288 VNET_SYSINIT(vnet_ipsec_init
, SI_SUB_PROTO_IFATTACHDOMAIN
, SI_ORDER_ANY
,
289 vnet_ipsec_init
, NULL
);
292 vnet_ipsec_uninit(const void *unused __unused
)
295 if_clone_detach(V_ipsec_cloner
);
296 free(V_ipsec_idhtbl
, M_IPSEC
);
298 * Use V_ipsec_idhtbl pointer as indicator that VNET is going to be
299 * destroyed, it is used by ipsec_srcaddr() callback.
301 V_ipsec_idhtbl
= NULL
;
305 if (IS_DEFAULT_VNET(curvnet
))
306 ip_encap_unregister_srcaddr(ipsec4_srctab
);
307 free(V_ipsec4_srchtbl
, M_IPSEC
);
310 if (IS_DEFAULT_VNET(curvnet
))
311 ip6_encap_unregister_srcaddr(ipsec6_srctab
);
312 free(V_ipsec6_srchtbl
, M_IPSEC
);
315 VNET_SYSUNINIT(vnet_ipsec_uninit
, SI_SUB_PROTO_IFATTACHDOMAIN
, SI_ORDER_ANY
,
316 vnet_ipsec_uninit
, NULL
);
318 static struct secpolicy
*
319 ipsec_getpolicy(struct ipsec_softc
*sc
, int dir
, sa_family_t af
)
325 return (sc
->sp
[(dir
== IPSEC_DIR_INBOUND
? 0: 1)]);
329 return (sc
->sp
[(dir
== IPSEC_DIR_INBOUND
? 0: 1)
339 static struct secasindex
*
340 ipsec_getsaidx(struct ipsec_softc
*sc
, int dir
, sa_family_t af
)
342 struct secpolicy
*sp
;
344 sp
= ipsec_getpolicy(sc
, dir
, af
);
347 return (&sp
->req
[0]->saidx
);
351 ipsec_transmit(struct ifnet
*ifp
, struct mbuf
*m
)
354 struct ipsec_softc
*sc
;
355 struct secpolicy
*sp
;
362 error
= mac_ifnet_check_transmit(ifp
, m
);
370 if ((ifp
->if_drv_flags
& IFF_DRV_RUNNING
) == 0 ||
371 (ifp
->if_flags
& IFF_MONITOR
) != 0 ||
372 (ifp
->if_flags
& IFF_UP
) == 0 || sc
->family
== 0) {
377 /* Determine address family to correctly handle packet in BPF */
379 m_copydata(m
, 0, sizeof(*ip
), (char *)ip
);
387 case (IPV6_VERSION
>> 4):
392 error
= EAFNOSUPPORT
;
399 * XXX: for now just check presence of IPSEC_OUT_DONE mbuf tag.
400 * We can read full chain and compare destination address,
401 * proto and mode from xform_history with values from softc.
403 if (m_tag_find(m
, PACKET_TAG_IPSEC_OUT_DONE
, NULL
) != NULL
) {
408 sp
= ipsec_getpolicy(sc
, IPSEC_DIR_OUTBOUND
, af
);
410 M_SETFIB(m
, sc
->fibnum
);
412 BPF_MTAP2(ifp
, &af
, sizeof(af
), m
);
413 if_inc_counter(ifp
, IFCOUNTER_OPACKETS
, 1);
414 if_inc_counter(ifp
, IFCOUNTER_OBYTES
, m
->m_pkthdr
.len
);
419 error
= ipsec4_process_packet(ifp
, m
, ip
, sp
, NULL
,
425 error
= ipsec6_process_packet(ifp
, m
, sp
, NULL
, ifp
->if_mtu
);
429 panic("%s: unknown address family\n", __func__
);
433 if_inc_counter(ifp
, IFCOUNTER_OERRORS
, 1);
439 ipsec_qflush(struct ifnet
*ifp __unused
)
445 ipsec_output(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*dst
,
449 return (ifp
->if_transmit(ifp
, m
));
453 ipsec_if_input(struct mbuf
*m
, struct secasvar
*sav
, uint32_t af
)
456 struct secasindex
*saidx
;
457 struct ipsec_softc
*sc
;
460 if (sav
->state
!= SADB_SASTATE_MATURE
&&
461 sav
->state
!= SADB_SASTATE_DYING
) {
466 if (sav
->sah
->saidx
.mode
!= IPSEC_MODE_TUNNEL
||
467 sav
->sah
->saidx
.proto
!= IPPROTO_ESP
)
471 CK_LIST_FOREACH(sc
, ipsec_idhash(sav
->sah
->saidx
.reqid
), idhash
) {
474 saidx
= ipsec_getsaidx(sc
, IPSEC_DIR_INBOUND
,
475 sav
->sah
->saidx
.src
.sa
.sa_family
);
476 /* SA's reqid should match reqid in SP */
478 sav
->sah
->saidx
.reqid
!= saidx
->reqid
)
480 /* SAH's addresses should match tunnel endpoints. */
481 if (key_sockaddrcmp(&sav
->sah
->saidx
.dst
.sa
,
482 &saidx
->dst
.sa
, 0) != 0)
484 if (key_sockaddrcmp(&sav
->sah
->saidx
.src
.sa
,
485 &saidx
->src
.sa
, 0) == 0)
490 /* Tunnel was not found. Nothing to do. */
494 if ((ifp
->if_drv_flags
& IFF_DRV_RUNNING
) == 0 ||
495 (ifp
->if_flags
& IFF_UP
) == 0) {
501 * We found matching and working tunnel.
502 * Set its ifnet as receiving interface.
504 m
->m_pkthdr
.rcvif
= ifp
;
507 M_SETFIB(m
, ifp
->if_fib
);
508 BPF_MTAP2(ifp
, &af
, sizeof(af
), m
);
509 if_inc_counter(ifp
, IFCOUNTER_IPACKETS
, 1);
510 if_inc_counter(ifp
, IFCOUNTER_IBYTES
, m
->m_pkthdr
.len
);
511 if ((ifp
->if_flags
& IFF_MONITOR
) != 0) {
521 ipsec_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
)
523 struct ifreq
*ifr
= (struct ifreq
*)data
;
524 struct sockaddr
*dst
, *src
;
525 struct ipsec_softc
*sc
;
526 struct secasindex
*saidx
;
528 struct sockaddr_in
*sin
= NULL
;
531 struct sockaddr_in6
*sin6
= NULL
;
538 ifp
->if_flags
|= IFF_UP
;
545 if (ifr
->ifr_mtu
< IPSEC_MTU_MIN
||
546 ifr
->ifr_mtu
> IPSEC_MTU_MAX
)
549 ifp
->if_mtu
= ifr
->ifr_mtu
;
552 sx_xlock(&ipsec_ioctl_sx
);
554 /* Check that softc is still here */
563 case SIOCSIFPHYADDR_IN6
:
569 src
= (struct sockaddr
*)
570 &(((struct in_aliasreq
*)data
)->ifra_addr
);
571 dst
= (struct sockaddr
*)
572 &(((struct in_aliasreq
*)data
)->ifra_dstaddr
);
576 case SIOCSIFPHYADDR_IN6
:
577 src
= (struct sockaddr
*)
578 &(((struct in6_aliasreq
*)data
)->ifra_addr
);
579 dst
= (struct sockaddr
*)
580 &(((struct in6_aliasreq
*)data
)->ifra_dstaddr
);
586 /* sa_family must be equal */
587 if (src
->sa_family
!= dst
->sa_family
||
588 src
->sa_len
!= dst
->sa_len
)
591 /* validate sa_len */
592 switch (src
->sa_family
) {
595 if (src
->sa_len
!= sizeof(struct sockaddr_in
))
601 if (src
->sa_len
!= sizeof(struct sockaddr_in6
))
606 error
= EAFNOSUPPORT
;
609 /* check sa_family looks sane for the cmd */
610 error
= EAFNOSUPPORT
;
614 if (src
->sa_family
== AF_INET
)
619 case SIOCSIFPHYADDR_IN6
:
620 if (src
->sa_family
== AF_INET6
)
625 error
= EADDRNOTAVAIL
;
626 switch (src
->sa_family
) {
629 if (satosin(src
)->sin_addr
.s_addr
== INADDR_ANY
||
630 satosin(dst
)->sin_addr
.s_addr
== INADDR_ANY
)
636 if (IN6_IS_ADDR_UNSPECIFIED(
637 &satosin6(src
)->sin6_addr
) ||
638 IN6_IS_ADDR_UNSPECIFIED(
639 &satosin6(dst
)->sin6_addr
))
642 * Check validity of the scope zone ID of the
643 * addresses, and convert it into the kernel
644 * internal form if necessary.
646 error
= sa6_embedscope(satosin6(src
), 0);
649 error
= sa6_embedscope(satosin6(dst
), 0);
654 error
= ipsec_set_addresses(ifp
, src
, dst
);
657 ipsec_delete_tunnel(sc
);
659 case SIOCGIFPSRCADDR
:
660 case SIOCGIFPDSTADDR
:
662 case SIOCGIFPSRCADDR_IN6
:
663 case SIOCGIFPDSTADDR_IN6
:
665 if (sc
->family
== 0) {
666 error
= EADDRNOTAVAIL
;
669 saidx
= ipsec_getsaidx(sc
, IPSEC_DIR_OUTBOUND
, sc
->family
);
676 case SIOCGIFPSRCADDR
:
677 case SIOCGIFPDSTADDR
:
678 if (saidx
->src
.sa
.sa_family
!= AF_INET
) {
679 error
= EADDRNOTAVAIL
;
682 sin
= (struct sockaddr_in
*)&ifr
->ifr_addr
;
683 memset(sin
, 0, sizeof(*sin
));
684 sin
->sin_family
= AF_INET
;
685 sin
->sin_len
= sizeof(*sin
);
689 case SIOCGIFPSRCADDR_IN6
:
690 case SIOCGIFPDSTADDR_IN6
:
691 if (saidx
->src
.sa
.sa_family
!= AF_INET6
) {
692 error
= EADDRNOTAVAIL
;
695 sin6
= (struct sockaddr_in6
*)
696 &(((struct in6_ifreq
*)data
)->ifr_addr
);
697 memset(sin6
, 0, sizeof(*sin6
));
698 sin6
->sin6_family
= AF_INET6
;
699 sin6
->sin6_len
= sizeof(*sin6
);
703 error
= EAFNOSUPPORT
;
708 case SIOCGIFPSRCADDR
:
709 sin
->sin_addr
= saidx
->src
.sin
.sin_addr
;
711 case SIOCGIFPDSTADDR
:
712 sin
->sin_addr
= saidx
->dst
.sin
.sin_addr
;
716 case SIOCGIFPSRCADDR_IN6
:
717 sin6
->sin6_addr
= saidx
->src
.sin6
.sin6_addr
;
719 case SIOCGIFPDSTADDR_IN6
:
720 sin6
->sin6_addr
= saidx
->dst
.sin6
.sin6_addr
;
729 case SIOCGIFPSRCADDR
:
730 case SIOCGIFPDSTADDR
:
731 error
= prison_if(curthread
->td_ucred
,
732 (struct sockaddr
*)sin
);
734 memset(sin
, 0, sizeof(*sin
));
738 case SIOCGIFPSRCADDR_IN6
:
739 case SIOCGIFPDSTADDR_IN6
:
740 error
= prison_if(curthread
->td_ucred
,
741 (struct sockaddr
*)sin6
);
743 error
= sa6_recoverscope(sin6
);
745 memset(sin6
, 0, sizeof(*sin6
));
750 ifr
->ifr_fib
= sc
->fibnum
;
753 if ((error
= priv_check(curthread
, PRIV_NET_SETIFFIB
)) != 0)
755 if (ifr
->ifr_fib
>= rt_numfibs
)
758 sc
->fibnum
= ifr
->ifr_fib
;
762 error
= copyout(&reqid
, ifr_data_get_ptr(ifr
), sizeof(reqid
));
765 if ((error
= priv_check(curthread
, PRIV_NET_SETIFCAP
)) != 0)
767 error
= copyin(ifr_data_get_ptr(ifr
), &reqid
, sizeof(reqid
));
770 error
= ipsec_set_reqid(sc
, reqid
);
777 sx_xunlock(&ipsec_ioctl_sx
);
782 * Check that ingress address belongs to local host.
785 ipsec_set_running(struct ipsec_softc
*sc
)
787 struct secasindex
*saidx
;
790 saidx
= ipsec_getsaidx(sc
, IPSEC_DIR_OUTBOUND
, sc
->family
);
794 switch (sc
->family
) {
797 localip
= in_localip(saidx
->src
.sin
.sin_addr
);
802 localip
= in6_localip(&saidx
->src
.sin6
.sin6_addr
);
807 sc
->ifp
->if_drv_flags
|= IFF_DRV_RUNNING
;
809 sc
->ifp
->if_drv_flags
&= ~IFF_DRV_RUNNING
;
813 * ifaddr_event handler.
814 * Clear IFF_DRV_RUNNING flag when ingress address disappears to prevent
815 * source address spoofing.
818 ipsec_srcaddr(void *arg __unused
, const struct sockaddr
*sa
,
821 struct ipsec_softc
*sc
;
822 struct secasindex
*saidx
;
823 struct ipsec_iflist
*iflist
;
825 /* Check that VNET is ready */
826 if (V_ipsec_idhtbl
== NULL
)
830 iflist
= ipsec_srchash(sa
);
833 CK_LIST_FOREACH(sc
, iflist
, srchash
) {
836 saidx
= ipsec_getsaidx(sc
, IPSEC_DIR_OUTBOUND
, sa
->sa_family
);
838 key_sockaddrcmp(&saidx
->src
.sa
, sa
, 0) != 0)
840 ipsec_set_running(sc
);
845 * Allocate new private security policies for tunneling interface.
846 * Each tunneling interface has following security policies for
848 * 0.0.0.0/0[any] 0.0.0.0/0[any] -P in \
849 * ipsec esp/tunnel/RemoteIP-LocalIP/unique:reqid
850 * 0.0.0.0/0[any] 0.0.0.0/0[any] -P out \
851 * ipsec esp/tunnel/LocalIP-RemoteIP/unique:reqid
854 ipsec_newpolicies(struct ipsec_softc
*sc
, struct secpolicy
*sp
[IPSEC_SPCOUNT
],
855 const struct sockaddr
*src
, const struct sockaddr
*dst
, uint32_t reqid
)
857 struct ipsecrequest
*isr
;
860 memset(sp
, 0, sizeof(struct secpolicy
*) * IPSEC_SPCOUNT
);
861 for (i
= 0; i
< IPSEC_SPCOUNT
; i
++) {
862 if ((sp
[i
] = key_newsp()) == NULL
)
864 if ((isr
= ipsec_newisr()) == NULL
)
867 sp
[i
]->policy
= IPSEC_POLICY_IPSEC
;
868 sp
[i
]->state
= IPSEC_SPSTATE_DEAD
;
869 sp
[i
]->req
[sp
[i
]->tcount
++] = isr
;
870 sp
[i
]->created
= time_second
;
871 /* Use priority field to store if_index */
872 sp
[i
]->priority
= sc
->ifp
->if_index
;
873 isr
->level
= IPSEC_LEVEL_UNIQUE
;
874 isr
->saidx
.proto
= IPPROTO_ESP
;
875 isr
->saidx
.mode
= IPSEC_MODE_TUNNEL
;
876 isr
->saidx
.reqid
= reqid
;
878 sp
[i
]->spidx
.dir
= IPSEC_DIR_INBOUND
;
879 bcopy(src
, &isr
->saidx
.dst
, src
->sa_len
);
880 bcopy(dst
, &isr
->saidx
.src
, dst
->sa_len
);
882 sp
[i
]->spidx
.dir
= IPSEC_DIR_OUTBOUND
;
883 bcopy(src
, &isr
->saidx
.src
, src
->sa_len
);
884 bcopy(dst
, &isr
->saidx
.dst
, dst
->sa_len
);
886 sp
[i
]->spidx
.ul_proto
= IPSEC_ULPROTO_ANY
;
889 sp
[i
]->spidx
.src
.sa
.sa_family
=
890 sp
[i
]->spidx
.dst
.sa
.sa_family
= AF_INET
;
891 sp
[i
]->spidx
.src
.sa
.sa_len
=
892 sp
[i
]->spidx
.dst
.sa
.sa_len
=
893 sizeof(struct sockaddr_in
);
898 sp
[i
]->spidx
.src
.sa
.sa_family
=
899 sp
[i
]->spidx
.dst
.sa
.sa_family
= AF_INET6
;
900 sp
[i
]->spidx
.src
.sa
.sa_len
=
901 sp
[i
]->spidx
.dst
.sa
.sa_len
= sizeof(struct sockaddr_in6
);
906 for (i
= 0; i
< IPSEC_SPCOUNT
; i
++) {
914 ipsec_check_reqid(uint32_t reqid
)
916 struct ipsec_softc
*sc
;
918 sx_assert(&ipsec_ioctl_sx
, SA_XLOCKED
);
919 CK_LIST_FOREACH(sc
, ipsec_idhash(reqid
), idhash
) {
920 if (sc
->reqid
== reqid
)
927 * We use key_newreqid() to automatically obtain unique reqid.
928 * Then we check that given id is unique, i.e. it is not used by
929 * another if_ipsec(4) interface. This macro limits the number of
930 * tries to get unique id.
932 #define IPSEC_REQID_TRYCNT 64
934 ipsec_init_reqid(struct ipsec_softc
*sc
)
939 sx_assert(&ipsec_ioctl_sx
, SA_XLOCKED
);
940 if (sc
->reqid
!= 0) /* already initialized */
943 trycount
= IPSEC_REQID_TRYCNT
;
944 while (--trycount
> 0) {
945 reqid
= key_newreqid();
946 if (ipsec_check_reqid(reqid
) == 0)
952 CK_LIST_INSERT_HEAD(ipsec_idhash(reqid
), sc
, idhash
);
957 * Set or update reqid for given tunneling interface.
958 * When specified reqid is zero, generate new one.
959 * We are protected by ioctl_sx lock from concurrent id generation.
960 * Also softc would not disappear while we hold ioctl_sx lock.
963 ipsec_set_reqid(struct ipsec_softc
*sc
, uint32_t reqid
)
965 struct secasindex
*saidx
;
967 sx_assert(&ipsec_ioctl_sx
, SA_XLOCKED
);
969 if (sc
->reqid
== reqid
&& reqid
!= 0)
973 /* Check that specified reqid doesn't exist */
974 if (ipsec_check_reqid(reqid
) != 0)
976 if (sc
->reqid
!= 0) {
977 CK_LIST_REMOVE(sc
, idhash
);
981 CK_LIST_INSERT_HEAD(ipsec_idhash(reqid
), sc
, idhash
);
983 /* Generate new reqid */
984 if (ipsec_init_reqid(sc
) != 0)
988 /* Tunnel isn't fully configured, just return. */
992 saidx
= ipsec_getsaidx(sc
, IPSEC_DIR_OUTBOUND
, sc
->family
);
993 KASSERT(saidx
!= NULL
,
994 ("saidx is NULL, but family is %d", sc
->family
));
995 return (ipsec_set_tunnel(sc
, &saidx
->src
.sa
, &saidx
->dst
.sa
,
1000 * Set tunnel endpoints addresses.
1003 ipsec_set_addresses(struct ifnet
*ifp
, struct sockaddr
*src
,
1004 struct sockaddr
*dst
)
1006 struct ipsec_softc
*sc
;
1007 struct secasindex
*saidx
;
1009 sx_assert(&ipsec_ioctl_sx
, SA_XLOCKED
);
1012 if (sc
->family
!= 0) {
1013 saidx
= ipsec_getsaidx(sc
, IPSEC_DIR_OUTBOUND
,
1015 if (saidx
!= NULL
&& saidx
->reqid
== sc
->reqid
&&
1016 key_sockaddrcmp(&saidx
->src
.sa
, src
, 0) == 0 &&
1017 key_sockaddrcmp(&saidx
->dst
.sa
, dst
, 0) == 0)
1018 return (0); /* Nothing has been changed. */
1020 /* If reqid is not set, generate new one. */
1021 if (ipsec_init_reqid(sc
) != 0)
1023 return (ipsec_set_tunnel(sc
, src
, dst
, sc
->reqid
));
1027 ipsec_set_tunnel(struct ipsec_softc
*sc
, struct sockaddr
*src
,
1028 struct sockaddr
*dst
, uint32_t reqid
)
1030 struct epoch_tracker et
;
1031 struct ipsec_iflist
*iflist
;
1032 struct secpolicy
*sp
[IPSEC_SPCOUNT
];
1035 sx_assert(&ipsec_ioctl_sx
, SA_XLOCKED
);
1037 /* Allocate SP with new addresses. */
1038 iflist
= ipsec_srchash(src
);
1039 if (iflist
== NULL
) {
1040 sc
->ifp
->if_drv_flags
&= ~IFF_DRV_RUNNING
;
1041 return (EAFNOSUPPORT
);
1043 if (ipsec_newpolicies(sc
, sp
, src
, dst
, reqid
) == 0) {
1044 /* Add new policies to SPDB */
1045 if (key_register_ifnet(sp
, IPSEC_SPCOUNT
) != 0) {
1046 for (i
= 0; i
< IPSEC_SPCOUNT
; i
++)
1050 if (sc
->family
!= 0)
1051 ipsec_delete_tunnel(sc
);
1052 for (i
= 0; i
< IPSEC_SPCOUNT
; i
++)
1054 sc
->family
= src
->sa_family
;
1055 CK_LIST_INSERT_HEAD(iflist
, sc
, srchash
);
1057 sc
->ifp
->if_drv_flags
&= ~IFF_DRV_RUNNING
;
1060 NET_EPOCH_ENTER(et
);
1061 ipsec_set_running(sc
);
1067 ipsec_delete_tunnel(struct ipsec_softc
*sc
)
1071 sx_assert(&ipsec_ioctl_sx
, SA_XLOCKED
);
1073 sc
->ifp
->if_drv_flags
&= ~IFF_DRV_RUNNING
;
1074 if (sc
->family
!= 0) {
1075 CK_LIST_REMOVE(sc
, srchash
);
1078 * Make sure that ipsec_if_input() will not do access
1079 * to softc's policies.
1083 key_unregister_ifnet(sc
->sp
, IPSEC_SPCOUNT
);
1084 for (i
= 0; i
< IPSEC_SPCOUNT
; i
++)
1085 key_freesp(&sc
->sp
[i
]);