1 /* $NetBSD: xform_ipip.c,v 1.55 2017/11/15 10:42:41 knakahara Exp $ */ 2 /* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ 3 /* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */ 4 5 /* 6 * The authors of this code are John Ioannidis (ji@tla.org), 7 * Angelos D. Keromytis (kermit@csd.uch.gr) and 8 * Niels Provos (provos@physnet.uni-hamburg.de). 9 * 10 * The original version of this code was written by John Ioannidis 11 * for BSD/OS in Athens, Greece, in November 1995. 12 * 13 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 14 * by Angelos D. Keromytis. 15 * 16 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 17 * and Niels Provos. 18 * 19 * Additional features in 1999 by Angelos D. Keromytis. 20 * 21 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, 22 * Angelos D. Keromytis and Niels Provos. 23 * Copyright (c) 2001, Angelos D. Keromytis. 24 * 25 * Permission to use, copy, and modify this software with or without fee 26 * is hereby granted, provided that this entire notice is included in 27 * all copies of any software which is or includes a copy or 28 * modification of this software. 29 * You may use this code under the GNU public license if you so wish. Please 30 * contribute changes back to the authors under this freer than GPL license 31 * so that we may further the use of strong encryption without limitations to 32 * all. 33 * 34 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 35 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 36 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 37 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 38 * PURPOSE. 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.55 2017/11/15 10:42:41 knakahara Exp $"); 43 44 /* 45 * IP-inside-IP processing 46 */ 47 #if defined(_KERNEL_OPT) 48 #include "opt_inet.h" 49 #endif 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/mbuf.h> 54 #include <sys/socket.h> 55 #include <sys/kernel.h> 56 #include <sys/protosw.h> 57 #include <sys/sysctl.h> 58 59 #include <net/if.h> 60 #include <net/route.h> 61 #include <net/netisr.h> 62 63 #include <netinet/in.h> 64 #include <netinet/in_systm.h> 65 #include <netinet/in_var.h> 66 #include <netinet/ip.h> 67 #include <netinet/ip_ecn.h> 68 #include <netinet/ip_var.h> 69 #include <netinet/ip_encap.h> 70 71 #include <netipsec/ipsec.h> 72 #include <netipsec/ipsec_private.h> 73 #include <netipsec/xform.h> 74 75 #include <netipsec/ipip_var.h> 76 77 #ifdef MROUTING 78 #include <netinet/ip_mroute.h> 79 #endif 80 81 #ifdef INET6 82 #include <netinet/ip6.h> 83 #include <netipsec/ipsec6.h> 84 #include <netinet6/in6_var.h> 85 #include <netinet6/ip6protosw.h> 86 #endif 87 88 #include <netipsec/key.h> 89 #include <netipsec/key_debug.h> 90 91 typedef void pr_in_input_t (struct mbuf *m, ...); 92 93 /* 94 * We can control the acceptance of IP4 packets by altering the sysctl 95 * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. 96 */ 97 int ipip_allow = 0; 98 99 percpu_t *ipipstat_percpu; 100 101 #ifdef SYSCTL_DECL 102 SYSCTL_DECL(_net_inet_ipip); 103 104 SYSCTL_INT(_net_inet_ipip, OID_AUTO, 105 ipip_allow, CTLFLAG_RW, &ipip_allow, 0, ""); 106 SYSCTL_STRUCT(_net_inet_ipip, IPSECCTL_STATS, 107 stats, CTLFLAG_RD, &ipipstat, ipipstat, ""); 108 109 #endif 110 111 void ipe4_attach(void); 112 113 114 /* XXX IPCOMP */ 115 #define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) 116 117 static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); 118 119 #ifdef INET6 120 /* 121 * Really only a wrapper for ipip_input(), for use with IPv6. 122 */ 123 int 124 ip4_input6(struct mbuf **m, int *offp, int proto, void *eparg __unused) 125 { 126 #if 0 127 /* If we do not accept IP-in-IP explicitly, drop. */ 128 if (!ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { 129 DPRINTF(("%s: dropped due to policy\n", __func__)); 130 IPIP_STATINC(IPIP_STAT_PDROPS); 131 m_freem(*m); 132 return IPPROTO_DONE; 133 } 134 #endif 135 _ipip_input(*m, *offp, NULL); 136 return IPPROTO_DONE; 137 } 138 #endif /* INET6 */ 139 140 #ifdef INET 141 /* 142 * Really only a wrapper for ipip_input(), for use with IPv4. 143 */ 144 void 145 ip4_input(struct mbuf *m, int off, int proto, void *eparg __unused) 146 { 147 148 #if 0 149 /* If we do not accept IP-in-IP explicitly, drop. */ 150 if (!ipip_allow && (m->m_flags & M_IPSEC) == 0) { 151 DPRINTF(("%s: dropped due to policy\n", __func__)); 152 IPIP_STATINC(IPIP_STAT_PDROPS); 153 m_freem(m); 154 return; 155 } 156 #endif 157 158 _ipip_input(m, off, NULL); 159 } 160 #endif /* INET */ 161 162 /* 163 * ipip_input gets called when we receive an IP{46} encapsulated packet, 164 * either because we got it at a real interface, or because AH or ESP 165 * were being used in tunnel mode (in which case the rcvif element will 166 * contain the address of the encX interface associated with the tunnel. 167 */ 168 169 static void 170 _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) 171 { 172 register struct sockaddr_in *sin; 173 register struct ifnet *ifp; 174 register struct ifaddr *ifa; 175 pktqueue_t *pktq = NULL; 176 struct ip *ipo; 177 #ifdef INET6 178 register struct sockaddr_in6 *sin6; 179 struct ip6_hdr *ip6 = NULL; 180 uint8_t itos; 181 #endif 182 uint8_t otos; 183 uint8_t v; 184 int hlen; 185 186 IPIP_STATINC(IPIP_STAT_IPACKETS); 187 188 m_copydata(m, 0, 1, &v); 189 190 switch (v >> 4) { 191 #ifdef INET 192 case 4: 193 hlen = sizeof(struct ip); 194 break; 195 #endif /* INET */ 196 #ifdef INET6 197 case 6: 198 hlen = sizeof(struct ip6_hdr); 199 break; 200 #endif 201 default: 202 DPRINTF(("%s: bad protocol version 0x%x (%u) " 203 "for outer header\n", __func__, v, v>>4)); 204 IPIP_STATINC(IPIP_STAT_FAMILY); 205 m_freem(m); 206 return /* EAFNOSUPPORT */; 207 } 208 209 /* Bring the IP header in the first mbuf, if not there already */ 210 if (m->m_len < hlen) { 211 if ((m = m_pullup(m, hlen)) == NULL) { 212 DPRINTF(("%s: m_pullup (1) failed\n", __func__)); 213 IPIP_STATINC(IPIP_STAT_HDROPS); 214 return; 215 } 216 } 217 218 ipo = mtod(m, struct ip *); 219 220 #ifdef MROUTING 221 if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) { 222 if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) { 223 ipip_mroute_input (m, iphlen); 224 return; 225 } 226 } 227 #endif /* MROUTING */ 228 229 /* Keep outer ecn field. */ 230 switch (v >> 4) { 231 #ifdef INET 232 case 4: 233 otos = ipo->ip_tos; 234 break; 235 #endif /* INET */ 236 #ifdef INET6 237 case 6: 238 otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; 239 break; 240 #endif 241 default: 242 panic("%s: unknown ip version %u (outer)", __func__, v >> 4); 243 } 244 245 /* Remove outer IP header */ 246 m_adj(m, iphlen); 247 248 /* Sanity check */ 249 if (m->m_pkthdr.len < sizeof(struct ip)) { 250 IPIP_STATINC(IPIP_STAT_HDROPS); 251 m_freem(m); 252 return; 253 } 254 255 m_copydata(m, 0, 1, &v); 256 257 switch (v >> 4) { 258 #ifdef INET 259 case 4: 260 hlen = sizeof(struct ip); 261 break; 262 #endif /* INET */ 263 264 #ifdef INET6 265 case 6: 266 hlen = sizeof(struct ip6_hdr); 267 break; 268 #endif 269 default: 270 DPRINTF(("%s: bad protocol version %#x (%u) " 271 "for inner header\n", __func__, v, v >> 4)); 272 IPIP_STATINC(IPIP_STAT_FAMILY); 273 m_freem(m); 274 return; /* EAFNOSUPPORT */ 275 } 276 277 /* 278 * Bring the inner IP header in the first mbuf, if not there already. 279 */ 280 if (m->m_len < hlen) { 281 if ((m = m_pullup(m, hlen)) == NULL) { 282 DPRINTF(("%s: m_pullup (2) failed\n", __func__)); 283 IPIP_STATINC(IPIP_STAT_HDROPS); 284 return; 285 } 286 } 287 288 /* 289 * RFC 1853 specifies that the inner TTL should not be touched on 290 * decapsulation. There's no reason this comment should be here, but 291 * this is as good as any a position. 292 */ 293 294 /* Some sanity checks in the inner IP header */ 295 switch (v >> 4) { 296 #ifdef INET 297 case 4: 298 ipo = mtod(m, struct ip *); 299 ip_ecn_egress(ip4_ipsec_ecn, &otos, &ipo->ip_tos); 300 break; 301 #endif /* INET */ 302 #ifdef INET6 303 case 6: 304 ip6 = (struct ip6_hdr *) ipo; 305 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 306 ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos); 307 ip6->ip6_flow &= ~htonl(0xff << 20); 308 ip6->ip6_flow |= htonl((uint32_t) itos << 20); 309 break; 310 #endif 311 default: 312 panic("%s: unknown ip version %u (inner)", __func__, v>>4); 313 } 314 315 /* Check for local address spoofing. */ 316 if ((m_get_rcvif_NOMPSAFE(m) == NULL || 317 !(m_get_rcvif_NOMPSAFE(m)->if_flags & IFF_LOOPBACK)) && 318 ipip_allow != 2) { 319 int s = pserialize_read_enter(); 320 IFNET_READER_FOREACH(ifp) { 321 IFADDR_READER_FOREACH(ifa, ifp) { 322 #ifdef INET 323 if (ipo) { 324 if (ifa->ifa_addr->sa_family != 325 AF_INET) 326 continue; 327 328 sin = (struct sockaddr_in *) ifa->ifa_addr; 329 330 if (sin->sin_addr.s_addr == 331 ipo->ip_src.s_addr) { 332 pserialize_read_exit(s); 333 IPIP_STATINC(IPIP_STAT_SPOOF); 334 m_freem(m); 335 return; 336 } 337 } 338 #endif /* INET */ 339 340 #ifdef INET6 341 if (ip6) { 342 if (ifa->ifa_addr->sa_family != 343 AF_INET6) 344 continue; 345 346 sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; 347 348 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { 349 pserialize_read_exit(s); 350 IPIP_STATINC(IPIP_STAT_SPOOF); 351 m_freem(m); 352 return; 353 } 354 355 } 356 #endif /* INET6 */ 357 } 358 } 359 pserialize_read_exit(s); 360 } 361 362 /* Statistics */ 363 IPIP_STATADD(IPIP_STAT_IBYTES, m->m_pkthdr.len - iphlen); 364 365 /* 366 * Interface pointer stays the same; if no IPsec processing has 367 * been done (or will be done), this will point to a normal 368 * interface. Otherwise, it'll point to an enc interface, which 369 * will allow a packet filter to distinguish between secure and 370 * untrusted packets. 371 */ 372 373 switch (v >> 4) { 374 #ifdef INET 375 case 4: 376 pktq = ip_pktq; 377 break; 378 #endif 379 #ifdef INET6 380 case 6: 381 pktq = ip6_pktq; 382 break; 383 #endif 384 default: 385 panic("%s: should never reach here", __func__); 386 } 387 388 int s = splnet(); 389 if (__predict_false(!pktq_enqueue(pktq, m, 0))) { 390 IPIP_STATINC(IPIP_STAT_QFULL); 391 m_freem(m); 392 } 393 splx(s); 394 } 395 396 int 397 ipip_output( 398 struct mbuf *m, 399 const struct ipsecrequest *isr, 400 struct secasvar *sav, 401 struct mbuf **mp, 402 int skip, 403 int protoff 404 ) 405 { 406 char buf[IPSEC_ADDRSTRLEN]; 407 uint8_t tp, otos; 408 struct secasindex *saidx; 409 int error; 410 #ifdef INET 411 uint8_t itos; 412 struct ip *ipo; 413 #endif /* INET */ 414 #ifdef INET6 415 struct ip6_hdr *ip6, *ip6o; 416 #endif /* INET6 */ 417 418 IPSEC_SPLASSERT_SOFTNET(__func__); 419 KASSERT(sav != NULL); 420 421 /* XXX Deal with empty TDB source/destination addresses. */ 422 423 m_copydata(m, 0, 1, &tp); 424 tp = (tp >> 4) & 0xff; /* Get the IP version number. */ 425 426 saidx = &sav->sah->saidx; 427 switch (saidx->dst.sa.sa_family) { 428 #ifdef INET 429 case AF_INET: 430 if (saidx->src.sa.sa_family != AF_INET || 431 saidx->src.sin.sin_addr.s_addr == INADDR_ANY || 432 saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) { 433 DPRINTF(("%s: unspecified tunnel endpoint " 434 "address in SA %s/%08lx\n", __func__, 435 ipsec_address(&saidx->dst, buf, sizeof(buf)), 436 (u_long) ntohl(sav->spi))); 437 IPIP_STATINC(IPIP_STAT_UNSPEC); 438 error = EINVAL; 439 goto bad; 440 } 441 442 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 443 if (m == 0) { 444 DPRINTF(("%s: M_PREPEND failed\n", __func__)); 445 IPIP_STATINC(IPIP_STAT_HDROPS); 446 error = ENOBUFS; 447 goto bad; 448 } 449 450 ipo = mtod(m, struct ip *); 451 452 ipo->ip_v = IPVERSION; 453 ipo->ip_hl = 5; 454 ipo->ip_len = htons(m->m_pkthdr.len); 455 ipo->ip_ttl = ip_defttl; 456 ipo->ip_sum = 0; 457 ipo->ip_src = saidx->src.sin.sin_addr; 458 ipo->ip_dst = saidx->dst.sin.sin_addr; 459 ipo->ip_id = ip_newid(NULL); 460 461 /* If the inner protocol is IP... */ 462 if (tp == IPVERSION) { 463 /* Save ECN notification */ 464 m_copydata(m, sizeof(struct ip) + 465 offsetof(struct ip, ip_tos), 466 sizeof(uint8_t), &itos); 467 468 ipo->ip_p = IPPROTO_IPIP; 469 470 /* 471 * We should be keeping tunnel soft-state and 472 * send back ICMPs if needed. 473 */ 474 m_copydata(m, sizeof(struct ip) + 475 offsetof(struct ip, ip_off), 476 sizeof(uint16_t), &ipo->ip_off); 477 ipo->ip_off &= ~ htons(IP_DF | IP_MF | IP_OFFMASK); 478 } 479 #ifdef INET6 480 else if (tp == (IPV6_VERSION >> 4)) { 481 uint32_t itos32; 482 483 /* Save ECN notification. */ 484 m_copydata(m, sizeof(struct ip) + 485 offsetof(struct ip6_hdr, ip6_flow), 486 sizeof(uint32_t), &itos32); 487 itos = ntohl(itos32) >> 20; 488 ipo->ip_p = IPPROTO_IPV6; 489 ipo->ip_off = 0; 490 } 491 #endif /* INET6 */ 492 else { 493 goto nofamily; 494 } 495 496 otos = 0; 497 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 498 ipo->ip_tos = otos; 499 break; 500 #endif /* INET */ 501 502 #ifdef INET6 503 case AF_INET6: 504 if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) || 505 saidx->src.sa.sa_family != AF_INET6 || 506 IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) { 507 DPRINTF(("%s: unspecified tunnel endpoint " 508 "address in SA %s/%08lx\n", __func__, 509 ipsec_address(&saidx->dst, buf, sizeof(buf)), 510 (u_long) ntohl(sav->spi))); 511 IPIP_STATINC(IPIP_STAT_UNSPEC); 512 error = ENOBUFS; 513 goto bad; 514 } 515 516 if (tp == (IPV6_VERSION >> 4)) { 517 /* scoped address handling */ 518 ip6 = mtod(m, struct ip6_hdr *); 519 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 520 ip6->ip6_src.s6_addr16[1] = 0; 521 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 522 ip6->ip6_dst.s6_addr16[1] = 0; 523 } 524 525 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); 526 if (m == 0) { 527 DPRINTF(("%s: M_PREPEND failed\n", __func__)); 528 IPIP_STATINC(IPIP_STAT_HDROPS); 529 error = ENOBUFS; 530 goto bad; 531 } 532 533 /* Initialize IPv6 header */ 534 ip6o = mtod(m, struct ip6_hdr *); 535 ip6o->ip6_flow = 0; 536 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; 537 ip6o->ip6_vfc |= IPV6_VERSION; 538 ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o)); 539 ip6o->ip6_hlim = ip_defttl; 540 ip6o->ip6_dst = saidx->dst.sin6.sin6_addr; 541 ip6o->ip6_src = saidx->src.sin6.sin6_addr; 542 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_dst)) 543 ip6o->ip6_dst.s6_addr16[1] = htons(saidx->dst.sin6.sin6_scope_id); 544 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_src)) 545 ip6o->ip6_src.s6_addr16[1] = htons(saidx->src.sin6.sin6_scope_id); 546 547 #ifdef INET 548 if (tp == IPVERSION) { 549 /* Save ECN notification */ 550 m_copydata(m, sizeof(struct ip6_hdr) + 551 offsetof(struct ip, ip_tos), sizeof(uint8_t), 552 &itos); 553 554 /* This is really IPVERSION. */ 555 ip6o->ip6_nxt = IPPROTO_IPIP; 556 } else 557 #endif /* INET */ 558 if (tp == (IPV6_VERSION >> 4)) { 559 uint32_t itos32; 560 561 /* Save ECN notification. */ 562 m_copydata(m, sizeof(struct ip6_hdr) + 563 offsetof(struct ip6_hdr, ip6_flow), 564 sizeof(uint32_t), &itos32); 565 itos = ntohl(itos32) >> 20; 566 567 ip6o->ip6_nxt = IPPROTO_IPV6; 568 } else { 569 goto nofamily; 570 } 571 572 otos = 0; 573 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 574 ip6o->ip6_flow |= htonl((uint32_t) otos << 20); 575 break; 576 #endif /* INET6 */ 577 578 default: 579 nofamily: 580 DPRINTF(("%s: unsupported protocol family %u\n", __func__, 581 saidx->dst.sa.sa_family)); 582 IPIP_STATINC(IPIP_STAT_FAMILY); 583 error = EAFNOSUPPORT; /* XXX diffs from openbsd */ 584 goto bad; 585 } 586 587 IPIP_STATINC(IPIP_STAT_OPACKETS); 588 *mp = m; 589 590 #ifdef INET 591 if (saidx->dst.sa.sa_family == AF_INET) { 592 #if 0 593 if (sav->tdb_xform->xf_type == XF_IP4) 594 tdb->tdb_cur_bytes += 595 m->m_pkthdr.len - sizeof(struct ip); 596 #endif 597 IPIP_STATADD(IPIP_STAT_OBYTES, 598 m->m_pkthdr.len - sizeof(struct ip)); 599 } 600 #endif /* INET */ 601 602 #ifdef INET6 603 if (saidx->dst.sa.sa_family == AF_INET6) { 604 #if 0 605 if (sav->tdb_xform->xf_type == XF_IP4) 606 tdb->tdb_cur_bytes += 607 m->m_pkthdr.len - sizeof(struct ip6_hdr); 608 #endif 609 IPIP_STATADD(IPIP_STAT_OBYTES, 610 m->m_pkthdr.len - sizeof(struct ip6_hdr)); 611 } 612 #endif /* INET6 */ 613 614 return 0; 615 bad: 616 if (m) 617 m_freem(m); 618 *mp = NULL; 619 return (error); 620 } 621 622 static int 623 ipe4_init(struct secasvar *sav, const struct xformsw *xsp) 624 { 625 sav->tdb_xform = xsp; 626 return 0; 627 } 628 629 static int 630 ipe4_zeroize(struct secasvar *sav) 631 { 632 sav->tdb_xform = NULL; 633 return 0; 634 } 635 636 static int 637 ipe4_input( 638 struct mbuf *m, 639 struct secasvar *sav, 640 int skip, 641 int protoff 642 ) 643 { 644 /* This is a rather serious mistake, so no conditional printing. */ 645 printf("%s: should never be called\n", __func__); 646 if (m) 647 m_freem(m); 648 return EOPNOTSUPP; 649 } 650 651 static struct xformsw ipe4_xformsw = { 652 .xf_type = XF_IP4, 653 .xf_flags = 0, 654 .xf_name = "IPv4 Simple Encapsulation", 655 .xf_init = ipe4_init, 656 .xf_zeroize = ipe4_zeroize, 657 .xf_input = ipe4_input, 658 .xf_output = ipip_output, 659 .xf_next = NULL, 660 }; 661 662 #ifdef INET 663 static struct encapsw ipe4_encapsw = { 664 .encapsw4 = { 665 .pr_input = ip4_input, 666 .pr_ctlinput = NULL, 667 } 668 }; 669 #endif 670 #ifdef INET6 671 static struct encapsw ipe4_encapsw6 = { 672 .encapsw6 = { 673 .pr_input = ip4_input6, 674 .pr_ctlinput = NULL, 675 } 676 }; 677 #endif 678 679 /* 680 * Check the encapsulated packet to see if we want it 681 */ 682 static int 683 ipe4_encapcheck(struct mbuf *m, 684 int off, 685 int proto, 686 void *arg 687 ) 688 { 689 /* 690 * Only take packets coming from IPSEC tunnels; the rest 691 * must be handled by the gif tunnel code. Note that we 692 * also return a minimum priority when we want the packet 693 * so any explicit gif tunnels take precedence. 694 */ 695 return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); 696 } 697 698 void 699 ipe4_attach(void) 700 { 701 702 ipipstat_percpu = percpu_alloc(sizeof(uint64_t) * IPIP_NSTATS); 703 704 xform_register(&ipe4_xformsw); 705 /* attach to encapsulation framework */ 706 /* XXX save return cookie for detach on module remove */ 707 708 encapinit(); 709 /* This function is called before ifinit(). Who else gets lock? */ 710 (void)encap_lock_enter(); 711 /* ipe4_encapsw and ipe4_encapsw must be added atomically */ 712 #ifdef INET 713 (void) encap_attach_func(AF_INET, -1, 714 ipe4_encapcheck, &ipe4_encapsw, NULL); 715 #endif 716 #ifdef INET6 717 (void) encap_attach_func(AF_INET6, -1, 718 ipe4_encapcheck, &ipe4_encapsw6, NULL); 719 #endif 720 encap_lock_exit(); 721 } 722