[BACK]Return to if_gif.c CVS log [TXT][DIR] Up to [local] / sys / net

Annotation of sys/net/if_gif.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_gif.c,v 1.45 2007/05/26 17:13:30 jason Exp $       */
        !             2: /*     $KAME: if_gif.c,v 1.43 2001/02/20 08:51:07 itojun Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
        !             6:  * All rights reserved.
        !             7:  *
        !             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.
        !            19:  *
        !            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:
        !            33: #include <sys/param.h>
        !            34: #include <sys/systm.h>
        !            35: #include <sys/kernel.h>
        !            36: #include <sys/mbuf.h>
        !            37: #include <sys/socket.h>
        !            38: #include <sys/sockio.h>
        !            39: #include <sys/syslog.h>
        !            40:
        !            41: #include <net/if.h>
        !            42: #include <net/if_types.h>
        !            43: #include <net/route.h>
        !            44: #include <net/bpf.h>
        !            45:
        !            46: #ifdef INET
        !            47: #include <netinet/in.h>
        !            48: #include <netinet/in_systm.h>
        !            49: #include <netinet/in_var.h>
        !            50: #include <netinet/in_gif.h>
        !            51: #include <netinet/ip.h>
        !            52: #endif /* INET */
        !            53:
        !            54: #ifdef INET6
        !            55: #ifndef INET
        !            56: #include <netinet/in.h>
        !            57: #endif
        !            58: #include <netinet/ip6.h>
        !            59: #include <netinet6/in6_gif.h>
        !            60: #endif /* INET6 */
        !            61:
        !            62: #include <net/if_gif.h>
        !            63:
        !            64: #include "bpfilter.h"
        !            65: #include "bridge.h"
        !            66:
        !            67: void   gifattach(int);
        !            68: int    gif_clone_create(struct if_clone *, int);
        !            69: int    gif_clone_destroy(struct ifnet *);
        !            70:
        !            71: /*
        !            72:  * gif global variable definitions
        !            73:  */
        !            74: struct gif_softc_head gif_softc_list;
        !            75: struct if_clone gif_cloner =
        !            76:     IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
        !            77:
        !            78: /* ARGSUSED */
        !            79: void
        !            80: gifattach(count)
        !            81:        int count;
        !            82: {
        !            83:        LIST_INIT(&gif_softc_list);
        !            84:        if_clone_attach(&gif_cloner);
        !            85: }
        !            86:
        !            87: int
        !            88: gif_clone_create(ifc, unit)
        !            89:        struct if_clone *ifc;
        !            90:        int unit;
        !            91: {
        !            92:        struct gif_softc *sc;
        !            93:        int s;
        !            94:
        !            95:        sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
        !            96:        if (!sc)
        !            97:                return (ENOMEM);
        !            98:        bzero(sc, sizeof(*sc));
        !            99:
        !           100:        snprintf(sc->gif_if.if_xname, sizeof sc->gif_if.if_xname,
        !           101:             "%s%d", ifc->ifc_name, unit);
        !           102:        sc->gif_if.if_mtu    = GIF_MTU;
        !           103:        sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
        !           104:        sc->gif_if.if_ioctl  = gif_ioctl;
        !           105:        sc->gif_if.if_start  = gif_start;
        !           106:        sc->gif_if.if_output = gif_output;
        !           107:        sc->gif_if.if_type   = IFT_GIF;
        !           108:        IFQ_SET_MAXLEN(&sc->gif_if.if_snd, ifqmaxlen);
        !           109:        IFQ_SET_READY(&sc->gif_if.if_snd);
        !           110:        sc->gif_if.if_softc = sc;
        !           111:        if_attach(&sc->gif_if);
        !           112:        if_alloc_sadl(&sc->gif_if);
        !           113:
        !           114: #if NBPFILTER > 0
        !           115:        bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL,
        !           116:            sizeof(u_int));
        !           117: #endif
        !           118:        s = splnet();
        !           119:        LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list);
        !           120:        splx(s);
        !           121:
        !           122:        return (0);
        !           123: }
        !           124:
        !           125: int
        !           126: gif_clone_destroy(ifp)
        !           127:        struct ifnet *ifp;
        !           128: {
        !           129:        struct gif_softc *sc = ifp->if_softc;
        !           130:        int s;
        !           131:
        !           132:        s = splnet();
        !           133:        LIST_REMOVE(sc, gif_list);
        !           134:        splx(s);
        !           135:
        !           136:        if_detach(ifp);
        !           137:
        !           138:        if (sc->gif_psrc)
        !           139:                free((caddr_t)sc->gif_psrc, M_IFADDR);
        !           140:        sc->gif_psrc = NULL;
        !           141:        if (sc->gif_pdst)
        !           142:                free((caddr_t)sc->gif_pdst, M_IFADDR);
        !           143:        sc->gif_pdst = NULL;
        !           144:        free(sc, M_DEVBUF);
        !           145:        return (0);
        !           146: }
        !           147:
        !           148: void
        !           149: gif_start(ifp)
        !           150:        struct ifnet *ifp;
        !           151: {
        !           152:        struct gif_softc *sc = (struct gif_softc*)ifp;
        !           153:        struct mbuf *m;
        !           154:        struct m_tag *mtag;
        !           155:        int family;
        !           156:        int s;
        !           157:        u_int8_t tp;
        !           158:
        !           159:        /* is interface up and running? */
        !           160:        if ((ifp->if_flags & (IFF_OACTIVE | IFF_UP)) != IFF_UP ||
        !           161:            sc->gif_psrc == NULL || sc->gif_pdst == NULL)
        !           162:                return;
        !           163:
        !           164:        /* are the tunnel endpoints valid? */
        !           165: #ifdef INET
        !           166:        if (sc->gif_psrc->sa_family != AF_INET)
        !           167: #endif
        !           168: #ifdef INET6
        !           169:                if (sc->gif_psrc->sa_family != AF_INET6)
        !           170: #endif
        !           171:                        return;
        !           172:
        !           173:        s = splnet();
        !           174:        ifp->if_flags |= IFF_OACTIVE;
        !           175:        splx(s);
        !           176:
        !           177:        while (1) {
        !           178:                s = splnet();
        !           179:                IFQ_DEQUEUE(&ifp->if_snd, m);
        !           180:                splx(s);
        !           181:
        !           182:                if (m == NULL)
        !           183:                        break;
        !           184:
        !           185:                /*
        !           186:                 * gif may cause infinite recursion calls when misconfigured.
        !           187:                 * We'll prevent this by detecting loops.
        !           188:                 */
        !           189:                for (mtag = m_tag_find(m, PACKET_TAG_GIF, NULL); mtag;
        !           190:                    mtag = m_tag_find(m, PACKET_TAG_GIF, mtag)) {
        !           191:                        if (!bcmp((caddr_t)(mtag + 1), &ifp,
        !           192:                            sizeof(struct ifnet *))) {
        !           193:                                IF_DROP(&ifp->if_snd);
        !           194:                                log(LOG_NOTICE, "gif_output: "
        !           195:                                    "recursively called too many times\n");
        !           196:                                m_freem(m);
        !           197:                                break;
        !           198:                        }
        !           199:                }
        !           200:                if (mtag)
        !           201:                        continue;
        !           202:
        !           203:                mtag = m_tag_get(PACKET_TAG_GIF, sizeof(caddr_t), M_NOWAIT);
        !           204:                if (mtag == NULL) {
        !           205:                        m_freem(m);
        !           206:                        break;
        !           207:                }
        !           208:                bcopy(&ifp, mtag + 1, sizeof(caddr_t));
        !           209:                m_tag_prepend(m, mtag);
        !           210:
        !           211:                /*
        !           212:                 * remove multicast and broadcast flags or encapsulated paket
        !           213:                 * ends up as multicast or broadcast packet.
        !           214:                 */
        !           215:                m->m_flags &= ~(M_BCAST|M_MCAST);
        !           216:
        !           217:                /* extract address family */
        !           218:                family = AF_UNSPEC;
        !           219:                tp = *mtod(m, u_int8_t *);
        !           220:                tp = (tp >> 4) & 0xff;  /* Get the IP version number. */
        !           221: #ifdef INET
        !           222:                if (tp == IPVERSION)
        !           223:                        family = AF_INET;
        !           224: #endif
        !           225: #ifdef INET6
        !           226:                if (tp == (IPV6_VERSION >> 4))
        !           227:                        family = AF_INET6;
        !           228: #endif
        !           229:
        !           230: #if NBRIDGE > 0
        !           231:                /*
        !           232:                 * Check if the packet is comming via bridge and needs
        !           233:                 * etherip encapsulation or not.
        !           234:                 */
        !           235:                if (ifp->if_bridge && (m->m_flags & M_PROTO1)) {
        !           236:                        m->m_flags &= ~M_PROTO1;
        !           237:                        family = AF_LINK;
        !           238:                }
        !           239: #endif
        !           240:
        !           241: #if NBPFILTER > 0
        !           242:                if (ifp->if_bpf)
        !           243:                        bpf_mtap_af(ifp->if_bpf, family, m, BPF_DIRECTION_OUT);
        !           244: #endif
        !           245:                ifp->if_opackets++;
        !           246:                ifp->if_obytes += m->m_pkthdr.len;
        !           247:
        !           248:                switch (sc->gif_psrc->sa_family) {
        !           249: #ifdef INET
        !           250:                case AF_INET:
        !           251:                        in_gif_output(ifp, family, m);
        !           252:                        break;
        !           253: #endif
        !           254: #ifdef INET6
        !           255:                case AF_INET6:
        !           256:                        in6_gif_output(ifp, family, m);
        !           257:                        break;
        !           258: #endif
        !           259:                default:
        !           260:                        m_freem(m);
        !           261:                        break;
        !           262:                }
        !           263:        }
        !           264:
        !           265:        ifp->if_flags &= ~IFF_OACTIVE;
        !           266: }
        !           267:
        !           268: int
        !           269: gif_output(ifp, m, dst, rt)
        !           270:        struct ifnet *ifp;
        !           271:        struct mbuf *m;
        !           272:        struct sockaddr *dst;
        !           273:        struct rtentry *rt;     /* added in net2 */
        !           274: {
        !           275:        struct gif_softc *sc = (struct gif_softc*)ifp;
        !           276:        int error = 0;
        !           277:        int s;
        !           278:
        !           279:        if (!(ifp->if_flags & IFF_UP) ||
        !           280:            sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
        !           281:                m_freem(m);
        !           282:                error = ENETDOWN;
        !           283:                goto end;
        !           284:        }
        !           285:
        !           286:        switch (sc->gif_psrc->sa_family) {
        !           287: #ifdef INET
        !           288:        case AF_INET:
        !           289:                break;
        !           290: #endif
        !           291: #ifdef INET6
        !           292:        case AF_INET6:
        !           293:                break;
        !           294: #endif
        !           295:        default:
        !           296:                m_freem(m);
        !           297:                error = ENETDOWN;
        !           298:                goto end;
        !           299:        }
        !           300:
        !           301:        s = splnet();
        !           302:        /*
        !           303:         * Queue message on interface, and start output if interface
        !           304:         * not yet active.
        !           305:         */
        !           306:        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
        !           307:        if (error) {
        !           308:                /* mbuf is already freed */
        !           309:                splx(s);
        !           310:                return (error);
        !           311:        }
        !           312:        if ((ifp->if_flags & IFF_OACTIVE) == 0)
        !           313:                (*ifp->if_start)(ifp);
        !           314:        splx(s);
        !           315:        return (error);
        !           316:
        !           317: end:
        !           318:        if (error)
        !           319:                ifp->if_oerrors++;
        !           320:        return (error);
        !           321: }
        !           322:
        !           323: int
        !           324: gif_ioctl(ifp, cmd, data)
        !           325:        struct ifnet *ifp;
        !           326:        u_long cmd;
        !           327:        caddr_t data;
        !           328: {
        !           329:        struct gif_softc *sc  = (struct gif_softc*)ifp;
        !           330:        struct ifreq     *ifr = (struct ifreq*)data;
        !           331:        int error = 0, size;
        !           332:        struct sockaddr *dst, *src;
        !           333:        struct sockaddr *sa;
        !           334:        int s;
        !           335:        struct gif_softc *sc2;
        !           336:
        !           337:        switch (cmd) {
        !           338:        case SIOCSIFADDR:
        !           339:                break;
        !           340:
        !           341:        case SIOCSIFDSTADDR:
        !           342:                break;
        !           343:
        !           344:        case SIOCADDMULTI:
        !           345:        case SIOCDELMULTI:
        !           346:                switch (ifr->ifr_addr.sa_family) {
        !           347: #ifdef INET
        !           348:                case AF_INET:   /* IP supports Multicast */
        !           349:                        break;
        !           350: #endif /* INET */
        !           351: #ifdef INET6
        !           352:                case AF_INET6:  /* IP6 supports Multicast */
        !           353:                        break;
        !           354: #endif /* INET6 */
        !           355:                default:  /* Other protocols doesn't support Multicast */
        !           356:                        error = EAFNOSUPPORT;
        !           357:                        break;
        !           358:                }
        !           359:                break;
        !           360:
        !           361:        case SIOCSIFPHYADDR:
        !           362: #ifdef INET6
        !           363:        case SIOCSIFPHYADDR_IN6:
        !           364: #endif /* INET6 */
        !           365:        case SIOCSLIFPHYADDR:
        !           366:                switch (cmd) {
        !           367: #ifdef INET
        !           368:                case SIOCSIFPHYADDR:
        !           369:                        src = (struct sockaddr *)
        !           370:                                &(((struct in_aliasreq *)data)->ifra_addr);
        !           371:                        dst = (struct sockaddr *)
        !           372:                                &(((struct in_aliasreq *)data)->ifra_dstaddr);
        !           373:                        break;
        !           374: #endif
        !           375: #ifdef INET6
        !           376:                case SIOCSIFPHYADDR_IN6:
        !           377:                        src = (struct sockaddr *)
        !           378:                                &(((struct in6_aliasreq *)data)->ifra_addr);
        !           379:                        dst = (struct sockaddr *)
        !           380:                                &(((struct in6_aliasreq *)data)->ifra_dstaddr);
        !           381:                        break;
        !           382: #endif
        !           383:                case SIOCSLIFPHYADDR:
        !           384:                        src = (struct sockaddr *)
        !           385:                                &(((struct if_laddrreq *)data)->addr);
        !           386:                        dst = (struct sockaddr *)
        !           387:                                &(((struct if_laddrreq *)data)->dstaddr);
        !           388:                        break;
        !           389:                default:
        !           390:                        return (EINVAL);
        !           391:                }
        !           392:
        !           393:                /* sa_family must be equal */
        !           394:                if (src->sa_family != dst->sa_family)
        !           395:                        return (EINVAL);
        !           396:
        !           397:                /* validate sa_len */
        !           398:                switch (src->sa_family) {
        !           399: #ifdef INET
        !           400:                case AF_INET:
        !           401:                        if (src->sa_len != sizeof(struct sockaddr_in))
        !           402:                                return (EINVAL);
        !           403:                        break;
        !           404: #endif
        !           405: #ifdef INET6
        !           406:                case AF_INET6:
        !           407:                        if (src->sa_len != sizeof(struct sockaddr_in6))
        !           408:                                return (EINVAL);
        !           409:                        break;
        !           410: #endif
        !           411:                default:
        !           412:                        return (EAFNOSUPPORT);
        !           413:                }
        !           414:                switch (dst->sa_family) {
        !           415: #ifdef INET
        !           416:                case AF_INET:
        !           417:                        if (dst->sa_len != sizeof(struct sockaddr_in))
        !           418:                                return (EINVAL);
        !           419:                        break;
        !           420: #endif
        !           421: #ifdef INET6
        !           422:                case AF_INET6:
        !           423:                        if (dst->sa_len != sizeof(struct sockaddr_in6))
        !           424:                                return (EINVAL);
        !           425:                        break;
        !           426: #endif
        !           427:                default:
        !           428:                        return (EAFNOSUPPORT);
        !           429:                }
        !           430:
        !           431:                /* check sa_family looks sane for the cmd */
        !           432:                switch (cmd) {
        !           433:                case SIOCSIFPHYADDR:
        !           434:                        if (src->sa_family == AF_INET)
        !           435:                                break;
        !           436:                        return (EAFNOSUPPORT);
        !           437: #ifdef INET6
        !           438:                case SIOCSIFPHYADDR_IN6:
        !           439:                        if (src->sa_family == AF_INET6)
        !           440:                                break;
        !           441:                        return (EAFNOSUPPORT);
        !           442: #endif /* INET6 */
        !           443:                case SIOCSLIFPHYADDR:
        !           444:                        /* checks done in the above */
        !           445:                        break;
        !           446:                }
        !           447:
        !           448:                LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
        !           449:                        if (sc2 == sc)
        !           450:                                continue;
        !           451:                        if (!sc2->gif_pdst || !sc2->gif_psrc)
        !           452:                                continue;
        !           453:                        if (sc2->gif_pdst->sa_family != dst->sa_family ||
        !           454:                            sc2->gif_pdst->sa_len != dst->sa_len ||
        !           455:                            sc2->gif_psrc->sa_family != src->sa_family ||
        !           456:                            sc2->gif_psrc->sa_len != src->sa_len)
        !           457:                                continue;
        !           458:                        /* can't configure same pair of address onto two gifs */
        !           459:                        if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
        !           460:                            bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
        !           461:                                error = EADDRNOTAVAIL;
        !           462:                                goto bad;
        !           463:                        }
        !           464:
        !           465:                        /* can't configure multiple multi-dest interfaces */
        !           466: #define multidest(x) \
        !           467:        (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
        !           468: #ifdef INET6
        !           469: #define multidest6(x) \
        !           470:        (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
        !           471: #endif
        !           472:                        if (dst->sa_family == AF_INET &&
        !           473:                            multidest(dst) && multidest(sc2->gif_pdst)) {
        !           474:                                error = EADDRNOTAVAIL;
        !           475:                                goto bad;
        !           476:                        }
        !           477: #ifdef INET6
        !           478:                        if (dst->sa_family == AF_INET6 &&
        !           479:                            multidest6(dst) && multidest6(sc2->gif_pdst)) {
        !           480:                                error = EADDRNOTAVAIL;
        !           481:                                goto bad;
        !           482:                        }
        !           483: #endif
        !           484:                }
        !           485:
        !           486:                if (sc->gif_psrc)
        !           487:                        free((caddr_t)sc->gif_psrc, M_IFADDR);
        !           488:                sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK);
        !           489:                bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
        !           490:                sc->gif_psrc = sa;
        !           491:
        !           492:                if (sc->gif_pdst)
        !           493:                        free((caddr_t)sc->gif_pdst, M_IFADDR);
        !           494:                sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK);
        !           495:                bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
        !           496:                sc->gif_pdst = sa;
        !           497:
        !           498:                s = splnet();
        !           499:                ifp->if_flags |= IFF_RUNNING;
        !           500:                if_up(ifp);             /* send up RTM_IFINFO */
        !           501:                splx(s);
        !           502:
        !           503:                error = 0;
        !           504:                break;
        !           505:
        !           506: #ifdef SIOCDIFPHYADDR
        !           507:        case SIOCDIFPHYADDR:
        !           508:                if (sc->gif_psrc) {
        !           509:                        free((caddr_t)sc->gif_psrc, M_IFADDR);
        !           510:                        sc->gif_psrc = NULL;
        !           511:                }
        !           512:                if (sc->gif_pdst) {
        !           513:                        free((caddr_t)sc->gif_pdst, M_IFADDR);
        !           514:                        sc->gif_pdst = NULL;
        !           515:                }
        !           516:                /* change the IFF_{UP, RUNNING} flag as well? */
        !           517:                break;
        !           518: #endif
        !           519:
        !           520:        case SIOCGIFPSRCADDR:
        !           521: #ifdef INET6
        !           522:        case SIOCGIFPSRCADDR_IN6:
        !           523: #endif /* INET6 */
        !           524:                if (sc->gif_psrc == NULL) {
        !           525:                        error = EADDRNOTAVAIL;
        !           526:                        goto bad;
        !           527:                }
        !           528:                src = sc->gif_psrc;
        !           529:                switch (cmd) {
        !           530: #ifdef INET
        !           531:                case SIOCGIFPSRCADDR:
        !           532:                        dst = &ifr->ifr_addr;
        !           533:                        size = sizeof(ifr->ifr_addr);
        !           534:                        break;
        !           535: #endif /* INET */
        !           536: #ifdef INET6
        !           537:                case SIOCGIFPSRCADDR_IN6:
        !           538:                        dst = (struct sockaddr *)
        !           539:                                &(((struct in6_ifreq *)data)->ifr_addr);
        !           540:                        size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
        !           541:                        break;
        !           542: #endif /* INET6 */
        !           543:                default:
        !           544:                        error = EADDRNOTAVAIL;
        !           545:                        goto bad;
        !           546:                }
        !           547:                if (src->sa_len > size)
        !           548:                        return (EINVAL);
        !           549:                bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
        !           550:                break;
        !           551:
        !           552:        case SIOCGIFPDSTADDR:
        !           553: #ifdef INET6
        !           554:        case SIOCGIFPDSTADDR_IN6:
        !           555: #endif /* INET6 */
        !           556:                if (sc->gif_pdst == NULL) {
        !           557:                        error = EADDRNOTAVAIL;
        !           558:                        goto bad;
        !           559:                }
        !           560:                src = sc->gif_pdst;
        !           561:                switch (cmd) {
        !           562: #ifdef INET
        !           563:                case SIOCGIFPDSTADDR:
        !           564:                        dst = &ifr->ifr_addr;
        !           565:                        size = sizeof(ifr->ifr_addr);
        !           566:                        break;
        !           567: #endif /* INET */
        !           568: #ifdef INET6
        !           569:                case SIOCGIFPDSTADDR_IN6:
        !           570:                        dst = (struct sockaddr *)
        !           571:                                &(((struct in6_ifreq *)data)->ifr_addr);
        !           572:                        size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
        !           573:                        break;
        !           574: #endif /* INET6 */
        !           575:                default:
        !           576:                        error = EADDRNOTAVAIL;
        !           577:                        goto bad;
        !           578:                }
        !           579:                if (src->sa_len > size)
        !           580:                        return (EINVAL);
        !           581:                bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
        !           582:                break;
        !           583:
        !           584:        case SIOCGLIFPHYADDR:
        !           585:                if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
        !           586:                        error = EADDRNOTAVAIL;
        !           587:                        goto bad;
        !           588:                }
        !           589:
        !           590:                /* copy src */
        !           591:                src = sc->gif_psrc;
        !           592:                dst = (struct sockaddr *)
        !           593:                        &(((struct if_laddrreq *)data)->addr);
        !           594:                size = sizeof(((struct if_laddrreq *)data)->addr);
        !           595:                if (src->sa_len > size)
        !           596:                        return (EINVAL);
        !           597:                bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
        !           598:
        !           599:                /* copy dst */
        !           600:                src = sc->gif_pdst;
        !           601:                dst = (struct sockaddr *)
        !           602:                        &(((struct if_laddrreq *)data)->dstaddr);
        !           603:                size = sizeof(((struct if_laddrreq *)data)->dstaddr);
        !           604:                if (src->sa_len > size)
        !           605:                        return (EINVAL);
        !           606:                bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
        !           607:                break;
        !           608:
        !           609:        case SIOCSIFFLAGS:
        !           610:                /* if_ioctl() takes care of it */
        !           611:                break;
        !           612:
        !           613:        case SIOCSIFMTU:
        !           614:                if (ifr->ifr_mtu < GIF_MTU_MIN || ifr->ifr_mtu > GIF_MTU_MAX)
        !           615:                        error = EINVAL;
        !           616:                else
        !           617:                        ifp->if_mtu = ifr->ifr_mtu;
        !           618:                break;
        !           619:
        !           620:        default:
        !           621:                error = EINVAL;
        !           622:                break;
        !           623:        }
        !           624:  bad:
        !           625:        return (error);
        !           626: }

CVSweb