[BACK]Return to ip6_forward.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Annotation of src/sys/netinet6/ip6_forward.c, Revision 1.12.2.7

1.12.2.7! he          1: /*     $NetBSD: ip6_forward.c,v 1.12.2.6 2001/10/25 13:22:12 jhawk Exp $       */
1.12.2.4  itojun      2: /*     $KAME: ip6_forward.c,v 1.56 2000/09/22 04:01:37 itojun Exp $    */
1.3       thorpej     3:
1.2       itojun      4: /*
                      5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      6:  * All rights reserved.
1.10      itojun      7:  *
1.2       itojun      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the project nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
1.10      itojun     19:  *
1.2       itojun     20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
1.12.2.2  itojun     33: #include "opt_ipsec.h"
                     34:
1.2       itojun     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/malloc.h>
                     38: #include <sys/mbuf.h>
                     39: #include <sys/domain.h>
                     40: #include <sys/protosw.h>
                     41: #include <sys/socket.h>
                     42: #include <sys/errno.h>
                     43: #include <sys/time.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/syslog.h>
                     46:
                     47: #include <net/if.h>
                     48: #include <net/route.h>
1.12.2.7! he         49: #ifdef PFIL_HOOKS
        !            50: #include <net/pfil.h>
        !            51: #endif
1.2       itojun     52:
                     53: #include <netinet/in.h>
                     54: #include <netinet/in_var.h>
1.7       itojun     55: #include <netinet/ip_var.h>
1.8       itojun     56: #include <netinet/ip6.h>
1.2       itojun     57: #include <netinet6/ip6_var.h>
1.8       itojun     58: #include <netinet/icmp6.h>
1.5       itojun     59: #include <netinet6/nd6.h>
                     60:
1.12.2.2  itojun     61: #ifdef IPSEC
1.5       itojun     62: #include <netinet6/ipsec.h>
                     63: #include <netkey/key.h>
1.12.2.2  itojun     64: #endif /* IPSEC */
1.5       itojun     65:
                     66: #ifdef IPV6FIREWALL
                     67: #include <netinet6/ip6_fw.h>
                     68: #endif
                     69:
                     70: #include <net/net_osdep.h>
1.2       itojun     71:
                     72: struct route_in6 ip6_forward_rt;
                     73:
                     74: /*
                     75:  * Forward a packet.  If some error occurs return the sender
                     76:  * an icmp packet.  Note we can't always generate a meaningful
                     77:  * icmp message because icmp doesn't have a large enough repertoire
                     78:  * of codes and types.
                     79:  *
                     80:  * If not forwarding, just drop the packet.  This could be confusing
                     81:  * if ipforwarding was zero but some routing protocol was advancing
                     82:  * us as a gateway to somewhere.  However, we must let the routing
                     83:  * protocol deal with that.
                     84:  *
                     85:  */
                     86:
                     87: void
                     88: ip6_forward(m, srcrt)
                     89:        struct mbuf *m;
                     90:        int srcrt;
                     91: {
1.5       itojun     92:        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1.2       itojun     93:        register struct sockaddr_in6 *dst;
                     94:        register struct rtentry *rt;
                     95:        int error, type = 0, code = 0;
1.5       itojun     96:        struct mbuf *mcopy = NULL;
1.10      itojun     97:        struct ifnet *origifp;  /* maybe unnecessary */
1.12.2.7! he         98: #ifdef PFIL_HOOKS
        !            99:        struct packet_filter_hook *pfh;
        !           100:        struct mbuf *m1;
        !           101:        int rv;
        !           102: #endif /* PFIL_HOOKS */
1.12.2.2  itojun    103: #ifdef IPSEC
1.5       itojun    104:        struct secpolicy *sp = NULL;
                    105: #endif
                    106:        long time_second = time.tv_sec;
                    107:
1.12.2.2  itojun    108: #ifdef IPSEC
1.5       itojun    109:        /*
                    110:         * Check AH/ESP integrity.
                    111:         */
                    112:        /*
                    113:         * Don't increment ip6s_cantforward because this is the check
                    114:         * before forwarding packet actually.
                    115:         */
                    116:        if (ipsec6_in_reject(m, NULL)) {
                    117:                ipsec6stat.in_polvio++;
                    118:                m_freem(m);
                    119:                return;
                    120:        }
1.12.2.2  itojun    121: #endif /*IPSEC*/
1.2       itojun    122:
1.12.2.3  itojun    123:        /*
                    124:         * Do not forward packets to multicast destination (should be handled
                    125:         * by ip6_mforward().
                    126:         * Do not forward packets with unspecified source.  It was discussed
                    127:         * in July 2000, on ipngwg mailing list.
                    128:         */
1.9       itojun    129:        if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
1.12.2.3  itojun    130:            IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
                    131:            IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
1.2       itojun    132:                ip6stat.ip6s_cantforward++;
1.5       itojun    133:                /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
1.2       itojun    134:                if (ip6_log_time + ip6_log_interval < time_second) {
                    135:                        ip6_log_time = time_second;
                    136:                        log(LOG_DEBUG,
                    137:                            "cannot forward "
                    138:                            "from %s to %s nxt %d received on %s\n",
1.9       itojun    139:                            ip6_sprintf(&ip6->ip6_src),
                    140:                            ip6_sprintf(&ip6->ip6_dst),
1.2       itojun    141:                            ip6->ip6_nxt,
1.5       itojun    142:                            if_name(m->m_pkthdr.rcvif));
1.2       itojun    143:                }
                    144:                m_freem(m);
                    145:                return;
                    146:        }
                    147:
                    148:        if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
1.5       itojun    149:                /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
1.2       itojun    150:                icmp6_error(m, ICMP6_TIME_EXCEEDED,
                    151:                                ICMP6_TIME_EXCEED_TRANSIT, 0);
                    152:                return;
                    153:        }
                    154:        ip6->ip6_hlim -= IPV6_HLIMDEC;
                    155:
1.5       itojun    156:        /*
                    157:         * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -
                    158:         * size of IPv6 + ICMPv6 headers) bytes of the packet in case
                    159:         * we need to generate an ICMP6 message to the src.
                    160:         * Thanks to M_EXT, in most cases copy will not occur.
                    161:         *
                    162:         * It is important to save it before IPsec processing as IPsec
                    163:         * processing may modify the mbuf.
                    164:         */
                    165:        mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
                    166:
1.12.2.2  itojun    167: #ifdef IPSEC
1.5       itojun    168:        /* get a security policy for this packet */
1.12.2.4  itojun    169:        sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING,
                    170:            &error);
1.5       itojun    171:        if (sp == NULL) {
                    172:                ipsec6stat.out_inval++;
                    173:                ip6stat.ip6s_cantforward++;
                    174:                if (mcopy) {
                    175: #if 0
                    176:                        /* XXX: what icmp ? */
                    177: #else
                    178:                        m_freem(mcopy);
                    179: #endif
                    180:                }
                    181:                m_freem(m);
                    182:                return;
                    183:        }
                    184:
                    185:        error = 0;
                    186:
                    187:        /* check policy */
                    188:        switch (sp->policy) {
                    189:        case IPSEC_POLICY_DISCARD:
                    190:                /*
                    191:                 * This packet is just discarded.
                    192:                 */
                    193:                ipsec6stat.out_polvio++;
                    194:                ip6stat.ip6s_cantforward++;
                    195:                key_freesp(sp);
                    196:                if (mcopy) {
                    197: #if 0
                    198:                        /* XXX: what icmp ? */
                    199: #else
                    200:                        m_freem(mcopy);
                    201: #endif
                    202:                }
                    203:                m_freem(m);
                    204:                return;
                    205:
                    206:        case IPSEC_POLICY_BYPASS:
                    207:        case IPSEC_POLICY_NONE:
                    208:                /* no need to do IPsec. */
                    209:                key_freesp(sp);
                    210:                goto skip_ipsec;
1.12.2.1  itojun    211:
1.5       itojun    212:        case IPSEC_POLICY_IPSEC:
                    213:                if (sp->req == NULL) {
                    214:                        /* XXX should be panic ? */
                    215:                        printf("ip6_forward: No IPsec request specified.\n");
                    216:                        ip6stat.ip6s_cantforward++;
                    217:                        key_freesp(sp);
                    218:                        if (mcopy) {
                    219: #if 0
                    220:                                /* XXX: what icmp ? */
                    221: #else
                    222:                                m_freem(mcopy);
                    223: #endif
                    224:                        }
                    225:                        m_freem(m);
                    226:                        return;
                    227:                }
                    228:                /* do IPsec */
                    229:                break;
                    230:
                    231:        case IPSEC_POLICY_ENTRUST:
                    232:        default:
                    233:                /* should be panic ?? */
                    234:                printf("ip6_forward: Invalid policy found. %d\n", sp->policy);
                    235:                key_freesp(sp);
                    236:                goto skip_ipsec;
                    237:        }
                    238:
                    239:     {
                    240:        struct ipsec_output_state state;
                    241:
                    242:        /*
                    243:         * All the extension headers will become inaccessible
                    244:         * (since they can be encrypted).
                    245:         * Don't panic, we need no more updates to extension headers
                    246:         * on inner IPv6 packet (since they are now encapsulated).
                    247:         *
                    248:         * IPv6 [ESP|AH] IPv6 [extension headers] payload
                    249:         */
                    250:        bzero(&state, sizeof(state));
                    251:        state.m = m;
                    252:        state.ro = NULL;        /* update at ipsec6_output_tunnel() */
                    253:        state.dst = NULL;       /* update at ipsec6_output_tunnel() */
                    254:
                    255:        error = ipsec6_output_tunnel(&state, sp, 0);
                    256:
                    257:        m = state.m;
                    258: #if 0  /* XXX allocate a route (ro, dst) again later */
                    259:        ro = (struct route_in6 *)state.ro;
                    260:        dst = (struct sockaddr_in6 *)state.dst;
                    261: #endif
                    262:        key_freesp(sp);
                    263:
                    264:        if (error) {
                    265:                /* mbuf is already reclaimed in ipsec6_output_tunnel. */
                    266:                switch (error) {
                    267:                case EHOSTUNREACH:
                    268:                case ENETUNREACH:
                    269:                case EMSGSIZE:
                    270:                case ENOBUFS:
                    271:                case ENOMEM:
                    272:                        break;
                    273:                default:
                    274:                        printf("ip6_output (ipsec): error code %d\n", error);
                    275:                        /*fall through*/
                    276:                case ENOENT:
                    277:                        /* don't show these error codes to the user */
                    278:                        break;
                    279:                }
                    280:                ip6stat.ip6s_cantforward++;
                    281:                if (mcopy) {
                    282: #if 0
                    283:                        /* XXX: what icmp ? */
                    284: #else
                    285:                        m_freem(mcopy);
                    286: #endif
                    287:                }
                    288:                m_freem(m);
                    289:                return;
                    290:        }
                    291:     }
                    292:     skip_ipsec:
1.12.2.2  itojun    293: #endif /* IPSEC */
1.5       itojun    294:
1.2       itojun    295:        dst = &ip6_forward_rt.ro_dst;
                    296:        if (!srcrt) {
                    297:                /*
                    298:                 * ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst
                    299:                 */
                    300:                if (ip6_forward_rt.ro_rt == 0 ||
                    301:                    (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0) {
                    302:                        if (ip6_forward_rt.ro_rt) {
                    303:                                RTFREE(ip6_forward_rt.ro_rt);
                    304:                                ip6_forward_rt.ro_rt = 0;
                    305:                        }
                    306:                        /* this probably fails but give it a try again */
1.5       itojun    307:                        rtalloc((struct route *)&ip6_forward_rt);
1.2       itojun    308:                }
1.12.2.1  itojun    309:
1.2       itojun    310:                if (ip6_forward_rt.ro_rt == 0) {
                    311:                        ip6stat.ip6s_noroute++;
1.5       itojun    312:                        /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
                    313:                        if (mcopy) {
                    314:                                icmp6_error(mcopy, ICMP6_DST_UNREACH,
                    315:                                            ICMP6_DST_UNREACH_NOROUTE, 0);
                    316:                        }
                    317:                        m_freem(m);
1.2       itojun    318:                        return;
                    319:                }
                    320:        } else if ((rt = ip6_forward_rt.ro_rt) == 0 ||
                    321:                 !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr)) {
                    322:                if (ip6_forward_rt.ro_rt) {
                    323:                        RTFREE(ip6_forward_rt.ro_rt);
                    324:                        ip6_forward_rt.ro_rt = 0;
                    325:                }
                    326:                bzero(dst, sizeof(*dst));
                    327:                dst->sin6_len = sizeof(struct sockaddr_in6);
                    328:                dst->sin6_family = AF_INET6;
                    329:                dst->sin6_addr = ip6->ip6_dst;
                    330:
                    331:                rtalloc((struct route *)&ip6_forward_rt);
                    332:                if (ip6_forward_rt.ro_rt == 0) {
                    333:                        ip6stat.ip6s_noroute++;
1.5       itojun    334:                        /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
                    335:                        if (mcopy) {
                    336:                                icmp6_error(mcopy, ICMP6_DST_UNREACH,
                    337:                                            ICMP6_DST_UNREACH_NOROUTE, 0);
                    338:                        }
                    339:                        m_freem(m);
1.2       itojun    340:                        return;
                    341:                }
                    342:        }
                    343:        rt = ip6_forward_rt.ro_rt;
1.9       itojun    344:
                    345:        /*
                    346:         * Scope check: if a packet can't be delivered to its destination
                    347:         * for the reason that the destination is beyond the scope of the
                    348:         * source address, discard the packet and return an icmp6 destination
                    349:         * unreachable error with Code 2 (beyond scope of source address).
                    350:         * [draft-ietf-ipngwg-icmp-v3-00.txt, Section 3.1]
                    351:         */
                    352:        if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) !=
                    353:            in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)) {
                    354:                ip6stat.ip6s_cantforward++;
                    355:                ip6stat.ip6s_badscope++;
                    356:                in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
                    357:
                    358:                if (ip6_log_time + ip6_log_interval < time_second) {
                    359:                        ip6_log_time = time_second;
                    360:                        log(LOG_DEBUG,
                    361:                            "cannot forward "
                    362:                            "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
                    363:                            ip6_sprintf(&ip6->ip6_src),
                    364:                            ip6_sprintf(&ip6->ip6_dst),
                    365:                            ip6->ip6_nxt,
                    366:                            if_name(m->m_pkthdr.rcvif), if_name(rt->rt_ifp));
                    367:                }
                    368:                if (mcopy)
                    369:                        icmp6_error(mcopy, ICMP6_DST_UNREACH,
                    370:                                    ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
                    371:                m_freem(m);
                    372:                return;
                    373:        }
                    374:
1.5       itojun    375:        if (m->m_pkthdr.len > rt->rt_ifp->if_mtu) {
                    376:                in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
                    377:                if (mcopy) {
                    378:                        u_long mtu;
1.12.2.2  itojun    379: #ifdef IPSEC
1.7       itojun    380:                        struct secpolicy *sp;
                    381:                        int ipsecerror;
                    382:                        size_t ipsechdrsiz;
                    383: #endif
1.5       itojun    384:
                    385:                        mtu = rt->rt_ifp->if_mtu;
1.12.2.2  itojun    386: #ifdef IPSEC
1.7       itojun    387:                        /*
                    388:                         * When we do IPsec tunnel ingress, we need to play
                    389:                         * with if_mtu value (decrement IPsec header size
                    390:                         * from mtu value).  The code is much simpler than v4
                    391:                         * case, as we have the outgoing interface for
                    392:                         * encapsulated packet as "rt->rt_ifp".
                    393:                         */
                    394:                        sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
                    395:                                IP_FORWARDING, &ipsecerror);
                    396:                        if (sp) {
                    397:                                ipsechdrsiz = ipsec6_hdrsiz(mcopy,
                    398:                                        IPSEC_DIR_OUTBOUND, NULL);
                    399:                                if (ipsechdrsiz < mtu)
                    400:                                        mtu -= ipsechdrsiz;
                    401:                        }
                    402:
                    403:                        /*
1.10      itojun    404:                         * if mtu becomes less than minimum MTU,
1.7       itojun    405:                         * tell minimum MTU (and I'll need to fragment it).
                    406:                         */
                    407:                        if (mtu < IPV6_MMTU)
                    408:                                mtu = IPV6_MMTU;
                    409: #endif
1.5       itojun    410:                        icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
                    411:                }
                    412:                m_freem(m);
1.2       itojun    413:                return;
                    414:        }
                    415:
                    416:        if (rt->rt_flags & RTF_GATEWAY)
                    417:                dst = (struct sockaddr_in6 *)rt->rt_gateway;
                    418:
                    419:        /*
                    420:         * If we are to forward the packet using the same interface
                    421:         * as one we got the packet from, perhaps we should send a redirect
                    422:         * to sender to shortcut a hop.
                    423:         * Only send redirect if source is sending directly to us,
                    424:         * and if packet was not source routed (or has any options).
                    425:         * Also, don't send redirect if forwarding using a route
                    426:         * modified by a redirect.
                    427:         */
                    428:        if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
                    429:            (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0)
                    430:                type = ND_REDIRECT;
                    431:
1.5       itojun    432: #ifdef IPV6FIREWALL
                    433:        /*
                    434:         * Check with the firewall...
                    435:         */
                    436:        if (ip6_fw_chk_ptr) {
                    437:                u_short port = 0;
                    438:                /* If ipfw says divert, we have to just drop packet */
                    439:                if ((*ip6_fw_chk_ptr)(&ip6, rt->rt_ifp, &port, &m)) {
                    440:                        m_freem(m);
                    441:                        goto freecopy;
                    442:                }
                    443:                if (!m)
                    444:                        goto freecopy;
                    445:        }
                    446: #endif
                    447:
1.10      itojun    448:        /*
                    449:         * Fake scoped addresses. Note that even link-local source or
                    450:         * destinaion can appear, if the originating node just sends the
                    451:         * packet to us (without address resolution for the destination).
                    452:         * Since both icmp6_error and icmp6_redirect_output fill the embedded
                    453:         * link identifiers, we can do this stuff after make a copy for
                    454:         * returning error.
                    455:         */
                    456:        if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
                    457:                /*
                    458:                 * See corresponding comments in ip6_output.
                    459:                 * XXX: but is it possible that ip6_forward() sends a packet
                    460:                 *      to a loopback interface? I don't think so, and thus
                    461:                 *      I bark here. (jinmei@kame.net)
1.12      itojun    462:                 * XXX: it is common to route invalid packets to loopback.
1.12.2.1  itojun    463:                 *      also, the codepath will be visited on use of ::1 in
                    464:                 *      rthdr. (itojun)
1.10      itojun    465:                 */
1.12.2.1  itojun    466: #if 1
                    467:                if (0)
                    468: #else
                    469:                if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
                    470: #endif
                    471:                {
1.12      itojun    472:                        printf("ip6_forward: outgoing interface is loopback. "
                    473:                               "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
                    474:                               ip6_sprintf(&ip6->ip6_src),
                    475:                               ip6_sprintf(&ip6->ip6_dst),
                    476:                               ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
                    477:                               if_name(rt->rt_ifp));
                    478:                }
1.12.2.1  itojun    479:
1.10      itojun    480:                if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
                    481:                        origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])];
                    482:                else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
                    483:                        origifp = ifindex2ifnet[ntohs(ip6->ip6_dst.s6_addr16[1])];
                    484:                else
                    485:                        origifp = rt->rt_ifp;
                    486:        }
                    487:        else
                    488:                origifp = rt->rt_ifp;
                    489: #ifndef FAKE_LOOPBACK_IF
1.11      itojun    490:        if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
1.10      itojun    491: #else
                    492:        if (1)
                    493: #endif
                    494:        {
                    495:                if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
                    496:                        ip6->ip6_src.s6_addr16[1] = 0;
                    497:                if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
                    498:                        ip6->ip6_dst.s6_addr16[1] = 0;
                    499:        }
                    500:
1.12.2.7! he        501: #ifdef PFIL_HOOKS
        !           502:        /*
        !           503:         * Run through list of hooks for output packets.
        !           504:         */
        !           505:        m1 = m;
        !           506:        pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
        !           507:        for (; pfh; pfh = pfh->pfil_link.tqe_next)
        !           508:                if (pfh->pfil_func) {
        !           509:                        rv = pfh->pfil_func(ip6, sizeof(*ip6),
        !           510:                                            rt->rt_ifp, 1, &m1);
        !           511:                        m = m1;
        !           512:                        if (m == NULL)
        !           513:                                goto freecopy;
        !           514:                        if (rv) {
        !           515:                                error = EHOSTUNREACH;
        !           516:                                goto senderr;
        !           517:                        }
        !           518:                        ip6 = mtod(m, struct ip6_hdr *);
        !           519:                }
        !           520: #endif /* PFIL_HOOKS */
        !           521:
1.5       itojun    522: #ifdef OLDIP6OUTPUT
1.2       itojun    523:        error = (*rt->rt_ifp->if_output)(rt->rt_ifp, m,
                    524:                                         (struct sockaddr *)dst,
                    525:                                         ip6_forward_rt.ro_rt);
1.5       itojun    526: #else
1.10      itojun    527:        error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
                    528: #endif
1.5       itojun    529:        if (error) {
                    530:                in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
1.2       itojun    531:                ip6stat.ip6s_cantforward++;
1.5       itojun    532:        } else {
1.2       itojun    533:                ip6stat.ip6s_forward++;
1.5       itojun    534:                in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward);
1.2       itojun    535:                if (type)
                    536:                        ip6stat.ip6s_redirectsent++;
                    537:                else {
                    538:                        if (mcopy)
                    539:                                goto freecopy;
                    540:                }
                    541:        }
1.12.2.7! he        542:
        !           543: #ifdef PFIL_HOOKS
        !           544:  senderr:
        !           545: #endif
1.2       itojun    546:        if (mcopy == NULL)
                    547:                return;
                    548:
                    549:        switch (error) {
                    550:        case 0:
                    551: #if 1
                    552:                if (type == ND_REDIRECT) {
                    553:                        icmp6_redirect_output(mcopy, rt);
                    554:                        return;
                    555:                }
                    556: #endif
                    557:                goto freecopy;
                    558:
                    559:        case EMSGSIZE:
                    560:                /* xxx MTU is constant in PPP? */
                    561:                goto freecopy;
                    562:
                    563:        case ENOBUFS:
                    564:                /* Tell source to slow down like source quench in IP? */
                    565:                goto freecopy;
                    566:
                    567:        case ENETUNREACH:       /* shouldn't happen, checked above */
                    568:        case EHOSTUNREACH:
                    569:        case ENETDOWN:
                    570:        case EHOSTDOWN:
                    571:        default:
                    572:                type = ICMP6_DST_UNREACH;
                    573:                code = ICMP6_DST_UNREACH_ADDR;
                    574:                break;
                    575:        }
                    576:        icmp6_error(mcopy, type, code, 0);
                    577:        return;
                    578:
                    579:  freecopy:
                    580:        m_freem(mcopy);
1.5       itojun    581:        return;
1.2       itojun    582: }

CVSweb <webmaster@jp.NetBSD.org>