[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

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