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

Annotation of sys/netinet/ipsec_input.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ipsec_input.c,v 1.84 2007/05/28 17:16:39 henning 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:  * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
                      8:  * 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: #include "pf.h"
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/protosw.h>
                     43: #include <sys/mbuf.h>
                     44: #include <sys/socket.h>
                     45: #include <sys/sysctl.h>
                     46: #include <sys/kernel.h>
                     47:
                     48: #include <net/if.h>
                     49: #include <net/netisr.h>
                     50: #include <net/bpf.h>
                     51:
                     52: #if NPF > 0
                     53: #include <net/pfvar.h>
                     54: #endif
                     55:
                     56: #include <netinet/in.h>
                     57: #include <netinet/in_systm.h>
                     58: #include <netinet/ip.h>
                     59: #include <netinet/ip_var.h>
                     60: #include <netinet/in_var.h>
                     61: #include <netinet/ip_icmp.h>
                     62: #include <netinet/tcp.h>
                     63: #include <netinet/udp.h>
                     64:
                     65: #ifdef INET6
                     66: #ifndef INET
                     67: #include <netinet/in.h>
                     68: #endif
                     69: #include <netinet/ip6.h>
                     70: #include <netinet6/ip6_var.h>
                     71: #include <netinet6/ip6protosw.h>
                     72: #endif /* INET6 */
                     73:
                     74: #include <netinet/ip_ipsp.h>
                     75: #include <netinet/ip_esp.h>
                     76: #include <netinet/ip_ah.h>
                     77: #include <netinet/ip_ipcomp.h>
                     78:
                     79: #include <net/if_enc.h>
                     80:
                     81: #include "bpfilter.h"
                     82:
                     83: void *ipsec_common_ctlinput(int, struct sockaddr *, void *, int);
                     84:
                     85: #ifdef ENCDEBUG
                     86: #define DPRINTF(x)     if (encdebug) printf x
                     87: #else
                     88: #define DPRINTF(x)
                     89: #endif
                     90:
                     91: /* sysctl variables */
                     92: int esp_enable = 1;
                     93: int ah_enable = 1;
                     94: int ipcomp_enable = 0;
                     95:
                     96: int *espctl_vars[ESPCTL_MAXID] = ESPCTL_VARS;
                     97: int *ahctl_vars[AHCTL_MAXID] = AHCTL_VARS;
                     98: int *ipcompctl_vars[IPCOMPCTL_MAXID] = IPCOMPCTL_VARS;
                     99:
                    100: #ifdef INET6
                    101: extern struct ip6protosw inet6sw[];
                    102: extern u_char ip6_protox[];
                    103: #endif
                    104:
                    105: /*
                    106:  * ipsec_common_input() gets called when we receive an IPsec-protected packet
                    107:  * in IPv4 or IPv6. All it does is find the right TDB and call the appropriate
                    108:  * transform. The callback takes care of further processing (like ingress
                    109:  * filtering).
                    110:  */
                    111: int
                    112: ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto,
                    113:     int udpencap)
                    114: {
                    115: #define IPSEC_ISTAT(x,y,z) (sproto == IPPROTO_ESP ? (x)++ : \
                    116:                            sproto == IPPROTO_AH ? (y)++ : (z)++)
                    117:
                    118:        union sockaddr_union dst_address;
                    119:        struct timeval tv;
                    120:        struct tdb *tdbp;
                    121:        u_int32_t spi;
                    122:        u_int16_t cpi;
                    123:        int s, error;
                    124:
                    125:        IPSEC_ISTAT(espstat.esps_input, ahstat.ahs_input,
                    126:            ipcompstat.ipcomps_input);
                    127:
                    128:        if (m == 0) {
                    129:                DPRINTF(("ipsec_common_input(): NULL packet received\n"));
                    130:                IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
                    131:                    ipcompstat.ipcomps_hdrops);
                    132:                return EINVAL;
                    133:        }
                    134:
                    135:        if ((sproto == IPPROTO_ESP && !esp_enable) ||
                    136:            (sproto == IPPROTO_AH && !ah_enable) ||
                    137:            (sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
                    138:                rip_input(m, skip, sproto);
                    139:                return 0;
                    140:        }
                    141:
                    142:        if (m->m_pkthdr.len - skip < 2 * sizeof(u_int32_t)) {
                    143:                m_freem(m);
                    144:                IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
                    145:                    ipcompstat.ipcomps_hdrops);
                    146:                DPRINTF(("ipsec_common_input(): packet too small\n"));
                    147:                return EINVAL;
                    148:        }
                    149:
                    150:        /* Retrieve the SPI from the relevant IPsec header */
                    151:        if (sproto == IPPROTO_ESP)
                    152:                m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
                    153:        else if (sproto == IPPROTO_AH)
                    154:                m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
                    155:                    (caddr_t) &spi);
                    156:        else if (sproto == IPPROTO_IPCOMP) {
                    157:                m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t),
                    158:                    (caddr_t) &cpi);
                    159:                spi = ntohl(htons(cpi));
                    160:        }
                    161:
                    162:        /*
                    163:         * Find tunnel control block and (indirectly) call the appropriate
                    164:         * kernel crypto routine. The resulting mbuf chain is a valid
                    165:         * IP packet ready to go through input processing.
                    166:         */
                    167:
                    168:        bzero(&dst_address, sizeof(dst_address));
                    169:        dst_address.sa.sa_family = af;
                    170:
                    171:        switch (af) {
                    172: #ifdef INET
                    173:        case AF_INET:
                    174:                dst_address.sin.sin_len = sizeof(struct sockaddr_in);
                    175:                m_copydata(m, offsetof(struct ip, ip_dst),
                    176:                    sizeof(struct in_addr),
                    177:                    (caddr_t) &(dst_address.sin.sin_addr));
                    178:                break;
                    179: #endif /* INET */
                    180:
                    181: #ifdef INET6
                    182:        case AF_INET6:
                    183:                dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6);
                    184:                m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
                    185:                    sizeof(struct in6_addr),
                    186:                    (caddr_t) &(dst_address.sin6.sin6_addr));
                    187:                in6_recoverscope(&dst_address.sin6, &dst_address.sin6.sin6_addr,
                    188:                    NULL);
                    189:                break;
                    190: #endif /* INET6 */
                    191:
                    192:        default:
                    193:                DPRINTF(("ipsec_common_input(): unsupported protocol "
                    194:                    "family %d\n", af));
                    195:                m_freem(m);
                    196:                IPSEC_ISTAT(espstat.esps_nopf, ahstat.ahs_nopf,
                    197:                    ipcompstat.ipcomps_nopf);
                    198:                return EPFNOSUPPORT;
                    199:        }
                    200:
                    201:        s = spltdb();
                    202:        tdbp = gettdb(spi, &dst_address, sproto);
                    203:        if (tdbp == NULL) {
                    204:                splx(s);
                    205:                DPRINTF(("ipsec_common_input(): could not find SA for "
                    206:                    "packet to %s, spi %08x\n",
                    207:                    ipsp_address(dst_address), ntohl(spi)));
                    208:                m_freem(m);
                    209:                IPSEC_ISTAT(espstat.esps_notdb, ahstat.ahs_notdb,
                    210:                    ipcompstat.ipcomps_notdb);
                    211:                return ENOENT;
                    212:        }
                    213:
                    214:        if (tdbp->tdb_flags & TDBF_INVALID) {
                    215:                splx(s);
                    216:                DPRINTF(("ipsec_common_input(): attempted to use invalid SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
                    217:                m_freem(m);
                    218:                IPSEC_ISTAT(espstat.esps_invalid, ahstat.ahs_invalid,
                    219:                    ipcompstat.ipcomps_invalid);
                    220:                return EINVAL;
                    221:        }
                    222:
                    223:        if (udpencap && !(tdbp->tdb_flags & TDBF_UDPENCAP)) {
                    224:                splx(s);
                    225:                DPRINTF(("ipsec_common_input(): attempted to use non-udpencap SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
                    226:                m_freem(m);
                    227:                espstat.esps_udpinval++;
                    228:                return EINVAL;
                    229:        }
                    230:
                    231:        if (tdbp->tdb_xform == NULL) {
                    232:                splx(s);
                    233:                DPRINTF(("ipsec_common_input(): attempted to use uninitialized SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto));
                    234:                m_freem(m);
                    235:                IPSEC_ISTAT(espstat.esps_noxform, ahstat.ahs_noxform,
                    236:                    ipcompstat.ipcomps_noxform);
                    237:                return ENXIO;
                    238:        }
                    239:
                    240:        if (tdbp->tdb_dst.sa.sa_family == AF_INET &&
                    241:            sproto != IPPROTO_IPCOMP) {
                    242:                /*
                    243:                 * XXX The fragment conflicts with scoped nature of
                    244:                 * IPv6, so do it for only for IPv4 for now.
                    245:                 */
                    246:                m->m_pkthdr.rcvif = &encif[0].sc_if;
                    247:        }
                    248:
                    249:        /* Register first use, setup expiration timer. */
                    250:        if (tdbp->tdb_first_use == 0) {
                    251:                tdbp->tdb_first_use = time_second;
                    252:
                    253:                tv.tv_usec = 0;
                    254:
                    255:                tv.tv_sec = tdbp->tdb_exp_first_use + tdbp->tdb_first_use;
                    256:                if (tdbp->tdb_flags & TDBF_FIRSTUSE)
                    257:                        timeout_add(&tdbp->tdb_first_tmo, hzto(&tv));
                    258:
                    259:                tv.tv_sec = tdbp->tdb_first_use + tdbp->tdb_soft_first_use;
                    260:                if (tdbp->tdb_flags & TDBF_SOFT_FIRSTUSE)
                    261:                        timeout_add(&tdbp->tdb_sfirst_tmo, hzto(&tv));
                    262:        }
                    263:
                    264:        /*
                    265:         * Call appropriate transform and return -- callback takes care of
                    266:         * everything else.
                    267:         */
                    268:        error = (*(tdbp->tdb_xform->xf_input))(m, tdbp, skip, protoff);
                    269:        splx(s);
                    270:        return error;
                    271: }
                    272:
                    273: /*
                    274:  * IPsec input callback, called by the transform callback. Takes care of
                    275:  * filtering and other sanity checks on the processed packet.
                    276:  */
                    277: int
                    278: ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff,
                    279:     struct m_tag *mt)
                    280: {
                    281:        int prot, af, sproto;
                    282:
                    283: #if NBPFILTER > 0
                    284:        struct ifnet *bpfif;
                    285: #endif
                    286:
                    287: #ifdef INET
                    288:        struct ip *ip, ipn;
                    289: #endif /* INET */
                    290:
                    291: #ifdef INET6
                    292:        struct ip6_hdr *ip6, ip6n;
                    293: #endif /* INET6 */
                    294:        struct m_tag *mtag;
                    295:        struct tdb_ident *tdbi;
                    296:
                    297:        af = tdbp->tdb_dst.sa.sa_family;
                    298:        sproto = tdbp->tdb_sproto;
                    299:
                    300:        tdbp->tdb_last_used = time_second;
                    301:
                    302:        /* Sanity check */
                    303:        if (m == NULL) {
                    304:                /* The called routine will print a message if necessary */
                    305:                IPSEC_ISTAT(espstat.esps_badkcr, ahstat.ahs_badkcr,
                    306:                    ipcompstat.ipcomps_badkcr);
                    307:                return EINVAL;
                    308:        }
                    309:
                    310: #ifdef INET
                    311:        /* Fix IPv4 header */
                    312:        if (tdbp->tdb_dst.sa.sa_family == AF_INET) {
                    313:                if ((m->m_len < skip) && ((m = m_pullup(m, skip)) == NULL)) {
                    314:                        DPRINTF(("ipsec_common_input_cb(): processing failed "
                    315:                            "for SA %s/%08x\n", ipsp_address(tdbp->tdb_dst),
                    316:                            ntohl(tdbp->tdb_spi)));
                    317:                        IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
                    318:                            ipcompstat.ipcomps_hdrops);
                    319:                        return ENOBUFS;
                    320:                }
                    321:
                    322:                ip = mtod(m, struct ip *);
                    323:                ip->ip_len = htons(m->m_pkthdr.len);
                    324:                ip->ip_sum = 0;
                    325:                ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
                    326:                prot = ip->ip_p;
                    327:
                    328:                /* IP-in-IP encapsulation */
                    329:                if (prot == IPPROTO_IPIP) {
                    330:                        if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
                    331:                                m_freem(m);
                    332:                                IPSEC_ISTAT(espstat.esps_hdrops,
                    333:                                    ahstat.ahs_hdrops,
                    334:                                    ipcompstat.ipcomps_hdrops);
                    335:                                return EINVAL;
                    336:                        }
                    337:                        /* ipn will now contain the inner IPv4 header */
                    338:                        m_copydata(m, skip, sizeof(struct ip),
                    339:                            (caddr_t) &ipn);
                    340:
                    341:                        /*
                    342:                         * Check that the inner source address is the same as
                    343:                         * the proxy address, if available.
                    344:                         */
                    345:                        if ((tdbp->tdb_proxy.sa.sa_family == AF_INET &&
                    346:                            tdbp->tdb_proxy.sin.sin_addr.s_addr !=
                    347:                            INADDR_ANY &&
                    348:                            ipn.ip_src.s_addr !=
                    349:                            tdbp->tdb_proxy.sin.sin_addr.s_addr) ||
                    350:                            (tdbp->tdb_proxy.sa.sa_family != AF_INET &&
                    351:                                tdbp->tdb_proxy.sa.sa_family != 0)) {
                    352:
                    353:                                DPRINTF(("ipsec_common_input_cb(): inner "
                    354:                                    "source address %s doesn't correspond to "
                    355:                                    "expected proxy source %s, SA %s/%08x\n",
                    356:                                    inet_ntoa4(ipn.ip_src),
                    357:                                    ipsp_address(tdbp->tdb_proxy),
                    358:                                    ipsp_address(tdbp->tdb_dst),
                    359:                                    ntohl(tdbp->tdb_spi)));
                    360:
                    361:                                m_freem(m);
                    362:                                IPSEC_ISTAT(espstat.esps_pdrops,
                    363:                                    ahstat.ahs_pdrops,
                    364:                                    ipcompstat.ipcomps_pdrops);
                    365:                                return EACCES;
                    366:                        }
                    367:                }
                    368:
                    369: #if INET6
                    370:                /* IPv6-in-IP encapsulation. */
                    371:                if (prot == IPPROTO_IPV6) {
                    372:                        if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
                    373:                                m_freem(m);
                    374:                                IPSEC_ISTAT(espstat.esps_hdrops,
                    375:                                    ahstat.ahs_hdrops,
                    376:                                    ipcompstat.ipcomps_hdrops);
                    377:                                return EINVAL;
                    378:                        }
                    379:                        /* ip6n will now contain the inner IPv6 header. */
                    380:                        m_copydata(m, skip, sizeof(struct ip6_hdr),
                    381:                            (caddr_t) &ip6n);
                    382:
                    383:                        /*
                    384:                         * Check that the inner source address is the same as
                    385:                         * the proxy address, if available.
                    386:                         */
                    387:                        if ((tdbp->tdb_proxy.sa.sa_family == AF_INET6 &&
                    388:                            !IN6_IS_ADDR_UNSPECIFIED(&tdbp->tdb_proxy.sin6.sin6_addr) &&
                    389:                            !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
                    390:                                &tdbp->tdb_proxy.sin6.sin6_addr)) ||
                    391:                            (tdbp->tdb_proxy.sa.sa_family != AF_INET6 &&
                    392:                                tdbp->tdb_proxy.sa.sa_family != 0)) {
                    393:
                    394:                                DPRINTF(("ipsec_common_input_cb(): inner "
                    395:                                    "source address %s doesn't correspond to "
                    396:                                    "expected proxy source %s, SA %s/%08x\n",
                    397:                                    ip6_sprintf(&ip6n.ip6_src),
                    398:                                    ipsp_address(tdbp->tdb_proxy),
                    399:                                    ipsp_address(tdbp->tdb_dst),
                    400:                                    ntohl(tdbp->tdb_spi)));
                    401:
                    402:                                m_freem(m);
                    403:                                IPSEC_ISTAT(espstat.esps_pdrops,
                    404:                                    ahstat.ahs_pdrops,
                    405:                                    ipcompstat.ipcomps_pdrops);
                    406:                                return EACCES;
                    407:                        }
                    408:                }
                    409: #endif /* INET6 */
                    410:        }
                    411: #endif /* INET */
                    412:
                    413: #ifdef INET6
                    414:        /* Fix IPv6 header */
                    415:        if (af == INET6)
                    416:        {
                    417:                if (m->m_len < sizeof(struct ip6_hdr) &&
                    418:                    (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
                    419:
                    420:                        DPRINTF(("ipsec_common_input_cb(): processing failed "
                    421:                            "for SA %s/%08x\n", ipsp_address(tdbp->tdb_dst),
                    422:                            ntohl(tdbp->tdb_spi)));
                    423:
                    424:                        IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
                    425:                            ipcompstat.ipcomps_hdrops);
                    426:                        return EACCES;
                    427:                }
                    428:
                    429:                ip6 = mtod(m, struct ip6_hdr *);
                    430:                ip6->ip6_plen = htons(m->m_pkthdr.len -
                    431:                    sizeof(struct ip6_hdr));
                    432:
                    433:                /* Save protocol */
                    434:                m_copydata(m, protoff, 1, (unsigned char *) &prot);
                    435:
                    436: #ifdef INET
                    437:                /* IP-in-IP encapsulation */
                    438:                if (prot == IPPROTO_IPIP) {
                    439:                        if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
                    440:                                m_freem(m);
                    441:                                IPSEC_ISTAT(espstat.esps_hdrops,
                    442:                                    ahstat.ahs_hdrops,
                    443:                                    ipcompstat.ipcomps_hdrops);
                    444:                                return EINVAL;
                    445:                        }
                    446:                        /* ipn will now contain the inner IPv4 header */
                    447:                        m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
                    448:
                    449:                        /*
                    450:                         * Check that the inner source address is the same as
                    451:                         * the proxy address, if available.
                    452:                         */
                    453:                        if ((tdbp->tdb_proxy.sa.sa_family == AF_INET &&
                    454:                            tdbp->tdb_proxy.sin.sin_addr.s_addr !=
                    455:                            INADDR_ANY &&
                    456:                            ipn.ip_src.s_addr !=
                    457:                                tdbp->tdb_proxy.sin.sin_addr.s_addr) ||
                    458:                            (tdbp->tdb_proxy.sa.sa_family != AF_INET &&
                    459:                                tdbp->tdb_proxy.sa.sa_family != 0)) {
                    460:
                    461:                                DPRINTF(("ipsec_common_input_cb(): inner "
                    462:                                    "source address %s doesn't correspond to "
                    463:                                    "expected proxy source %s, SA %s/%08x\n",
                    464:                                    inet_ntoa4(ipn.ip_src),
                    465:                                    ipsp_address(tdbp->tdb_proxy),
                    466:                                    ipsp_address(tdbp->tdb_dst),
                    467:                                    ntohl(tdbp->tdb_spi)));
                    468:
                    469:                                m_freem(m);
                    470:                                IPSEC_ISTAT(espstat.esps_pdrops,
                    471:                                    ahstat.ahs_pdrops,
                    472:                                    ipcompstat.ipcomps_pdrops);
                    473:                                return EACCES;
                    474:                        }
                    475:                }
                    476: #endif /* INET */
                    477:
                    478:                /* IPv6-in-IP encapsulation */
                    479:                if (prot == IPPROTO_IPV6) {
                    480:                        if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
                    481:                                m_freem(m);
                    482:                                IPSEC_ISTAT(espstat.esps_hdrops,
                    483:                                    ahstat.ahs_hdrops,
                    484:                                    ipcompstat.ipcomps_hdrops);
                    485:                                return EINVAL;
                    486:                        }
                    487:                        /* ip6n will now contain the inner IPv6 header. */
                    488:                        m_copydata(m, skip, sizeof(struct ip6_hdr),
                    489:                            (caddr_t) &ip6n);
                    490:
                    491:                        /*
                    492:                         * Check that the inner source address is the same as
                    493:                         * the proxy address, if available.
                    494:                         */
                    495:                        if ((tdbp->tdb_proxy.sa.sa_family == AF_INET6 &&
                    496:                            !IN6_IS_ADDR_UNSPECIFIED(&tdbp->tdb_proxy.sin6.sin6_addr) &&
                    497:                            !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
                    498:                                &tdbp->tdb_proxy.sin6.sin6_addr)) ||
                    499:                            (tdbp->tdb_proxy.sa.sa_family != AF_INET6 &&
                    500:                                tdbp->tdb_proxy.sa.sa_family != 0)) {
                    501:
                    502:                                DPRINTF(("ipsec_common_input_cb(): inner "
                    503:                                    "source address %s doesn't correspond to "
                    504:                                    "expected proxy source %s, SA %s/%08x\n",
                    505:                                    ip6_sprintf(&ip6n.ip6_src),
                    506:                                    ipsp_address(tdbp->tdb_proxy),
                    507:                                    ipsp_address(tdbp->tdb_dst),
                    508:                                    ntohl(tdbp->tdb_spi)));
                    509:
                    510:                                m_freem(m);
                    511:                                IPSEC_ISTAT(espstat.esps_pdrops,
                    512:                                    ahstat.ahs_pdrops,
                    513:                                    ipcompstat.ipcomps_pdrops);
                    514:                                return EACCES;
                    515:                        }
                    516:                }
                    517:        }
                    518: #endif /* INET6 */
                    519:
                    520:        /*
                    521:         * Record what we've done to the packet (under what SA it was
                    522:         * processed). If we've been passed an mtag, it means the packet
                    523:         * was already processed by an ethernet/crypto combo card and
                    524:         * thus has a tag attached with all the right information, but
                    525:         * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to
                    526:         * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type.
                    527:         */
                    528:        if (mt == NULL && tdbp->tdb_sproto != IPPROTO_IPCOMP) {
                    529:                mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
                    530:                    sizeof(struct tdb_ident), M_NOWAIT);
                    531:                if (mtag == NULL) {
                    532:                        m_freem(m);
                    533:                        DPRINTF(("ipsec_common_input_cb(): failed to "
                    534:                            "get tag\n"));
                    535:                        IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops,
                    536:                            ipcompstat.ipcomps_hdrops);
                    537:                        return ENOMEM;
                    538:                }
                    539:
                    540:                tdbi = (struct tdb_ident *)(mtag + 1);
                    541:                bcopy(&tdbp->tdb_dst, &tdbi->dst,
                    542:                    sizeof(union sockaddr_union));
                    543:                tdbi->proto = tdbp->tdb_sproto;
                    544:                tdbi->spi = tdbp->tdb_spi;
                    545:
                    546:                m_tag_prepend(m, mtag);
                    547:        } else {
                    548:                if (mt != NULL)
                    549:                        mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
                    550:        }
                    551:
                    552:        if (sproto == IPPROTO_ESP) {
                    553:                /* Packet is confidential ? */
                    554:                if (tdbp->tdb_encalgxform)
                    555:                        m->m_flags |= M_CONF;
                    556:
                    557:                /* Check if we had authenticated ESP. */
                    558:                if (tdbp->tdb_authalgxform)
                    559:                        m->m_flags |= M_AUTH;
                    560:        } else if (sproto == IPPROTO_AH)
                    561:                m->m_flags |= M_AUTH | M_AUTH_AH;
                    562:
                    563: #if NPF > 0
                    564:        /* Add pf tag if requested. */
                    565:        if (pf_tag_packet(m, tdbp->tdb_tag, -1))
                    566:                DPRINTF(("failed to tag ipsec packet\n"));
                    567: #endif
                    568:
                    569:        if (tdbp->tdb_flags & TDBF_TUNNELING)
                    570:                m->m_flags |= M_TUNNEL;
                    571:
                    572: #if NBPFILTER > 0
                    573:        bpfif = &encif[0].sc_if;
                    574:        bpfif->if_ipackets++;
                    575:        bpfif->if_ibytes += m->m_pkthdr.len;
                    576:
                    577:        if (bpfif->if_bpf) {
                    578:                struct enchdr hdr;
                    579:
                    580:                hdr.af = af;
                    581:                hdr.spi = tdbp->tdb_spi;
                    582:                hdr.flags = m->m_flags & (M_AUTH|M_CONF|M_AUTH_AH);
                    583:
                    584:                bpf_mtap_hdr(bpfif->if_bpf, (char *)&hdr, ENC_HDRLEN, m,
                    585:                    BPF_DIRECTION_IN);
                    586:        }
                    587: #endif
                    588:
                    589:        /* Call the appropriate IPsec transform callback. */
                    590:        switch (af) {
                    591: #ifdef INET
                    592:        case AF_INET:
                    593:                switch (sproto)
                    594:                {
                    595:                case IPPROTO_ESP:
                    596:                        return esp4_input_cb(m);
                    597:
                    598:                case IPPROTO_AH:
                    599:                        return ah4_input_cb(m);
                    600:
                    601:                case IPPROTO_IPCOMP:
                    602:                        return ipcomp4_input_cb(m);
                    603:
                    604:                default:
                    605:                        DPRINTF(("ipsec_common_input_cb(): unknown/unsupported"
                    606:                            " security protocol %d\n", sproto));
                    607:                        m_freem(m);
                    608:                        return EPFNOSUPPORT;
                    609:                }
                    610:                break;
                    611: #endif /* INET */
                    612:
                    613: #ifdef INET6
                    614:        case AF_INET6:
                    615:                switch (sproto) {
                    616:                case IPPROTO_ESP:
                    617:                        return esp6_input_cb(m, skip, protoff);
                    618:
                    619:                case IPPROTO_AH:
                    620:                        return ah6_input_cb(m, skip, protoff);
                    621:
                    622:                case IPPROTO_IPCOMP:
                    623:                        return ipcomp6_input_cb(m, skip, protoff);
                    624:
                    625:                default:
                    626:                        DPRINTF(("ipsec_common_input_cb(): unknown/unsupported"
                    627:                            " security protocol %d\n", sproto));
                    628:                        m_freem(m);
                    629:                        return EPFNOSUPPORT;
                    630:                }
                    631:                break;
                    632: #endif /* INET6 */
                    633:
                    634:        default:
                    635:                DPRINTF(("ipsec_common_input_cb(): unknown/unsupported "
                    636:                    "protocol family %d\n", af));
                    637:                m_freem(m);
                    638:                return EPFNOSUPPORT;
                    639:        }
                    640: #undef IPSEC_ISTAT
                    641: }
                    642:
                    643: int
                    644: esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                    645:     size_t newlen)
                    646: {
                    647:        if (name[0] < ESPCTL_MAXID)
                    648:                return (sysctl_int_arr(espctl_vars, name, namelen,
                    649:                    oldp, oldlenp, newp, newlen));
                    650:        return (ENOPROTOOPT);
                    651: }
                    652:
                    653: int
                    654: ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                    655:     size_t newlen)
                    656: {
                    657:        if (name[0] < AHCTL_MAXID)
                    658:                return (sysctl_int_arr(ahctl_vars, name, namelen,
                    659:                    oldp, oldlenp, newp, newlen));
                    660:        return (ENOPROTOOPT);
                    661: }
                    662:
                    663: int
                    664: ipcomp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                    665:     size_t newlen)
                    666: {
                    667:        if (name[0] < IPCOMPCTL_MAXID)
                    668:                return (sysctl_int_arr(ipcompctl_vars, name, namelen,
                    669:                    oldp, oldlenp, newp, newlen));
                    670:        return (ENOPROTOOPT);
                    671: }
                    672:
                    673: #ifdef INET
                    674: /* IPv4 AH wrapper. */
                    675: void
                    676: ah4_input(struct mbuf *m, ...)
                    677: {
                    678:        int skip;
                    679:
                    680:        va_list ap;
                    681:        va_start(ap, m);
                    682:        skip = va_arg(ap, int);
                    683:        va_end(ap);
                    684:
                    685:        ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
                    686:            IPPROTO_AH, 0);
                    687:        return;
                    688: }
                    689:
                    690: /* IPv4 AH callback. */
                    691: int
                    692: ah4_input_cb(struct mbuf *m, ...)
                    693: {
                    694:        struct ifqueue *ifq = &ipintrq;
                    695:        int s = splnet();
                    696:
                    697:        /*
                    698:         * Interface pointer is already in first mbuf; chop off the
                    699:         * `outer' header and reschedule.
                    700:         */
                    701:
                    702:        if (IF_QFULL(ifq)) {
                    703:                IF_DROP(ifq);
                    704:                ahstat.ahs_qfull++;
                    705:                splx(s);
                    706:
                    707:                m_freem(m);
                    708:                DPRINTF(("ah4_input_cb(): dropped packet because of full "
                    709:                    "IP queue\n"));
                    710:                return ENOBUFS;
                    711:        }
                    712:
                    713:        IF_ENQUEUE(ifq, m);
                    714:        schednetisr(NETISR_IP);
                    715:        splx(s);
                    716:        return 0;
                    717: }
                    718:
                    719:
                    720: void *
                    721: ah4_ctlinput(int cmd, struct sockaddr *sa, void *v)
                    722: {
                    723:        if (sa->sa_family != AF_INET ||
                    724:            sa->sa_len != sizeof(struct sockaddr_in))
                    725:                return (NULL);
                    726:
                    727:        return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_AH));
                    728: }
                    729:
                    730: /* IPv4 ESP wrapper. */
                    731: void
                    732: esp4_input(struct mbuf *m, ...)
                    733: {
                    734:        int skip;
                    735:
                    736:        va_list ap;
                    737:        va_start(ap, m);
                    738:        skip = va_arg(ap, int);
                    739:        va_end(ap);
                    740:
                    741:        ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
                    742:            IPPROTO_ESP, 0);
                    743: }
                    744:
                    745: /* IPv4 ESP callback. */
                    746: int
                    747: esp4_input_cb(struct mbuf *m, ...)
                    748: {
                    749:        struct ifqueue *ifq = &ipintrq;
                    750:        int s = splnet();
                    751:
                    752:        /*
                    753:         * Interface pointer is already in first mbuf; chop off the
                    754:         * `outer' header and reschedule.
                    755:         */
                    756:        if (IF_QFULL(ifq)) {
                    757:                IF_DROP(ifq);
                    758:                espstat.esps_qfull++;
                    759:                splx(s);
                    760:
                    761:                m_freem(m);
                    762:                DPRINTF(("esp4_input_cb(): dropped packet because of full "
                    763:                    "IP queue\n"));
                    764:                return ENOBUFS;
                    765:        }
                    766:
                    767:        IF_ENQUEUE(ifq, m);
                    768:        schednetisr(NETISR_IP);
                    769:        splx(s);
                    770:        return 0;
                    771: }
                    772:
                    773: /* IPv4 IPCOMP wrapper */
                    774: void
                    775: ipcomp4_input(struct mbuf *m, ...)
                    776: {
                    777:        int skip;
                    778:        va_list ap;
                    779:        va_start(ap, m);
                    780:        skip = va_arg(ap, int);
                    781:        va_end(ap);
                    782:
                    783:        ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET,
                    784:            IPPROTO_IPCOMP, 0);
                    785: }
                    786:
                    787: /* IPv4 IPCOMP callback */
                    788: int
                    789: ipcomp4_input_cb(struct mbuf *m, ...)
                    790: {
                    791:        struct ifqueue *ifq = &ipintrq;
                    792:        int s = splnet();
                    793:
                    794:        /*
                    795:         * Interface pointer is already in first mbuf; chop off the
                    796:         * `outer' header and reschedule.
                    797:         */
                    798:        if (IF_QFULL(ifq)) {
                    799:                IF_DROP(ifq);
                    800:                ipcompstat.ipcomps_qfull++;
                    801:                splx(s);
                    802:
                    803:                m_freem(m);
                    804:                DPRINTF(("ipcomp4_input_cb(): dropped packet because of full IP queue\n"));
                    805:                return ENOBUFS;
                    806:        }
                    807:
                    808:        IF_ENQUEUE(ifq, m);
                    809:        schednetisr(NETISR_IP);
                    810:        splx(s);
                    811:
                    812:        return 0;
                    813: }
                    814:
                    815: void *
                    816: ipsec_common_ctlinput(int cmd, struct sockaddr *sa, void *v, int proto)
                    817: {
                    818:        extern u_int ip_mtudisc_timeout;
                    819:        struct ip *ip = v;
                    820:        int s;
                    821:
                    822:        if (cmd == PRC_MSGSIZE && ip && ip_mtudisc && ip->ip_v == 4) {
                    823:                struct tdb *tdbp;
                    824:                struct sockaddr_in dst;
                    825:                struct icmp *icp;
                    826:                int hlen = ip->ip_hl << 2;
                    827:                u_int32_t spi, mtu;
                    828:                ssize_t adjust;
                    829:
                    830:                /* Find the right MTU. */
                    831:                icp = (struct icmp *)((caddr_t) ip -
                    832:                    offsetof(struct icmp, icmp_ip));
                    833:                mtu = ntohs(icp->icmp_nextmtu);
                    834:
                    835:                /*
                    836:                 * Ignore the packet, if we do not receive a MTU
                    837:                 * or the MTU is too small to be acceptable.
                    838:                 */
                    839:                if (mtu < 296)
                    840:                        return (NULL);
                    841:
                    842:                bzero(&dst, sizeof(struct sockaddr_in));
                    843:                dst.sin_family = AF_INET;
                    844:                dst.sin_len = sizeof(struct sockaddr_in);
                    845:                dst.sin_addr.s_addr = ip->ip_dst.s_addr;
                    846:
                    847:                bcopy((caddr_t)ip + hlen, &spi, sizeof(u_int32_t));
                    848:
                    849:                s = spltdb();
                    850:                tdbp = gettdb(spi, (union sockaddr_union *)&dst, proto);
                    851:                if (tdbp == NULL || tdbp->tdb_flags & TDBF_INVALID) {
                    852:                        splx(s);
                    853:                        return (NULL);
                    854:                }
                    855:
                    856:                /* Walk the chain backswards to the first tdb */
                    857:                for (; tdbp; tdbp = tdbp->tdb_inext) {
                    858:                        if (tdbp->tdb_flags & TDBF_INVALID ||
                    859:                            (adjust = ipsec_hdrsz(tdbp)) == -1) {
                    860:                                splx(s);
                    861:                                return (NULL);
                    862:                        }
                    863:
                    864:                        mtu -= adjust;
                    865:
                    866:                        /* Store adjusted MTU in tdb */
                    867:                        tdbp->tdb_mtu = mtu;
                    868:                        tdbp->tdb_mtutimeout = time_second +
                    869:                            ip_mtudisc_timeout;
                    870:                        DPRINTF(("ipsec_common_ctlinput: "
                    871:                            "spi %08x mtu %d adjust %d\n",
                    872:                            ntohl(tdbp->tdb_spi), tdbp->tdb_mtu,
                    873:                            adjust));
                    874:                }
                    875:                splx(s);
                    876:                return (NULL);
                    877:        }
                    878:        return (NULL);
                    879: }
                    880:
                    881: void *
                    882: udpencap_ctlinput(int cmd, struct sockaddr *sa, void *v)
                    883: {
                    884:        struct ip *ip = v;
                    885:        struct tdb *tdbp;
                    886:        struct icmp *icp;
                    887:        u_int32_t mtu;
                    888:        ssize_t adjust;
                    889:        struct sockaddr_in dst, src;
                    890:        union sockaddr_union *su_dst, *su_src;
                    891:        int s;
                    892:
                    893:        icp = (struct icmp *)((caddr_t) ip - offsetof(struct icmp, icmp_ip));
                    894:        mtu = ntohs(icp->icmp_nextmtu);
                    895:
                    896:        /*
                    897:         * Ignore the packet, if we do not receive a MTU
                    898:         * or the MTU is too small to be acceptable.
                    899:         */
                    900:        if (mtu < 296)
                    901:                return (NULL);
                    902:
                    903:        bzero(&dst, sizeof(dst));
                    904:        dst.sin_family = AF_INET;
                    905:        dst.sin_len = sizeof(struct sockaddr_in);
                    906:        dst.sin_addr.s_addr = ip->ip_dst.s_addr;
                    907:        su_dst = (union sockaddr_union *)&dst;
                    908:        bzero(&src, sizeof(src));
                    909:        src.sin_family = AF_INET;
                    910:        src.sin_len = sizeof(struct sockaddr_in);
                    911:        src.sin_addr.s_addr = ip->ip_src.s_addr;
                    912:        su_src = (union sockaddr_union *)&src;
                    913:
                    914:        s = spltdb();
                    915:        tdbp = gettdbbysrcdst(0, su_src, su_dst, IPPROTO_ESP);
                    916:
                    917:        for (; tdbp != NULL; tdbp = tdbp->tdb_snext) {
                    918:                if (tdbp->tdb_sproto == IPPROTO_ESP &&
                    919:                    ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_UDPENCAP))
                    920:                    == TDBF_UDPENCAP) &&
                    921:                    !bcmp(&tdbp->tdb_dst, &dst, SA_LEN(&su_dst->sa)) &&
                    922:                    !bcmp(&tdbp->tdb_src, &src, SA_LEN(&su_src->sa))) {
                    923:                        if ((adjust = ipsec_hdrsz(tdbp)) != -1) {
                    924:                                /* Store adjusted MTU in tdb */
                    925:                                tdbp->tdb_mtu = mtu - adjust;
                    926:                                tdbp->tdb_mtutimeout = time_second +
                    927:                                    ip_mtudisc_timeout;
                    928:                                DPRINTF(("udpencap_ctlinput: "
                    929:                                    "spi %08x mtu %d adjust %d\n",
                    930:                                    ntohl(tdbp->tdb_spi), tdbp->tdb_mtu,
                    931:                                    adjust));
                    932:                        }
                    933:                }
                    934:        }
                    935:        splx(s);
                    936:        return (NULL);
                    937: }
                    938:
                    939: void *
                    940: esp4_ctlinput(int cmd, struct sockaddr *sa, void *v)
                    941: {
                    942:        if (sa->sa_family != AF_INET ||
                    943:            sa->sa_len != sizeof(struct sockaddr_in))
                    944:                return (NULL);
                    945:
                    946:        return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_ESP));
                    947: }
                    948: #endif /* INET */
                    949:
                    950: #ifdef INET6
                    951: /* IPv6 AH wrapper. */
                    952: int
                    953: ah6_input(struct mbuf **mp, int *offp, int proto)
                    954: {
                    955:        int l = 0;
                    956:        int protoff, nxt;
                    957:        struct ip6_ext ip6e;
                    958:
                    959:        if (*offp < sizeof(struct ip6_hdr)) {
                    960:                DPRINTF(("ah6_input(): bad offset\n"));
                    961:                return IPPROTO_DONE;
                    962:        } else if (*offp == sizeof(struct ip6_hdr)) {
                    963:                protoff = offsetof(struct ip6_hdr, ip6_nxt);
                    964:        } else {
                    965:                /* Chase down the header chain... */
                    966:                protoff = sizeof(struct ip6_hdr);
                    967:                nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt;
                    968:
                    969:                do {
                    970:                        protoff += l;
                    971:                        m_copydata(*mp, protoff, sizeof(ip6e),
                    972:                            (caddr_t) &ip6e);
                    973:
                    974:                        if (nxt == IPPROTO_AH)
                    975:                                l = (ip6e.ip6e_len + 2) << 2;
                    976:                        else
                    977:                                l = (ip6e.ip6e_len + 1) << 3;
                    978: #ifdef DIAGNOSTIC
                    979:                        if (l <= 0)
                    980:                                panic("ah6_input: l went zero or negative");
                    981: #endif
                    982:
                    983:                        nxt = ip6e.ip6e_nxt;
                    984:                } while (protoff + l < *offp);
                    985:
                    986:                /* Malformed packet check */
                    987:                if (protoff + l != *offp) {
                    988:                        DPRINTF(("ah6_input(): bad packet header chain\n"));
                    989:                        ahstat.ahs_hdrops++;
                    990:                        m_freem(*mp);
                    991:                        *mp = NULL;
                    992:                        return IPPROTO_DONE;
                    993:                }
                    994:                protoff += offsetof(struct ip6_ext, ip6e_nxt);
                    995:        }
                    996:        ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
                    997:        return IPPROTO_DONE;
                    998: }
                    999:
                   1000: /* IPv6 AH callback. */
                   1001: int
                   1002: ah6_input_cb(struct mbuf *m, int off, int protoff)
                   1003: {
                   1004:        int nxt;
                   1005:        u_int8_t nxt8;
                   1006:        int nest = 0;
                   1007:
                   1008:        /* Retrieve new protocol */
                   1009:        m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
                   1010:        nxt = nxt8;
                   1011:
                   1012:        /*
                   1013:         * see the end of ip6_input for this logic.
                   1014:         * IPPROTO_IPV[46] case will be processed just like other ones
                   1015:         */
                   1016:        while (nxt != IPPROTO_DONE) {
                   1017:                if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
                   1018:                        ip6stat.ip6s_toomanyhdr++;
                   1019:                        goto bad;
                   1020:                }
                   1021:
                   1022:                /*
                   1023:                 * Protection against faulty packet - there should be
                   1024:                 * more sanity checks in header chain processing.
                   1025:                 */
                   1026:                if (m->m_pkthdr.len < off) {
                   1027:                        ip6stat.ip6s_tooshort++;
                   1028:                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
                   1029:                        goto bad;
                   1030:                }
                   1031:                nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
                   1032:        }
                   1033:        return 0;
                   1034:
                   1035:  bad:
                   1036:        m_freem(m);
                   1037:        return EINVAL;
                   1038: }
                   1039:
                   1040: /* IPv6 ESP wrapper. */
                   1041: int
                   1042: esp6_input(struct mbuf **mp, int *offp, int proto)
                   1043: {
                   1044:        int l = 0;
                   1045:        int protoff, nxt;
                   1046:        struct ip6_ext ip6e;
                   1047:
                   1048:        if (*offp < sizeof(struct ip6_hdr)) {
                   1049:                DPRINTF(("esp6_input(): bad offset\n"));
                   1050:                return IPPROTO_DONE;
                   1051:        } else if (*offp == sizeof(struct ip6_hdr)) {
                   1052:                protoff = offsetof(struct ip6_hdr, ip6_nxt);
                   1053:        } else {
                   1054:                /* Chase down the header chain... */
                   1055:                protoff = sizeof(struct ip6_hdr);
                   1056:                nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt;
                   1057:
                   1058:                do {
                   1059:                        protoff += l;
                   1060:                        m_copydata(*mp, protoff, sizeof(ip6e),
                   1061:                            (caddr_t) &ip6e);
                   1062:
                   1063:                        if (nxt == IPPROTO_AH)
                   1064:                                l = (ip6e.ip6e_len + 2) << 2;
                   1065:                        else
                   1066:                                l = (ip6e.ip6e_len + 1) << 3;
                   1067: #ifdef DIAGNOSTIC
                   1068:                        if (l <= 0)
                   1069:                                panic("esp6_input: l went zero or negative");
                   1070: #endif
                   1071:
                   1072:                        nxt = ip6e.ip6e_nxt;
                   1073:                } while (protoff + l < *offp);
                   1074:
                   1075:                /* Malformed packet check */
                   1076:                if (protoff + l != *offp) {
                   1077:                        DPRINTF(("esp6_input(): bad packet header chain\n"));
                   1078:                        espstat.esps_hdrops++;
                   1079:                        m_freem(*mp);
                   1080:                        *mp = NULL;
                   1081:                        return IPPROTO_DONE;
                   1082:                }
                   1083:                protoff += offsetof(struct ip6_ext, ip6e_nxt);
                   1084:        }
                   1085:        ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
                   1086:        return IPPROTO_DONE;
                   1087:
                   1088: }
                   1089:
                   1090: /* IPv6 ESP callback */
                   1091: int
                   1092: esp6_input_cb(struct mbuf *m, int skip, int protoff)
                   1093: {
                   1094:        return ah6_input_cb(m, skip, protoff);
                   1095: }
                   1096:
                   1097: /* IPv6 IPcomp wrapper */
                   1098: int
                   1099: ipcomp6_input(struct mbuf **mp, int *offp, int proto)
                   1100: {
                   1101:        int l = 0;
                   1102:        int protoff, nxt;
                   1103:        struct ip6_ext ip6e;
                   1104:
                   1105:        if (*offp < sizeof(struct ip6_hdr)) {
                   1106:                DPRINTF(("ipcomp6_input(): bad offset\n"));
                   1107:                return IPPROTO_DONE;
                   1108:        } else if (*offp == sizeof(struct ip6_hdr)) {
                   1109:                protoff = offsetof(struct ip6_hdr, ip6_nxt);
                   1110:        } else {
                   1111:                /* Chase down the header chain... */
                   1112:                protoff = sizeof(struct ip6_hdr);
                   1113:                nxt = (mtod(*mp, struct ip6_hdr *))->ip6_nxt;
                   1114:
                   1115:                do {
                   1116:                        protoff += l;
                   1117:                        m_copydata(*mp, protoff, sizeof(ip6e),
                   1118:                            (caddr_t) &ip6e);
                   1119:                        if (nxt == IPPROTO_AH)
                   1120:                                l = (ip6e.ip6e_len + 2) << 2;
                   1121:                        else
                   1122:                                l = (ip6e.ip6e_len + 1) << 3;
                   1123: #ifdef DIAGNOSTIC
                   1124:                        if (l <= 0)
                   1125:                                panic("ipcomp6_input: l went zero or negative");
                   1126: #endif
                   1127:
                   1128:                        nxt = ip6e.ip6e_nxt;
                   1129:                } while (protoff + l < *offp);
                   1130:
                   1131:                /* Malformed packet check */
                   1132:                if (protoff + l != *offp) {
                   1133:                        DPRINTF(("ipcomp6_input(): bad packet header chain\n"));
                   1134:                        ipcompstat.ipcomps_hdrops++;
                   1135:                        m_freem(*mp);
                   1136:                        *mp = NULL;
                   1137:                        return IPPROTO_DONE;
                   1138:                }
                   1139:
                   1140:                protoff += offsetof(struct ip6_ext, ip6e_nxt);
                   1141:        }
                   1142:        ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto, 0);
                   1143:        return IPPROTO_DONE;
                   1144: }
                   1145:
                   1146: /* IPv6 IPcomp callback */
                   1147: int
                   1148: ipcomp6_input_cb(struct mbuf *m, int skip, int protoff)
                   1149: {
                   1150:        return ah6_input_cb(m, skip, protoff);
                   1151: }
                   1152:
                   1153: #endif /* INET6 */

CVSweb