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

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

1.1       nbrk        1: /*     $OpenBSD: in.c,v 1.49 2007/07/20 19:00:35 claudio Exp $ */
                      2: /*     $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (C) 2001 WIDE Project.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. Neither the name of the project nor the names of its contributors
                     16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
                     33:  * Copyright (c) 1982, 1986, 1991, 1993
                     34:  *     The Regents of the University of California.  All rights reserved.
                     35:  *
                     36:  * Redistribution and use in source and binary forms, with or without
                     37:  * modification, are permitted provided that the following conditions
                     38:  * are met:
                     39:  * 1. Redistributions of source code must retain the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer.
                     41:  * 2. Redistributions in binary form must reproduce the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer in the
                     43:  *    documentation and/or other materials provided with the distribution.
                     44:  * 3. Neither the name of the University nor the names of its contributors
                     45:  *    may be used to endorse or promote products derived from this software
                     46:  *    without specific prior written permission.
                     47:  *
                     48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     58:  * SUCH DAMAGE.
                     59:  *
                     60:  *     @(#)in.c        8.2 (Berkeley) 11/15/93
                     61:  */
                     62:
                     63: #include <sys/param.h>
                     64: #include <sys/systm.h>
                     65: #include <sys/ioctl.h>
                     66: #include <sys/malloc.h>
                     67: #include <sys/socket.h>
                     68: #include <sys/socketvar.h>
                     69:
                     70: #include <net/if.h>
                     71: #include <net/route.h>
                     72:
                     73: #include "carp.h"
                     74: #if NCARP > 0
                     75: #include <net/if_types.h>
                     76: #endif
                     77:
                     78: #include <netinet/in.h>
                     79: #include <netinet/in_var.h>
                     80: #include <netinet/igmp_var.h>
                     81:
                     82: #ifdef MROUTING
                     83: #include <netinet/ip_mroute.h>
                     84: #endif
                     85:
                     86: #include "ether.h"
                     87:
                     88: #ifdef INET
                     89:
                     90: int in_mask2len(struct in_addr *);
                     91: void in_len2mask(struct in_addr *, int);
                     92: int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
                     93:        struct ifnet *);
                     94:
                     95: int in_addprefix(struct in_ifaddr *, int);
                     96: int in_scrubprefix(struct in_ifaddr *);
                     97:
                     98: #ifndef SUBNETSARELOCAL
                     99: #define        SUBNETSARELOCAL 0
                    100: #endif
                    101:
                    102: #ifndef HOSTZEROBROADCAST
                    103: #define HOSTZEROBROADCAST 1
                    104: #endif
                    105:
                    106: int subnetsarelocal = SUBNETSARELOCAL;
                    107: int hostzeroisbroadcast = HOSTZEROBROADCAST;
                    108:
                    109: /*
                    110:  * Return 1 if an internet address is for a ``local'' host
                    111:  * (one to which we have a connection).  If subnetsarelocal
                    112:  * is true, this includes other subnets of the local net.
                    113:  * Otherwise, it includes only the directly-connected (sub)nets.
                    114:  */
                    115: int
                    116: in_localaddr(in)
                    117:        struct in_addr in;
                    118: {
                    119:        struct in_ifaddr *ia;
                    120:
                    121:        if (subnetsarelocal) {
                    122:                TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
                    123:                        if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
                    124:                                return (1);
                    125:        } else {
                    126:                TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
                    127:                        if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
                    128:                                return (1);
                    129:        }
                    130:        return (0);
                    131: }
                    132:
                    133: /*
                    134:  * Determine whether an IP address is in a reserved set of addresses
                    135:  * that may not be forwarded, or whether datagrams to that destination
                    136:  * may be forwarded.
                    137:  */
                    138: int
                    139: in_canforward(in)
                    140:        struct in_addr in;
                    141: {
                    142:        u_int32_t net;
                    143:
                    144:        if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
                    145:                return (0);
                    146:        if (IN_CLASSA(in.s_addr)) {
                    147:                net = in.s_addr & IN_CLASSA_NET;
                    148:                if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
                    149:                        return (0);
                    150:        }
                    151:        return (1);
                    152: }
                    153:
                    154: /*
                    155:  * Trim a mask in a sockaddr
                    156:  */
                    157: void
                    158: in_socktrim(ap)
                    159:        struct sockaddr_in *ap;
                    160: {
                    161:        char *cplim = (char *) &ap->sin_addr;
                    162:        char *cp = (char *) (&ap->sin_addr + 1);
                    163:
                    164:        ap->sin_len = 0;
                    165:        while (--cp >= cplim)
                    166:                if (*cp) {
                    167:                        (ap)->sin_len = cp - (char *) (ap) + 1;
                    168:                        break;
                    169:                }
                    170: }
                    171:
                    172: int
                    173: in_mask2len(mask)
                    174:        struct in_addr *mask;
                    175: {
                    176:        int x, y;
                    177:        u_char *p;
                    178:
                    179:        p = (u_char *)mask;
                    180:        for (x = 0; x < sizeof(*mask); x++) {
                    181:                if (p[x] != 0xff)
                    182:                        break;
                    183:        }
                    184:        y = 0;
                    185:        if (x < sizeof(*mask)) {
                    186:                for (y = 0; y < 8; y++) {
                    187:                        if ((p[x] & (0x80 >> y)) == 0)
                    188:                                break;
                    189:                }
                    190:        }
                    191:        return x * 8 + y;
                    192: }
                    193:
                    194: void
                    195: in_len2mask(mask, len)
                    196:        struct in_addr *mask;
                    197:        int len;
                    198: {
                    199:        int i;
                    200:        u_char *p;
                    201:
                    202:        p = (u_char *)mask;
                    203:        bzero(mask, sizeof(*mask));
                    204:        for (i = 0; i < len / 8; i++)
                    205:                p[i] = 0xff;
                    206:        if (len % 8)
                    207:                p[i] = (0xff00 >> (len % 8)) & 0xff;
                    208: }
                    209:
                    210: int    in_interfaces;          /* number of external internet interfaces */
                    211:
                    212: /*
                    213:  * Generic internet control operations (ioctl's).
                    214:  * Ifp is 0 if not an interface-specific ioctl.
                    215:  */
                    216: /* ARGSUSED */
                    217: int
                    218: in_control(so, cmd, data, ifp)
                    219:        struct socket *so;
                    220:        u_long cmd;
                    221:        caddr_t data;
                    222:        struct ifnet *ifp;
                    223: {
                    224:        struct ifreq *ifr = (struct ifreq *)data;
                    225:        struct in_ifaddr *ia = 0;
                    226:        struct in_aliasreq *ifra = (struct in_aliasreq *)data;
                    227:        struct sockaddr_in oldaddr;
                    228:        int error, hostIsNew, maskIsNew;
                    229:        int newifaddr;
                    230:        int s;
                    231:
                    232:        switch (cmd) {
                    233:        case SIOCALIFADDR:
                    234:        case SIOCDLIFADDR:
                    235:                if ((so->so_state & SS_PRIV) == 0)
                    236:                        return (EPERM);
                    237:                /* FALLTHROUGH */
                    238:        case SIOCGLIFADDR:
                    239:                if (!ifp)
                    240:                        return EINVAL;
                    241:                return in_lifaddr_ioctl(so, cmd, data, ifp);
                    242:        }
                    243:
                    244:        /*
                    245:         * Find address for this interface, if it exists.
                    246:         */
                    247:        if (ifp)
                    248:                TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
                    249:                        if (ia->ia_ifp == ifp)
                    250:                                break;
                    251:
                    252:        switch (cmd) {
                    253:
                    254:        case SIOCAIFADDR:
                    255:        case SIOCDIFADDR:
                    256:                if (ifra->ifra_addr.sin_family == AF_INET)
                    257:                        for (; ia != TAILQ_END(&in_ifaddr);
                    258:                            ia = TAILQ_NEXT(ia, ia_list)) {
                    259:                                if (ia->ia_ifp == ifp &&
                    260:                                    ia->ia_addr.sin_addr.s_addr ==
                    261:                                        ifra->ifra_addr.sin_addr.s_addr)
                    262:                                    break;
                    263:                        }
                    264:                if (cmd == SIOCDIFADDR && ia == 0)
                    265:                        return (EADDRNOTAVAIL);
                    266:                /* FALLTHROUGH */
                    267:        case SIOCSIFADDR:
                    268:        case SIOCSIFNETMASK:
                    269:        case SIOCSIFDSTADDR:
                    270:                if ((so->so_state & SS_PRIV) == 0)
                    271:                        return (EPERM);
                    272:
                    273:                if (ifp == 0)
                    274:                        panic("in_control");
                    275:                if (ia == (struct in_ifaddr *)0) {
                    276:                        ia = (struct in_ifaddr *)
                    277:                                malloc(sizeof *ia, M_IFADDR, M_WAITOK);
                    278:                        bzero((caddr_t)ia, sizeof *ia);
                    279:                        s = splsoftnet();
                    280:                        TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
                    281:                        TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
                    282:                            ifa_list);
                    283:                        ia->ia_addr.sin_family = AF_INET;
                    284:                        ia->ia_addr.sin_len = sizeof(ia->ia_addr);
                    285:                        ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
                    286:                        ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
                    287:                        ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
                    288:                        ia->ia_sockmask.sin_len = 8;
                    289:                        if (ifp->if_flags & IFF_BROADCAST) {
                    290:                                ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
                    291:                                ia->ia_broadaddr.sin_family = AF_INET;
                    292:                        }
                    293:                        ia->ia_ifp = ifp;
                    294:                        LIST_INIT(&ia->ia_multiaddrs);
                    295:                        if ((ifp->if_flags & IFF_LOOPBACK) == 0)
                    296:                                in_interfaces++;
                    297:                        splx(s);
                    298:
                    299:                        newifaddr = 1;
                    300:                } else
                    301:                        newifaddr = 0;
                    302:                break;
                    303:
                    304:        case SIOCSIFBRDADDR:
                    305:                if ((so->so_state & SS_PRIV) == 0)
                    306:                        return (EPERM);
                    307:                /* FALLTHROUGH */
                    308:
                    309:        case SIOCGIFADDR:
                    310:        case SIOCGIFNETMASK:
                    311:        case SIOCGIFDSTADDR:
                    312:        case SIOCGIFBRDADDR:
                    313:                if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
                    314:                        struct in_ifaddr *ia2;
                    315:
                    316:                        for (ia2 = ia; ia2 != TAILQ_END(&in_ifaddr);
                    317:                            ia2 = TAILQ_NEXT(ia2, ia_list)) {
                    318:                                if (ia2->ia_ifp == ifp &&
                    319:                                    ia2->ia_addr.sin_addr.s_addr ==
                    320:                                    satosin(&ifr->ifr_addr)->sin_addr.s_addr)
                    321:                                        break;
                    322:                        }
                    323:                        if (ia2 && ia2->ia_ifp == ifp)
                    324:                                ia = ia2;
                    325:                }
                    326:                if (ia == (struct in_ifaddr *)0)
                    327:                        return (EADDRNOTAVAIL);
                    328:                break;
                    329:        }
                    330:        switch (cmd) {
                    331:
                    332:        case SIOCGIFADDR:
                    333:                *satosin(&ifr->ifr_addr) = ia->ia_addr;
                    334:                break;
                    335:
                    336:        case SIOCGIFBRDADDR:
                    337:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
                    338:                        return (EINVAL);
                    339:                *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
                    340:                break;
                    341:
                    342:        case SIOCGIFDSTADDR:
                    343:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                    344:                        return (EINVAL);
                    345:                *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
                    346:                break;
                    347:
                    348:        case SIOCGIFNETMASK:
                    349:                *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
                    350:                break;
                    351:
                    352:        case SIOCSIFDSTADDR:
                    353:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                    354:                        return (EINVAL);
                    355:                s = splsoftnet();
                    356:                oldaddr = ia->ia_dstaddr;
                    357:                ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
                    358:                if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
                    359:                                        (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
                    360:                        ia->ia_dstaddr = oldaddr;
                    361:                        splx(s);
                    362:                        return (error);
                    363:                }
                    364:                if (ia->ia_flags & IFA_ROUTE) {
                    365:                        ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
                    366:                        rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
                    367:                        ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
                    368:                        rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
                    369:                }
                    370:                splx(s);
                    371:                break;
                    372:
                    373:        case SIOCSIFBRDADDR:
                    374:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
                    375:                        return (EINVAL);
                    376:                ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
                    377:                break;
                    378:
                    379:        case SIOCSIFADDR:
                    380:                s = splsoftnet();
                    381:                error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
                    382:                if (!error)
                    383:                        dohooks(ifp->if_addrhooks, 0);
                    384:                else if (newifaddr) {
                    385:                        splx(s);
                    386:                        goto cleanup;
                    387:                }
                    388:                splx(s);
                    389:                return error;
                    390:
                    391:        case SIOCSIFNETMASK:
                    392:                ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
                    393:                    ifra->ifra_addr.sin_addr.s_addr;
                    394:                break;
                    395:
                    396:        case SIOCAIFADDR:
                    397:                maskIsNew = 0;
                    398:                hostIsNew = 1;
                    399:                error = 0;
                    400:                s = splsoftnet();
                    401:                if (ia->ia_addr.sin_family == AF_INET) {
                    402:                        if (ifra->ifra_addr.sin_len == 0) {
                    403:                                ifra->ifra_addr = ia->ia_addr;
                    404:                                hostIsNew = 0;
                    405:                        } else if (ifra->ifra_addr.sin_addr.s_addr ==
                    406:                                               ia->ia_addr.sin_addr.s_addr)
                    407:                                hostIsNew = 0;
                    408:                }
                    409:                if (ifra->ifra_mask.sin_len) {
                    410:                        in_ifscrub(ifp, ia);
                    411:                        ia->ia_sockmask = ifra->ifra_mask;
                    412:                        ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
                    413:                        maskIsNew = 1;
                    414:                }
                    415:                if ((ifp->if_flags & IFF_POINTOPOINT) &&
                    416:                    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
                    417:                        in_ifscrub(ifp, ia);
                    418:                        ia->ia_dstaddr = ifra->ifra_dstaddr;
                    419:                        maskIsNew  = 1; /* We lie; but the effect's the same */
                    420:                }
                    421:                if (ifra->ifra_addr.sin_family == AF_INET &&
                    422:                    (hostIsNew || maskIsNew)) {
                    423:                        error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
                    424:                }
                    425:                if ((ifp->if_flags & IFF_BROADCAST) &&
                    426:                    (ifra->ifra_broadaddr.sin_family == AF_INET))
                    427:                        ia->ia_broadaddr = ifra->ifra_broadaddr;
                    428:                if (!error)
                    429:                        dohooks(ifp->if_addrhooks, 0);
                    430:                else if (newifaddr) {
                    431:                        splx(s);
                    432:                        goto cleanup;
                    433:                }
                    434:                splx(s);
                    435:                return (error);
                    436:
                    437:        case SIOCDIFADDR: {
                    438:
                    439:                error = 0;
                    440: cleanup:
                    441:                /*
                    442:                 * Even if the individual steps were safe, shouldn't
                    443:                 * these kinds of changes happen atomically?  What
                    444:                 * should happen to a packet that was routed after
                    445:                 * the scrub but before the other steps?
                    446:                 */
                    447:                s = splsoftnet();
                    448:                in_ifscrub(ifp, ia);
                    449:                TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
                    450:                TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
                    451:                if (ia->ia_allhosts != NULL) {
                    452:                        in_delmulti(ia->ia_allhosts);
                    453:                        ia->ia_allhosts = NULL;
                    454:                }
                    455:                IFAFREE((&ia->ia_ifa));
                    456:                dohooks(ifp->if_addrhooks, 0);
                    457:                splx(s);
                    458:                return (error);
                    459:                }
                    460:
                    461: #ifdef MROUTING
                    462:        case SIOCGETVIFCNT:
                    463:        case SIOCGETSGCNT:
                    464:                return (mrt_ioctl(so, cmd, data));
                    465: #endif /* MROUTING */
                    466:
                    467:        default:
                    468:                if (ifp == 0 || ifp->if_ioctl == 0)
                    469:                        return (EOPNOTSUPP);
                    470:                return ((*ifp->if_ioctl)(ifp, cmd, data));
                    471:        }
                    472:        return (0);
                    473: }
                    474:
                    475: /*
                    476:  * SIOC[GAD]LIFADDR.
                    477:  *     SIOCGLIFADDR: get first address. (???)
                    478:  *     SIOCGLIFADDR with IFLR_PREFIX:
                    479:  *             get first address that matches the specified prefix.
                    480:  *     SIOCALIFADDR: add the specified address.
                    481:  *     SIOCALIFADDR with IFLR_PREFIX:
                    482:  *             EINVAL since we can't deduce hostid part of the address.
                    483:  *     SIOCDLIFADDR: delete the specified address.
                    484:  *     SIOCDLIFADDR with IFLR_PREFIX:
                    485:  *             delete the first address that matches the specified prefix.
                    486:  * return values:
                    487:  *     EINVAL on invalid parameters
                    488:  *     EADDRNOTAVAIL on prefix match failed/specified address not found
                    489:  *     other values may be returned from in_ioctl()
                    490:  */
                    491: int
                    492: in_lifaddr_ioctl(so, cmd, data, ifp)
                    493:        struct socket *so;
                    494:        u_long cmd;
                    495:        caddr_t data;
                    496:        struct ifnet *ifp;
                    497: {
                    498:        struct if_laddrreq *iflr = (struct if_laddrreq *)data;
                    499:        struct ifaddr *ifa;
                    500:        struct sockaddr *sa;
                    501:
                    502:        /* sanity checks */
                    503:        if (!data || !ifp) {
                    504:                panic("invalid argument to in_lifaddr_ioctl");
                    505:                /*NOTRECHED*/
                    506:        }
                    507:
                    508:        switch (cmd) {
                    509:        case SIOCGLIFADDR:
                    510:                /* address must be specified on GET with IFLR_PREFIX */
                    511:                if ((iflr->flags & IFLR_PREFIX) == 0)
                    512:                        break;
                    513:                /*FALLTHROUGH*/
                    514:        case SIOCALIFADDR:
                    515:        case SIOCDLIFADDR:
                    516:                /* address must be specified on ADD and DELETE */
                    517:                sa = (struct sockaddr *)&iflr->addr;
                    518:                if (sa->sa_family != AF_INET)
                    519:                        return EINVAL;
                    520:                if (sa->sa_len != sizeof(struct sockaddr_in))
                    521:                        return EINVAL;
                    522:                /* XXX need improvement */
                    523:                sa = (struct sockaddr *)&iflr->dstaddr;
                    524:                if (sa->sa_family
                    525:                 && sa->sa_family != AF_INET)
                    526:                        return EINVAL;
                    527:                if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
                    528:                        return EINVAL;
                    529:                break;
                    530:        default: /*shouldn't happen*/
                    531: #if 0
                    532:                panic("invalid cmd to in_lifaddr_ioctl");
                    533:                /*NOTREACHED*/
                    534: #else
                    535:                return EOPNOTSUPP;
                    536: #endif
                    537:        }
                    538:        if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
                    539:                return EINVAL;
                    540:
                    541:        switch (cmd) {
                    542:        case SIOCALIFADDR:
                    543:            {
                    544:                struct in_aliasreq ifra;
                    545:
                    546:                if (iflr->flags & IFLR_PREFIX)
                    547:                        return EINVAL;
                    548:
                    549:                /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
                    550:                bzero(&ifra, sizeof(ifra));
                    551:                bcopy(iflr->iflr_name, ifra.ifra_name,
                    552:                        sizeof(ifra.ifra_name));
                    553:
                    554:                bcopy(&iflr->addr, &ifra.ifra_addr,
                    555:                        ((struct sockaddr *)&iflr->addr)->sa_len);
                    556:
                    557:                if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {   /*XXX*/
                    558:                        bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
                    559:                                ((struct sockaddr *)&iflr->dstaddr)->sa_len);
                    560:                }
                    561:
                    562:                ifra.ifra_mask.sin_family = AF_INET;
                    563:                ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
                    564:                in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
                    565:
                    566:                return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp);
                    567:            }
                    568:        case SIOCGLIFADDR:
                    569:        case SIOCDLIFADDR:
                    570:            {
                    571:                struct in_ifaddr *ia;
                    572:                struct in_addr mask, candidate, match;
                    573:                struct sockaddr_in *sin;
                    574:                int cmp;
                    575:
                    576:                bzero(&mask, sizeof(mask));
                    577:                if (iflr->flags & IFLR_PREFIX) {
                    578:                        /* lookup a prefix rather than address. */
                    579:                        in_len2mask(&mask, iflr->prefixlen);
                    580:
                    581:                        sin = (struct sockaddr_in *)&iflr->addr;
                    582:                        match.s_addr = sin->sin_addr.s_addr;
                    583:                        match.s_addr &= mask.s_addr;
                    584:
                    585:                        /* if you set extra bits, that's wrong */
                    586:                        if (match.s_addr != sin->sin_addr.s_addr)
                    587:                                return EINVAL;
                    588:
                    589:                        cmp = 1;
                    590:                } else {
                    591:                        if (cmd == SIOCGLIFADDR) {
                    592:                                /* on getting an address, take the 1st match */
                    593:                                cmp = 0;        /*XXX*/
                    594:                        } else {
                    595:                                /* on deleting an address, do exact match */
                    596:                                in_len2mask(&mask, 32);
                    597:                                sin = (struct sockaddr_in *)&iflr->addr;
                    598:                                match.s_addr = sin->sin_addr.s_addr;
                    599:
                    600:                                cmp = 1;
                    601:                        }
                    602:                }
                    603:
                    604:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                    605:                        if (ifa->ifa_addr->sa_family != AF_INET)
                    606:                                continue;
                    607:                        if (!cmp)
                    608:                                break;
                    609:                        candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
                    610:                        candidate.s_addr &= mask.s_addr;
                    611:                        if (candidate.s_addr == match.s_addr)
                    612:                                break;
                    613:                }
                    614:                if (!ifa)
                    615:                        return EADDRNOTAVAIL;
                    616:                ia = (struct in_ifaddr *)ifa;
                    617:
                    618:                if (cmd == SIOCGLIFADDR) {
                    619:                        /* fill in the if_laddrreq structure */
                    620:                        bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
                    621:
                    622:                        if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
                    623:                                bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
                    624:                                        ia->ia_dstaddr.sin_len);
                    625:                        } else
                    626:                                bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
                    627:
                    628:                        iflr->prefixlen =
                    629:                                in_mask2len(&ia->ia_sockmask.sin_addr);
                    630:
                    631:                        iflr->flags = 0;        /*XXX*/
                    632:
                    633:                        return 0;
                    634:                } else {
                    635:                        struct in_aliasreq ifra;
                    636:
                    637:                        /* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
                    638:                        bzero(&ifra, sizeof(ifra));
                    639:                        bcopy(iflr->iflr_name, ifra.ifra_name,
                    640:                                sizeof(ifra.ifra_name));
                    641:
                    642:                        bcopy(&ia->ia_addr, &ifra.ifra_addr,
                    643:                                ia->ia_addr.sin_len);
                    644:                        if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
                    645:                                bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
                    646:                                        ia->ia_dstaddr.sin_len);
                    647:                        }
                    648:                        bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
                    649:                                ia->ia_sockmask.sin_len);
                    650:
                    651:                        return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp);
                    652:                }
                    653:            }
                    654:        }
                    655:
                    656:        return EOPNOTSUPP;      /*just for safety*/
                    657: }
                    658:
                    659: /*
                    660:  * Delete any existing route for an interface.
                    661:  */
                    662: void
                    663: in_ifscrub(ifp, ia)
                    664:        struct ifnet *ifp;
                    665:        struct in_ifaddr *ia;
                    666: {
                    667:        in_scrubprefix(ia);
                    668: }
                    669:
                    670: /*
                    671:  * Initialize an interface's internet address
                    672:  * and routing table entry.
                    673:  */
                    674: int
                    675: in_ifinit(ifp, ia, sin, scrub)
                    676:        struct ifnet *ifp;
                    677:        struct in_ifaddr *ia;
                    678:        struct sockaddr_in *sin;
                    679:        int scrub;
                    680: {
                    681:        u_int32_t i = sin->sin_addr.s_addr;
                    682:        struct sockaddr_in oldaddr;
                    683:        int s = splnet(), flags = RTF_UP, error;
                    684:
                    685:        oldaddr = ia->ia_addr;
                    686:        ia->ia_addr = *sin;
                    687:        /*
                    688:         * Give the interface a chance to initialize
                    689:         * if this is its first address,
                    690:         * and to validate the address if necessary.
                    691:         */
                    692:        if (ifp->if_ioctl &&
                    693:            (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
                    694:                ia->ia_addr = oldaddr;
                    695:                splx(s);
                    696:                return (error);
                    697:        }
                    698:        splx(s);
                    699:
                    700:        /*
                    701:         * How should a packet be routed during
                    702:         * an address change--and is it safe?
                    703:         * Is the "ifp" even in a consistent state?
                    704:         * Be safe for now.
                    705:         */
                    706:        splassert(IPL_SOFTNET);
                    707:
                    708:        if (scrub) {
                    709:                ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
                    710:                in_ifscrub(ifp, ia);
                    711:                ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
                    712:        }
                    713:        if (IN_CLASSA(i))
                    714:                ia->ia_netmask = IN_CLASSA_NET;
                    715:        else if (IN_CLASSB(i))
                    716:                ia->ia_netmask = IN_CLASSB_NET;
                    717:        else
                    718:                ia->ia_netmask = IN_CLASSC_NET;
                    719:        /*
                    720:         * The subnet mask usually includes at least the standard network part,
                    721:         * but may may be smaller in the case of supernetting.
                    722:         * If it is set, we believe it.
                    723:         */
                    724:        if (ia->ia_subnetmask == 0) {
                    725:                ia->ia_subnetmask = ia->ia_netmask;
                    726:                ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
                    727:        } else
                    728:                ia->ia_netmask &= ia->ia_subnetmask;
                    729:        ia->ia_net = i & ia->ia_netmask;
                    730:        ia->ia_subnet = i & ia->ia_subnetmask;
                    731:        in_socktrim(&ia->ia_sockmask);
                    732:        /*
                    733:         * Add route for the network.
                    734:         */
                    735:        ia->ia_ifa.ifa_metric = ifp->if_metric;
                    736:        if (ifp->if_flags & IFF_BROADCAST) {
                    737:                ia->ia_broadaddr.sin_addr.s_addr =
                    738:                        ia->ia_subnet | ~ia->ia_subnetmask;
                    739:                ia->ia_netbroadcast.s_addr =
                    740:                        ia->ia_net | ~ia->ia_netmask;
                    741:        } else if (ifp->if_flags & IFF_LOOPBACK) {
                    742:                ia->ia_dstaddr = ia->ia_addr;
                    743:                flags |= RTF_HOST;
                    744:        } else if (ifp->if_flags & IFF_POINTOPOINT) {
                    745:                if (ia->ia_dstaddr.sin_family != AF_INET)
                    746:                        return (0);
                    747:                flags |= RTF_HOST;
                    748:        }
                    749:        error = in_addprefix(ia, flags);
                    750:        /*
                    751:         * If the interface supports multicast, join the "all hosts"
                    752:         * multicast group on that interface.
                    753:         */
                    754:        if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
                    755:                struct in_addr addr;
                    756:
                    757:                addr.s_addr = INADDR_ALLHOSTS_GROUP;
                    758:                ia->ia_allhosts = in_addmulti(&addr, ifp);
                    759:        }
                    760:        return (error);
                    761: }
                    762:
                    763: #define rtinitflags(x) \
                    764:        ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
                    765:            ? RTF_HOST : 0)
                    766:
                    767: /*
                    768:  * add a route to prefix ("connected route" in cisco terminology).
                    769:  * does nothing if there's some interface address with the same prefix already.
                    770:  */
                    771: int
                    772: in_addprefix(target, flags)
                    773:        struct in_ifaddr *target;
                    774:        int flags;
                    775: {
                    776:        struct in_ifaddr *ia;
                    777:        struct in_addr prefix, mask, p;
                    778:        int error;
                    779:
                    780:        if ((flags & RTF_HOST) != 0)
                    781:                prefix = target->ia_dstaddr.sin_addr;
                    782:        else {
                    783:                prefix = target->ia_addr.sin_addr;
                    784:                mask = target->ia_sockmask.sin_addr;
                    785:                prefix.s_addr &= mask.s_addr;
                    786:        }
                    787:
                    788:        TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
                    789:                if (rtinitflags(ia)) {
                    790:                        p = ia->ia_dstaddr.sin_addr;
                    791:                        if (prefix.s_addr != p.s_addr)
                    792:                                continue;
                    793:                } else {
                    794:                        p = ia->ia_addr.sin_addr;
                    795:                        p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
                    796:                        if (prefix.s_addr != p.s_addr ||
                    797:                            mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
                    798:                                continue;
                    799:                }
                    800:                if ((ia->ia_flags & IFA_ROUTE) == 0)
                    801:                        continue;
                    802: #if NCARP > 0
                    803:                /* move to a real interface instead of carp interface */
                    804:                if (ia->ia_ifp->if_type == IFT_CARP &&
                    805:                    target->ia_ifp->if_type != IFT_CARP) {
                    806:                        rtinit(&(ia->ia_ifa), (int)RTM_DELETE,
                    807:                            rtinitflags(ia));
                    808:                        ia->ia_flags &= ~IFA_ROUTE;
                    809:                        break;
                    810:                }
                    811: #endif
                    812:                /*
                    813:                 * if we got a matching prefix route inserted by other
                    814:                 * interface adderss, we don't need to bother
                    815:                 */
                    816:                return 0;
                    817:        }
                    818:
                    819:        /*
                    820:         * noone seem to have prefix route.  insert it.
                    821:         */
                    822:        error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
                    823:        if (!error)
                    824:                target->ia_flags |= IFA_ROUTE;
                    825:        return error;
                    826: }
                    827:
                    828: /*
                    829:  * remove a route to prefix ("connected route" in cisco terminology).
                    830:  * re-installs the route by using another interface address, if there's one
                    831:  * with the same prefix (otherwise we lose the route mistakenly).
                    832:  */
                    833: int
                    834: in_scrubprefix(target)
                    835:        struct in_ifaddr *target;
                    836: {
                    837:        struct in_ifaddr *ia;
                    838:        struct in_addr prefix, mask, p;
                    839:        int error;
                    840:
                    841:        if ((target->ia_flags & IFA_ROUTE) == 0)
                    842:                return 0;
                    843:
                    844:        if (rtinitflags(target))
                    845:                prefix = target->ia_dstaddr.sin_addr;
                    846:        else {
                    847:                prefix = target->ia_addr.sin_addr;
                    848:                mask = target->ia_sockmask.sin_addr;
                    849:                prefix.s_addr &= mask.s_addr;
                    850:        }
                    851:
                    852:        TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
                    853:                if (rtinitflags(ia))
                    854:                        p = ia->ia_dstaddr.sin_addr;
                    855:                else {
                    856:                        p = ia->ia_addr.sin_addr;
                    857:                        p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
                    858:                }
                    859:
                    860:                if (prefix.s_addr != p.s_addr)
                    861:                        continue;
                    862:
                    863:                /*
                    864:                 * if we got a matching prefix route, move IFA_ROUTE to him
                    865:                 */
                    866:                if ((ia->ia_flags & IFA_ROUTE) == 0) {
                    867:                        rtinit(&(target->ia_ifa), (int)RTM_DELETE,
                    868:                            rtinitflags(target));
                    869:                        target->ia_flags &= ~IFA_ROUTE;
                    870:
                    871:                        error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
                    872:                            rtinitflags(ia) | RTF_UP);
                    873:                        if (error == 0)
                    874:                                ia->ia_flags |= IFA_ROUTE;
                    875:                        return error;
                    876:                }
                    877:        }
                    878:
                    879:        /*
                    880:         * noone seem to have prefix route.  remove it.
                    881:         */
                    882:        rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
                    883:        target->ia_flags &= ~IFA_ROUTE;
                    884:        return 0;
                    885: }
                    886:
                    887: #undef rtinitflags
                    888:
                    889: /*
                    890:  * Return 1 if the address might be a local broadcast address.
                    891:  */
                    892: int
                    893: in_broadcast(in, ifp)
                    894:        struct in_addr in;
                    895:        struct ifnet *ifp;
                    896: {
                    897:        struct ifnet *ifn, *if_first, *if_target;
                    898:        struct ifaddr *ifa;
                    899:
                    900:        if (in.s_addr == INADDR_BROADCAST ||
                    901:            in.s_addr == INADDR_ANY)
                    902:                return 1;
                    903:
                    904:        if (ifp == NULL) {
                    905:                if_first = TAILQ_FIRST(&ifnet);
                    906:                if_target = 0;
                    907:        } else {
                    908:                if_first = ifp;
                    909:                if_target = TAILQ_NEXT(ifp, if_list);
                    910:        }
                    911:
                    912: #define ia (ifatoia(ifa))
                    913:        /*
                    914:         * Look through the list of addresses for a match
                    915:         * with a broadcast address.
                    916:         * If ifp is NULL, check against all the interfaces.
                    917:         */
                    918:         for (ifn = if_first; ifn != if_target; ifn = TAILQ_NEXT(ifn, if_list)) {
                    919:                if ((ifn->if_flags & IFF_BROADCAST) == 0)
                    920:                        continue;
                    921:                TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
                    922:                        if (ifa->ifa_addr->sa_family == AF_INET &&
                    923:                            in.s_addr != ia->ia_addr.sin_addr.s_addr &&
                    924:                            (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
                    925:                             in.s_addr == ia->ia_netbroadcast.s_addr ||
                    926:                             (hostzeroisbroadcast &&
                    927:                              /*
                    928:                               * Check for old-style (host 0) broadcast.
                    929:                               */
                    930:                              (in.s_addr == ia->ia_subnet ||
                    931:                               in.s_addr == ia->ia_net))))
                    932:                                return 1;
                    933:        }
                    934:        return (0);
                    935: #undef ia
                    936: }
                    937:
                    938: /*
                    939:  * Add an address to the list of IP multicast addresses for a given interface.
                    940:  */
                    941: struct in_multi *
                    942: in_addmulti(ap, ifp)
                    943:        struct in_addr *ap;
                    944:        struct ifnet *ifp;
                    945: {
                    946:        struct in_multi *inm;
                    947:        struct ifreq ifr;
                    948:        struct in_ifaddr *ia;
                    949:        int s = splsoftnet();
                    950:
                    951:        /*
                    952:         * See if address already in list.
                    953:         */
                    954:        IN_LOOKUP_MULTI(*ap, ifp, inm);
                    955:        if (inm != NULL) {
                    956:                /*
                    957:                 * Found it; just increment the reference count.
                    958:                 */
                    959:                ++inm->inm_refcount;
                    960:        } else {
                    961:                /*
                    962:                 * New address; allocate a new multicast record
                    963:                 * and link it into the interface's multicast list.
                    964:                 */
                    965:                inm = (struct in_multi *)malloc(sizeof(*inm),
                    966:                    M_IPMADDR, M_NOWAIT);
                    967:                if (inm == NULL) {
                    968:                        splx(s);
                    969:                        return (NULL);
                    970:                }
                    971:                inm->inm_addr = *ap;
                    972:                inm->inm_refcount = 1;
                    973:                IFP_TO_IA(ifp, ia);
                    974:                if (ia == NULL) {
                    975:                        free(inm, M_IPMADDR);
                    976:                        splx(s);
                    977:                        return (NULL);
                    978:                }
                    979:                inm->inm_ia = ia;
                    980:                ia->ia_ifa.ifa_refcnt++;
                    981:                LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
                    982:                /*
                    983:                 * Ask the network driver to update its multicast reception
                    984:                 * filter appropriately for the new address.
                    985:                 */
                    986:                satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
                    987:                satosin(&ifr.ifr_addr)->sin_family = AF_INET;
                    988:                satosin(&ifr.ifr_addr)->sin_addr = *ap;
                    989:                if ((ifp->if_ioctl == NULL) ||
                    990:                    (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
                    991:                        LIST_REMOVE(inm, inm_list);
                    992:                        IFAFREE(&inm->inm_ia->ia_ifa);
                    993:                        free(inm, M_IPMADDR);
                    994:                        splx(s);
                    995:                        return (NULL);
                    996:                }
                    997:                /*
                    998:                 * Let IGMP know that we have joined a new IP multicast group.
                    999:                 */
                   1000:                igmp_joingroup(inm);
                   1001:        }
                   1002:        splx(s);
                   1003:        return (inm);
                   1004: }
                   1005:
                   1006: /*
                   1007:  * Delete a multicast address record.
                   1008:  */
                   1009: void
                   1010: in_delmulti(inm)
                   1011:        struct in_multi *inm;
                   1012: {
                   1013:        struct ifreq ifr;
                   1014:        struct ifnet *ifp;
                   1015:        int s = splsoftnet();
                   1016:
                   1017:        if (--inm->inm_refcount == 0) {
                   1018:                /*
                   1019:                 * No remaining claims to this record; let IGMP know that
                   1020:                 * we are leaving the multicast group.
                   1021:                 */
                   1022:                igmp_leavegroup(inm);
                   1023:                /*
                   1024:                 * Unlink from list.
                   1025:                 */
                   1026:                LIST_REMOVE(inm, inm_list);
                   1027:                ifp = inm->inm_ia->ia_ifp;
                   1028:                IFAFREE(&inm->inm_ia->ia_ifa);
                   1029:
                   1030:                if (ifp) {
                   1031:                        /*
                   1032:                         * Notify the network driver to update its multicast
                   1033:                         * reception filter.
                   1034:                         */
                   1035:                        satosin(&ifr.ifr_addr)->sin_family = AF_INET;
                   1036:                        satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
                   1037:                        (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
                   1038:                }
                   1039:                free(inm, M_IPMADDR);
                   1040:        }
                   1041:        splx(s);
                   1042: }
                   1043:
                   1044: #endif

CVSweb