Annotation of sys/netinet/ip_ipip.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ip_ipip.c,v 1.39 2007/02/10 15:34:22 claudio Exp $ */
! 2: /*
! 3: * The authors of this code are John Ioannidis (ji@tla.org),
! 4: * Angelos D. Keromytis (kermit@csd.uch.gr) and
! 5: * Niels Provos (provos@physnet.uni-hamburg.de).
! 6: *
! 7: * The original version of this code was written by John Ioannidis
! 8: * for BSD/OS in Athens, Greece, in November 1995.
! 9: *
! 10: * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
! 11: * by Angelos D. Keromytis.
! 12: *
! 13: * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
! 14: * and Niels Provos.
! 15: *
! 16: * Additional features in 1999 by Angelos D. Keromytis.
! 17: *
! 18: * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
! 19: * Angelos D. Keromytis and Niels Provos.
! 20: * Copyright (c) 2001, Angelos D. Keromytis.
! 21: *
! 22: * Permission to use, copy, and modify this software with or without fee
! 23: * is hereby granted, provided that this entire notice is included in
! 24: * all copies of any software which is or includes a copy or
! 25: * modification of this software.
! 26: * You may use this code under the GNU public license if you so wish. Please
! 27: * contribute changes back to the authors under this freer than GPL license
! 28: * so that we may further the use of strong encryption without limitations to
! 29: * all.
! 30: *
! 31: * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
! 32: * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
! 33: * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
! 34: * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
! 35: * PURPOSE.
! 36: */
! 37:
! 38: /*
! 39: * IP-inside-IP processing
! 40: */
! 41:
! 42: #include <sys/param.h>
! 43: #include <sys/systm.h>
! 44: #include <sys/mbuf.h>
! 45: #include <sys/socket.h>
! 46: #include <sys/sysctl.h>
! 47:
! 48: #include <net/if.h>
! 49: #include <net/route.h>
! 50: #include <net/netisr.h>
! 51: #include <net/bpf.h>
! 52:
! 53: #include <netinet/in.h>
! 54: #include <netinet/in_systm.h>
! 55: #include <netinet/ip.h>
! 56: #include <netinet/in_pcb.h>
! 57: #include <netinet/in_var.h>
! 58: #include <netinet/ip_var.h>
! 59: #include <netinet/ip_ecn.h>
! 60:
! 61: #ifdef MROUTING
! 62: #include <netinet/ip_mroute.h>
! 63: #endif
! 64:
! 65: #include <netinet/ip_ipsp.h>
! 66: #include <netinet/ip_ipip.h>
! 67:
! 68: #include "bpfilter.h"
! 69:
! 70: #ifdef ENCDEBUG
! 71: #define DPRINTF(x) if (encdebug) printf x
! 72: #else
! 73: #define DPRINTF(x)
! 74: #endif
! 75:
! 76: /*
! 77: * We can control the acceptance of IP4 packets by altering the sysctl
! 78: * net.inet.ipip.allow value. Zero means drop them, all else is acceptance.
! 79: */
! 80: int ipip_allow = 0;
! 81:
! 82: struct ipipstat ipipstat;
! 83:
! 84: #ifdef INET6
! 85: /*
! 86: * Really only a wrapper for ipip_input(), for use with IPv6.
! 87: */
! 88: int
! 89: ip4_input6(struct mbuf **m, int *offp, int proto)
! 90: {
! 91: /* If we do not accept IP-in-IP explicitly, drop. */
! 92: if (!ipip_allow && ((*m)->m_flags & (M_AUTH|M_CONF)) == 0) {
! 93: DPRINTF(("ip4_input6(): dropped due to policy\n"));
! 94: ipipstat.ipips_pdrops++;
! 95: m_freem(*m);
! 96: return IPPROTO_DONE;
! 97: }
! 98:
! 99: ipip_input(*m, *offp, NULL);
! 100: return IPPROTO_DONE;
! 101: }
! 102: #endif /* INET6 */
! 103:
! 104: #ifdef INET
! 105: /*
! 106: * Really only a wrapper for ipip_input(), for use with IPv4.
! 107: */
! 108: void
! 109: ip4_input(struct mbuf *m, ...)
! 110: {
! 111: va_list ap;
! 112: int iphlen;
! 113:
! 114: /* If we do not accept IP-in-IP explicitly, drop. */
! 115: if (!ipip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
! 116: DPRINTF(("ip4_input(): dropped due to policy\n"));
! 117: ipipstat.ipips_pdrops++;
! 118: m_freem(m);
! 119: return;
! 120: }
! 121:
! 122: va_start(ap, m);
! 123: iphlen = va_arg(ap, int);
! 124: va_end(ap);
! 125:
! 126: ipip_input(m, iphlen, NULL);
! 127: }
! 128: #endif /* INET */
! 129:
! 130: /*
! 131: * ipip_input gets called when we receive an IP{46} encapsulated packet,
! 132: * either because we got it at a real interface, or because AH or ESP
! 133: * were being used in tunnel mode (in which case the rcvif element will
! 134: * contain the address of the encX interface associated with the tunnel.
! 135: */
! 136:
! 137: void
! 138: ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
! 139: {
! 140: struct sockaddr_in *sin;
! 141: struct ifnet *ifp;
! 142: struct ifaddr *ifa;
! 143: struct ifqueue *ifq = NULL;
! 144: struct ip *ipo;
! 145: #ifdef INET6
! 146: struct sockaddr_in6 *sin6;
! 147: struct ip6_hdr *ip6 = NULL;
! 148: u_int8_t itos;
! 149: #endif
! 150: u_int8_t nxt;
! 151: int isr;
! 152: u_int8_t otos;
! 153: u_int8_t v;
! 154: int hlen, s;
! 155:
! 156: ipipstat.ipips_ipackets++;
! 157:
! 158: m_copydata(m, 0, 1, &v);
! 159:
! 160: switch (v >> 4) {
! 161: #ifdef INET
! 162: case 4:
! 163: hlen = sizeof(struct ip);
! 164: break;
! 165: #endif /* INET */
! 166: #ifdef INET6
! 167: case 6:
! 168: hlen = sizeof(struct ip6_hdr);
! 169: break;
! 170: #endif
! 171: default:
! 172: ipipstat.ipips_family++;
! 173: m_freem(m);
! 174: return /* EAFNOSUPPORT */;
! 175: }
! 176:
! 177: /* Bring the IP header in the first mbuf, if not there already */
! 178: if (m->m_len < hlen) {
! 179: if ((m = m_pullup(m, hlen)) == NULL) {
! 180: DPRINTF(("ipip_input(): m_pullup() failed\n"));
! 181: ipipstat.ipips_hdrops++;
! 182: return;
! 183: }
! 184: }
! 185:
! 186: ipo = mtod(m, struct ip *);
! 187:
! 188: /* Keep outer ecn field. */
! 189: switch (v >> 4) {
! 190: #ifdef INET
! 191: case 4:
! 192: otos = ipo->ip_tos;
! 193: break;
! 194: #endif /* INET */
! 195: #ifdef INET6
! 196: case 6:
! 197: otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
! 198: break;
! 199: #endif
! 200: default:
! 201: panic("ipip_input: should never reach here");
! 202: }
! 203:
! 204: /* Remove outer IP header */
! 205: m_adj(m, iphlen);
! 206:
! 207: /* Sanity check */
! 208: if (m->m_pkthdr.len < sizeof(struct ip)) {
! 209: ipipstat.ipips_hdrops++;
! 210: m_freem(m);
! 211: return;
! 212: }
! 213:
! 214: m_copydata(m, 0, 1, &v);
! 215:
! 216: switch (v >> 4) {
! 217: #ifdef INET
! 218: case 4:
! 219: hlen = sizeof(struct ip);
! 220: break;
! 221: #endif /* INET */
! 222:
! 223: #ifdef INET6
! 224: case 6:
! 225: hlen = sizeof(struct ip6_hdr);
! 226: break;
! 227: #endif
! 228: default:
! 229: ipipstat.ipips_family++;
! 230: m_freem(m);
! 231: return; /* EAFNOSUPPORT */
! 232: }
! 233:
! 234: /*
! 235: * Bring the inner IP header in the first mbuf, if not there already.
! 236: */
! 237: if (m->m_len < hlen) {
! 238: if ((m = m_pullup(m, hlen)) == NULL) {
! 239: DPRINTF(("ipip_input(): m_pullup() failed\n"));
! 240: ipipstat.ipips_hdrops++;
! 241: return;
! 242: }
! 243: }
! 244:
! 245: /*
! 246: * RFC 1853 specifies that the inner TTL should not be touched on
! 247: * decapsulation. There's no reason this comment should be here, but
! 248: * this is as good as any a position.
! 249: */
! 250:
! 251: /* Some sanity checks in the inner IP header */
! 252: switch (v >> 4) {
! 253: #ifdef INET
! 254: case 4:
! 255: ipo = mtod(m, struct ip *);
! 256: nxt = ipo->ip_p;
! 257: if (!ip_ecn_egress(ECN_ALLOWED, &otos, &ipo->ip_tos)) {
! 258: m_freem(m);
! 259: return;
! 260: }
! 261: break;
! 262: #endif /* INET */
! 263: #ifdef INET6
! 264: case 6:
! 265: ip6 = (struct ip6_hdr *) ipo;
! 266: nxt = ip6->ip6_nxt;
! 267: itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
! 268: if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) {
! 269: m_freem(m);
! 270: return;
! 271: }
! 272: ip6->ip6_flow &= ~htonl(0xff << 20);
! 273: ip6->ip6_flow |= htonl((u_int32_t) itos << 20);
! 274: break;
! 275: #endif
! 276: default:
! 277: panic("ipip_input: should never reach here");
! 278: }
! 279:
! 280: /* Check for local address spoofing. */
! 281: if ((m->m_pkthdr.rcvif == NULL ||
! 282: !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) &&
! 283: ipip_allow != 2) {
! 284: TAILQ_FOREACH(ifp, &ifnet, if_list) {
! 285: TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
! 286: #ifdef INET
! 287: if (ipo) {
! 288: if (ifa->ifa_addr->sa_family !=
! 289: AF_INET)
! 290: continue;
! 291:
! 292: sin = (struct sockaddr_in *) ifa->ifa_addr;
! 293:
! 294: if (sin->sin_addr.s_addr ==
! 295: ipo->ip_src.s_addr) {
! 296: ipipstat.ipips_spoof++;
! 297: m_freem(m);
! 298: return;
! 299: }
! 300: }
! 301: #endif /* INET */
! 302:
! 303: #ifdef INET6
! 304: if (ip6) {
! 305: if (ifa->ifa_addr->sa_family !=
! 306: AF_INET6)
! 307: continue;
! 308:
! 309: sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
! 310:
! 311: if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
! 312: ipipstat.ipips_spoof++;
! 313: m_freem(m);
! 314: return;
! 315: }
! 316:
! 317: }
! 318: #endif /* INET6 */
! 319: }
! 320: }
! 321: }
! 322:
! 323: /* Statistics */
! 324: ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
! 325:
! 326: /*
! 327: * Interface pointer stays the same; if no IPsec processing has
! 328: * been done (or will be done), this will point to a normal
! 329: * interface. Otherwise, it'll point to an enc interface, which
! 330: * will allow a packet filter to distinguish between secure and
! 331: * untrusted packets.
! 332: */
! 333:
! 334: switch (v >> 4) {
! 335: #ifdef INET
! 336: case 4:
! 337: ifq = &ipintrq;
! 338: isr = NETISR_IP;
! 339: break;
! 340: #endif
! 341: #ifdef INET6
! 342: case 6:
! 343: ifq = &ip6intrq;
! 344: isr = NETISR_IPV6;
! 345: break;
! 346: #endif
! 347: default:
! 348: panic("ipip_input: should never reach here");
! 349: }
! 350:
! 351: #if NBPFILTER > 0
! 352: if (gifp && gifp->if_bpf)
! 353: bpf_mtap_af(gifp->if_bpf, ifq == &ipintrq ? AF_INET : AF_INET6,
! 354: m, BPF_DIRECTION_IN);
! 355: #endif
! 356:
! 357: s = splnet(); /* isn't it already? */
! 358: if (IF_QFULL(ifq)) {
! 359: IF_DROP(ifq);
! 360: m_freem(m);
! 361: ipipstat.ipips_qfull++;
! 362:
! 363: splx(s);
! 364:
! 365: DPRINTF(("ipip_input(): packet dropped because of full "
! 366: "queue\n"));
! 367: return;
! 368: }
! 369:
! 370: IF_ENQUEUE(ifq, m);
! 371: schednetisr(isr);
! 372: splx(s);
! 373: return;
! 374: }
! 375:
! 376: int
! 377: ipip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int dummy,
! 378: int dummy2)
! 379: {
! 380: u_int8_t tp, otos;
! 381:
! 382: #ifdef INET
! 383: u_int8_t itos;
! 384: struct ip *ipo;
! 385: #endif /* INET */
! 386:
! 387: #ifdef INET6
! 388: struct ip6_hdr *ip6, *ip6o;
! 389: #endif /* INET6 */
! 390:
! 391: /* XXX Deal with empty TDB source/destination addresses. */
! 392:
! 393: m_copydata(m, 0, 1, &tp);
! 394: tp = (tp >> 4) & 0xff; /* Get the IP version number. */
! 395:
! 396: switch (tdb->tdb_dst.sa.sa_family) {
! 397: #ifdef INET
! 398: case AF_INET:
! 399: if (tdb->tdb_src.sa.sa_family != AF_INET ||
! 400: tdb->tdb_src.sin.sin_addr.s_addr == INADDR_ANY ||
! 401: tdb->tdb_dst.sin.sin_addr.s_addr == INADDR_ANY) {
! 402:
! 403: DPRINTF(("ipip_output(): unspecified tunnel endpoind "
! 404: "address in SA %s/%08x\n",
! 405: ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
! 406:
! 407: ipipstat.ipips_unspec++;
! 408: m_freem(m);
! 409: *mp = NULL;
! 410: return EINVAL;
! 411: }
! 412:
! 413: M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
! 414: if (m == 0) {
! 415: DPRINTF(("ipip_output(): M_PREPEND failed\n"));
! 416: ipipstat.ipips_hdrops++;
! 417: *mp = NULL;
! 418: return ENOBUFS;
! 419: }
! 420:
! 421: ipo = mtod(m, struct ip *);
! 422:
! 423: ipo->ip_v = IPVERSION;
! 424: ipo->ip_hl = 5;
! 425: ipo->ip_len = htons(m->m_pkthdr.len);
! 426: ipo->ip_ttl = ip_defttl;
! 427: ipo->ip_sum = 0;
! 428: ipo->ip_src = tdb->tdb_src.sin.sin_addr;
! 429: ipo->ip_dst = tdb->tdb_dst.sin.sin_addr;
! 430:
! 431: /*
! 432: * We do the htons() to prevent snoopers from determining our
! 433: * endianness.
! 434: */
! 435: ipo->ip_id = htons(ip_randomid());
! 436:
! 437: /* If the inner protocol is IP... */
! 438: if (tp == IPVERSION) {
! 439: /* Save ECN notification */
! 440: m_copydata(m, sizeof(struct ip) +
! 441: offsetof(struct ip, ip_tos),
! 442: sizeof(u_int8_t), (caddr_t) &itos);
! 443:
! 444: ipo->ip_p = IPPROTO_IPIP;
! 445:
! 446: /*
! 447: * We should be keeping tunnel soft-state and
! 448: * send back ICMPs if needed.
! 449: */
! 450: m_copydata(m, sizeof(struct ip) +
! 451: offsetof(struct ip, ip_off),
! 452: sizeof(u_int16_t), (caddr_t) &ipo->ip_off);
! 453: NTOHS(ipo->ip_off);
! 454: ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK);
! 455: HTONS(ipo->ip_off);
! 456: }
! 457: #ifdef INET6
! 458: else if (tp == (IPV6_VERSION >> 4)) {
! 459: u_int32_t itos32;
! 460:
! 461: /* Save ECN notification. */
! 462: m_copydata(m, sizeof(struct ip) +
! 463: offsetof(struct ip6_hdr, ip6_flow),
! 464: sizeof(u_int32_t), (caddr_t) &itos32);
! 465: itos = ntohl(itos32) >> 20;
! 466: ipo->ip_p = IPPROTO_IPV6;
! 467: ipo->ip_off = 0;
! 468: }
! 469: #endif /* INET6 */
! 470: else {
! 471: m_freem(m);
! 472: *mp = NULL;
! 473: ipipstat.ipips_family++;
! 474: return EAFNOSUPPORT;
! 475: }
! 476:
! 477: otos = 0;
! 478: ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
! 479: ipo->ip_tos = otos;
! 480: break;
! 481: #endif /* INET */
! 482:
! 483: #ifdef INET6
! 484: case AF_INET6:
! 485: if (IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr) ||
! 486: tdb->tdb_src.sa.sa_family != AF_INET6 ||
! 487: IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_src.sin6.sin6_addr)) {
! 488:
! 489: DPRINTF(("ipip_output(): unspecified tunnel endpoind "
! 490: "address in SA %s/%08x\n",
! 491: ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
! 492:
! 493: ipipstat.ipips_unspec++;
! 494: m_freem(m);
! 495: *mp = NULL;
! 496: return ENOBUFS;
! 497: }
! 498:
! 499: /* scoped address handling */
! 500: ip6 = mtod(m, struct ip6_hdr *);
! 501: if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
! 502: ip6->ip6_src.s6_addr16[1] = 0;
! 503: if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
! 504: ip6->ip6_dst.s6_addr16[1] = 0;
! 505:
! 506: M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
! 507: if (m == 0) {
! 508: DPRINTF(("ipip_output(): M_PREPEND failed\n"));
! 509: ipipstat.ipips_hdrops++;
! 510: *mp = NULL;
! 511: return ENOBUFS;
! 512: }
! 513:
! 514: /* Initialize IPv6 header */
! 515: ip6o = mtod(m, struct ip6_hdr *);
! 516: ip6o->ip6_flow = 0;
! 517: ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
! 518: ip6o->ip6_vfc |= IPV6_VERSION;
! 519: ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o));
! 520: ip6o->ip6_hlim = ip_defttl;
! 521: in6_embedscope(&ip6o->ip6_src, &tdb->tdb_src.sin6, NULL, NULL);
! 522: in6_embedscope(&ip6o->ip6_dst, &tdb->tdb_dst.sin6, NULL, NULL);
! 523:
! 524: #ifdef INET
! 525: if (tp == IPVERSION) {
! 526: /* Save ECN notification */
! 527: m_copydata(m, sizeof(struct ip6_hdr) +
! 528: offsetof(struct ip, ip_tos), sizeof(u_int8_t),
! 529: (caddr_t) &itos);
! 530:
! 531: /* This is really IPVERSION. */
! 532: ip6o->ip6_nxt = IPPROTO_IPIP;
! 533: }
! 534: else
! 535: #endif /* INET */
! 536: if (tp == (IPV6_VERSION >> 4)) {
! 537: u_int32_t itos32;
! 538:
! 539: /* Save ECN notification. */
! 540: m_copydata(m, sizeof(struct ip6_hdr) +
! 541: offsetof(struct ip6_hdr, ip6_flow),
! 542: sizeof(u_int32_t), (caddr_t) &itos32);
! 543: itos = ntohl(itos32) >> 20;
! 544:
! 545: ip6o->ip6_nxt = IPPROTO_IPV6;
! 546: } else {
! 547: m_freem(m);
! 548: *mp = NULL;
! 549: ipipstat.ipips_family++;
! 550: return EAFNOSUPPORT;
! 551: }
! 552:
! 553: otos = 0;
! 554: ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
! 555: ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
! 556: break;
! 557: #endif /* INET6 */
! 558:
! 559: default:
! 560: DPRINTF(("ipip_output(): unsupported protocol family %d\n",
! 561: tdb->tdb_dst.sa.sa_family));
! 562: m_freem(m);
! 563: *mp = NULL;
! 564: ipipstat.ipips_family++;
! 565: return EAFNOSUPPORT;
! 566: }
! 567:
! 568: ipipstat.ipips_opackets++;
! 569: *mp = m;
! 570:
! 571: #ifdef INET
! 572: if (tdb->tdb_dst.sa.sa_family == AF_INET) {
! 573: if (tdb->tdb_xform->xf_type == XF_IP4)
! 574: tdb->tdb_cur_bytes +=
! 575: m->m_pkthdr.len - sizeof(struct ip);
! 576:
! 577: ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip);
! 578: }
! 579: #endif /* INET */
! 580:
! 581: #ifdef INET6
! 582: if (tdb->tdb_dst.sa.sa_family == AF_INET6) {
! 583: if (tdb->tdb_xform->xf_type == XF_IP4)
! 584: tdb->tdb_cur_bytes +=
! 585: m->m_pkthdr.len - sizeof(struct ip6_hdr);
! 586:
! 587: ipipstat.ipips_obytes +=
! 588: m->m_pkthdr.len - sizeof(struct ip6_hdr);
! 589: }
! 590: #endif /* INET6 */
! 591:
! 592: return 0;
! 593: }
! 594:
! 595: #ifdef IPSEC
! 596: int
! 597: ipe4_attach()
! 598: {
! 599: return 0;
! 600: }
! 601:
! 602: int
! 603: ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
! 604: {
! 605: tdbp->tdb_xform = xsp;
! 606: return 0;
! 607: }
! 608:
! 609: int
! 610: ipe4_zeroize(struct tdb *tdbp)
! 611: {
! 612: return 0;
! 613: }
! 614:
! 615: void
! 616: ipe4_input(struct mbuf *m, ...)
! 617: {
! 618: /* This is a rather serious mistake, so no conditional printing. */
! 619: printf("ipe4_input(): should never be called\n");
! 620: if (m)
! 621: m_freem(m);
! 622: }
! 623: #endif /* IPSEC */
! 624:
! 625: int
! 626: ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
! 627: size_t newlen)
! 628: {
! 629: /* All sysctl names at this level are terminal. */
! 630: if (namelen != 1)
! 631: return (ENOTDIR);
! 632:
! 633: switch (name[0]) {
! 634: case IPIPCTL_ALLOW:
! 635: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow));
! 636: default:
! 637: return (ENOPROTOOPT);
! 638: }
! 639: /* NOTREACHED */
! 640: }
CVSweb