if_ipsec.c revision 1.4 1 /* $NetBSD: if_ipsec.c,v 1.4 2018/03/09 10:59:36 knakahara Exp $ */
2
3 /*
4 * Copyright (c) 2017 Internet Initiative Japan Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.4 2018/03/09 10:59:36 knakahara Exp $");
31
32 #ifdef _KERNEL_OPT
33 #include "opt_inet.h"
34 #endif
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/mbuf.h>
40 #include <sys/socket.h>
41 #include <sys/sockio.h>
42 #include <sys/errno.h>
43 #include <sys/ioctl.h>
44 #include <sys/time.h>
45 #include <sys/syslog.h>
46 #include <sys/cpu.h>
47 #include <sys/kmem.h>
48 #include <sys/mutex.h>
49 #include <sys/pserialize.h>
50 #include <sys/psref.h>
51
52 #include <net/if.h>
53 #include <net/if_types.h>
54 #include <net/route.h>
55 #include <net/bpf.h>
56 #include <net/pfkeyv2.h>
57
58 #include <netinet/in.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/ip.h>
61 #ifdef INET
62 #include <netinet/in_var.h>
63 #endif /* INET */
64
65 #ifdef INET6
66 #include <netinet6/in6_var.h>
67 #include <netinet/ip6.h>
68 #include <netinet6/ip6_var.h>
69 #endif /* INET6 */
70
71 #include <netinet/ip_encap.h>
72
73 #include <net/if_ipsec.h>
74
75 #include <net/raw_cb.h>
76 #include <net/pfkeyv2.h>
77
78 #include <netipsec/key.h>
79 #include <netipsec/ipsec.h>
80 #include <netipsec/ipsecif.h>
81
82 static void if_ipsec_ro_init_pc(void *, void *, struct cpu_info *);
83 static void if_ipsec_ro_fini_pc(void *, void *, struct cpu_info *);
84
85 static int if_ipsec_clone_create(struct if_clone *, int);
86 static int if_ipsec_clone_destroy(struct ifnet *);
87
88 static inline int if_ipsec_out_direct(struct ipsec_variant *, struct mbuf *, int);
89 static inline void if_ipsec_in_enqueue(struct mbuf *, int, struct ifnet *);
90
91 static int if_ipsec_encap_attach(struct ipsec_variant *);
92 static int if_ipsec_encap_detach(struct ipsec_variant *);
93 static int if_ipsec_set_tunnel(struct ifnet *,
94 struct sockaddr *, struct sockaddr *);
95 static void if_ipsec_delete_tunnel(struct ifnet *);
96 static int if_ipsec_ensure_flags(struct ifnet *, short);
97 static void if_ipsec_attach0(struct ipsec_softc *);
98
99 static int if_ipsec_update_variant(struct ipsec_softc *,
100 struct ipsec_variant *, struct ipsec_variant *);
101
102 /* sadb_msg */
103 static inline void if_ipsec_add_mbuf(struct mbuf *, void *, size_t);
104 static inline void if_ipsec_add_pad(struct mbuf *, size_t);
105 static inline size_t if_ipsec_set_sadb_addr(struct sadb_address *,
106 struct sockaddr *, int, uint16_t);
107 static inline size_t if_ipsec_set_sadb_src(struct sadb_address *,
108 struct sockaddr *, int);
109 static inline size_t if_ipsec_set_sadb_dst(struct sadb_address *,
110 struct sockaddr *, int);
111 static inline size_t if_ipsec_set_sadb_x_policy(struct sadb_x_policy *,
112 struct sadb_x_ipsecrequest *, uint16_t, uint8_t, uint32_t, uint8_t);
113 static inline void if_ipsec_set_sadb_msg(struct sadb_msg *, uint16_t, uint8_t);
114 static inline void if_ipsec_set_sadb_msg_add(struct sadb_msg *, uint16_t);
115 static inline void if_ipsec_set_sadb_msg_del(struct sadb_msg *, uint16_t);
116 /* SPD */
117 static int if_ipsec_share_sp(struct ipsec_variant *);
118 static int if_ipsec_unshare_sp(struct ipsec_variant *);
119 static inline struct secpolicy *if_ipsec_add_sp0(struct sockaddr *,
120 in_port_t, struct sockaddr *, in_port_t, int, int, int, u_int);
121 static inline int if_ipsec_del_sp0(struct secpolicy *);
122 static int if_ipsec_add_sp(struct ipsec_variant *,
123 struct sockaddr *, in_port_t, struct sockaddr *, in_port_t);
124 static void if_ipsec_del_sp(struct ipsec_variant *);
125 static int if_ipsec_replace_sp(struct ipsec_softc *, struct ipsec_variant *,
126 struct ipsec_variant *);
127
128 static int if_ipsec_set_addr_port(struct sockaddr *, struct sockaddr *,
129 in_port_t);
130 #define IF_IPSEC_GATHER_PSRC_ADDR_PORT(var, target) \
131 if_ipsec_set_addr_port(target, (var)->iv_psrc, (var)->iv_sport)
132 #define IF_IPSEC_GATHER_PDST_ADDR_PORT(var, target) \
133 if_ipsec_set_addr_port(target, (var)->iv_pdst, (var)->iv_dport)
134
135 /*
136 * ipsec global variable definitions
137 */
138
139 /* This list is used in ioctl context only. */
140 LIST_HEAD(ipsec_sclist, ipsec_softc);
141 static struct {
142 struct ipsec_sclist list;
143 kmutex_t lock;
144 } ipsec_softcs __cacheline_aligned;
145
146 pserialize_t ipsec_psz __read_mostly;
147 struct psref_class *iv_psref_class __read_mostly;
148
149 struct if_clone ipsec_cloner =
150 IF_CLONE_INITIALIZER("ipsec", if_ipsec_clone_create, if_ipsec_clone_destroy);
151 static int max_ipsec_nesting = MAX_IPSEC_NEST;
152
153 /* ARGSUSED */
154 void
155 ipsecifattach(int count)
156 {
157
158 mutex_init(&ipsec_softcs.lock, MUTEX_DEFAULT, IPL_NONE);
159 LIST_INIT(&ipsec_softcs.list);
160
161 ipsec_psz = pserialize_create();
162 iv_psref_class = psref_class_create("ipsecvar", IPL_SOFTNET);
163
164 if_clone_attach(&ipsec_cloner);
165 }
166
167 static int
168 if_ipsec_clone_create(struct if_clone *ifc, int unit)
169 {
170 struct ipsec_softc *sc;
171 struct ipsec_variant *var;
172
173 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
174
175 if_initname(&sc->ipsec_if, ifc->ifc_name, unit);
176
177 if_ipsec_attach0(sc);
178
179 var = kmem_zalloc(sizeof(*var), KM_SLEEP);
180 var->iv_softc = sc;
181 psref_target_init(&var->iv_psref, iv_psref_class);
182
183 sc->ipsec_var = var;
184 mutex_init(&sc->ipsec_lock, MUTEX_DEFAULT, IPL_NONE);
185 sc->ipsec_ro_percpu = percpu_alloc(sizeof(struct ipsec_ro));
186 percpu_foreach(sc->ipsec_ro_percpu, if_ipsec_ro_init_pc, NULL);
187
188 mutex_enter(&ipsec_softcs.lock);
189 LIST_INSERT_HEAD(&ipsec_softcs.list, sc, ipsec_list);
190 mutex_exit(&ipsec_softcs.lock);
191 return 0;
192 }
193
194 static void
195 if_ipsec_attach0(struct ipsec_softc *sc)
196 {
197
198 sc->ipsec_if.if_addrlen = 0;
199 sc->ipsec_if.if_mtu = IPSEC_MTU;
200 sc->ipsec_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
201 /* set ipsec(4) specific default flags. */
202 sc->ipsec_if.if_flags |= IFF_FWD_IPV6;
203 sc->ipsec_if.if_extflags = IFEF_NO_LINK_STATE_CHANGE | IFEF_MPSAFE;
204 sc->ipsec_if.if_ioctl = if_ipsec_ioctl;
205 sc->ipsec_if.if_output = if_ipsec_output;
206 sc->ipsec_if.if_type = IFT_IPSEC;
207 sc->ipsec_if.if_dlt = DLT_NULL;
208 sc->ipsec_if.if_softc = sc;
209 IFQ_SET_READY(&sc->ipsec_if.if_snd);
210 if_initialize(&sc->ipsec_if);
211 if_alloc_sadl(&sc->ipsec_if);
212 bpf_attach(&sc->ipsec_if, DLT_NULL, sizeof(u_int));
213 if_register(&sc->ipsec_if);
214 }
215
216 static void
217 if_ipsec_ro_init_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
218 {
219 struct ipsec_ro *iro = p;
220
221 mutex_init(&iro->ir_lock, MUTEX_DEFAULT, IPL_NONE);
222 }
223
224 static void
225 if_ipsec_ro_fini_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
226 {
227 struct ipsec_ro *iro = p;
228
229 rtcache_free(&iro->ir_ro);
230
231 mutex_destroy(&iro->ir_lock);
232 }
233
234 static int
235 if_ipsec_clone_destroy(struct ifnet *ifp)
236 {
237 struct ipsec_softc *sc = ifp->if_softc;
238 struct ipsec_variant *var;
239 int bound;
240
241 mutex_enter(&ipsec_softcs.lock);
242 LIST_REMOVE(sc, ipsec_list);
243 mutex_exit(&ipsec_softcs.lock);
244
245 bound = curlwp_bind();
246 if_ipsec_delete_tunnel(&sc->ipsec_if);
247 curlwp_bindx(bound);
248
249 bpf_detach(ifp);
250 if_detach(ifp);
251
252 percpu_foreach(sc->ipsec_ro_percpu, if_ipsec_ro_fini_pc, NULL);
253 percpu_free(sc->ipsec_ro_percpu, sizeof(struct ipsec_ro));
254
255 mutex_destroy(&sc->ipsec_lock);
256
257 var = sc->ipsec_var;
258 kmem_free(var, sizeof(*var));
259 kmem_free(sc, sizeof(*sc));
260
261 return 0;
262 }
263
264 static inline bool
265 if_ipsec_nat_t(struct ipsec_softc *sc)
266 {
267
268 return (sc->ipsec_if.if_flags & IFF_NAT_T) != 0;
269 }
270
271 static inline bool
272 if_ipsec_fwd_ipv6(struct ipsec_softc *sc)
273 {
274
275 return (sc->ipsec_if.if_flags & IFF_FWD_IPV6) != 0;
276 }
277
278 int
279 if_ipsec_encap_func(struct mbuf *m, int off, int proto, void *arg)
280 {
281 struct ip ip;
282 struct ipsec_softc *sc;
283 struct ipsec_variant *var = NULL;
284 struct psref psref;
285 int ret = 0;
286
287 sc = arg;
288 KASSERT(sc != NULL);
289
290 if ((sc->ipsec_if.if_flags & IFF_UP) == 0)
291 goto out;
292
293 var = if_ipsec_getref_variant(sc, &psref);
294 if (if_ipsec_variant_is_unconfigured(var))
295 goto out;
296
297 switch (proto) {
298 case IPPROTO_IPV4:
299 case IPPROTO_IPV6:
300 break;
301 default:
302 goto out;
303 }
304
305 if (m->m_pkthdr.len < sizeof(ip))
306 goto out;
307
308 m_copydata(m, 0, sizeof(ip), &ip);
309 switch (ip.ip_v) {
310 #ifdef INET
311 case IPVERSION:
312 if (var->iv_psrc->sa_family != AF_INET ||
313 var->iv_pdst->sa_family != AF_INET)
314 goto out;
315 ret = ipsecif4_encap_func(m, &ip, var);
316 break;
317 #endif
318 default:
319 goto out;
320 }
321
322 out:
323 if (var != NULL)
324 if_ipsec_putref_variant(var, &psref);
325 return ret;
326 }
327
328 /*
329 * ipsec(4) I/F may cause infinite recursion calls when misconfigured.
330 * We'll prevent this by introducing upper limit.
331 */
332 static int
333 if_ipsec_check_nesting(struct ifnet *ifp, struct mbuf *m)
334 {
335
336 return if_tunnel_check_nesting(ifp, m, max_ipsec_nesting);
337 }
338
339 int
340 if_ipsec_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
341 const struct rtentry *rt)
342 {
343 struct ipsec_softc *sc = ifp->if_softc;
344 struct ipsec_variant *var;
345 struct psref psref;
346 int error;
347 int bound;
348
349 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
350
351 error = if_ipsec_check_nesting(ifp, m);
352 if (error) {
353 m_freem(m);
354 goto noref_end;
355 }
356
357 if ((ifp->if_flags & IFF_UP) == 0) {
358 m_freem(m);
359 error = ENETDOWN;
360 goto noref_end;
361 }
362
363
364 bound = curlwp_bind();
365 var = if_ipsec_getref_variant(sc, &psref);
366 if (if_ipsec_variant_is_unconfigured(var)) {
367 m_freem(m);
368 error = ENETDOWN;
369 goto end;
370 }
371
372 m->m_flags &= ~(M_BCAST|M_MCAST);
373
374 /* use DLT_NULL encapsulation here to pass inner af type */
375 M_PREPEND(m, sizeof(int), M_DONTWAIT);
376 if (!m) {
377 error = ENOBUFS;
378 goto end;
379 }
380 *mtod(m, int *) = dst->sa_family;
381
382 #if INET6
383 /* drop IPv6 packet if IFF_FWD_IPV6 is not set */
384 if (dst->sa_family == AF_INET6 &&
385 !if_ipsec_fwd_ipv6(sc)) {
386 /*
387 * IPv6 packet is not allowed to forward,that is not error.
388 */
389 error = 0;
390 IF_DROP(&ifp->if_snd);
391 m_freem(m);
392 goto end;
393 }
394 #endif
395
396 error = if_ipsec_out_direct(var, m, dst->sa_family);
397
398 end:
399 if_ipsec_putref_variant(var, &psref);
400 curlwp_bindx(bound);
401 noref_end:
402 if (error)
403 ifp->if_oerrors++;
404
405 return error;
406 }
407
408 static inline int
409 if_ipsec_out_direct(struct ipsec_variant *var, struct mbuf *m, int family)
410 {
411 struct ifnet *ifp = &var->iv_softc->ipsec_if;
412 int error;
413 int len;
414
415 KASSERT(if_ipsec_heldref_variant(var));
416 KASSERT(var->iv_output != NULL);
417
418 len = m->m_pkthdr.len;
419
420 /* input DLT_NULL frame to BPF */
421 bpf_mtap(ifp, m);
422
423 /* grab and chop off inner af type */
424 /* XXX need pullup? */
425 m_adj(m, sizeof(int));
426
427 error = var->iv_output(var, family, m);
428 if (error)
429 return error;
430
431 ifp->if_opackets++;
432 ifp->if_obytes += len;
433
434 return 0;
435 }
436
437 void
438 if_ipsec_input(struct mbuf *m, int af, struct ifnet *ifp)
439 {
440
441 KASSERT(ifp != NULL);
442
443 m_set_rcvif(m, ifp);
444
445 bpf_mtap_af(ifp, af, m);
446
447 if_ipsec_in_enqueue(m, af, ifp);
448
449 return;
450 }
451
452 static inline void
453 if_ipsec_in_enqueue(struct mbuf *m, int af, struct ifnet *ifp)
454 {
455 pktqueue_t *pktq;
456 int pktlen;
457
458 /*
459 * Put the packet to the network layer input queue according to the
460 * specified address family.
461 */
462 switch (af) {
463 #ifdef INET
464 case AF_INET:
465 pktq = ip_pktq;
466 break;
467 #endif
468 #ifdef INET6
469 case AF_INET6:
470 pktq = ip6_pktq;
471 break;
472 #endif
473 default:
474 ifp->if_ierrors++;
475 m_freem(m);
476 return;
477 }
478
479 #if 1
480 const u_int h = curcpu()->ci_index;
481 #else
482 const uint32_t h = pktq_rps_hash(m);
483 #endif
484 pktlen = m->m_pkthdr.len;
485 if (__predict_true(pktq_enqueue(pktq, m, h))) {
486 ifp->if_ibytes += pktlen;
487 ifp->if_ipackets++;
488 } else {
489 m_freem(m);
490 }
491
492 return;
493 }
494
495 static inline int
496 if_ipsec_check_salen(struct sockaddr *addr)
497 {
498
499 switch (addr->sa_family) {
500 #ifdef INET
501 case AF_INET:
502 if (addr->sa_len != sizeof(struct sockaddr_in))
503 return EINVAL;
504 break;
505 #endif /* INET */
506 #ifdef INET6
507 case AF_INET6:
508 if (addr->sa_len != sizeof(struct sockaddr_in6))
509 return EINVAL;
510 break;
511 #endif /* INET6 */
512 default:
513 return EAFNOSUPPORT;
514 }
515
516 return 0;
517 }
518
519 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
520 int
521 if_ipsec_ioctl(struct ifnet *ifp, u_long cmd, void *data)
522 {
523 struct ipsec_softc *sc = ifp->if_softc;
524 struct ipsec_variant *var = NULL;
525 struct ifreq *ifr = (struct ifreq*)data;
526 struct ifaddr *ifa = (struct ifaddr*)data;
527 int error = 0, size;
528 struct sockaddr *dst, *src;
529 u_long mtu;
530 short oflags = ifp->if_flags;
531 int bound;
532 struct psref psref;
533
534 switch (cmd) {
535 case SIOCINITIFADDR:
536 ifp->if_flags |= IFF_UP;
537 ifa->ifa_rtrequest = p2p_rtrequest;
538 break;
539
540 case SIOCSIFDSTADDR:
541 break;
542
543 case SIOCADDMULTI:
544 case SIOCDELMULTI:
545 switch (ifr->ifr_addr.sa_family) {
546 #ifdef INET
547 case AF_INET: /* IP supports Multicast */
548 break;
549 #endif /* INET */
550 #ifdef INET6
551 case AF_INET6: /* IP6 supports Multicast */
552 break;
553 #endif /* INET6 */
554 default: /* Other protocols doesn't support Multicast */
555 error = EAFNOSUPPORT;
556 break;
557 }
558 break;
559
560 case SIOCSIFMTU:
561 mtu = ifr->ifr_mtu;
562 if (mtu < IPSEC_MTU_MIN || mtu > IPSEC_MTU_MAX)
563 return EINVAL;
564 else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
565 error = 0;
566 break;
567
568 #ifdef INET
569 case SIOCSIFPHYADDR:
570 #endif
571 #ifdef INET6
572 case SIOCSIFPHYADDR_IN6:
573 #endif /* INET6 */
574 case SIOCSLIFPHYADDR:
575 switch (cmd) {
576 #ifdef INET
577 case SIOCSIFPHYADDR:
578 src = (struct sockaddr *)
579 &(((struct in_aliasreq *)data)->ifra_addr);
580 dst = (struct sockaddr *)
581 &(((struct in_aliasreq *)data)->ifra_dstaddr);
582 break;
583 #endif /* INET */
584 #ifdef INET6
585 case SIOCSIFPHYADDR_IN6:
586 src = (struct sockaddr *)
587 &(((struct in6_aliasreq *)data)->ifra_addr);
588 dst = (struct sockaddr *)
589 &(((struct in6_aliasreq *)data)->ifra_dstaddr);
590 break;
591 #endif /* INET6 */
592 case SIOCSLIFPHYADDR:
593 src = (struct sockaddr *)
594 &(((struct if_laddrreq *)data)->addr);
595 dst = (struct sockaddr *)
596 &(((struct if_laddrreq *)data)->dstaddr);
597 break;
598 default:
599 return EINVAL;
600 }
601
602 /* sa_family must be equal */
603 if (src->sa_family != dst->sa_family)
604 return EINVAL;
605
606 error = if_ipsec_check_salen(src);
607 if (error)
608 return error;
609 error = if_ipsec_check_salen(dst);
610 if (error)
611 return error;
612
613 /* check sa_family looks sane for the cmd */
614 switch (cmd) {
615 #ifdef INET
616 case SIOCSIFPHYADDR:
617 if (src->sa_family == AF_INET)
618 break;
619 return EAFNOSUPPORT;
620 #endif /* INET */
621 #ifdef INET6
622 case SIOCSIFPHYADDR_IN6:
623 if (src->sa_family == AF_INET6)
624 break;
625 return EAFNOSUPPORT;
626 #endif /* INET6 */
627 case SIOCSLIFPHYADDR:
628 /* checks done in the above */
629 break;
630 }
631 /*
632 * calls if_ipsec_getref_variant() for other softcs to check
633 * address pair duplicattion
634 */
635 bound = curlwp_bind();
636 error = if_ipsec_set_tunnel(&sc->ipsec_if, src, dst);
637 if (error)
638 goto bad;
639 break;
640
641 case SIOCDIFPHYADDR:
642 bound = curlwp_bind();
643 if_ipsec_delete_tunnel(&sc->ipsec_if);
644 curlwp_bindx(bound);
645 break;
646
647 case SIOCGIFPSRCADDR:
648 #ifdef INET6
649 case SIOCGIFPSRCADDR_IN6:
650 #endif /* INET6 */
651 bound = curlwp_bind();
652 var = if_ipsec_getref_variant(sc, &psref);
653 if (var->iv_psrc == NULL) {
654 error = EADDRNOTAVAIL;
655 goto bad;
656 }
657 src = var->iv_psrc;
658 switch (cmd) {
659 #ifdef INET
660 case SIOCGIFPSRCADDR:
661 dst = &ifr->ifr_addr;
662 size = sizeof(ifr->ifr_addr);
663 break;
664 #endif /* INET */
665 #ifdef INET6
666 case SIOCGIFPSRCADDR_IN6:
667 dst = (struct sockaddr *)
668 &(((struct in6_ifreq *)data)->ifr_addr);
669 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
670 break;
671 #endif /* INET6 */
672 default:
673 error = EADDRNOTAVAIL;
674 goto bad;
675 }
676 if (src->sa_len > size) {
677 error = EINVAL;
678 goto bad;
679 }
680 error = IF_IPSEC_GATHER_PSRC_ADDR_PORT(var, dst);
681 if (error)
682 goto bad;
683 if_ipsec_putref_variant(var, &psref);
684 curlwp_bindx(bound);
685 break;
686
687 case SIOCGIFPDSTADDR:
688 #ifdef INET6
689 case SIOCGIFPDSTADDR_IN6:
690 #endif /* INET6 */
691 bound = curlwp_bind();
692 var = if_ipsec_getref_variant(sc, &psref);
693 if (var->iv_pdst == NULL) {
694 error = EADDRNOTAVAIL;
695 goto bad;
696 }
697 src = var->iv_pdst;
698 switch (cmd) {
699 #ifdef INET
700 case SIOCGIFPDSTADDR:
701 dst = &ifr->ifr_addr;
702 size = sizeof(ifr->ifr_addr);
703 break;
704 #endif /* INET */
705 #ifdef INET6
706 case SIOCGIFPDSTADDR_IN6:
707 dst = (struct sockaddr *)
708 &(((struct in6_ifreq *)data)->ifr_addr);
709 size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
710 break;
711 #endif /* INET6 */
712 default:
713 error = EADDRNOTAVAIL;
714 goto bad;
715 }
716 if (src->sa_len > size) {
717 error = EINVAL;
718 goto bad;
719 }
720 error = IF_IPSEC_GATHER_PDST_ADDR_PORT(var, dst);
721 if (error)
722 goto bad;
723 if_ipsec_putref_variant(var, &psref);
724 curlwp_bindx(bound);
725 break;
726
727 case SIOCGLIFPHYADDR:
728 bound = curlwp_bind();
729 var = if_ipsec_getref_variant(sc, &psref);
730 if (if_ipsec_variant_is_unconfigured(var)) {
731 error = EADDRNOTAVAIL;
732 goto bad;
733 }
734
735 /* copy src */
736 src = var->iv_psrc;
737 dst = (struct sockaddr *)
738 &(((struct if_laddrreq *)data)->addr);
739 size = sizeof(((struct if_laddrreq *)data)->addr);
740 if (src->sa_len > size) {
741 error = EINVAL;
742 goto bad;
743 }
744 error = IF_IPSEC_GATHER_PSRC_ADDR_PORT(var, dst);
745 if (error)
746 goto bad;
747
748 /* copy dst */
749 src = var->iv_pdst;
750 dst = (struct sockaddr *)
751 &(((struct if_laddrreq *)data)->dstaddr);
752 size = sizeof(((struct if_laddrreq *)data)->dstaddr);
753 if (src->sa_len > size) {
754 error = EINVAL;
755 goto bad;
756 }
757 error = IF_IPSEC_GATHER_PDST_ADDR_PORT(var, dst);
758 if (error)
759 goto bad;
760 if_ipsec_putref_variant(var, &psref);
761 curlwp_bindx(bound);
762 break;
763
764 default:
765 error = ifioctl_common(ifp, cmd, data);
766 if (!error) {
767 bound = curlwp_bind();
768 error = if_ipsec_ensure_flags(&sc->ipsec_if, oflags);
769 if (error)
770 goto bad;
771 }
772 break;
773 }
774 return error;
775
776 bad:
777 if (var != NULL)
778 if_ipsec_putref_variant(var, &psref);
779 curlwp_bindx(bound);
780
781 return error;
782 }
783
784 struct encap_funcs {
785 #ifdef INET
786 int (*ef_inet)(struct ipsec_variant *);
787 #endif
788 #ifdef INET6
789 int (*ef_inet6)(struct ipsec_variant *);
790 #endif
791 };
792
793 static struct encap_funcs ipsec_encap_attach = {
794 #ifdef INET
795 .ef_inet = ipsecif4_attach,
796 #endif
797 #ifdef INET6
798 .ef_inet6 = &ipsecif6_attach,
799 #endif
800 };
801
802 static struct encap_funcs ipsec_encap_detach = {
803 #ifdef INET
804 .ef_inet = ipsecif4_detach,
805 #endif
806 #ifdef INET6
807 .ef_inet6 = &ipsecif6_detach,
808 #endif
809 };
810
811 static int
812 if_ipsec_encap_common(struct ipsec_variant *var, struct encap_funcs *funcs)
813 {
814 int error;
815
816 KASSERT(var != NULL);
817 KASSERT(if_ipsec_variant_is_configured(var));
818
819 switch (var->iv_psrc->sa_family) {
820 #ifdef INET
821 case AF_INET:
822 error = (funcs->ef_inet)(var);
823 break;
824 #endif /* INET */
825 #ifdef INET6
826 case AF_INET6:
827 error = (funcs->ef_inet6)(var);
828 break;
829 #endif /* INET6 */
830 default:
831 error = EINVAL;
832 break;
833 }
834
835 return error;
836 }
837
838 static int
839 if_ipsec_encap_attach(struct ipsec_variant *var)
840 {
841
842 return if_ipsec_encap_common(var, &ipsec_encap_attach);
843 }
844
845 static int
846 if_ipsec_encap_detach(struct ipsec_variant *var)
847 {
848
849 return if_ipsec_encap_common(var, &ipsec_encap_detach);
850 }
851
852 /*
853 * Validate and set ipsec(4) I/F configurations.
854 * (1) validate
855 * (1-1) Check the argument src and dst address pair will change
856 * configuration from current src and dst address pair.
857 * (1-2) Check any ipsec(4) I/F uses duplicated src and dst address pair
858 * with argument src and dst address pair, except for NAT-T shared
859 * tunnels.
860 * (2) set
861 * (2-1) Create variant for new configuration.
862 * (2-2) Create temporary "null" variant used to avoid to access
863 * dangling variant while SPs are deleted and added.
864 * (2-3) Swap variant include its SPs.
865 * (2-4) Cleanup last configurations.
866 */
867 static int
868 if_ipsec_set_tunnel(struct ifnet *ifp,
869 struct sockaddr *src, struct sockaddr *dst)
870 {
871 struct ipsec_softc *sc = ifp->if_softc;
872 struct ipsec_softc *sc2;
873 struct ipsec_variant *ovar, *nvar, *nullvar;
874 struct sockaddr *osrc, *odst;
875 struct sockaddr *nsrc, *ndst;
876 in_port_t nsport = 0, ndport = 0;
877 int error;
878
879 error = encap_lock_enter();
880 if (error)
881 return error;
882
883 nsrc = sockaddr_dup(src, M_WAITOK);
884 ndst = sockaddr_dup(dst, M_WAITOK);
885 nvar = kmem_zalloc(sizeof(*nvar), KM_SLEEP);
886 nullvar = kmem_zalloc(sizeof(*nullvar), KM_SLEEP);
887
888 mutex_enter(&sc->ipsec_lock);
889
890 ovar = sc->ipsec_var;
891
892 switch(nsrc->sa_family) {
893 #ifdef INET
894 case AF_INET:
895 nsport = satosin(src)->sin_port;
896 /*
897 * avoid confuse SP when NAT-T disabled,
898 * e.g.
899 * expected: 10.0.1.2[any] 10.0.1.1[any] 4(ipv4)
900 * confuse : 10.0.1.2[600] 10.0.1.1[600] 4(ipv4)
901 */
902 satosin(nsrc)->sin_port = 0;
903 ndport = satosin(dst)->sin_port;
904 satosin(ndst)->sin_port = 0;
905 break;
906 #endif /* INET */
907 #ifdef INET6
908 case AF_INET6:
909 nsport = satosin6(src)->sin6_port;
910 satosin6(nsrc)->sin6_port = 0;
911 ndport = satosin6(dst)->sin6_port;
912 satosin6(ndst)->sin6_port = 0;
913 break;
914 #endif /* INET6 */
915 default:
916 log(LOG_DEBUG,
917 "%s: Invalid address family: %d.\n",
918 __func__, src->sa_family);
919 error = EINVAL;
920 goto out;
921 }
922
923 /*
924 * (1-1) Check the argument src and dst address pair will change
925 * configuration from current src and dst address pair.
926 */
927 if ((ovar->iv_pdst && sockaddr_cmp(ovar->iv_pdst, dst) == 0) &&
928 (ovar->iv_psrc && sockaddr_cmp(ovar->iv_psrc, src) == 0) &&
929 (ovar->iv_sport == nsport && ovar->iv_dport == ndport)) {
930 /* address and port pair not changed. */
931 error = 0;
932 goto out;
933 }
934
935 /*
936 * (1-2) Check any ipsec(4) I/F uses duplicated src and dst address pair
937 * with argument src and dst address pair, except for NAT-T shared
938 * tunnels.
939 */
940 mutex_enter(&ipsec_softcs.lock);
941 LIST_FOREACH(sc2, &ipsec_softcs.list, ipsec_list) {
942 struct ipsec_variant *var2;
943 struct psref psref;
944
945 if (sc2 == sc)
946 continue;
947 var2 = if_ipsec_getref_variant(sc2, &psref);
948 if (if_ipsec_variant_is_unconfigured(var2)) {
949 if_ipsec_putref_variant(var2, &psref);
950 continue;
951 }
952 if (if_ipsec_nat_t(sc) || if_ipsec_nat_t(sc2)) {
953 if_ipsec_putref_variant(var2, &psref);
954 continue; /* NAT-T shared tunnel */
955 }
956 if (sockaddr_cmp(var2->iv_pdst, dst) == 0 &&
957 sockaddr_cmp(var2->iv_psrc, src) == 0) {
958 if_ipsec_putref_variant(var2, &psref);
959 mutex_exit(&ipsec_softcs.lock);
960 error = EADDRNOTAVAIL;
961 goto out;
962 }
963
964 if_ipsec_putref_variant(var2, &psref);
965 /* XXX both end must be valid? (I mean, not 0.0.0.0) */
966 }
967 mutex_exit(&ipsec_softcs.lock);
968
969
970 osrc = ovar->iv_psrc;
971 odst = ovar->iv_pdst;
972
973 /*
974 * (2-1) Create ipsec_variant for new configuration.
975 */
976 if_ipsec_copy_variant(nvar, ovar);
977 nvar->iv_psrc = nsrc;
978 nvar->iv_pdst = ndst;
979 nvar->iv_sport = nsport;
980 nvar->iv_dport = ndport;
981 nvar->iv_encap_cookie4 = NULL;
982 nvar->iv_encap_cookie6 = NULL;
983 psref_target_init(&nvar->iv_psref, iv_psref_class);
984 error = if_ipsec_encap_attach(nvar);
985 if (error)
986 goto out;
987
988 /*
989 * (2-2) Create temporary "null" variant.
990 */
991 if_ipsec_copy_variant(nullvar, ovar);
992 if_ipsec_clear_config(nullvar);
993 psref_target_init(&nullvar->iv_psref, iv_psref_class);
994 membar_producer();
995 /*
996 * (2-3) Swap variant include its SPs.
997 */
998 error = if_ipsec_update_variant(sc, nvar, nullvar);
999 if (error) {
1000 if_ipsec_encap_detach(nvar);
1001 goto out;
1002 }
1003
1004 mutex_exit(&sc->ipsec_lock);
1005
1006 /*
1007 * (2-4) Cleanup last configurations.
1008 */
1009 if (if_ipsec_variant_is_configured(ovar))
1010 if_ipsec_encap_detach(ovar);
1011 encap_lock_exit();
1012
1013 if (osrc != NULL)
1014 sockaddr_free(osrc);
1015 if (odst != NULL)
1016 sockaddr_free(odst);
1017 kmem_free(ovar, sizeof(*ovar));
1018 kmem_free(nullvar, sizeof(*nullvar));
1019
1020 return 0;
1021
1022 out:
1023 mutex_exit(&sc->ipsec_lock);
1024 encap_lock_exit();
1025
1026 sockaddr_free(nsrc);
1027 sockaddr_free(ndst);
1028 kmem_free(nvar, sizeof(*nvar));
1029 kmem_free(nullvar, sizeof(*nullvar));
1030
1031 return error;
1032 }
1033
1034 /*
1035 * Validate and delete ipsec(4) I/F configurations.
1036 * (1) validate
1037 * (1-1) Check current src and dst address pair are null,
1038 * which means the ipsec(4) I/F is already done deletetunnel.
1039 * (2) delete
1040 * (2-1) Create variant for deleted status.
1041 * (2-2) Create temporary "null" variant used to avoid to access
1042 * dangling variant while SPs are deleted and added.
1043 * NOTE:
1044 * The contents of temporary "null" variant equal to the variant
1045 * of (2-1), however two psref_target_destroy() synchronization
1046 * points are necessary to avoid to access dangling variant
1047 * while SPs are deleted and added. To implement that simply,
1048 * we use the same manner as if_ipsec_set_tunnel(), that is,
1049 * create extra "null" variant and use it temporarily.
1050 * (2-3) Swap variant include its SPs.
1051 * (2-4) Cleanup last configurations.
1052 */
1053 static void
1054 if_ipsec_delete_tunnel(struct ifnet *ifp)
1055 {
1056 struct ipsec_softc *sc = ifp->if_softc;
1057 struct ipsec_variant *ovar, *nvar, *nullvar;
1058 struct sockaddr *osrc, *odst;
1059 int error;
1060
1061 error = encap_lock_enter();
1062 if (error)
1063 return;
1064
1065 nvar = kmem_zalloc(sizeof(*nvar), KM_SLEEP);
1066 nullvar = kmem_zalloc(sizeof(*nullvar), KM_SLEEP);
1067
1068 mutex_enter(&sc->ipsec_lock);
1069
1070 ovar = sc->ipsec_var;
1071 osrc = ovar->iv_psrc;
1072 odst = ovar->iv_pdst;
1073 /*
1074 * (1-1) Check current src and dst address pair are null,
1075 * which means the ipsec(4) I/F is already done deletetunnel.
1076 */
1077 if (osrc == NULL || odst == NULL) {
1078 /* address pair not changed. */
1079 mutex_exit(&sc->ipsec_lock);
1080 encap_lock_exit();
1081 kmem_free(nvar, sizeof(*nvar));
1082 return;
1083 }
1084
1085 /*
1086 * (2-1) Create variant for deleted status.
1087 */
1088 if_ipsec_copy_variant(nvar, ovar);
1089 if_ipsec_clear_config(nvar);
1090 psref_target_init(&nvar->iv_psref, iv_psref_class);
1091
1092 /*
1093 * (2-2) Create temporary "null" variant used to avoid to access
1094 * dangling variant while SPs are deleted and added.
1095 */
1096 if_ipsec_copy_variant(nullvar, ovar);
1097 if_ipsec_clear_config(nullvar);
1098 psref_target_init(&nullvar->iv_psref, iv_psref_class);
1099 membar_producer();
1100 /*
1101 * (2-3) Swap variant include its SPs.
1102 */
1103 /* if_ipsec_update_variant() does not fail when delete SP only. */
1104 (void)if_ipsec_update_variant(sc, nvar, nullvar);
1105
1106 mutex_exit(&sc->ipsec_lock);
1107
1108 /*
1109 * (2-4) Cleanup last configurations.
1110 */
1111 if (if_ipsec_variant_is_configured(ovar))
1112 if_ipsec_encap_detach(ovar);
1113 encap_lock_exit();
1114
1115 sockaddr_free(osrc);
1116 sockaddr_free(odst);
1117 kmem_free(ovar, sizeof(*ovar));
1118 kmem_free(nullvar, sizeof(*nullvar));
1119 }
1120
1121 /*
1122 * Check IFF_NAT_T and IFF_FWD_IPV6 flags, therefore update SPs if needed.
1123 * (1) check
1124 * (1-1) Check flags are changed.
1125 * (1-2) Check current src and dst address pair. If they are null,
1126 * that means the ipsec(4) I/F is deletetunnel'ed, so it is
1127 * not needed to update.
1128 * (2) update
1129 * (2-1) Create variant for new SPs.
1130 * (2-2) Create temporary "null" variant used to avoid to access
1131 * dangling variant while SPs are deleted and added.
1132 * NOTE:
1133 * There is the same problem as if_ipsec_delete_tunnel().
1134 * (2-3) Swap variant include its SPs.
1135 * (2-4) Cleanup unused configurations.
1136 * NOTE: use the same encap_cookies.
1137 */
1138 static int
1139 if_ipsec_ensure_flags(struct ifnet *ifp, short oflags)
1140 {
1141 struct ipsec_softc *sc = ifp->if_softc;
1142 struct ipsec_variant *ovar, *nvar, *nullvar;
1143 int error;
1144
1145 /*
1146 * (1) Check flags are changed.
1147 */
1148 if ((oflags & (IFF_NAT_T|IFF_FWD_IPV6)) ==
1149 (ifp->if_flags & (IFF_NAT_T|IFF_FWD_IPV6)))
1150 return 0; /* flags not changed. */
1151
1152 error = encap_lock_enter();
1153 if (error)
1154 return error;
1155
1156 nvar = kmem_zalloc(sizeof(*nvar), KM_SLEEP);
1157 nullvar = kmem_zalloc(sizeof(*nullvar), KM_SLEEP);
1158
1159 mutex_enter(&sc->ipsec_lock);
1160
1161 ovar = sc->ipsec_var;
1162 /*
1163 * (1-2) Check current src and dst address pair.
1164 */
1165 if (if_ipsec_variant_is_unconfigured(ovar)) {
1166 /* nothing to do */
1167 mutex_exit(&sc->ipsec_lock);
1168 return 0;
1169 }
1170
1171 /*
1172 * (2-1) Create variant for new SPs.
1173 */
1174 if_ipsec_copy_variant(nvar, ovar);
1175 psref_target_init(&nvar->iv_psref, iv_psref_class);
1176 /*
1177 * (2-2) Create temporary "null" variant used to avoid to access
1178 * dangling variant while SPs are deleted and added.
1179 */
1180 if_ipsec_copy_variant(nullvar, ovar);
1181 if_ipsec_clear_config(nullvar);
1182 psref_target_init(&nullvar->iv_psref, iv_psref_class);
1183 membar_producer();
1184 /*
1185 * (2-3) Swap variant include its SPs.
1186 */
1187 error = if_ipsec_update_variant(sc, nvar, nullvar);
1188
1189 mutex_exit(&sc->ipsec_lock);
1190 encap_lock_exit();
1191
1192 /*
1193 * (2-4) Cleanup unused configurations.
1194 */
1195 if (!error)
1196 kmem_free(ovar, sizeof(*ovar));
1197 else
1198 kmem_free(nvar, sizeof(*ovar));
1199 kmem_free(nullvar, sizeof(*nullvar));
1200
1201 return error;
1202 }
1203
1204 /*
1205 * SPD management
1206 */
1207
1208 /*
1209 * Share SP set with other NAT-T ipsec(4) I/F(s).
1210 * Return 1, when "var" shares SP set.
1211 * Return 0, when "var" cannot share SP set.
1212 *
1213 * NOTE:
1214 * if_ipsec_share_sp() and if_ipsec_unshare_sp() would require global lock
1215 * to exclude other ipsec(4) I/Fs set_tunnel/delete_tunnel. E.g. when ipsec0
1216 * and ipsec1 can share SP set, running ipsec0's set_tunnel and ipsec1's
1217 * set_tunnel causes race.
1218 * Currently, (fortunately) encap_lock works as this global lock.
1219 */
1220 static int
1221 if_ipsec_share_sp(struct ipsec_variant *var)
1222 {
1223 struct ipsec_softc *sc = var->iv_softc;
1224 struct ipsec_softc *sc2;
1225 struct ipsec_variant *var2;
1226 struct psref psref;
1227
1228 KASSERT(encap_lock_held());
1229 KASSERT(var->iv_psrc != NULL && var->iv_pdst != NULL);
1230
1231 mutex_enter(&ipsec_softcs.lock);
1232 LIST_FOREACH(sc2, &ipsec_softcs.list, ipsec_list) {
1233 if (sc2 == sc)
1234 continue;
1235 var2 = if_ipsec_getref_variant(sc2, &psref);
1236 if (if_ipsec_variant_is_unconfigured(var2)) {
1237 if_ipsec_putref_variant(var2, &psref);
1238 continue;
1239 }
1240 if (sockaddr_cmp(var2->iv_pdst, var->iv_pdst) != 0 ||
1241 sockaddr_cmp(var2->iv_psrc, var->iv_psrc) != 0) {
1242 if_ipsec_putref_variant(var2, &psref);
1243 continue;
1244 }
1245
1246 break;
1247 }
1248 mutex_exit(&ipsec_softcs.lock);
1249 if (sc2 == NULL)
1250 return 0; /* not shared */
1251
1252 IV_SP_IN(var) = IV_SP_IN(var2);
1253 IV_SP_IN6(var) = IV_SP_IN6(var2);
1254 IV_SP_OUT(var) = IV_SP_OUT(var2);
1255 IV_SP_OUT6(var) = IV_SP_OUT6(var2);
1256
1257 if_ipsec_putref_variant(var2, &psref);
1258 return 1; /* shared */
1259 }
1260
1261 /*
1262 * Unshare SP set with other NAT-T ipsec(4) I/F(s).
1263 * Return 1, when "var" shared SP set, and then unshare them.
1264 * Return 0, when "var" did not share SP set.
1265 *
1266 * NOTE:
1267 * See if_ipsec_share_sp()'s note.
1268 */
1269 static int
1270 if_ipsec_unshare_sp(struct ipsec_variant *var)
1271 {
1272 struct ipsec_softc *sc = var->iv_softc;
1273 struct ipsec_softc *sc2;
1274 struct ipsec_variant *var2;
1275 struct psref psref;
1276
1277 KASSERT(encap_lock_held());
1278
1279 if (!var->iv_pdst || !var->iv_psrc)
1280 return 0;
1281
1282 mutex_enter(&ipsec_softcs.lock);
1283 LIST_FOREACH(sc2, &ipsec_softcs.list, ipsec_list) {
1284 if (sc2 == sc)
1285 continue;
1286 var2 = if_ipsec_getref_variant(sc2, &psref);
1287 if (!var2->iv_pdst || !var2->iv_psrc) {
1288 if_ipsec_putref_variant(var2, &psref);
1289 continue;
1290 }
1291 if (sockaddr_cmp(var2->iv_pdst, var->iv_pdst) != 0 ||
1292 sockaddr_cmp(var2->iv_psrc, var->iv_psrc) != 0) {
1293 if_ipsec_putref_variant(var2, &psref);
1294 continue;
1295 }
1296
1297 break;
1298 }
1299 mutex_exit(&ipsec_softcs.lock);
1300 if (sc2 == NULL)
1301 return 0; /* not shared */
1302
1303 IV_SP_IN(var) = NULL;
1304 IV_SP_IN6(var) = NULL;
1305 IV_SP_OUT(var) = NULL;
1306 IV_SP_OUT6(var) = NULL;
1307 if_ipsec_putref_variant(var2, &psref);
1308 return 1; /* shared */
1309 }
1310
1311 static inline void
1312 if_ipsec_add_mbuf(struct mbuf *m0, void *data, size_t len)
1313 {
1314 struct mbuf *m;
1315
1316 MGET(m, M_WAITOK | M_ZERO, MT_DATA);
1317 m->m_len = PFKEY_ALIGN8(len);
1318 m_copyback(m, 0, len, data);
1319 m_cat(m0, m);
1320 }
1321
1322 static inline void
1323 if_ipsec_add_pad(struct mbuf *m0, size_t len)
1324 {
1325 struct mbuf *m;
1326
1327 if (len == 0)
1328 return;
1329
1330 MGET(m, M_WAITOK | M_ZERO, MT_DATA);
1331 m->m_len = len;
1332 m_cat(m0, m);
1333 }
1334
1335 static inline size_t
1336 if_ipsec_set_sadb_addr(struct sadb_address *saaddr, struct sockaddr *addr,
1337 int proto, uint16_t exttype)
1338 {
1339 size_t size;
1340
1341 KASSERT(saaddr != NULL);
1342 KASSERT(addr != NULL);
1343
1344 size = sizeof(*saaddr) + PFKEY_ALIGN8(addr->sa_len);
1345 saaddr->sadb_address_len = PFKEY_UNIT64(size);
1346 saaddr->sadb_address_exttype = exttype;
1347 saaddr->sadb_address_proto = proto;
1348 switch (addr->sa_family) {
1349 #ifdef INET
1350 case AF_INET:
1351 saaddr->sadb_address_prefixlen = sizeof(struct in_addr) << 3;
1352 break;
1353 #endif /* INET */
1354 #ifdef INET6
1355 case AF_INET6:
1356 saaddr->sadb_address_prefixlen = sizeof(struct in6_addr) << 3;
1357 break;
1358 #endif /* INET6 */
1359 default:
1360 log(LOG_DEBUG,
1361 "%s: Invalid address family: %d.\n",
1362 __func__, addr->sa_family);
1363 break;
1364 }
1365 saaddr->sadb_address_reserved = 0;
1366
1367 return size;
1368 }
1369
1370 static inline size_t
1371 if_ipsec_set_sadb_src(struct sadb_address *sasrc, struct sockaddr *src,
1372 int proto)
1373 {
1374
1375 return if_ipsec_set_sadb_addr(sasrc, src, proto,
1376 SADB_EXT_ADDRESS_SRC);
1377 }
1378
1379 static inline size_t
1380 if_ipsec_set_sadb_dst(struct sadb_address *sadst, struct sockaddr *dst,
1381 int proto)
1382 {
1383
1384 return if_ipsec_set_sadb_addr(sadst, dst, proto,
1385 SADB_EXT_ADDRESS_DST);
1386 }
1387
1388 static inline size_t
1389 if_ipsec_set_sadb_x_policy(struct sadb_x_policy *xpl,
1390 struct sadb_x_ipsecrequest *xisr, uint16_t policy, uint8_t dir, uint32_t id,
1391 uint8_t level)
1392 {
1393 size_t size;
1394
1395 KASSERT(policy != IPSEC_POLICY_IPSEC || xisr != NULL);
1396
1397 size = sizeof(*xpl);
1398 if (policy == IPSEC_POLICY_IPSEC) {
1399 size += PFKEY_ALIGN8(sizeof(*xisr));
1400 }
1401 xpl->sadb_x_policy_len = PFKEY_UNIT64(size);
1402 xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1403 xpl->sadb_x_policy_type = policy;
1404 xpl->sadb_x_policy_dir = dir;
1405 xpl->sadb_x_policy_reserved = 0;
1406 xpl->sadb_x_policy_id = id;
1407 xpl->sadb_x_policy_reserved2 = 0;
1408
1409 if (policy == IPSEC_POLICY_IPSEC) {
1410 xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(sizeof(*xisr));
1411 xisr->sadb_x_ipsecrequest_proto = IPPROTO_ESP;
1412 xisr->sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
1413 xisr->sadb_x_ipsecrequest_level = level;
1414 xisr->sadb_x_ipsecrequest_reqid = key_newreqid();
1415 }
1416
1417 return size;
1418 }
1419
1420 static inline void
1421 if_ipsec_set_sadb_msg(struct sadb_msg *msg, uint16_t extlen, uint8_t msgtype)
1422 {
1423
1424 KASSERT(msg != NULL);
1425
1426 msg->sadb_msg_version = PF_KEY_V2;
1427 msg->sadb_msg_type = msgtype;
1428 msg->sadb_msg_errno = 0;
1429 msg->sadb_msg_satype = SADB_SATYPE_UNSPEC;
1430 msg->sadb_msg_len = PFKEY_UNIT64(sizeof(*msg)) + extlen;
1431 msg->sadb_msg_reserved = 0;
1432 msg->sadb_msg_seq = 0; /* XXXX */
1433 msg->sadb_msg_pid = 0; /* XXXX */
1434 }
1435
1436 static inline void
1437 if_ipsec_set_sadb_msg_add(struct sadb_msg *msg, uint16_t extlen)
1438 {
1439
1440 if_ipsec_set_sadb_msg(msg, extlen, SADB_X_SPDADD);
1441 }
1442
1443 static inline void
1444 if_ipsec_set_sadb_msg_del(struct sadb_msg *msg, uint16_t extlen)
1445 {
1446
1447 if_ipsec_set_sadb_msg(msg, extlen, SADB_X_SPDDELETE2);
1448 }
1449
1450 static int
1451 if_ipsec_set_addr_port(struct sockaddr *addrport, struct sockaddr *addr,
1452 in_port_t port)
1453 {
1454 int error = 0;
1455
1456 sockaddr_copy(addrport, addr->sa_len, addr);
1457
1458 switch (addr->sa_family) {
1459 #ifdef INET
1460 case AF_INET: {
1461 struct sockaddr_in *sin = satosin(addrport);
1462 sin->sin_port = port;
1463 break;
1464 }
1465 #endif /* INET */
1466 #ifdef INET6
1467 case AF_INET6: {
1468 struct sockaddr_in6 *sin6 = satosin6(addrport);
1469 sin6->sin6_port = port;
1470 break;
1471 }
1472 #endif /* INET6 */
1473 default:
1474 log(LOG_DEBUG,
1475 "%s: Invalid address family: %d.\n",
1476 __func__, addr->sa_family);
1477 error = EINVAL;
1478 }
1479
1480 return error;
1481 }
1482
1483 static struct secpolicy *
1484 if_ipsec_add_sp0(struct sockaddr *src, in_port_t sport,
1485 struct sockaddr *dst, in_port_t dport,
1486 int dir, int proto, int level, u_int policy)
1487 {
1488 struct sadb_msg msg;
1489 struct sadb_address xsrc, xdst;
1490 struct sadb_x_policy xpl;
1491 struct sadb_x_ipsecrequest xisr;
1492 size_t size;
1493 size_t padlen;
1494 uint16_t ext_msg_len = 0;
1495 struct mbuf *m;
1496
1497 memset(&msg, 0, sizeof(msg));
1498 memset(&xsrc, 0, sizeof(xsrc));
1499 memset(&xdst, 0, sizeof(xdst));
1500 memset(&xpl, 0, sizeof(xpl));
1501 memset(&xisr, 0, sizeof(xisr));
1502
1503 MGETHDR(m, M_WAITOK, MT_DATA);
1504
1505 size = if_ipsec_set_sadb_src(&xsrc, src, proto);
1506 ext_msg_len += PFKEY_UNIT64(size);
1507 size = if_ipsec_set_sadb_dst(&xdst, dst, proto);
1508 ext_msg_len += PFKEY_UNIT64(size);
1509 size = if_ipsec_set_sadb_x_policy(&xpl, &xisr, policy, dir, 0, level);
1510 ext_msg_len += PFKEY_UNIT64(size);
1511 if_ipsec_set_sadb_msg_add(&msg, ext_msg_len);
1512
1513 /* build PF_KEY message */
1514
1515 m->m_len = sizeof(msg);
1516 m_copyback(m, 0, sizeof(msg), &msg);
1517
1518 if_ipsec_add_mbuf(m, &xsrc, sizeof(xsrc));
1519 if (sport == 0) {
1520 if_ipsec_add_mbuf(m, src, src->sa_len);
1521 } else {
1522 struct sockaddr addrport;
1523
1524 if_ipsec_set_addr_port(&addrport, src, sport);
1525 if_ipsec_add_mbuf(m, &addrport, addrport.sa_len);
1526 }
1527 padlen = PFKEY_UNUNIT64(xsrc.sadb_address_len)
1528 - (sizeof(xsrc) + PFKEY_ALIGN8(src->sa_len));
1529 if_ipsec_add_pad(m, padlen);
1530
1531 if_ipsec_add_mbuf(m, &xdst, sizeof(xdst));
1532 if (dport == 0) {
1533 if_ipsec_add_mbuf(m, dst, dst->sa_len);
1534 } else {
1535 struct sockaddr addrport;
1536
1537 if_ipsec_set_addr_port(&addrport, dst, dport);
1538 if_ipsec_add_mbuf(m, &addrport, addrport.sa_len);
1539 }
1540 padlen = PFKEY_UNUNIT64(xdst.sadb_address_len)
1541 - (sizeof(xdst) + PFKEY_ALIGN8(dst->sa_len));
1542 if_ipsec_add_pad(m, padlen);
1543
1544 if_ipsec_add_mbuf(m, &xpl, sizeof(xpl));
1545 if (policy == IPSEC_POLICY_IPSEC)
1546 if_ipsec_add_mbuf(m, &xisr, sizeof(xisr));
1547
1548 /* key_kpi_spdadd() has already done KEY_SP_REF(). */
1549 return key_kpi_spdadd(m);
1550 }
1551
1552 static int
1553 if_ipsec_add_sp(struct ipsec_variant *var,
1554 struct sockaddr *src, in_port_t sport,
1555 struct sockaddr *dst, in_port_t dport)
1556 {
1557 struct ipsec_softc *sc = var->iv_softc;
1558 int level;
1559 u_int v6policy;
1560
1561 /*
1562 * must delete sp before add it.
1563 */
1564 KASSERT(IV_SP_IN(var) == NULL);
1565 KASSERT(IV_SP_OUT(var) == NULL);
1566 KASSERT(IV_SP_IN6(var) == NULL);
1567 KASSERT(IV_SP_OUT6(var) == NULL);
1568
1569 /*
1570 * can be shared?
1571 */
1572 if (if_ipsec_share_sp(var))
1573 return 0;
1574
1575 if (if_ipsec_nat_t(sc))
1576 level = IPSEC_LEVEL_REQUIRE;
1577 else
1578 level = IPSEC_LEVEL_UNIQUE;
1579
1580 if (if_ipsec_fwd_ipv6(sc))
1581 v6policy = IPSEC_POLICY_IPSEC;
1582 else
1583 v6policy = IPSEC_POLICY_DISCARD;
1584
1585 IV_SP_IN(var) = if_ipsec_add_sp0(dst, dport, src, sport,
1586 IPSEC_DIR_INBOUND, IPPROTO_IPIP, level, IPSEC_POLICY_IPSEC);
1587 if (IV_SP_IN(var) == NULL)
1588 goto fail;
1589 IV_SP_OUT(var) = if_ipsec_add_sp0(src, sport, dst, dport,
1590 IPSEC_DIR_OUTBOUND, IPPROTO_IPIP, level, IPSEC_POLICY_IPSEC);
1591 if (IV_SP_OUT(var) == NULL)
1592 goto fail;
1593 IV_SP_IN6(var) = if_ipsec_add_sp0(dst, dport, src, sport,
1594 IPSEC_DIR_INBOUND, IPPROTO_IPV6, level, v6policy);
1595 if (IV_SP_IN6(var) == NULL)
1596 goto fail;
1597 IV_SP_OUT6(var) = if_ipsec_add_sp0(src, sport, dst, dport,
1598 IPSEC_DIR_OUTBOUND, IPPROTO_IPV6, level, v6policy);
1599 if (IV_SP_OUT6(var) == NULL)
1600 goto fail;
1601
1602 return 0;
1603
1604 fail:
1605 if (IV_SP_IN6(var) != NULL) {
1606 if_ipsec_del_sp0(IV_SP_IN6(var));
1607 IV_SP_IN6(var) = NULL;
1608 }
1609 if (IV_SP_OUT(var) != NULL) {
1610 if_ipsec_del_sp0(IV_SP_OUT(var));
1611 IV_SP_OUT(var) = NULL;
1612 }
1613 if (IV_SP_IN(var) != NULL) {
1614 if_ipsec_del_sp0(IV_SP_IN(var));
1615 IV_SP_IN(var) = NULL;
1616 }
1617
1618 return EEXIST;
1619 }
1620
1621 static int
1622 if_ipsec_del_sp0(struct secpolicy *sp)
1623 {
1624 struct sadb_msg msg;
1625 struct sadb_x_policy xpl;
1626 size_t size;
1627 uint16_t ext_msg_len = 0;
1628 int error;
1629 struct mbuf *m;
1630
1631 if (sp == NULL)
1632 return 0;
1633
1634 memset(&msg, 0, sizeof(msg));
1635 memset(&xpl, 0, sizeof(xpl));
1636
1637 MGETHDR(m, M_WAITOK, MT_DATA);
1638
1639 size = if_ipsec_set_sadb_x_policy(&xpl, NULL, 0, 0, sp->id, 0);
1640 ext_msg_len += PFKEY_UNIT64(size);
1641
1642 if_ipsec_set_sadb_msg_del(&msg, ext_msg_len);
1643
1644 m->m_len = sizeof(msg);
1645 m_copyback(m, 0, sizeof(msg), &msg);
1646
1647 if_ipsec_add_mbuf(m, &xpl, sizeof(xpl));
1648
1649 /* unreference correspond to key_kpi_spdadd(). */
1650 KEY_SP_UNREF(&sp);
1651 error = key_kpi_spddelete2(m);
1652 if (error != 0) {
1653 log(LOG_ERR, "%s: cannot delete SP(ID=%u) (error=%d).\n",
1654 __func__, sp->id, error);
1655 }
1656 return error;
1657 }
1658
1659 static void
1660 if_ipsec_del_sp(struct ipsec_variant *var)
1661 {
1662
1663 /* are the SPs shared? */
1664 if (if_ipsec_unshare_sp(var))
1665 return;
1666
1667 (void)if_ipsec_del_sp0(IV_SP_OUT(var));
1668 (void)if_ipsec_del_sp0(IV_SP_IN(var));
1669 (void)if_ipsec_del_sp0(IV_SP_OUT6(var));
1670 (void)if_ipsec_del_sp0(IV_SP_IN6(var));
1671 IV_SP_IN(var) = NULL;
1672 IV_SP_IN6(var) = NULL;
1673 IV_SP_OUT(var) = NULL;
1674 IV_SP_OUT6(var) = NULL;
1675 }
1676
1677 static int
1678 if_ipsec_replace_sp(struct ipsec_softc *sc, struct ipsec_variant *ovar,
1679 struct ipsec_variant *nvar)
1680 {
1681 in_port_t src_port = 0;
1682 in_port_t dst_port = 0;
1683 struct sockaddr *src;
1684 struct sockaddr *dst;
1685 int error = 0;
1686
1687 KASSERT(mutex_owned(&sc->ipsec_lock));
1688
1689 if_ipsec_del_sp(ovar);
1690
1691 src = nvar->iv_psrc;
1692 dst = nvar->iv_pdst;
1693 if (if_ipsec_nat_t(sc)) {
1694 /* NAT-T enabled */
1695 src_port = nvar->iv_sport;
1696 dst_port = nvar->iv_dport;
1697 }
1698 if (src && dst)
1699 error = if_ipsec_add_sp(nvar, src, src_port, dst, dst_port);
1700
1701 return error;
1702 }
1703
1704 /*
1705 * ipsec_variant and its SPs update API.
1706 *
1707 * Assumption:
1708 * reader side dereferences sc->ipsec_var in reader critical section only,
1709 * that is, all of reader sides do not reader the sc->ipsec_var after
1710 * pserialize_perform().
1711 */
1712 static int
1713 if_ipsec_update_variant(struct ipsec_softc *sc, struct ipsec_variant *nvar,
1714 struct ipsec_variant *nullvar)
1715 {
1716 struct ifnet *ifp = &sc->ipsec_if;
1717 struct ipsec_variant *ovar = sc->ipsec_var;
1718 int error;
1719
1720 KASSERT(mutex_owned(&sc->ipsec_lock));
1721
1722 /*
1723 * To keep consistency between ipsec(4) I/F settings and SPs,
1724 * we stop packet processing while replacing SPs, that is, we set
1725 * "null" config variant to sc->ipsec_var.
1726 */
1727 sc->ipsec_var = nullvar;
1728 pserialize_perform(ipsec_psz);
1729 psref_target_destroy(&ovar->iv_psref, iv_psref_class);
1730
1731 error = if_ipsec_replace_sp(sc, ovar, nvar);
1732 if (!error)
1733 sc->ipsec_var = nvar;
1734 else {
1735 sc->ipsec_var = ovar; /* rollback */
1736 psref_target_init(&ovar->iv_psref, iv_psref_class);
1737 }
1738
1739 pserialize_perform(ipsec_psz);
1740 psref_target_destroy(&nullvar->iv_psref, iv_psref_class);
1741
1742 if (if_ipsec_variant_is_configured(sc->ipsec_var))
1743 ifp->if_flags |= IFF_RUNNING;
1744 else
1745 ifp->if_flags &= ~IFF_RUNNING;
1746
1747 return error;
1748 }
1749