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

Annotation of src/sys/netinet6/in6_gif.c, Revision 1.95

1.95    ! knakahar    1: /*     $NetBSD: in6_gif.c,v 1.94 2019/09/19 06:07:25 knakahara Exp $   */
1.21      itojun      2: /*     $KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 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.14      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.14      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:  */
1.23      lukem      32:
                     33: #include <sys/cdefs.h>
1.95    ! knakahar   34: __KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.94 2019/09/19 06:07:25 knakahara Exp $");
1.2       itojun     35:
1.62      pooka      36: #ifdef _KERNEL_OPT
1.2       itojun     37: #include "opt_inet.h"
1.62      pooka      38: #endif
1.2       itojun     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/socket.h>
                     43: #include <sys/sockio.h>
                     44: #include <sys/mbuf.h>
                     45: #include <sys/errno.h>
                     46: #include <sys/ioctl.h>
1.15      itojun     47: #include <sys/queue.h>
                     48: #include <sys/syslog.h>
1.43      mlelstv    49: #include <sys/kernel.h>
1.14      itojun     50:
1.2       itojun     51: #include <net/if.h>
                     52: #include <net/route.h>
                     53:
                     54: #include <netinet/in.h>
                     55: #include <netinet/in_systm.h>
                     56: #ifdef INET
                     57: #include <netinet/ip.h>
                     58: #endif
1.14      itojun     59: #include <netinet/ip_encap.h>
1.11      itojun     60: #ifdef INET6
                     61: #include <netinet/ip6.h>
1.2       itojun     62: #include <netinet6/ip6_var.h>
1.55      thorpej    63: #include <netinet6/ip6_private.h>
1.2       itojun     64: #include <netinet6/in6_gif.h>
1.14      itojun     65: #include <netinet6/in6_var.h>
1.68      riastrad   66: #endif
1.71      knakahar   67: #include <netinet6/ip6protosw.h> /* for struct ip6ctlparam */
1.2       itojun     68: #include <netinet/ip_ecn.h>
                     69:
                     70: #include <net/if_gif.h>
                     71:
1.88      knakahar   72: static int gif_validate6(const struct ip6_hdr *, struct gif_variant *,
1.58      dsl        73:        struct ifnet *);
1.26      itojun     74:
                     75: int    ip6_gif_hlim = GIF_HLIM;
1.95    ! knakahar   76: int    ip6_gif_pmtu = 0;
1.21      itojun     77:
1.71      knakahar   78: static const struct encapsw in6_gif_encapsw;
1.27      itojun     79:
1.52      christos   80: /*
                     81:  * family - family of the packet to be encapsulate.
                     82:  */
                     83:
1.88      knakahar   84: static int
                     85: in6_gif_output(struct gif_variant *var, int family, struct mbuf *m)
1.2       itojun     86: {
1.53      dyoung     87:        struct rtentry *rt;
1.88      knakahar   88:        struct gif_softc *sc;
                     89:        struct sockaddr_in6 *sin6_src;
                     90:        struct sockaddr_in6 *sin6_dst;
                     91:        struct ifnet *ifp;
1.2       itojun     92:        struct ip6_hdr *ip6;
1.94      knakahar   93:        struct route *ro_pc;
                     94:        kmutex_t *lock_pc;
1.24      itojun     95:        int proto, error;
1.2       itojun     96:        u_int8_t itos, otos;
                     97:
1.88      knakahar   98:        KASSERT(gif_heldref_variant(var));
                     99:
                    100:        sin6_src = satosin6(var->gv_psrc);
                    101:        sin6_dst = satosin6(var->gv_pdst);
                    102:        ifp = &var->gv_softc->gif_if;
                    103:
1.2       itojun    104:        if (sin6_src == NULL || sin6_dst == NULL ||
                    105:            sin6_src->sin6_family != AF_INET6 ||
                    106:            sin6_dst->sin6_family != AF_INET6) {
                    107:                m_freem(m);
                    108:                return EAFNOSUPPORT;
                    109:        }
                    110:
                    111:        switch (family) {
                    112: #ifdef INET
                    113:        case AF_INET:
                    114:            {
                    115:                struct ip *ip;
                    116:
                    117:                proto = IPPROTO_IPV4;
                    118:                if (m->m_len < sizeof(*ip)) {
                    119:                        m = m_pullup(m, sizeof(*ip));
                    120:                        if (!m)
                    121:                                return ENOBUFS;
                    122:                }
                    123:                ip = mtod(m, struct ip *);
                    124:                itos = ip->ip_tos;
                    125:                break;
                    126:            }
                    127: #endif
                    128: #ifdef INET6
                    129:        case AF_INET6:
                    130:            {
                    131:                proto = IPPROTO_IPV6;
                    132:                if (m->m_len < sizeof(*ip6)) {
                    133:                        m = m_pullup(m, sizeof(*ip6));
                    134:                        if (!m)
                    135:                                return ENOBUFS;
                    136:                }
                    137:                ip6 = mtod(m, struct ip6_hdr *);
                    138:                itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
                    139:                break;
                    140:            }
1.18      itojun    141: #endif
1.2       itojun    142:        default:
1.12      itojun    143: #ifdef DEBUG
1.2       itojun    144:                printf("in6_gif_output: warning: unknown family %d passed\n",
                    145:                        family);
                    146: #endif
                    147:                m_freem(m);
                    148:                return EAFNOSUPPORT;
                    149:        }
1.29      itojun    150:
1.2       itojun    151:        /* prepend new IP header */
                    152:        M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
                    153:        if (m && m->m_len < sizeof(struct ip6_hdr))
                    154:                m = m_pullup(m, sizeof(struct ip6_hdr));
1.21      itojun    155:        if (m == NULL)
1.2       itojun    156:                return ENOBUFS;
                    157:
                    158:        ip6 = mtod(m, struct ip6_hdr *);
                    159:        ip6->ip6_flow   = 0;
1.9       itojun    160:        ip6->ip6_vfc    &= ~IPV6_VERSION_MASK;
                    161:        ip6->ip6_vfc    |= IPV6_VERSION;
1.36      itojun    162: #if 0  /* ip6->ip6_plen will be filled by ip6_output */
                    163:        ip6->ip6_plen   = htons((u_int16_t)m->m_pkthdr.len);
                    164: #endif
1.2       itojun    165:        ip6->ip6_nxt    = proto;
                    166:        ip6->ip6_hlim   = ip6_gif_hlim;
                    167:        ip6->ip6_src    = sin6_src->sin6_addr;
1.20      itojun    168:        /* bidirectional configured tunnel mode */
                    169:        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
                    170:                ip6->ip6_dst = sin6_dst->sin6_addr;
                    171:        else  {
                    172:                m_freem(m);
                    173:                return ENETUNREACH;
1.2       itojun    174:        }
1.19      itojun    175:        if (ifp->if_flags & IFF_LINK1)
1.2       itojun    176:                ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
1.19      itojun    177:        else
                    178:                ip_ecn_ingress(ECN_NOCARE, &otos, &itos);
                    179:        ip6->ip6_flow &= ~ntohl(0xff00000);
                    180:        ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
1.2       itojun    181:
1.88      knakahar  182:        sc = ifp->if_softc;
1.94      knakahar  183:        if_tunnel_get_ro(sc->gif_ro_percpu, &ro_pc, &lock_pc);
                    184:        rt = rtcache_lookup(ro_pc, var->gv_pdst);
1.80      ozaki-r   185:        if (rt == NULL) {
1.94      knakahar  186:                if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.51      dyoung    187:                m_freem(m);
                    188:                return ENETUNREACH;
1.47      joerg     189:        }
1.14      itojun    190:
1.47      joerg     191:        /* If the route constitutes infinite encapsulation, punt. */
1.53      dyoung    192:        if (rt->rt_ifp == ifp) {
1.94      knakahar  193:                rtcache_unref(rt, ro_pc);
                    194:                rtcache_free(ro_pc);
                    195:                if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.47      joerg     196:                m_freem(m);
                    197:                return ENETUNREACH;     /* XXX */
1.2       itojun    198:        }
1.94      knakahar  199:        rtcache_unref(rt, ro_pc);
1.29      itojun    200:
1.14      itojun    201: #ifdef IPV6_MINMTU
1.95    ! knakahar  202:        int flags;
        !           203:
1.14      itojun    204:        /*
1.95    ! knakahar  205:         * - GIF_PMTU_MINMTU
        !           206:         *   Force fragmentation to minimum MTU to avoid path MTU discovery
        !           207:         * - GIF_PMTU_OUTERMTU
        !           208:         *   Trust outer MTU is large enough to send all packets
        !           209:         *
        !           210:         * It is too painful to ask for resend of inner packet, to achieve
1.14      itojun    211:         * path MTU discovery for encapsulated packets.
1.95    ! knakahar  212:         *
        !           213:         * See RFC4459.
1.14      itojun    214:         */
1.95    ! knakahar  215:        if (sc->gif_pmtu == GIF_PMTU_SYSDEFAULT) {
        !           216:                switch (ip6_gif_pmtu) {
        !           217:                case GIF_PMTU_MINMTU:
        !           218:                        flags = IPV6_MINMTU;
        !           219:                        break;
        !           220:                case GIF_PMTU_OUTERMTU:
        !           221:                        flags = 0;
        !           222:                        break;
        !           223:                default:
        !           224: #ifdef DEBUG
        !           225:                        log(LOG_DEBUG, "%s: ignore unexpected ip6_gif_pmtu %d\n",
        !           226:                            __func__, ip6_gif_pmtu);
        !           227: #endif
        !           228:                        flags = IPV6_MINMTU;
        !           229:                        break;
        !           230:                }
        !           231:        } else {
        !           232:                switch (sc->gif_pmtu) {
        !           233:                case GIF_PMTU_MINMTU:
        !           234:                        flags = IPV6_MINMTU;
        !           235:                        break;
        !           236:                case GIF_PMTU_OUTERMTU:
        !           237:                        flags = 0;
        !           238:                        break;
        !           239:                default:
        !           240: #ifdef DEBUG
        !           241:                        log(LOG_DEBUG, "%s: ignore unexpected gif_pmtu of %s %d\n",
        !           242:                            __func__, ifp->if_xname, sc->gif_pmtu);
        !           243: #endif
        !           244:                        flags = IPV6_MINMTU;
        !           245:                        break;
        !           246:                }
        !           247:        }
        !           248:
        !           249:        error = ip6_output(m, 0, ro_pc, flags, NULL, NULL, NULL);
1.14      itojun    250: #else
1.94      knakahar  251:        error = ip6_output(m, 0, ro_pc, 0, NULL, NULL, NULL);
1.14      itojun    252: #endif
1.94      knakahar  253:        if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.30      itojun    254:        return (error);
1.2       itojun    255: }
                    256:
1.57      dyoung    257: int
1.87      knakahar  258: in6_gif_input(struct mbuf **mp, int *offp, int proto, void *eparg)
1.2       itojun    259: {
                    260:        struct mbuf *m = *mp;
1.88      knakahar  261:        struct gif_softc *sc = eparg;
                    262:        struct ifnet *gifp;
1.2       itojun    263:        struct ip6_hdr *ip6;
                    264:        int af = 0;
                    265:        u_int32_t otos;
                    266:
1.88      knakahar  267:        KASSERT(sc != NULL);
1.87      knakahar  268:
1.2       itojun    269:        ip6 = mtod(m, struct ip6_hdr *);
                    270:
1.88      knakahar  271:        gifp = &sc->gif_if;
1.89      knakahar  272:        if ((gifp->if_flags & IFF_UP) == 0) {
1.2       itojun    273:                m_freem(m);
1.55      thorpej   274:                IP6_STATINC(IP6_STAT_NOGIF);
1.2       itojun    275:                return IPPROTO_DONE;
                    276:        }
1.32      itojun    277: #ifndef GIF_ENCAPCHECK
1.88      knakahar  278:        struct psref psref_var;
                    279:        struct gif_variant *var = gif_getref_variant(sc, &psref_var);
1.63      knakahar  280:        /* other CPU do delete_tunnel */
1.88      knakahar  281:        if (var->gv_psrc == NULL || var->gv_pdst == NULL) {
                    282:                gif_putref_variant(var, &psref_var);
1.63      knakahar  283:                m_freem(m);
                    284:                IP6_STATINC(IP6_STAT_NOGIF);
                    285:                return IPPROTO_DONE;
                    286:        }
                    287:
1.74      ozaki-r   288:        struct psref psref;
                    289:        struct ifnet *rcvif = m_get_rcvif_psref(m, &psref);
1.88      knakahar  290:        if (rcvif == NULL || !gif_validate6(ip6, var, rcvif)) {
1.74      ozaki-r   291:                m_put_rcvif_psref(rcvif, &psref);
1.88      knakahar  292:                gif_putref_variant(var, &psref_var);
1.21      itojun    293:                m_freem(m);
1.55      thorpej   294:                IP6_STATINC(IP6_STAT_NOGIF);
1.21      itojun    295:                return IPPROTO_DONE;
                    296:        }
1.74      ozaki-r   297:        m_put_rcvif_psref(rcvif, &psref);
1.88      knakahar  298:        gif_putref_variant(var, &psref_var);
1.21      itojun    299: #endif
1.14      itojun    300:
1.2       itojun    301:        otos = ip6->ip6_flow;
                    302:        m_adj(m, *offp);
                    303:
                    304:        switch (proto) {
                    305: #ifdef INET
                    306:        case IPPROTO_IPV4:
                    307:            {
                    308:                struct ip *ip;
                    309:                u_int8_t otos8;
                    310:                af = AF_INET;
                    311:                otos8 = (ntohl(otos) >> 20) & 0xff;
                    312:                if (m->m_len < sizeof(*ip)) {
                    313:                        m = m_pullup(m, sizeof(*ip));
                    314:                        if (!m)
                    315:                                return IPPROTO_DONE;
                    316:                }
                    317:                ip = mtod(m, struct ip *);
                    318:                if (gifp->if_flags & IFF_LINK1)
                    319:                        ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos);
1.19      itojun    320:                else
                    321:                        ip_ecn_egress(ECN_NOCARE, &otos8, &ip->ip_tos);
1.2       itojun    322:                break;
                    323:            }
                    324: #endif /* INET */
                    325: #ifdef INET6
                    326:        case IPPROTO_IPV6:
                    327:            {
1.40      christos  328:                struct ip6_hdr *ip6x;
1.2       itojun    329:                af = AF_INET6;
1.40      christos  330:                if (m->m_len < sizeof(*ip6x)) {
                    331:                        m = m_pullup(m, sizeof(*ip6x));
1.2       itojun    332:                        if (!m)
                    333:                                return IPPROTO_DONE;
                    334:                }
1.40      christos  335:                ip6x = mtod(m, struct ip6_hdr *);
1.2       itojun    336:                if (gifp->if_flags & IFF_LINK1)
1.40      christos  337:                        ip6_ecn_egress(ECN_ALLOWED, &otos, &ip6x->ip6_flow);
1.19      itojun    338:                else
1.40      christos  339:                        ip6_ecn_egress(ECN_NOCARE, &otos, &ip6x->ip6_flow);
1.2       itojun    340:                break;
                    341:            }
1.17      itojun    342: #endif
1.2       itojun    343:        default:
1.55      thorpej   344:                IP6_STATINC(IP6_STAT_NOGIF);
1.2       itojun    345:                m_freem(m);
                    346:                return IPPROTO_DONE;
                    347:        }
1.29      itojun    348:
1.2       itojun    349:        gif_input(m, af, gifp);
                    350:        return IPPROTO_DONE;
1.14      itojun    351: }
                    352:
                    353: /*
1.21      itojun    354:  * validate outer address.
1.14      itojun    355:  */
1.21      itojun    356: static int
1.88      knakahar  357: gif_validate6(const struct ip6_hdr *ip6, struct gif_variant *var,
1.52      christos  358:        struct ifnet *ifp)
1.14      itojun    359: {
1.49      dyoung    360:        const struct sockaddr_in6 *src, *dst;
1.90      knakahar  361:        int ret;
1.14      itojun    362:
1.88      knakahar  363:        src = satosin6(var->gv_psrc);
                    364:        dst = satosin6(var->gv_pdst);
1.14      itojun    365:
1.90      knakahar  366:        ret = in6_tunnel_validate(ip6, &src->sin6_addr, &dst->sin6_addr);
                    367:        if (ret == 0)
1.14      itojun    368:                return 0;
                    369:
                    370:        /* ingress filters on outer source */
1.88      knakahar  371:        if ((var->gv_softc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) {
1.57      dyoung    372:                union {
                    373:                        struct sockaddr sa;
                    374:                        struct sockaddr_in6 sin6;
                    375:                } u;
1.14      itojun    376:                struct rtentry *rt;
                    377:
                    378:                /* XXX scopeid */
1.57      dyoung    379:                sockaddr_in6_init(&u.sin6, &ip6->ip6_src, 0, 0, 0);
                    380:                rt = rtalloc1(&u.sa, 0);
                    381:                if (rt == NULL || rt->rt_ifp != ifp) {
1.15      itojun    382: #if 0
1.84      ryo       383:                        char ip6buf[INET6_ADDRSTRLEN];
1.15      itojun    384:                        log(LOG_WARNING, "%s: packet from %s dropped "
1.88      knakahar  385:                            "due to ingress filter\n",
                    386:                            if_name(&var->gv_softc->gif_if),
1.85      christos  387:                            IN6_PRINT(ip6buf, &u.sin6.sin6_addr));
1.15      itojun    388: #endif
1.57      dyoung    389:                        if (rt != NULL)
1.81      ozaki-r   390:                                rt_unref(rt);
1.14      itojun    391:                        return 0;
                    392:                }
1.81      ozaki-r   393:                rt_unref(rt);
1.14      itojun    394:        }
                    395:
1.90      knakahar  396:        return ret;
1.21      itojun    397: }
                    398:
1.32      itojun    399: #ifdef GIF_ENCAPCHECK
1.21      itojun    400: /*
                    401:  * we know that we are in IFF_UP, outer address available, and outer family
                    402:  * matched the physical addr family.  see gif_encapcheck().
                    403:  */
                    404: int
1.88      knakahar  405: gif_encapcheck6(struct mbuf *m, int off, int proto, struct gif_variant *var)
1.21      itojun    406: {
                    407:        struct ip6_hdr ip6;
1.78      ozaki-r   408:        struct ifnet *ifp = NULL;
                    409:        int r;
                    410:        struct psref psref;
1.21      itojun    411:
1.50      christos  412:        m_copydata(m, 0, sizeof(ip6), (void *)&ip6);
1.78      ozaki-r   413:        if ((m->m_flags & M_PKTHDR) != 0)
                    414:                ifp = m_get_rcvif_psref(m, &psref);
                    415:
1.88      knakahar  416:        r = gif_validate6(&ip6, var, ifp);
1.21      itojun    417:
1.78      ozaki-r   418:        m_put_rcvif_psref(ifp, &psref);
                    419:        return r;
1.21      itojun    420: }
1.32      itojun    421: #endif
1.21      itojun    422:
                    423: int
1.88      knakahar  424: in6_gif_attach(struct gif_variant *var)
1.21      itojun    425: {
1.32      itojun    426: #ifndef GIF_ENCAPCHECK
1.21      itojun    427:        struct sockaddr_in6 mask6;
                    428:
1.57      dyoung    429:        memset(&mask6, 0, sizeof(mask6));
1.21      itojun    430:        mask6.sin6_len = sizeof(struct sockaddr_in6);
1.28      itojun    431:        mask6.sin6_addr.s6_addr32[0] = mask6.sin6_addr.s6_addr32[1] =
1.21      itojun    432:            mask6.sin6_addr.s6_addr32[2] = mask6.sin6_addr.s6_addr32[3] = ~0;
                    433:
1.88      knakahar  434:        if (!var->gv_psrc || !var->gv_pdst)
1.21      itojun    435:                return EINVAL;
1.88      knakahar  436:        var->gv_encap_cookie6 = encap_attach(AF_INET6, -1, var->gv_psrc,
                    437:            sin6tosa(&mask6), var->gv_pdst, sin6tosa(&mask6),
                    438:            (const void *)&in6_gif_encapsw, var->gv_softc);
1.21      itojun    439: #else
1.88      knakahar  440:        var->gv_encap_cookie6 = encap_attach_func(AF_INET6, -1, gif_encapcheck,
                    441:            &in6_gif_encapsw, var->gv_softc);
1.21      itojun    442: #endif
1.88      knakahar  443:        if (var->gv_encap_cookie6 == NULL)
1.21      itojun    444:                return EEXIST;
1.88      knakahar  445:
                    446:        var->gv_output = in6_gif_output;
1.21      itojun    447:        return 0;
                    448: }
                    449:
                    450: int
1.88      knakahar  451: in6_gif_detach(struct gif_variant *var)
1.21      itojun    452: {
                    453:        int error;
1.88      knakahar  454:        struct gif_softc *sc = var->gv_softc;
1.21      itojun    455:
1.88      knakahar  456:        error = encap_detach(var->gv_encap_cookie6);
                    457:        if (error == 0)
                    458:                var->gv_encap_cookie6 = NULL;
1.77      knakahar  459:
1.94      knakahar  460:        if_tunnel_ro_percpu_rtcache_free(sc->gif_ro_percpu);
1.77      knakahar  461:
                    462:        return error;
                    463: }
                    464:
1.56      ad        465: void *
1.72      knakahar  466: in6_gif_ctlinput(int cmd, const struct sockaddr *sa, void *d, void *eparg)
1.27      itojun    467: {
1.73      knakahar  468:        struct gif_softc *sc = eparg;
1.88      knakahar  469:        struct gif_variant *var;
1.27      itojun    470:        struct ip6ctlparam *ip6cp = NULL;
                    471:        struct ip6_hdr *ip6;
1.49      dyoung    472:        const struct sockaddr_in6 *dst6;
1.94      knakahar  473:        struct route *ro_pc;
                    474:        kmutex_t *lock_pc;
1.88      knakahar  475:        struct psref psref;
1.27      itojun    476:
                    477:        if (sa->sa_family != AF_INET6 ||
                    478:            sa->sa_len != sizeof(struct sockaddr_in6))
1.56      ad        479:                return NULL;
1.27      itojun    480:
                    481:        if ((unsigned)cmd >= PRC_NCMDS)
1.56      ad        482:                return NULL;
1.27      itojun    483:        if (cmd == PRC_HOSTDEAD)
                    484:                d = NULL;
                    485:        else if (inet6ctlerrmap[cmd] == 0)
1.56      ad        486:                return NULL;
1.27      itojun    487:
                    488:        /* if the parameter is from icmp6, decode it. */
                    489:        if (d != NULL) {
                    490:                ip6cp = (struct ip6ctlparam *)d;
                    491:                ip6 = ip6cp->ip6c_ip6;
                    492:        } else {
                    493:                ip6 = NULL;
                    494:        }
                    495:
                    496:        if (!ip6)
1.56      ad        497:                return NULL;
1.27      itojun    498:
1.91      knakahar  499:        var = gif_getref_variant(sc, &psref);
                    500:        if (var->gv_psrc == NULL || var->gv_pdst == NULL) {
                    501:                gif_putref_variant(var, &psref);
1.72      knakahar  502:                return NULL;
1.91      knakahar  503:        }
1.88      knakahar  504:        if (var->gv_psrc->sa_family != AF_INET6) {
                    505:                gif_putref_variant(var, &psref);
1.72      knakahar  506:                return NULL;
1.88      knakahar  507:        }
                    508:        gif_putref_variant(var, &psref);
1.72      knakahar  509:
1.94      knakahar  510:        if_tunnel_get_ro(sc->gif_ro_percpu, &ro_pc, &lock_pc);
                    511:        dst6 = satocsin6(rtcache_getdst(ro_pc));
1.72      knakahar  512:        /* XXX scope */
                    513:        if (dst6 == NULL)
                    514:                ;
                    515:        else if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst6->sin6_addr))
1.94      knakahar  516:                rtcache_free(ro_pc);
1.56      ad        517:
1.94      knakahar  518:        if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.56      ad        519:        return NULL;
1.2       itojun    520: }
1.56      ad        521:
1.72      knakahar  522: ENCAP_PR_WRAP_CTLINPUT(in6_gif_ctlinput)
1.56      ad        523: #define        in6_gif_ctlinput        in6_gif_ctlinput_wrapper
1.68      riastrad  524:
1.71      knakahar  525: static const struct encapsw in6_gif_encapsw = {
                    526:        .encapsw6 = {
                    527:                .pr_input       = in6_gif_input,
                    528:                .pr_ctlinput    = in6_gif_ctlinput,
                    529:        }
1.56      ad        530: };

CVSweb <webmaster@jp.NetBSD.org>