FreeBSD/Linux Kernel Cross Reference
sys/net/if_ipsec.c
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$");
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
80 static MALLOC_DEFINE(M_IPSEC, "ipsec", "IPsec Virtual Tunnel Interface");
81 static 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
89 struct 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
112 static struct rmlock ipsec_sc_lock;
113 RM_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
123 LIST_HEAD(ipsec_iflist, ipsec_softc);
124 static VNET_DEFINE(struct ipsec_iflist, ipsec_sc_list);
125 static VNET_DEFINE(struct ipsec_iflist *, ipsec_sc_htbl);
126 static 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
131 static uint32_t
132 ipsec_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 */
146 static struct sx ipsec_ioctl_sx;
147 SX_SYSINIT(ipsec_ioctl_sx, &ipsec_ioctl_sx, "ipsec_ioctl");
148
149 static int ipsec_init_reqid(struct ipsec_softc *);
150 static int ipsec_set_tunnel(struct ipsec_softc *, struct sockaddr *,
151 struct sockaddr *, uint32_t);
152 static void ipsec_delete_tunnel(struct ifnet *, int);
153
154 static int ipsec_set_addresses(struct ifnet *, struct sockaddr *,
155 struct sockaddr *);
156 static int ipsec_set_reqid(struct ifnet *, uint32_t);
157
158 static int ipsec_ioctl(struct ifnet *, u_long, caddr_t);
159 static int ipsec_transmit(struct ifnet *, struct mbuf *);
160 static int ipsec_output(struct ifnet *, struct mbuf *,
161 const struct sockaddr *, struct route *);
162 static void ipsec_qflush(struct ifnet *);
163 static int ipsec_clone_create(struct if_clone *, int, caddr_t);
164 static void ipsec_clone_destroy(struct ifnet *);
165
166 static VNET_DEFINE(struct if_clone *, ipsec_cloner);
167 #define V_ipsec_cloner VNET(ipsec_cloner)
168
169 static int
170 ipsec_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
198 static void
199 ipsec_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
221 static void
222 vnet_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 }
230 VNET_SYSINIT(vnet_ipsec_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
231 vnet_ipsec_init, NULL);
232
233 static void
234 vnet_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 }
240 VNET_SYSUNINIT(vnet_ipsec_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
241 vnet_ipsec_uninit, NULL);
242
243 static struct secpolicy *
244 ipsec_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
264 static struct secasindex *
265 ipsec_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
275 static int
276 ipsec_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 }
360 err:
361 if (error != 0)
362 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
363 return (error);
364 }
365
366 static void
367 ipsec_qflush(struct ifnet *ifp __unused)
368 {
369
370 }
371
372 static int
373 ipsec_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
380 int
381 ipsec_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? */
451 int
452 ipsec_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 }
706 bad:
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 */
720 static int
721 ipsec_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);
772 fail:
773 for (i = 0; i < IPSEC_SPCOUNT; i++)
774 key_freesp(&sp[i]);
775 return (ENOMEM);
776 }
777
778 static int
779 ipsec_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
798 static int
799 ipsec_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 */
827 static int
828 ipsec_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 */
871 static int
872 ipsec_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
931 static int
932 ipsec_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
975 static void
976 ipsec_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 }
Cache object: 0ba8281e92ed7bf495b4fb1e78ca977c
|