1 /* $NetBSD: ipsecif.c,v 1.12 2018/12/07 09:11:04 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: ipsecif.c,v 1.12 2018/12/07 09:11:04 knakahara Exp $"); 31 32 #ifdef _KERNEL_OPT 33 #include "opt_inet.h" 34 #include "opt_ipsec.h" 35 #endif 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/socket.h> 40 #include <sys/sockio.h> 41 #include <sys/mbuf.h> 42 #include <sys/errno.h> 43 #include <sys/ioctl.h> 44 #include <sys/syslog.h> 45 #include <sys/kernel.h> 46 47 #include <net/if.h> 48 #include <net/route.h> 49 50 #include <netinet/in.h> 51 #include <netinet/in_systm.h> 52 #include <netinet/ip.h> 53 #include <netinet/ip_var.h> 54 #include <netinet/in_var.h> 55 #include <netinet/ip_encap.h> 56 #include <netinet/ip_ecn.h> 57 #include <netinet/ip_private.h> 58 #include <netinet/udp.h> 59 60 #ifdef INET6 61 #include <netinet/ip6.h> 62 #include <netinet6/ip6_var.h> 63 #include <netinet6/ip6_private.h> 64 #include <netinet6/in6_var.h> 65 #include <netinet6/ip6protosw.h> /* for struct ip6ctlparam */ 66 #include <netinet/ip_ecn.h> 67 #endif 68 69 #include <netipsec/key.h> 70 #include <netipsec/ipsecif.h> 71 72 #include <net/if_ipsec.h> 73 74 static void ipsecif4_input(struct mbuf *, int, int, void *); 75 static int ipsecif4_output(struct ipsec_variant *, int, struct mbuf *); 76 static int ipsecif4_filter4(const struct ip *, struct ipsec_variant *, 77 struct ifnet *); 78 79 #ifdef INET6 80 static int ipsecif6_input(struct mbuf **, int *, int, void *); 81 static int ipsecif6_output(struct ipsec_variant *, int, struct mbuf *); 82 static int ipsecif6_filter6(const struct ip6_hdr *, struct ipsec_variant *, 83 struct ifnet *); 84 #endif 85 86 static int ip_ipsec_ttl = IPSEC_TTL; 87 static int ip_ipsec_copy_tos = 0; 88 #ifdef INET6 89 static int ip6_ipsec_hlim = IPSEC_HLIM; 90 static int ip6_ipsec_pmtu = 0; /* XXX: per interface configuration?? */ 91 static int ip6_ipsec_copy_tos = 0; 92 #endif 93 94 static const struct encapsw ipsecif4_encapsw = { 95 .encapsw4 = { 96 .pr_input = ipsecif4_input, 97 .pr_ctlinput = NULL, 98 } 99 }; 100 101 #ifdef INET6 102 static const struct encapsw ipsecif6_encapsw; 103 #endif 104 105 static struct mbuf * 106 ipsecif4_prepend_hdr(struct ipsec_variant *var, struct mbuf *m, 107 uint8_t proto, uint8_t tos) 108 { 109 struct ip *ip; 110 struct sockaddr_in *src, *dst; 111 112 src = satosin(var->iv_psrc); 113 dst = satosin(var->iv_pdst); 114 115 if (in_nullhost(src->sin_addr) || in_nullhost(src->sin_addr) || 116 src->sin_addr.s_addr == INADDR_BROADCAST || 117 dst->sin_addr.s_addr == INADDR_BROADCAST) { 118 m_freem(m); 119 return NULL; 120 } 121 m->m_flags &= ~M_BCAST; 122 123 if (IN_MULTICAST(src->sin_addr.s_addr) || 124 IN_MULTICAST(dst->sin_addr.s_addr)) { 125 m_freem(m); 126 return NULL; 127 } 128 129 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 130 if (m && M_UNWRITABLE(m, sizeof(struct ip))) 131 m = m_pullup(m, sizeof(struct ip)); 132 if (m == NULL) 133 return NULL; 134 135 ip = mtod(m, struct ip *); 136 ip->ip_v = IPVERSION; 137 ip->ip_off = htons(0); 138 if (m->m_pkthdr.len < IP_MINFRAGSIZE) 139 ip->ip_id = 0; 140 else 141 ip->ip_id = ip_newid(NULL); 142 ip->ip_hl = sizeof(*ip) >> 2; 143 if (ip_ipsec_copy_tos) 144 ip->ip_tos = tos; 145 else 146 ip->ip_tos = 0; 147 ip->ip_sum = 0; 148 ip->ip_src = src->sin_addr; 149 ip->ip_dst = dst->sin_addr; 150 ip->ip_p = proto; 151 ip->ip_ttl = ip_ipsec_ttl; 152 ip->ip_len = htons(m->m_pkthdr.len); 153 #ifndef IPSEC_TX_TOS_CLEAR 154 struct ifnet *ifp = &var->iv_softc->ipsec_if; 155 if (ifp->if_flags & IFF_ECN) 156 ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos); 157 else 158 ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos); 159 #endif 160 161 return m; 162 } 163 164 static int 165 ipsecif4_needfrag(struct mbuf *m, struct ipsecrequest *isr) 166 { 167 struct ip ip0; 168 struct ip *ip; 169 int mtu; 170 struct secasvar *sav; 171 172 sav = key_lookup_sa_bysaidx(&isr->saidx); 173 if (sav == NULL) 174 return 0; 175 176 if (!(sav->natt_type & UDP_ENCAP_ESPINUDP)) { 177 mtu = 0; 178 goto out; 179 } 180 181 if (m->m_len < sizeof(struct ip)) { 182 m_copydata(m, 0, sizeof(ip0), &ip0); 183 ip = &ip0; 184 } else { 185 ip = mtod(m, struct ip *); 186 } 187 mtu = sav->esp_frag; 188 if (ntohs(ip->ip_len) <= mtu) 189 mtu = 0; 190 191 out: 192 KEY_SA_UNREF(&sav); 193 return mtu; 194 } 195 196 static struct mbuf * 197 ipsecif4_flowinfo(struct mbuf *m, int family, int *proto0, u_int8_t *tos0) 198 { 199 const struct ip *ip; 200 int proto; 201 int tos; 202 203 KASSERT(proto0 != NULL); 204 KASSERT(tos0 != NULL); 205 206 switch (family) { 207 case AF_INET: 208 proto = IPPROTO_IPV4; 209 if (m->m_len < sizeof(*ip)) { 210 m = m_pullup(m, sizeof(*ip)); 211 if (m == NULL) { 212 *tos0 = 0; 213 *proto0 = 0; 214 return NULL; 215 } 216 } 217 ip = mtod(m, const struct ip *); 218 tos = ip->ip_tos; 219 /* TODO: support ALTQ for innner packet */ 220 break; 221 #ifdef INET6 222 case AF_INET6: { 223 const struct ip6_hdr *ip6; 224 proto = IPPROTO_IPV6; 225 if (m->m_len < sizeof(*ip6)) { 226 m = m_pullup(m, sizeof(*ip6)); 227 if (m == NULL) { 228 *tos0 = 0; 229 *proto0 = 0; 230 return NULL; 231 } 232 } 233 ip6 = mtod(m, const struct ip6_hdr *); 234 tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 235 /* TODO: support ALTQ for innner packet */ 236 break; 237 } 238 #endif /* INET6 */ 239 default: 240 *tos0 = 0; 241 *proto0 = 0; 242 return NULL; 243 } 244 245 *proto0 = proto; 246 *tos0 = tos; 247 return m; 248 } 249 250 static int 251 ipsecif4_fragout(struct ipsec_variant *var, int family, struct mbuf *m, int mtu) 252 { 253 struct ifnet *ifp = &var->iv_softc->ipsec_if; 254 struct mbuf *next; 255 struct m_tag *mtag; 256 int error; 257 258 KASSERT(if_ipsec_heldref_variant(var)); 259 260 mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS); 261 if (mtag) 262 m_tag_delete(m, mtag); 263 264 /* consider new IP header prepended in ipsecif4_output() */ 265 if (mtu <= sizeof(struct ip)) { 266 m_freem(m); 267 return ENETUNREACH; 268 } 269 m->m_pkthdr.csum_flags |= M_CSUM_IPv4; 270 error = ip_fragment(m, ifp, mtu - sizeof(struct ip)); 271 if (error) 272 return error; 273 274 for (error = 0; m; m = next) { 275 next = m->m_nextpkt; 276 m->m_nextpkt = NULL; 277 if (error) { 278 m_freem(m); 279 continue; 280 } 281 282 error = ipsecif4_output(var, family, m); 283 } 284 if (error == 0) 285 IP_STATINC(IP_STAT_FRAGMENTED); 286 287 return error; 288 } 289 290 int 291 ipsecif4_encap_func(struct mbuf *m, struct ip *ip, struct ipsec_variant *var) 292 { 293 struct m_tag *mtag; 294 struct sockaddr_in *src, *dst; 295 u_int16_t src_port = 0; 296 u_int16_t dst_port = 0; 297 298 KASSERT(var != NULL); 299 300 src = satosin(var->iv_psrc); 301 dst = satosin(var->iv_pdst); 302 mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS); 303 if (mtag) { 304 u_int16_t *ports; 305 306 ports = (u_int16_t *)(mtag + 1); 307 src_port = ports[0]; 308 dst_port = ports[1]; 309 } 310 311 /* address match */ 312 if (src->sin_addr.s_addr != ip->ip_dst.s_addr || 313 dst->sin_addr.s_addr != ip->ip_src.s_addr) 314 return 0; 315 316 /* UDP encap? */ 317 if (mtag == NULL && var->iv_sport == 0 && var->iv_dport == 0) 318 goto match; 319 320 /* port match */ 321 if (src_port != var->iv_dport || 322 dst_port != var->iv_sport) { 323 #ifdef DEBUG 324 printf("%s: port mismatch: pkt(%u, %u), if(%u, %u)\n", 325 __func__, ntohs(src_port), ntohs(dst_port), 326 ntohs(var->iv_sport), ntohs(var->iv_dport)); 327 #endif 328 return 0; 329 } 330 331 match: 332 /* 333 * hide NAT-T information from encapsulated traffics. 334 * they don't know about IPsec. 335 */ 336 if (mtag) 337 m_tag_delete(m, mtag); 338 return sizeof(src->sin_addr) + sizeof(dst->sin_addr); 339 } 340 341 static int 342 ipsecif4_output(struct ipsec_variant *var, int family, struct mbuf *m) 343 { 344 struct secpolicy *sp = NULL; 345 u_int8_t tos; 346 int proto; 347 int error; 348 int mtu; 349 u_long sa_mtu = 0; 350 351 KASSERT(if_ipsec_heldref_variant(var)); 352 KASSERT(if_ipsec_variant_is_configured(var)); 353 KASSERT(var->iv_psrc->sa_family == AF_INET); 354 KASSERT(var->iv_pdst->sa_family == AF_INET); 355 356 sp = IV_SP_OUT(var); 357 KASSERT(sp != NULL); 358 /* 359 * The SPs in ipsec_variant are prevented from freed by 360 * ipsec_variant->iv_psref. So, KEY_SP_REF() is unnecessary here. 361 */ 362 363 KASSERT(sp->policy != IPSEC_POLICY_NONE); 364 KASSERT(sp->policy != IPSEC_POLICY_ENTRUST); 365 KASSERT(sp->policy != IPSEC_POLICY_BYPASS); 366 if (sp->policy != IPSEC_POLICY_IPSEC) { 367 m_freem(m); 368 error = ENETUNREACH; 369 goto done; 370 } 371 372 /* get flowinfo */ 373 m = ipsecif4_flowinfo(m, family, &proto, &tos); 374 if (m == NULL) { 375 error = ENETUNREACH; 376 goto done; 377 } 378 379 /* prepend new IP header */ 380 m = ipsecif4_prepend_hdr(var, m, proto, tos); 381 if (m == NULL) { 382 error = ENETUNREACH; 383 goto done; 384 } 385 386 /* 387 * Normal netipsec's NAT-T fragmentation is done in ip_output(). 388 * See "natt_frag" processing. 389 * However, ipsec(4) interface's one is not done in the same way, 390 * so we must do NAT-T fragmentation by own code. 391 */ 392 /* NAT-T ESP fragmentation */ 393 mtu = ipsecif4_needfrag(m, sp->req); 394 if (mtu > 0) 395 return ipsecif4_fragout(var, family, m, mtu); 396 397 /* IPsec output */ 398 IP_STATINC(IP_STAT_LOCALOUT); 399 error = ipsec4_process_packet(m, sp->req, &sa_mtu); 400 if (error == ENOENT) 401 error = 0; 402 /* 403 * frangmentation is already done in ipsecif4_fragout(), 404 * so ipsec4_process_packet() must not do fragmentation here. 405 */ 406 KASSERT(sa_mtu == 0); 407 408 done: 409 return error; 410 } 411 412 #ifdef INET6 413 int 414 ipsecif6_encap_func(struct mbuf *m, struct ip6_hdr *ip6, struct ipsec_variant *var) 415 { 416 struct m_tag *mtag; 417 struct sockaddr_in6 *src, *dst; 418 u_int16_t src_port = 0; 419 u_int16_t dst_port = 0; 420 421 KASSERT(var != NULL); 422 423 src = satosin6(var->iv_psrc); 424 dst = satosin6(var->iv_pdst); 425 mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS); 426 if (mtag) { 427 u_int16_t *ports; 428 429 ports = (u_int16_t *)(mtag + 1); 430 src_port = ports[0]; 431 dst_port = ports[1]; 432 } 433 434 /* address match */ 435 if (!IN6_ARE_ADDR_EQUAL(&src->sin6_addr, &ip6->ip6_dst) || 436 !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_src)) 437 return 0; 438 439 /* UDP encap? */ 440 if (mtag == NULL && var->iv_sport == 0 && var->iv_dport == 0) 441 goto match; 442 443 /* port match */ 444 if (src_port != var->iv_dport || 445 dst_port != var->iv_sport) { 446 #ifdef DEBUG 447 printf("%s: port mismatch: pkt(%u, %u), if(%u, %u)\n", 448 __func__, ntohs(src_port), ntohs(dst_port), 449 ntohs(var->iv_sport), ntohs(var->iv_dport)); 450 #endif 451 return 0; 452 } 453 454 match: 455 /* 456 * hide NAT-T information from encapsulated traffics. 457 * they don't know about IPsec. 458 */ 459 if (mtag) 460 m_tag_delete(m, mtag); 461 return sizeof(src->sin6_addr) + sizeof(dst->sin6_addr); 462 } 463 464 static int 465 ipsecif6_output(struct ipsec_variant *var, int family, struct mbuf *m) 466 { 467 struct ifnet *ifp = &var->iv_softc->ipsec_if; 468 struct ipsec_softc *sc = ifp->if_softc; 469 struct ipsec_ro *iro; 470 struct rtentry *rt; 471 struct sockaddr_in6 *sin6_src; 472 struct sockaddr_in6 *sin6_dst; 473 struct ip6_hdr *ip6; 474 int proto, error; 475 u_int8_t itos, otos; 476 union { 477 struct sockaddr dst; 478 struct sockaddr_in6 dst6; 479 } u; 480 481 KASSERT(if_ipsec_heldref_variant(var)); 482 KASSERT(if_ipsec_variant_is_configured(var)); 483 484 sin6_src = satosin6(var->iv_psrc); 485 sin6_dst = satosin6(var->iv_pdst); 486 487 KASSERT(sin6_src->sin6_family == AF_INET6); 488 KASSERT(sin6_dst->sin6_family == AF_INET6); 489 490 switch (family) { 491 #ifdef INET 492 case AF_INET: 493 { 494 struct ip *ip; 495 496 proto = IPPROTO_IPV4; 497 if (m->m_len < sizeof(*ip)) { 498 m = m_pullup(m, sizeof(*ip)); 499 if (m == NULL) 500 return ENOBUFS; 501 } 502 ip = mtod(m, struct ip *); 503 itos = ip->ip_tos; 504 /* TODO: support ALTQ for innner packet */ 505 break; 506 } 507 #endif /* INET */ 508 case AF_INET6: 509 { 510 struct ip6_hdr *xip6; 511 proto = IPPROTO_IPV6; 512 if (m->m_len < sizeof(*xip6)) { 513 m = m_pullup(m, sizeof(*xip6)); 514 if (m == NULL) 515 return ENOBUFS; 516 } 517 xip6 = mtod(m, struct ip6_hdr *); 518 itos = (ntohl(xip6->ip6_flow) >> 20) & 0xff; 519 /* TODO: support ALTQ for innner packet */ 520 break; 521 } 522 default: 523 m_freem(m); 524 return EAFNOSUPPORT; 525 } 526 527 /* prepend new IP header */ 528 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); 529 if (m && M_UNWRITABLE(m, sizeof(struct ip6_hdr))) 530 m = m_pullup(m, sizeof(struct ip6_hdr)); 531 if (m == NULL) 532 return ENOBUFS; 533 534 ip6 = mtod(m, struct ip6_hdr *); 535 ip6->ip6_flow = 0; 536 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 537 ip6->ip6_vfc |= IPV6_VERSION; 538 #if 0 /* ip6->ip6_plen will be filled by ip6_output */ 539 ip6->ip6_plen = htons((u_short)m->m_pkthdr.len - sizeof(*ip6)); 540 #endif 541 ip6->ip6_nxt = proto; 542 ip6->ip6_hlim = ip6_ipsec_hlim; 543 ip6->ip6_src = sin6_src->sin6_addr; 544 /* bidirectional configured tunnel mode */ 545 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr)) { 546 ip6->ip6_dst = sin6_dst->sin6_addr; 547 } else { 548 m_freem(m); 549 return ENETUNREACH; 550 } 551 #ifndef IPSEC_TX_TOS_CLEAR 552 if (ifp->if_flags & IFF_ECN) 553 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 554 else 555 ip_ecn_ingress(ECN_NOCARE, &otos, &itos); 556 557 if (!ip6_ipsec_copy_tos) 558 otos = 0; 559 #else 560 if (ip6_ipsec_copy_tos) 561 otos = itos; 562 else 563 otos = 0; 564 #endif 565 ip6->ip6_flow &= ~ntohl(0xff00000); 566 ip6->ip6_flow |= htonl((u_int32_t)otos << 20); 567 568 sockaddr_in6_init(&u.dst6, &sin6_dst->sin6_addr, 0, 0, 0); 569 570 iro = percpu_getref(sc->ipsec_ro_percpu); 571 mutex_enter(iro->ir_lock); 572 if ((rt = rtcache_lookup(&iro->ir_ro, &u.dst)) == NULL) { 573 mutex_exit(iro->ir_lock); 574 percpu_putref(sc->ipsec_ro_percpu); 575 m_freem(m); 576 return ENETUNREACH; 577 } 578 579 if (rt->rt_ifp == ifp) { 580 rtcache_unref(rt, &iro->ir_ro); 581 rtcache_free(&iro->ir_ro); 582 mutex_exit(iro->ir_lock); 583 percpu_putref(sc->ipsec_ro_percpu); 584 m_freem(m); 585 return ENETUNREACH; 586 } 587 rtcache_unref(rt, &iro->ir_ro); 588 589 /* 590 * force fragmentation to minimum MTU, to avoid path MTU discovery. 591 * it is too painful to ask for resend of inner packet, to achieve 592 * path MTU discovery for encapsulated packets. 593 */ 594 error = ip6_output(m, 0, &iro->ir_ro, 595 ip6_ipsec_pmtu ? 0 : IPV6_MINMTU, 0, NULL, NULL); 596 if (error) 597 rtcache_free(&iro->ir_ro); 598 599 mutex_exit(iro->ir_lock); 600 percpu_putref(sc->ipsec_ro_percpu); 601 602 return error; 603 } 604 #endif /* INET6 */ 605 606 static void 607 ipsecif4_input(struct mbuf *m, int off, int proto, void *eparg) 608 { 609 struct ifnet *ipsecp; 610 struct ipsec_softc *sc = eparg; 611 struct ipsec_variant *var; 612 const struct ip *ip; 613 int af; 614 #ifndef IPSEC_TX_TOS_CLEAR 615 u_int8_t otos; 616 #endif 617 struct psref psref_rcvif; 618 struct psref psref_var; 619 struct ifnet *rcvif; 620 621 KASSERT(sc != NULL); 622 623 ipsecp = &sc->ipsec_if; 624 if ((ipsecp->if_flags & IFF_UP) == 0) { 625 m_freem(m); 626 ip_statinc(IP_STAT_NOIPSEC); 627 return; 628 } 629 630 var = if_ipsec_getref_variant(sc, &psref_var); 631 if (if_ipsec_variant_is_unconfigured(var)) { 632 if_ipsec_putref_variant(var, &psref_var); 633 m_freem(m); 634 ip_statinc(IP_STAT_NOIPSEC); 635 return; 636 } 637 638 ip = mtod(m, const struct ip *); 639 640 rcvif = m_get_rcvif_psref(m, &psref_rcvif); 641 if (rcvif == NULL || !ipsecif4_filter4(ip, var, rcvif)) { 642 m_put_rcvif_psref(rcvif, &psref_rcvif); 643 if_ipsec_putref_variant(var, &psref_var); 644 m_freem(m); 645 ip_statinc(IP_STAT_NOIPSEC); 646 return; 647 } 648 m_put_rcvif_psref(rcvif, &psref_rcvif); 649 if_ipsec_putref_variant(var, &psref_var); 650 #ifndef IPSEC_TX_TOS_CLEAR 651 otos = ip->ip_tos; 652 #endif 653 m_adj(m, off); 654 655 switch (proto) { 656 case IPPROTO_IPV4: 657 { 658 struct ip *xip; 659 af = AF_INET; 660 if (M_UNWRITABLE(m, sizeof(*xip))) { 661 m = m_pullup(m, sizeof(*xip)); 662 if (m == NULL) 663 return; 664 } 665 xip = mtod(m, struct ip *); 666 #ifndef IPSEC_TX_TOS_CLEAR 667 if (ipsecp->if_flags & IFF_ECN) 668 ip_ecn_egress(ECN_ALLOWED, &otos, &xip->ip_tos); 669 else 670 ip_ecn_egress(ECN_NOCARE, &otos, &xip->ip_tos); 671 #endif 672 break; 673 } 674 #ifdef INET6 675 case IPPROTO_IPV6: 676 { 677 struct ip6_hdr *ip6; 678 u_int8_t itos; 679 af = AF_INET6; 680 if (M_UNWRITABLE(m, sizeof(*ip6))) { 681 m = m_pullup(m, sizeof(*ip6)); 682 if (m == NULL) 683 return; 684 } 685 ip6 = mtod(m, struct ip6_hdr *); 686 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 687 #ifndef IPSEC_TX_TOS_CLEAR 688 if (ipsecp->if_flags & IFF_ECN) 689 ip_ecn_egress(ECN_ALLOWED, &otos, &itos); 690 else 691 ip_ecn_egress(ECN_NOCARE, &otos, &itos); 692 #endif 693 ip6->ip6_flow &= ~htonl(0xff << 20); 694 ip6->ip6_flow |= htonl((u_int32_t)itos << 20); 695 break; 696 } 697 #endif /* INET6 */ 698 default: 699 ip_statinc(IP_STAT_NOIPSEC); 700 m_freem(m); 701 return; 702 } 703 if_ipsec_input(m, af, ipsecp); 704 705 return; 706 } 707 708 /* 709 * validate and filter the pakcet 710 */ 711 static int 712 ipsecif4_filter4(const struct ip *ip, struct ipsec_variant *var, 713 struct ifnet *ifp) 714 { 715 struct sockaddr_in *src, *dst; 716 717 src = satosin(var->iv_psrc); 718 dst = satosin(var->iv_pdst); 719 720 return in_tunnel_validate(ip, src->sin_addr, dst->sin_addr); 721 } 722 723 #ifdef INET6 724 static int 725 ipsecif6_input(struct mbuf **mp, int *offp, int proto, void *eparg) 726 { 727 struct mbuf *m = *mp; 728 struct ifnet *ipsecp; 729 struct ipsec_softc *sc = eparg; 730 struct ipsec_variant *var; 731 struct ip6_hdr *ip6; 732 int af = 0; 733 #ifndef IPSEC_TX_TOS_CLEAR 734 u_int32_t otos; 735 #endif 736 struct psref psref_rcvif; 737 struct psref psref_var; 738 struct ifnet *rcvif; 739 740 KASSERT(eparg != NULL); 741 742 ipsecp = &sc->ipsec_if; 743 if ((ipsecp->if_flags & IFF_UP) == 0) { 744 m_freem(m); 745 IP6_STATINC(IP6_STAT_NOIPSEC); 746 return IPPROTO_DONE; 747 } 748 749 var = if_ipsec_getref_variant(sc, &psref_var); 750 if (if_ipsec_variant_is_unconfigured(var)) { 751 if_ipsec_putref_variant(var, &psref_var); 752 m_freem(m); 753 IP6_STATINC(IP6_STAT_NOIPSEC); 754 return IPPROTO_DONE; 755 } 756 757 ip6 = mtod(m, struct ip6_hdr *); 758 759 rcvif = m_get_rcvif_psref(m, &psref_rcvif); 760 if (rcvif == NULL || !ipsecif6_filter6(ip6, var, rcvif)) { 761 m_put_rcvif_psref(rcvif, &psref_rcvif); 762 if_ipsec_putref_variant(var, &psref_var); 763 m_freem(m); 764 IP6_STATINC(IP6_STAT_NOIPSEC); 765 return IPPROTO_DONE; 766 } 767 m_put_rcvif_psref(rcvif, &psref_rcvif); 768 if_ipsec_putref_variant(var, &psref_var); 769 770 #ifndef IPSEC_TX_TOS_CLEAR 771 otos = ip6->ip6_flow; 772 #endif 773 m_adj(m, *offp); 774 775 switch (proto) { 776 #ifdef INET 777 case IPPROTO_IPV4: 778 { 779 af = AF_INET; 780 #ifndef IPSEC_TX_TOS_CLEAR 781 struct ip *ip; 782 u_int8_t otos8; 783 otos8 = (ntohl(otos) >> 20) & 0xff; 784 785 if (M_UNWRITABLE(m, sizeof(*ip))) { 786 m = m_pullup(m, sizeof(*ip)); 787 if (m == NULL) 788 return IPPROTO_DONE; 789 } 790 ip = mtod(m, struct ip *); 791 if (ipsecp->if_flags & IFF_ECN) 792 ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos); 793 else 794 ip_ecn_egress(ECN_NOCARE, &otos8, &ip->ip_tos); 795 #endif 796 break; 797 } 798 #endif /* INET */ 799 case IPPROTO_IPV6: 800 { 801 af = AF_INET6; 802 #ifndef IPSEC_TX_TOS_CLEAR 803 struct ip6_hdr *xip6; 804 805 if (M_UNWRITABLE(m, sizeof(*xip6))) { 806 m = m_pullup(m, sizeof(*xip6)); 807 if (m == NULL) 808 return IPPROTO_DONE; 809 } 810 xip6 = mtod(m, struct ip6_hdr *); 811 if (ipsecp->if_flags & IFF_ECN) 812 ip6_ecn_egress(ECN_ALLOWED, &otos, &xip6->ip6_flow); 813 else 814 ip6_ecn_egress(ECN_NOCARE, &otos, &xip6->ip6_flow); 815 break; 816 #endif 817 } 818 default: 819 IP6_STATINC(IP6_STAT_NOIPSEC); 820 m_freem(m); 821 return IPPROTO_DONE; 822 } 823 824 if_ipsec_input(m, af, ipsecp); 825 return IPPROTO_DONE; 826 } 827 828 /* 829 * validate and filter the packet. 830 */ 831 static int 832 ipsecif6_filter6(const struct ip6_hdr *ip6, struct ipsec_variant *var, 833 struct ifnet *ifp) 834 { 835 struct sockaddr_in6 *src, *dst; 836 837 src = satosin6(var->iv_psrc); 838 dst = satosin6(var->iv_pdst); 839 840 return in6_tunnel_validate(ip6, &src->sin6_addr, &dst->sin6_addr); 841 } 842 #endif /* INET6 */ 843 844 int 845 ipsecif4_attach(struct ipsec_variant *var) 846 { 847 struct ipsec_softc *sc = var->iv_softc; 848 849 KASSERT(if_ipsec_variant_is_configured(var)); 850 851 if (var->iv_encap_cookie4 != NULL) 852 return EALREADY; 853 var->iv_encap_cookie4 = encap_attach_func(AF_INET, -1, if_ipsec_encap_func, 854 &ipsecif4_encapsw, sc); 855 if (var->iv_encap_cookie4 == NULL) 856 return EEXIST; 857 858 var->iv_output = ipsecif4_output; 859 return 0; 860 } 861 862 int 863 ipsecif4_detach(struct ipsec_variant *var) 864 { 865 int error; 866 867 if (var->iv_encap_cookie4 == NULL) 868 return 0; 869 870 var->iv_output = NULL; 871 error = encap_detach(var->iv_encap_cookie4); 872 if (error == 0) 873 var->iv_encap_cookie4 = NULL; 874 875 return error; 876 } 877 878 #ifdef INET6 879 int 880 ipsecif6_attach(struct ipsec_variant *var) 881 { 882 struct sockaddr_in6 mask6; 883 struct ipsec_softc *sc = var->iv_softc; 884 885 KASSERT(if_ipsec_variant_is_configured(var)); 886 KASSERT(var->iv_encap_cookie6 == NULL); 887 888 memset(&mask6, 0, sizeof(mask6)); 889 mask6.sin6_len = sizeof(struct sockaddr_in6); 890 mask6.sin6_addr.s6_addr32[0] = mask6.sin6_addr.s6_addr32[1] = 891 mask6.sin6_addr.s6_addr32[2] = mask6.sin6_addr.s6_addr32[3] = ~0; 892 893 var->iv_encap_cookie6 = encap_attach_func(AF_INET6, -1, if_ipsec_encap_func, 894 &ipsecif6_encapsw, sc); 895 if (var->iv_encap_cookie6 == NULL) 896 return EEXIST; 897 898 var->iv_output = ipsecif6_output; 899 return 0; 900 } 901 902 static void 903 ipsecif6_rtcache_free_pc(void *p, void *arg __unused, struct cpu_info *ci __unused) 904 { 905 struct ipsec_ro *iro = p; 906 907 mutex_enter(iro->ir_lock); 908 rtcache_free(&iro->ir_ro); 909 mutex_exit(iro->ir_lock); 910 } 911 912 int 913 ipsecif6_detach(struct ipsec_variant *var) 914 { 915 struct ipsec_softc *sc = var->iv_softc; 916 int error; 917 918 KASSERT(var->iv_encap_cookie6 != NULL); 919 920 percpu_foreach(sc->ipsec_ro_percpu, ipsecif6_rtcache_free_pc, NULL); 921 922 var->iv_output = NULL; 923 error = encap_detach(var->iv_encap_cookie6); 924 if (error == 0) 925 var->iv_encap_cookie6 = NULL; 926 return error; 927 } 928 929 void * 930 ipsecif6_ctlinput(int cmd, const struct sockaddr *sa, void *d, void *eparg) 931 { 932 struct ipsec_softc *sc = eparg; 933 struct ip6ctlparam *ip6cp = NULL; 934 struct ip6_hdr *ip6; 935 const struct sockaddr_in6 *dst6; 936 struct ipsec_ro *iro; 937 938 if (sa->sa_family != AF_INET6 || 939 sa->sa_len != sizeof(struct sockaddr_in6)) 940 return NULL; 941 942 if ((unsigned)cmd >= PRC_NCMDS) 943 return NULL; 944 if (cmd == PRC_HOSTDEAD) 945 d = NULL; 946 else if (inet6ctlerrmap[cmd] == 0) 947 return NULL; 948 949 /* if the parameter is from icmp6, decode it. */ 950 if (d != NULL) { 951 ip6cp = (struct ip6ctlparam *)d; 952 ip6 = ip6cp->ip6c_ip6; 953 } else { 954 ip6 = NULL; 955 } 956 957 if (!ip6) 958 return NULL; 959 960 iro = percpu_getref(sc->ipsec_ro_percpu); 961 mutex_enter(iro->ir_lock); 962 dst6 = satocsin6(rtcache_getdst(&iro->ir_ro)); 963 /* XXX scope */ 964 if (dst6 == NULL) 965 ; 966 else if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst6->sin6_addr)) 967 /* flush route cache */ 968 rtcache_free(&iro->ir_ro); 969 970 mutex_exit(iro->ir_lock); 971 percpu_putref(sc->ipsec_ro_percpu); 972 973 return NULL; 974 } 975 976 ENCAP_PR_WRAP_CTLINPUT(ipsecif6_ctlinput) 977 #define ipsecif6_ctlinput ipsecif6_ctlinput_wrapper 978 979 static const struct encapsw ipsecif6_encapsw = { 980 .encapsw6 = { 981 .pr_input = ipsecif6_input, 982 .pr_ctlinput = ipsecif6_ctlinput, 983 } 984 }; 985 #endif /* INET6 */ 986