1 /* $NetBSD: xform_ipip.c,v 1.28 2011/07/17 20:54:54 joerg 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.28 2011/07/17 20:54:54 joerg Exp $"); 43 44 /* 45 * IP-inside-IP processing 46 */ 47 #include "opt_inet.h" 48 #ifdef __FreeBSD__ 49 #include "opt_inet6.h" 50 #include "opt_random_ip_id.h" 51 #endif /* __FreeBSD__ */ 52 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/mbuf.h> 57 #include <sys/socket.h> 58 #include <sys/kernel.h> 59 #include <sys/protosw.h> 60 #include <sys/sysctl.h> 61 62 #include <net/if.h> 63 #include <net/route.h> 64 #include <net/netisr.h> 65 66 #include <netinet/in.h> 67 #include <netinet/in_systm.h> 68 #include <netinet/in_var.h> 69 #include <netinet/ip.h> 70 #include <netinet/ip_ecn.h> 71 #include <netinet/ip_var.h> 72 #include <netinet/ip_encap.h> 73 #ifdef __FreeBSD__ 74 #include <netinet/ipprotosw.h> 75 #endif 76 77 #include <netipsec/ipsec.h> 78 #include <netipsec/ipsec_private.h> 79 #include <netipsec/xform.h> 80 81 #include <netipsec/ipip_var.h> 82 83 #ifdef MROUTING 84 #include <netinet/ip_mroute.h> 85 #endif 86 87 #ifdef INET6 88 #include <netinet/ip6.h> 89 #include <netipsec/ipsec6.h> 90 # ifdef __FreeBSD__ 91 # include <netinet6/ip6_ecn.h> 92 # endif 93 #include <netinet6/in6_var.h> 94 #include <netinet6/ip6protosw.h> 95 #endif 96 97 #include <netipsec/key.h> 98 #include <netipsec/key_debug.h> 99 #include <netipsec/ipsec_osdep.h> 100 101 #ifdef __FreeBSD__ 102 typedef void pr_in_input_t (struct mbuf *, int, int); /* XXX FIX THIS */ 103 #else 104 typedef void pr_in_input_t (struct mbuf *m, ...); 105 #endif 106 107 /* 108 * We can control the acceptance of IP4 packets by altering the sysctl 109 * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. 110 */ 111 int ipip_allow = 0; 112 113 percpu_t *ipipstat_percpu; 114 115 #ifdef SYSCTL_DECL 116 SYSCTL_DECL(_net_inet_ipip); 117 118 SYSCTL_INT(_net_inet_ipip, OID_AUTO, 119 ipip_allow, CTLFLAG_RW, &ipip_allow, 0, ""); 120 SYSCTL_STRUCT(_net_inet_ipip, IPSECCTL_STATS, 121 stats, CTLFLAG_RD, &ipipstat, ipipstat, ""); 122 123 #endif 124 125 #ifdef __FreeBSD__ 126 static 127 #endif 128 void ipe4_attach(void); 129 130 131 /* XXX IPCOMP */ 132 #define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) 133 134 static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); 135 136 #ifdef INET6 137 /* 138 * Really only a wrapper for ipip_input(), for use with IPv6. 139 */ 140 int 141 ip4_input6(struct mbuf **m, int *offp, int proto) 142 { 143 #if 0 144 /* If we do not accept IP-in-IP explicitly, drop. */ 145 if (!ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { 146 DPRINTF(("ip4_input6: dropped due to policy\n")); 147 IPIP_STATINC(IPIP_STAT_PDROPS); 148 m_freem(*m); 149 return IPPROTO_DONE; 150 } 151 #endif 152 _ipip_input(*m, *offp, NULL); 153 return IPPROTO_DONE; 154 } 155 #endif /* INET6 */ 156 157 #ifdef INET 158 /* 159 * Really only a wrapper for ipip_input(), for use with IPv4. 160 */ 161 void 162 ip4_input(struct mbuf *m, ...) 163 { 164 va_list ap; 165 int iphlen; 166 167 #if 0 168 /* If we do not accept IP-in-IP explicitly, drop. */ 169 if (!ipip_allow && (m->m_flags & M_IPSEC) == 0) { 170 DPRINTF(("ip4_input: dropped due to policy\n")); 171 IPIP_STATINC(IPIP_STAT_PDROPS); 172 m_freem(m); 173 return; 174 } 175 #endif 176 va_start(ap, m); 177 iphlen = va_arg(ap, int); 178 va_end(ap); 179 180 _ipip_input(m, iphlen, NULL); 181 } 182 #endif /* INET */ 183 184 /* 185 * ipip_input gets called when we receive an IP{46} encapsulated packet, 186 * either because we got it at a real interface, or because AH or ESP 187 * were being used in tunnel mode (in which case the rcvif element will 188 * contain the address of the encX interface associated with the tunnel. 189 */ 190 191 static void 192 _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) 193 { 194 register struct sockaddr_in *sin; 195 register struct ifnet *ifp; 196 register struct ifaddr *ifa; 197 struct ifqueue *ifq = NULL; 198 struct ip *ipo; 199 #ifdef INET6 200 register struct sockaddr_in6 *sin6; 201 struct ip6_hdr *ip6 = NULL; 202 u_int8_t itos; 203 #endif 204 int isr; 205 u_int8_t otos; 206 u_int8_t v; 207 int hlen; 208 209 IPIP_STATINC(IPIP_STAT_IPACKETS); 210 211 m_copydata(m, 0, 1, &v); 212 213 switch (v >> 4) { 214 #ifdef INET 215 case 4: 216 hlen = sizeof(struct ip); 217 break; 218 #endif /* INET */ 219 #ifdef INET6 220 case 6: 221 hlen = sizeof(struct ip6_hdr); 222 break; 223 #endif 224 default: 225 DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " 226 "for outer header\n", v, v>>4)); 227 IPIP_STATINC(IPIP_STAT_FAMILY); 228 m_freem(m); 229 return /* EAFNOSUPPORT */; 230 } 231 232 /* Bring the IP header in the first mbuf, if not there already */ 233 if (m->m_len < hlen) { 234 if ((m = m_pullup(m, hlen)) == NULL) { 235 DPRINTF(("ipip_input: m_pullup (1) failed\n")); 236 IPIP_STATINC(IPIP_STAT_HDROPS); 237 return; 238 } 239 } 240 241 ipo = mtod(m, struct ip *); 242 243 #ifdef MROUTING 244 if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) { 245 if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) { 246 ipip_mroute_input (m, iphlen); 247 return; 248 } 249 } 250 #endif /* MROUTING */ 251 252 /* Keep outer ecn field. */ 253 switch (v >> 4) { 254 #ifdef INET 255 case 4: 256 otos = ipo->ip_tos; 257 break; 258 #endif /* INET */ 259 #ifdef INET6 260 case 6: 261 otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; 262 break; 263 #endif 264 default: 265 panic("ipip_input: unknown ip version %u (outer)", v>>4); 266 } 267 268 /* Remove outer IP header */ 269 m_adj(m, iphlen); 270 271 /* Sanity check */ 272 if (m->m_pkthdr.len < sizeof(struct ip)) { 273 IPIP_STATINC(IPIP_STAT_HDROPS); 274 m_freem(m); 275 return; 276 } 277 278 m_copydata(m, 0, 1, &v); 279 280 switch (v >> 4) { 281 #ifdef INET 282 case 4: 283 hlen = sizeof(struct ip); 284 break; 285 #endif /* INET */ 286 287 #ifdef INET6 288 case 6: 289 hlen = sizeof(struct ip6_hdr); 290 break; 291 #endif 292 default: 293 DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " 294 "for inner header\n", v, v>>4)); 295 IPIP_STATINC(IPIP_STAT_FAMILY); 296 m_freem(m); 297 return; /* EAFNOSUPPORT */ 298 } 299 300 /* 301 * Bring the inner IP header in the first mbuf, if not there already. 302 */ 303 if (m->m_len < hlen) { 304 if ((m = m_pullup(m, hlen)) == NULL) { 305 DPRINTF(("ipip_input: m_pullup (2) failed\n")); 306 IPIP_STATINC(IPIP_STAT_HDROPS); 307 return; 308 } 309 } 310 311 /* 312 * RFC 1853 specifies that the inner TTL should not be touched on 313 * decapsulation. There's no reason this comment should be here, but 314 * this is as good as any a position. 315 */ 316 317 /* Some sanity checks in the inner IP header */ 318 switch (v >> 4) { 319 #ifdef INET 320 case 4: 321 ipo = mtod(m, struct ip *); 322 ip_ecn_egress(ip4_ipsec_ecn, &otos, &ipo->ip_tos); 323 break; 324 #endif /* INET */ 325 #ifdef INET6 326 case 6: 327 ip6 = (struct ip6_hdr *) ipo; 328 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 329 ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos); 330 ip6->ip6_flow &= ~htonl(0xff << 20); 331 ip6->ip6_flow |= htonl((u_int32_t) itos << 20); 332 break; 333 #endif 334 default: 335 panic("ipip_input: unknown ip version %u (inner)", v>>4); 336 } 337 338 /* Check for local address spoofing. */ 339 if ((m->m_pkthdr.rcvif == NULL || 340 !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && 341 ipip_allow != 2) { 342 IFNET_FOREACH(ifp) { 343 IFADDR_FOREACH(ifa, ifp) { 344 #ifdef INET 345 if (ipo) { 346 if (ifa->ifa_addr->sa_family != 347 AF_INET) 348 continue; 349 350 sin = (struct sockaddr_in *) ifa->ifa_addr; 351 352 if (sin->sin_addr.s_addr == 353 ipo->ip_src.s_addr) { 354 IPIP_STATINC(IPIP_STAT_SPOOF); 355 m_freem(m); 356 return; 357 } 358 } 359 #endif /* INET */ 360 361 #ifdef INET6 362 if (ip6) { 363 if (ifa->ifa_addr->sa_family != 364 AF_INET6) 365 continue; 366 367 sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; 368 369 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { 370 IPIP_STATINC(IPIP_STAT_SPOOF); 371 m_freem(m); 372 return; 373 } 374 375 } 376 #endif /* INET6 */ 377 } 378 } 379 } 380 381 /* Statistics */ 382 IPIP_STATADD(IPIP_STAT_IBYTES, m->m_pkthdr.len - iphlen); 383 384 /* 385 * Interface pointer stays the same; if no IPsec processing has 386 * been done (or will be done), this will point to a normal 387 * interface. Otherwise, it'll point to an enc interface, which 388 * will allow a packet filter to distinguish between secure and 389 * untrusted packets. 390 */ 391 392 switch (v >> 4) { 393 #ifdef INET 394 case 4: 395 ifq = &ipintrq; 396 isr = NETISR_IP; 397 break; 398 #endif 399 #ifdef INET6 400 case 6: 401 ifq = &ip6intrq; 402 isr = NETISR_IPV6; 403 break; 404 #endif 405 default: 406 panic("ipip_input: should never reach here"); 407 } 408 409 if (!IF_HANDOFF(ifq, m, NULL)) { 410 IPIP_STATINC(IPIP_STAT_QFULL); 411 412 DPRINTF(("ipip_input: packet dropped because of full queue\n")); 413 } else { 414 schednetisr(isr); 415 } 416 } 417 418 int 419 ipip_output( 420 struct mbuf *m, 421 struct ipsecrequest *isr, 422 struct mbuf **mp, 423 int skip, 424 int protoff 425 ) 426 { 427 const struct secasvar *sav; 428 u_int8_t tp, otos; 429 struct secasindex *saidx; 430 int error; 431 #ifdef INET 432 u_int8_t itos; 433 struct ip *ipo; 434 #endif /* INET */ 435 #ifdef INET6 436 struct ip6_hdr *ip6, *ip6o; 437 #endif /* INET6 */ 438 439 IPSEC_SPLASSERT_SOFTNET("ipip_output"); 440 441 sav = isr->sav; 442 IPSEC_ASSERT(sav != NULL, ("ipip_output: null SA")); 443 IPSEC_ASSERT(sav->sah != NULL, ("ipip_output: null SAH")); 444 445 /* XXX Deal with empty TDB source/destination addresses. */ 446 447 m_copydata(m, 0, 1, &tp); 448 tp = (tp >> 4) & 0xff; /* Get the IP version number. */ 449 450 saidx = &sav->sah->saidx; 451 switch (saidx->dst.sa.sa_family) { 452 #ifdef INET 453 case AF_INET: 454 if (saidx->src.sa.sa_family != AF_INET || 455 saidx->src.sin.sin_addr.s_addr == INADDR_ANY || 456 saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) { 457 DPRINTF(("ipip_output: unspecified tunnel endpoint " 458 "address in SA %s/%08lx\n", 459 ipsec_address(&saidx->dst), 460 (u_long) ntohl(sav->spi))); 461 IPIP_STATINC(IPIP_STAT_UNSPEC); 462 error = EINVAL; 463 goto bad; 464 } 465 466 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 467 if (m == 0) { 468 DPRINTF(("ipip_output: M_PREPEND failed\n")); 469 IPIP_STATINC(IPIP_STAT_HDROPS); 470 error = ENOBUFS; 471 goto bad; 472 } 473 474 ipo = mtod(m, struct ip *); 475 476 ipo->ip_v = IPVERSION; 477 ipo->ip_hl = 5; 478 ipo->ip_len = htons(m->m_pkthdr.len); 479 ipo->ip_ttl = ip_defttl; 480 ipo->ip_sum = 0; 481 ipo->ip_src = saidx->src.sin.sin_addr; 482 ipo->ip_dst = saidx->dst.sin.sin_addr; 483 484 #if defined(__NetBSD__) 485 ipo->ip_id = ip_newid(NULL); 486 #elif defined(RANDOM_IP_ID) 487 ipo->ip_id = ip_randomid(); 488 #else 489 ipo->ip_id = htons(ip_id++); 490 #endif 491 492 /* If the inner protocol is IP... */ 493 if (tp == IPVERSION) { 494 /* Save ECN notification */ 495 m_copydata(m, sizeof(struct ip) + 496 offsetof(struct ip, ip_tos), 497 sizeof(u_int8_t), &itos); 498 499 ipo->ip_p = IPPROTO_IPIP; 500 501 /* 502 * We should be keeping tunnel soft-state and 503 * send back ICMPs if needed. 504 */ 505 m_copydata(m, sizeof(struct ip) + 506 offsetof(struct ip, ip_off), 507 sizeof(u_int16_t), &ipo->ip_off); 508 ipo->ip_off &= ~ IP_OFF_CONVERT(IP_DF | IP_MF | IP_OFFMASK); 509 } 510 #ifdef INET6 511 else if (tp == (IPV6_VERSION >> 4)) { 512 u_int32_t itos32; 513 514 /* Save ECN notification. */ 515 m_copydata(m, sizeof(struct ip) + 516 offsetof(struct ip6_hdr, ip6_flow), 517 sizeof(u_int32_t), &itos32); 518 itos = ntohl(itos32) >> 20; 519 ipo->ip_p = IPPROTO_IPV6; 520 ipo->ip_off = 0; 521 } 522 #endif /* INET6 */ 523 else { 524 goto nofamily; 525 } 526 527 otos = 0; 528 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 529 ipo->ip_tos = otos; 530 break; 531 #endif /* INET */ 532 533 #ifdef INET6 534 case AF_INET6: 535 if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) || 536 saidx->src.sa.sa_family != AF_INET6 || 537 IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) { 538 DPRINTF(("ipip_output: unspecified tunnel endpoint " 539 "address in SA %s/%08lx\n", 540 ipsec_address(&saidx->dst), 541 (u_long) ntohl(sav->spi))); 542 IPIP_STATINC(IPIP_STAT_UNSPEC); 543 error = ENOBUFS; 544 goto bad; 545 } 546 547 if (tp == (IPV6_VERSION >> 4)) { 548 /* scoped address handling */ 549 ip6 = mtod(m, struct ip6_hdr *); 550 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 551 ip6->ip6_src.s6_addr16[1] = 0; 552 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 553 ip6->ip6_dst.s6_addr16[1] = 0; 554 } 555 556 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); 557 if (m == 0) { 558 DPRINTF(("ipip_output: M_PREPEND failed\n")); 559 IPIP_STATINC(IPIP_STAT_HDROPS); 560 error = ENOBUFS; 561 goto bad; 562 } 563 564 /* Initialize IPv6 header */ 565 ip6o = mtod(m, struct ip6_hdr *); 566 ip6o->ip6_flow = 0; 567 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; 568 ip6o->ip6_vfc |= IPV6_VERSION; 569 ip6o->ip6_plen = htons(m->m_pkthdr.len); 570 ip6o->ip6_hlim = ip_defttl; 571 ip6o->ip6_dst = saidx->dst.sin6.sin6_addr; 572 ip6o->ip6_src = saidx->src.sin6.sin6_addr; 573 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_dst)) 574 ip6o->ip6_dst.s6_addr16[1] = htons(saidx->dst.sin6.sin6_scope_id); 575 if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_src)) 576 ip6o->ip6_src.s6_addr16[1] = htons(saidx->src.sin6.sin6_scope_id); 577 578 #ifdef INET 579 if (tp == IPVERSION) { 580 /* Save ECN notification */ 581 m_copydata(m, sizeof(struct ip6_hdr) + 582 offsetof(struct ip, ip_tos), sizeof(u_int8_t), 583 &itos); 584 585 /* This is really IPVERSION. */ 586 ip6o->ip6_nxt = IPPROTO_IPIP; 587 } else 588 #endif /* INET */ 589 if (tp == (IPV6_VERSION >> 4)) { 590 u_int32_t itos32; 591 592 /* Save ECN notification. */ 593 m_copydata(m, sizeof(struct ip6_hdr) + 594 offsetof(struct ip6_hdr, ip6_flow), 595 sizeof(u_int32_t), &itos32); 596 itos = ntohl(itos32) >> 20; 597 598 ip6o->ip6_nxt = IPPROTO_IPV6; 599 } else { 600 goto nofamily; 601 } 602 603 otos = 0; 604 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 605 ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); 606 break; 607 #endif /* INET6 */ 608 609 default: 610 nofamily: 611 DPRINTF(("ipip_output: unsupported protocol family %u\n", 612 saidx->dst.sa.sa_family)); 613 IPIP_STATINC(IPIP_STAT_FAMILY); 614 error = EAFNOSUPPORT; /* XXX diffs from openbsd */ 615 goto bad; 616 } 617 618 IPIP_STATINC(IPIP_STAT_OPACKETS); 619 *mp = m; 620 621 #ifdef INET 622 if (saidx->dst.sa.sa_family == AF_INET) { 623 #if 0 624 if (sav->tdb_xform->xf_type == XF_IP4) 625 tdb->tdb_cur_bytes += 626 m->m_pkthdr.len - sizeof(struct ip); 627 #endif 628 IPIP_STATADD(IPIP_STAT_OBYTES, 629 m->m_pkthdr.len - sizeof(struct ip)); 630 } 631 #endif /* INET */ 632 633 #ifdef INET6 634 if (saidx->dst.sa.sa_family == AF_INET6) { 635 #if 0 636 if (sav->tdb_xform->xf_type == XF_IP4) 637 tdb->tdb_cur_bytes += 638 m->m_pkthdr.len - sizeof(struct ip6_hdr); 639 #endif 640 IPIP_STATADD(IPIP_STAT_OBYTES, 641 m->m_pkthdr.len - sizeof(struct ip6_hdr)); 642 } 643 #endif /* INET6 */ 644 645 return 0; 646 bad: 647 if (m) 648 m_freem(m); 649 *mp = NULL; 650 return (error); 651 } 652 653 #ifdef FAST_IPSEC 654 static int 655 ipe4_init(struct secasvar *sav, const struct xformsw *xsp) 656 { 657 sav->tdb_xform = xsp; 658 return 0; 659 } 660 661 static int 662 ipe4_zeroize(struct secasvar *sav) 663 { 664 sav->tdb_xform = NULL; 665 return 0; 666 } 667 668 static int 669 ipe4_input( 670 struct mbuf *m, 671 const struct secasvar *sav, 672 int skip, 673 int protoff 674 ) 675 { 676 /* This is a rather serious mistake, so no conditional printing. */ 677 printf("ipe4_input: should never be called\n"); 678 if (m) 679 m_freem(m); 680 return EOPNOTSUPP; 681 } 682 683 static struct xformsw ipe4_xformsw = { 684 XF_IP4, 0, "IPv4 Simple Encapsulation", 685 ipe4_init, ipe4_zeroize, ipe4_input, ipip_output, 686 NULL, 687 }; 688 689 #ifdef INET 690 PR_WRAP_CTLOUTPUT(rip_ctloutput) 691 PR_WRAP_USRREQ(rip_usrreq) 692 #define rip_ctloutput rip_ctloutput_wrapper 693 #define rip_usrreq rip_usrreq_wrapper 694 695 extern struct domain inetdomain; 696 static struct ipprotosw ipe4_protosw = { 697 .pr_type = SOCK_RAW, 698 .pr_domain = &inetdomain, 699 .pr_protocol = IPPROTO_IPV4, 700 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 701 .pr_input = ip4_input, 702 .pr_output = 0, 703 .pr_ctlinput = 0, 704 .pr_ctloutput = rip_ctloutput, 705 .pr_usrreq = rip_usrreq, 706 .pr_init = 0, 707 .pr_fasttimo = 0, 708 .pr_slowtimo = 0, 709 .pr_drain = 0, 710 }; 711 #endif 712 #ifdef INET6 713 PR_WRAP_CTLOUTPUT(rip6_ctloutput) 714 PR_WRAP_USRREQ(rip6_usrreq) 715 #define rip6_ctloutput rip6_ctloutput_wrapper 716 #define rip6_usrreq rip6_usrreq_wrapper 717 718 extern struct domain inet6domain; 719 static struct ip6protosw ipe4_protosw6 = { 720 .pr_type = SOCK_RAW, 721 .pr_domain = &inet6domain, 722 .pr_protocol = IPPROTO_IPV6, 723 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 724 .pr_input = ip4_input6, 725 .pr_output = 0, 726 .pr_ctlinput = 0, 727 .pr_ctloutput = rip6_ctloutput, 728 .pr_usrreq = rip6_usrreq, 729 .pr_init = 0, 730 .pr_fasttimo = 0, 731 .pr_slowtimo = 0, 732 .pr_drain = 0, 733 }; 734 #endif 735 736 #endif /* FAST_IPSEC */ 737 738 /* 739 * Check the encapsulated packet to see if we want it 740 */ 741 static int 742 ipe4_encapcheck(struct mbuf *m, 743 int off, 744 int proto, 745 void *arg 746 ) 747 { 748 /* 749 * Only take packets coming from IPSEC tunnels; the rest 750 * must be handled by the gif tunnel code. Note that we 751 * also return a minimum priority when we want the packet 752 * so any explicit gif tunnels take precedence. 753 */ 754 return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); 755 } 756 757 INITFN void 758 ipe4_attach(void) 759 { 760 761 ipipstat_percpu = percpu_alloc(sizeof(uint64_t) * IPIP_NSTATS); 762 763 xform_register(&ipe4_xformsw); 764 /* attach to encapsulation framework */ 765 /* XXX save return cookie for detach on module remove */ 766 #ifdef INET 767 (void) encap_attach_func(AF_INET, -1, 768 ipe4_encapcheck, (struct protosw*) &ipe4_protosw, NULL); 769 #endif 770 #ifdef INET6 771 (void) encap_attach_func(AF_INET6, -1, 772 ipe4_encapcheck, (struct protosw*) &ipe4_protosw6, NULL); 773 #endif 774 } 775 776 #ifdef SYSINIT 777 SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL); 778 #endif 779 780