[BACK]Return to ip_ipip.c CVS log [TXT][DIR] Up to [local] / sys / netinet

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