[BACK]Return to at_control.c CVS log [TXT][DIR] Up to [local] / sys / netatalk

Annotation of sys/netatalk/at_control.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: at_control.c,v 1.10 2007/04/10 17:47:55 miod Exp $    */
                      2:
                      3: /*
                      4:  * Copyright (c) 1990,1991 Regents of The University of Michigan.
                      5:  * All Rights Reserved.
                      6:  */
                      7:
                      8: /*
                      9:  * The following is the contents of the COPYRIGHT file from the
                     10:  * netatalk-1.4a2 distribution, from which this file is derived.
                     11:  */
                     12: /*
                     13:  * Copyright (c) 1990,1996 Regents of The University of Michigan.
                     14:  *
                     15:  * All Rights Reserved.
                     16:  *
                     17:  *    Permission to use, copy, modify, and distribute this software and
                     18:  *    its documentation for any purpose and without fee is hereby granted,
                     19:  *    provided that the above copyright notice appears in all copies and
                     20:  *    that both that copyright notice and this permission notice appear
                     21:  *    in supporting documentation, and that the name of The University
                     22:  *    of Michigan not be used in advertising or publicity pertaining to
                     23:  *    distribution of the software without specific, written prior
                     24:  *    permission. This software is supplied as is without expressed or
                     25:  *    implied warranties of any kind.
                     26:  *
                     27:  * This product includes software developed by the University of
                     28:  * California, Berkeley and its contributors.
                     29:  *
                     30:  * Solaris code is encumbered by the following:
                     31:  *
                     32:  *     Copyright (C) 1996 by Sun Microsystems Computer Co.
                     33:  *
                     34:  *     Permission to use, copy, modify, and distribute this software and
                     35:  *     its documentation for any purpose and without fee is hereby
                     36:  *     granted, provided that the above copyright notice appear in all
                     37:  *     copies and that both that copyright notice and this permission
                     38:  *     notice appear in supporting documentation.  This software is
                     39:  *     provided "as is" without express or implied warranty.
                     40:  *
                     41:  * Research Systems Unix Group
                     42:  * The University of Michigan
                     43:  * c/o Wesley Craig
                     44:  * 535 W. William Street
                     45:  * Ann Arbor, Michigan
                     46:  * +1-313-764-2278
                     47:  * netatalk@umich.edu
                     48:  */
                     49: /*
                     50:  * None of the Solaris code mentioned is included in OpenBSD.
                     51:  * This code also relies heavily on previous effort in FreeBSD and NetBSD.
                     52:  */
                     53:
                     54: #include <sys/param.h>
                     55: #include <sys/systm.h>
                     56: #include <sys/kernel.h>
                     57: #include <sys/malloc.h>
                     58: #include <sys/mbuf.h>
                     59: #include <sys/protosw.h>
                     60: #include <sys/socket.h>
                     61: #include <sys/ioctl.h>
                     62: #include <sys/errno.h>
                     63: #include <sys/syslog.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/timeout.h>
                     66:
                     67: #include <net/if.h>
                     68: #include <net/route.h>
                     69: #include <netinet/in.h>
                     70: #undef s_net
                     71: #include <netinet/if_ether.h>
                     72: #include <net/if_llc.h>
                     73:
                     74: #include <netatalk/at.h>
                     75: #include <netatalk/at_var.h>
                     76: #include <netatalk/aarp.h>
                     77: #include <netatalk/phase2.h>
                     78: #include <netatalk/at_extern.h>
                     79:
                     80: #include <dev/rndvar.h>
                     81:
                     82: int    at_control( u_long, caddr_t, struct ifnet *, struct proc * );
                     83: static int at_scrub( struct ifnet *, struct at_ifaddr * );
                     84: static int at_ifinit( struct ifnet *, struct at_ifaddr *,
                     85:                                struct sockaddr_at * );
                     86: int at_broadcast( struct sockaddr_at * );
                     87:
                     88: static int aa_dorangeroute(struct ifaddr *, u_int, u_int, int);
                     89: static int aa_addsingleroute(struct ifaddr *, struct at_addr *,
                     90:                                        struct at_addr *);
                     91: static int aa_delsingleroute(struct ifaddr *, struct at_addr *,
                     92:                                        struct at_addr *);
                     93: static int aa_dosingleroute(struct ifaddr *, struct at_addr *,
                     94:                                        struct at_addr *, int, int );
                     95:
                     96: # define sateqaddr(a,b)        ((a)->sat_len == (b)->sat_len && \
                     97:                    (a)->sat_family == (b)->sat_family && \
                     98:                    (a)->sat_addr.s_net == (b)->sat_addr.s_net && \
                     99:                    (a)->sat_addr.s_node == (b)->sat_addr.s_node )
                    100:
                    101: extern struct timeout aarpprobe_timeout;
                    102:
                    103: int
                    104: at_control( cmd, data, ifp, p )
                    105:     u_long             cmd;
                    106:     caddr_t            data;
                    107:     struct ifnet       *ifp;
                    108:     struct proc                *p;
                    109: {
                    110:     struct ifreq       *ifr = (struct ifreq *)data;
                    111:     struct sockaddr_at *sat;
                    112:     struct netrange    *nr;
                    113:     struct at_aliasreq *ifra = (struct at_aliasreq *)data;
                    114:     struct at_ifaddr   *aa0;
                    115:     struct at_ifaddr   *aa = 0;
                    116:     struct ifaddr      *ifa, *ifa0;
                    117:
                    118:     if ( ifp ) {
                    119:        for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
                    120:            if ( aa->aa_ifp == ifp ) break;
                    121:        }
                    122:     }
                    123:
                    124:     switch ( cmd ) {
                    125:     case SIOCAIFADDR:
                    126:     case SIOCDIFADDR:
                    127:        if ( ifra->ifra_addr.sat_family == AF_APPLETALK ) {
                    128:            for ( ; aa; aa = aa->aa_next ) {
                    129:                if ( aa->aa_ifp == ifp &&
                    130:                        sateqaddr( &aa->aa_addr, &ifra->ifra_addr )) {
                    131:                    break;
                    132:                }
                    133:            }
                    134:        }
                    135:        if ( cmd == SIOCDIFADDR && aa == 0 ) {
                    136:            return( EADDRNOTAVAIL );
                    137:        }
                    138:        /*FALLTHROUGH*/
                    139:
                    140:     case SIOCSIFADDR:
                    141:        /*
                    142:         * What a great idea this is: Let's reverse the meaning of
                    143:         * the return...
                    144:         */
                    145:        if ( suser( p, 0 )) {
                    146:            return( EPERM );
                    147:        }
                    148:
                    149:        sat = satosat( &ifr->ifr_addr );
                    150:        nr = (struct netrange *)sat->sat_zero;
                    151:        if ( nr->nr_phase == 1 ) {
                    152:            for ( ; aa; aa = aa->aa_next ) {
                    153:                if ( aa->aa_ifp == ifp &&
                    154:                        ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
                    155:                    break;
                    156:                }
                    157:            }
                    158:        } else {                /* default to phase 2 */
                    159:            for ( ; aa; aa = aa->aa_next ) {
                    160:                if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) {
                    161:                    break;
                    162:                }
                    163:            }
                    164:        }
                    165:
                    166:        if ( ifp == 0 )
                    167:            panic( "at_control" );
                    168:
                    169:        if ( aa == (struct at_ifaddr *) 0 ) {
                    170:            aa0 = malloc(sizeof(struct at_ifaddr), M_IFADDR, M_WAITOK);
                    171:            bzero(aa0, sizeof(struct at_ifaddr));
                    172:
                    173:            if (( aa = at_ifaddr ) != NULL ) {
                    174:                /*
                    175:                 * Don't let the loopback be first, since the first
                    176:                 * address is the machine's default address for
                    177:                 * binding.
                    178:                 */
                    179:                if ( at_ifaddr->aa_ifp->if_flags & IFF_LOOPBACK ) {
                    180:                    aa = aa0;
                    181:                    aa->aa_next = at_ifaddr;
                    182:                    at_ifaddr = aa;
                    183:                } else {
                    184:                    for ( ; aa->aa_next; aa = aa->aa_next )
                    185:                        ;
                    186:                    aa->aa_next = aa0;
                    187:                }
                    188:            } else {
                    189:                at_ifaddr = aa0;
                    190:            }
                    191:
                    192:            aa = aa0;
                    193:
                    194:            if (( ifa = ifp->if_addrlist.tqh_first ) != NULL ) {
                    195:                for ( ; ifa->ifa_list.tqe_next; ifa = ifa->ifa_list.tqe_next )
                    196:                    ;
                    197:                ifa->ifa_list.tqe_next = (struct ifaddr *)aa;
                    198:            } else {
                    199:                ifp->if_addrlist.tqh_first = (struct ifaddr *)aa;
                    200:            }
                    201:
                    202:            /* FreeBSD found this. Whew */
                    203:            aa->aa_ifa.ifa_refcnt++;
                    204:
                    205:            aa->aa_ifa.ifa_addr = (struct sockaddr *)&aa->aa_addr;
                    206:            aa->aa_ifa.ifa_dstaddr = (struct sockaddr *)&aa->aa_addr;
                    207:            aa->aa_ifa.ifa_netmask = (struct sockaddr *)&aa->aa_netmask;
                    208:
                    209:            /*
                    210:             * Set/clear the phase 2 bit.
                    211:             */
                    212:            if ( nr->nr_phase == 1 ) {
                    213:                aa->aa_flags &= ~AFA_PHASE2;
                    214:            } else {
                    215:                aa->aa_flags |= AFA_PHASE2;
                    216:            }
                    217:            aa->aa_ifp = ifp;
                    218:        } else {
                    219:            at_scrub( ifp, aa );
                    220:        }
                    221:        break;
                    222:
                    223:     case SIOCGIFADDR :
                    224:        sat = satosat( &ifr->ifr_addr );
                    225:        nr = (struct netrange *)sat->sat_zero;
                    226:        if ( nr->nr_phase == 1 ) {
                    227:            for ( ; aa; aa = aa->aa_next ) {
                    228:                if ( aa->aa_ifp == ifp &&
                    229:                        ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
                    230:                    break;
                    231:                }
                    232:            }
                    233:        } else {                /* default to phase 2 */
                    234:            for ( ; aa; aa = aa->aa_next ) {
                    235:                if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) {
                    236:                    break;
                    237:                }
                    238:            }
                    239:        }
                    240:
                    241:        if ( aa == (struct at_ifaddr *) 0 )
                    242:            return( EADDRNOTAVAIL );
                    243:        break;
                    244:     }
                    245:
                    246:     switch ( cmd ) {
                    247:     case SIOCGIFADDR:
                    248:        *(struct sockaddr_at *)&ifr->ifr_addr = aa->aa_addr;
                    249:
                    250:        /* from FreeBSD : some cleanups about netranges */
                    251:        ((struct netrange *)&sat->sat_zero)->nr_phase
                    252:                = (aa->aa_flags & AFA_PHASE2) ? 2 : 1;
                    253:        ((struct netrange *)&sat->sat_zero)->nr_firstnet = aa->aa_firstnet;
                    254:        ((struct netrange *)&sat->sat_zero)->nr_lastnet = aa->aa_lastnet;
                    255:        break;
                    256:
                    257:     case SIOCSIFADDR:
                    258:        return( at_ifinit( ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr ));
                    259:
                    260:     case SIOCAIFADDR:
                    261:        if ( sateqaddr( &ifra->ifra_addr, &aa->aa_addr )) {
                    262:            return( 0 );
                    263:        }
                    264:        return( at_ifinit( ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr ));
                    265:
                    266:     case SIOCDIFADDR:
                    267:        at_scrub( ifp, aa );
                    268:        ifa0 = (struct ifaddr *)aa;
                    269:        if (( ifa = ifp->if_addrlist.tqh_first ) == ifa0 ) {
                    270:            ifp->if_addrlist.tqh_first = ifa->ifa_list.tqe_next;
                    271:        } else {
                    272:            while ( ifa->ifa_list.tqe_next &&
                    273:                        ( ifa->ifa_list.tqe_next != ifa0 )) {
                    274:                ifa = ifa->ifa_list.tqe_next;
                    275:            }
                    276:            if ( ifa->ifa_list.tqe_next ) {
                    277:                ifa->ifa_list.tqe_next = ifa0->ifa_list.tqe_next;
                    278:            } else {
                    279:                panic( "at_control" );
                    280:            }
                    281:        }
                    282:
                    283:        /* FreeBSD */
                    284:        IFAFREE(ifa0);
                    285:
                    286:        aa0 = aa;
                    287:        if ( aa0 == ( aa = at_ifaddr )) {
                    288:            at_ifaddr = aa->aa_next;
                    289:        } else {
                    290:            while ( aa->aa_next && ( aa->aa_next != aa0 )) {
                    291:                aa = aa->aa_next;
                    292:            }
                    293:            if ( aa->aa_next ) {
                    294:                aa->aa_next = aa0->aa_next;
                    295:            } else {
                    296:                panic( "at_control" );
                    297:            }
                    298:        }
                    299:
                    300:        /* FreeBSD */
                    301:        IFAFREE(ifa0);
                    302:        break;
                    303:
                    304:     default:
                    305:        if ( ifp == 0 || ifp->if_ioctl == 0 )
                    306:            return( EOPNOTSUPP );
                    307:        return( (*ifp->if_ioctl)( ifp, cmd, data ));
                    308:     }
                    309:     return( 0 );
                    310: }
                    311:
                    312: /* replaced this routine with the one from FreeBSD */
                    313: static int
                    314: at_scrub( ifp, aa )
                    315:     struct ifnet       *ifp;
                    316:     struct at_ifaddr   *aa;
                    317: {
                    318:     int                        error;
                    319:
                    320:     if ( aa->aa_flags & AFA_ROUTE ) {
                    321:        if (ifp->if_flags & IFF_LOOPBACK) {
                    322:                if ((error = aa_delsingleroute(&aa->aa_ifa,
                    323:                                        &aa->aa_addr.sat_addr,
                    324:                                        &aa->aa_netmask.sat_addr))) {
                    325:                        return( error );
                    326:                }
                    327:        } else if (ifp->if_flags & IFF_POINTOPOINT) {
                    328:                if ((error = rtinit( &aa->aa_ifa, RTM_DELETE, RTF_HOST)) != 0)
                    329:                        return( error );
                    330:        } else if (ifp->if_flags & IFF_BROADCAST) {
                    331:                error = aa_dorangeroute(&aa->aa_ifa,
                    332:                                ntohs(aa->aa_firstnet),
                    333:                                ntohs(aa->aa_lastnet),
                    334:                                RTM_DELETE );
                    335:        }
                    336:        aa->aa_ifa.ifa_flags &= ~IFA_ROUTE;
                    337:        aa->aa_flags &= ~AFA_ROUTE;
                    338:     }
                    339:     return( 0 );
                    340: }
                    341:
                    342: static int
                    343: at_ifinit( ifp, aa, sat )
                    344:     struct ifnet       *ifp;
                    345:     struct at_ifaddr   *aa;
                    346:     struct sockaddr_at *sat;
                    347: {
                    348:     struct netrange    nr, onr;
                    349:     struct sockaddr_at oldaddr;
                    350:     int                        s = splnet(), error = 0, i, j, netinc, nodeinc, nnets;
                    351:     u_int16_t          net;
                    352:
                    353:     oldaddr = aa->aa_addr;
                    354:     bzero( AA_SAT( aa ), sizeof( struct sockaddr_at ));
                    355:     bcopy( sat->sat_zero, &nr, sizeof( struct netrange ));
                    356:     bcopy( sat->sat_zero, AA_SAT( aa )->sat_zero, sizeof( struct netrange ));
                    357:     nnets = ntohs( nr.nr_lastnet ) - ntohs( nr.nr_firstnet ) + 1;
                    358:
                    359:     onr.nr_firstnet = aa->aa_firstnet;
                    360:     onr.nr_lastnet = aa->aa_lastnet;
                    361:     aa->aa_firstnet = nr.nr_firstnet;
                    362:     aa->aa_lastnet = nr.nr_lastnet;
                    363:
                    364:     /*
                    365:      * We could eliminate the need for a second phase 1 probe (post
                    366:      * autoconf) if we check whether we're resetting the node. Note
                    367:      * that phase 1 probes use only nodes, not net.node pairs.  Under
                    368:      * phase 2, both the net and node must be the same.
                    369:      */
                    370:     if ( ifp->if_flags & IFF_LOOPBACK ) {
                    371:        AA_SAT( aa )->sat_len = sat->sat_len;
                    372:        AA_SAT( aa )->sat_family = AF_APPLETALK;
                    373:        AA_SAT( aa )->sat_addr.s_net = sat->sat_addr.s_net;
                    374:        AA_SAT( aa )->sat_addr.s_node = sat->sat_addr.s_node;
                    375:     } else {
                    376:        aa->aa_flags |= AFA_PROBING;
                    377:        AA_SAT( aa )->sat_len = sizeof(struct sockaddr_at);
                    378:        AA_SAT( aa )->sat_family = AF_APPLETALK;
                    379:        if ( aa->aa_flags & AFA_PHASE2 ) {
                    380:            if ( sat->sat_addr.s_net == ATADDR_ANYNET ) {
                    381:                if ( nnets != 1 ) {
                    382:                    net = ntohs( nr.nr_firstnet ) +
                    383:                        arc4random() % ( nnets - 1 );
                    384:                } else {
                    385:                    net = ntohs( nr.nr_firstnet );
                    386:                }
                    387:            } else {
                    388:                if ( ntohs( sat->sat_addr.s_net ) < ntohs( nr.nr_firstnet ) ||
                    389:                        ntohs( sat->sat_addr.s_net ) > ntohs( nr.nr_lastnet )) {
                    390:                    aa->aa_addr = oldaddr;
                    391:                    aa->aa_firstnet = onr.nr_firstnet;
                    392:                    aa->aa_lastnet = onr.nr_lastnet;
                    393:                    splx(s);
                    394:                    return( EINVAL );
                    395:                }
                    396:                net = ntohs( sat->sat_addr.s_net );
                    397:            }
                    398:        } else {
                    399:            net = ntohs( sat->sat_addr.s_net );
                    400:        }
                    401:
                    402:        if ( sat->sat_addr.s_node == ATADDR_ANYNODE ) {
                    403:            AA_SAT( aa )->sat_addr.s_node = arc4random();
                    404:        } else {
                    405:            AA_SAT( aa )->sat_addr.s_node = sat->sat_addr.s_node;
                    406:        }
                    407:
                    408:        for ( i = nnets, netinc = 1; i > 0; net = ntohs( nr.nr_firstnet ) +
                    409:                (( net - ntohs( nr.nr_firstnet ) + netinc ) % nnets ), i-- ) {
                    410:            AA_SAT( aa )->sat_addr.s_net = htons( net );
                    411:
                    412:            for ( j = 0, nodeinc = arc4random() | 1; j < 256;
                    413:                    j++, AA_SAT( aa )->sat_addr.s_node += nodeinc ) {
                    414:                if ( AA_SAT( aa )->sat_addr.s_node > 253 ||
                    415:                        AA_SAT( aa )->sat_addr.s_node < 1 ) {
                    416:                    continue;
                    417:                }
                    418:                aa->aa_probcnt = 10;
                    419:                timeout_set(&aarpprobe_timeout, aarpprobe, ifp);
                    420:                /* XXX don't use hz so badly */
                    421:                timeout_add(&aarpprobe_timeout, hz / 5);
                    422:                if ( tsleep( aa, PPAUSE|PCATCH, "at_ifinit", 0 )) {
                    423:                    printf( "at_ifinit why did this happen?!\n" );
                    424:                    aa->aa_addr = oldaddr;
                    425:                    aa->aa_firstnet = onr.nr_firstnet;
                    426:                    aa->aa_lastnet = onr.nr_lastnet;
                    427:                    splx( s );
                    428:                    return( EINTR );
                    429:                }
                    430:                if (( aa->aa_flags & AFA_PROBING ) == 0 ) {
                    431:                    break;
                    432:                }
                    433:            }
                    434:            if (( aa->aa_flags & AFA_PROBING ) == 0 ) {
                    435:                break;
                    436:            }
                    437:            /* reset node for next network */
                    438:            AA_SAT( aa )->sat_addr.s_node = arc4random();
                    439:        }
                    440:
                    441:        if ( aa->aa_flags & AFA_PROBING ) {
                    442:            aa->aa_addr = oldaddr;
                    443:            aa->aa_firstnet = onr.nr_firstnet;
                    444:            aa->aa_lastnet = onr.nr_lastnet;
                    445:            splx( s );
                    446:            return( EADDRINUSE );
                    447:        }
                    448:     }
                    449:
                    450:     if ( ifp->if_ioctl &&
                    451:            ( error = (*ifp->if_ioctl)( ifp, SIOCSIFADDR, (caddr_t) aa ))) {
                    452:        aa->aa_addr = oldaddr;
                    453:        aa->aa_firstnet = onr.nr_firstnet;
                    454:        aa->aa_lastnet = onr.nr_lastnet;
                    455:        splx( s );
                    456:        return( error );
                    457:     }
                    458:
                    459:     bzero(&aa->aa_netmask, sizeof(aa->aa_netmask));
                    460:     aa->aa_netmask.sat_len = sizeof(struct sockaddr_at);
                    461:     aa->aa_netmask.sat_family = AF_APPLETALK;
                    462:     aa->aa_netmask.sat_addr.s_net = 0xffff;
                    463:     aa->aa_netmask.sat_addr.s_node = 0;
                    464:     /* XXX From FreeBSD. Why does it do this? */
                    465:     aa->aa_ifa.ifa_netmask =(struct sockaddr *) &(aa->aa_netmask);
                    466:
                    467:     /* This block came from FreeBSD too */
                    468:     /*
                    469:      * Initialize broadcast (or remote p2p) address
                    470:      */
                    471:     bzero(&aa->aa_broadaddr, sizeof(aa->aa_broadaddr));
                    472:     aa->aa_broadaddr.sat_len = sizeof(struct sockaddr_at);
                    473:     aa->aa_broadaddr.sat_family = AF_APPLETALK;
                    474:
                    475:     aa->aa_ifa.ifa_metric = ifp->if_metric;
                    476:     if (ifp->if_flags & IFF_BROADCAST) {
                    477:        aa->aa_broadaddr.sat_addr.s_net = htons(0);
                    478:        aa->aa_broadaddr.sat_addr.s_node = 0xff;
                    479:        aa->aa_ifa.ifa_broadaddr = (struct sockaddr *) &aa->aa_broadaddr;
                    480:        /* add the range of routes needed */
                    481:        error = aa_dorangeroute(&aa->aa_ifa,
                    482:                ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), RTM_ADD );
                    483:     }
                    484:     else if (ifp->if_flags & IFF_POINTOPOINT) {
                    485:        struct at_addr  rtaddr, rtmask;
                    486:
                    487:        bzero(&rtaddr, sizeof(rtaddr));
                    488:        bzero(&rtmask, sizeof(rtmask));
                    489:        /* fill in the far end if we know it here XXX */
                    490:        aa->aa_ifa.ifa_dstaddr = (struct sockaddr *) &aa->aa_broadaddr;
                    491:        error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask);
                    492:     }
                    493:     else if ( ifp->if_flags & IFF_LOOPBACK ) {
                    494:        struct at_addr  rtaddr, rtmask;
                    495:
                    496:        bzero(&rtaddr, sizeof(rtaddr));
                    497:        bzero(&rtmask, sizeof(rtmask));
                    498:        rtaddr.s_net = AA_SAT( aa )->sat_addr.s_net;
                    499:        rtaddr.s_node = AA_SAT( aa )->sat_addr.s_node;
                    500:        rtmask.s_net = 0xffff;
                    501:        rtmask.s_node = 0x0; /* XXX should not be so.. should be HOST route */
                    502:        error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask);
                    503:     }
                    504:
                    505:     if ( error ) {
                    506:        at_scrub( ifp, aa );
                    507:        aa->aa_addr = oldaddr;
                    508:        aa->aa_firstnet = onr.nr_firstnet;
                    509:        aa->aa_lastnet = onr.nr_lastnet;
                    510:        splx( s );
                    511:        return( error );
                    512:     }
                    513:
                    514:     aa->aa_ifa.ifa_flags |= IFA_ROUTE;
                    515:     aa->aa_flags |= AFA_ROUTE;
                    516:     splx( s );
                    517:     return( 0 );
                    518: }
                    519:
                    520: int
                    521: at_broadcast( sat )
                    522:     struct sockaddr_at *sat;
                    523: {
                    524:     struct at_ifaddr   *aa;
                    525:
                    526:     if ( sat->sat_addr.s_node != ATADDR_BCAST ) {
                    527:        return( 0 );
                    528:     }
                    529:     if ( sat->sat_addr.s_net == ATADDR_ANYNET ) {
                    530:        return( 1 );
                    531:     } else {
                    532:        for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
                    533:            if (( aa->aa_ifp->if_flags & IFF_BROADCAST ) &&
                    534:                 ( ntohs( sat->sat_addr.s_net ) >= ntohs( aa->aa_firstnet ) &&
                    535:                 ntohs( sat->sat_addr.s_net ) <= ntohs( aa->aa_lastnet ))) {
                    536:                return( 1 );
                    537:            }
                    538:        }
                    539:     }
                    540:     return( 0 );
                    541: }
                    542:
                    543: /* Yet another bunch of routines from FreeBSD. Those guys are good */
                    544: /*
                    545:  * aa_dorangeroute()
                    546:  *
                    547:  * Add a route for a range of networks from bot to top - 1.
                    548:  * Algorithm:
                    549:  *
                    550:  * Split the range into two subranges such that the middle
                    551:  * of the two ranges is the point where the highest bit of difference
                    552:  * between the two addresses, makes its transition
                    553:  * Each of the upper and lower ranges might not exist, or might be
                    554:  * representable by 1 or more netmasks. In addition, if both
                    555:  * ranges can be represented by the same netmask, then they can be merged
                    556:  * by using the next higher netmask..
                    557:  */
                    558:
                    559: static int
                    560: aa_dorangeroute(struct ifaddr *ifa, u_int bot, u_int top, int cmd)
                    561: {
                    562:        u_int mask1;
                    563:        struct at_addr addr;
                    564:        struct at_addr mask;
                    565:        int error;
                    566:
                    567:        /*
                    568:         * slight sanity check
                    569:         */
                    570:        if (bot > top) return (EINVAL);
                    571:
                    572:        addr.s_node = 0;
                    573:        mask.s_node = 0;
                    574:        /*
                    575:         * just start out with the lowest boundary
                    576:         * and keep extending the mask till it's too big.
                    577:         */
                    578:
                    579:         while (bot <= top) {
                    580:                mask1 = 1;
                    581:                while ((( bot & ~mask1) >= bot)
                    582:                   && (( bot | mask1) <= top)) {
                    583:                        mask1 <<= 1;
                    584:                        mask1 |= 1;
                    585:                }
                    586:                mask1 >>= 1;
                    587:                mask.s_net = htons(~mask1);
                    588:                addr.s_net = htons(bot);
                    589:                if(cmd == RTM_ADD) {
                    590:                error =  aa_addsingleroute(ifa,&addr,&mask);
                    591:                        if (error) {
                    592:                                /* XXX clean up? */
                    593:                                return (error);
                    594:                        }
                    595:                } else {
                    596:                        error =  aa_delsingleroute(ifa,&addr,&mask);
                    597:                }
                    598:                bot = (bot | mask1) + 1;
                    599:        }
                    600:        return 0;
                    601: }
                    602:
                    603: static int
                    604: aa_addsingleroute(struct ifaddr *ifa,
                    605:        struct at_addr *addr, struct at_addr *mask)
                    606: {
                    607:   int  error;
                    608:
                    609: #if 0
                    610:   printf("aa_addsingleroute: %x.%x mask %x.%x ...\n",
                    611:     ntohs(addr->s_net), addr->s_node,
                    612:     ntohs(mask->s_net), mask->s_node);
                    613: #endif
                    614:
                    615:   error = aa_dosingleroute(ifa, addr, mask, RTM_ADD, RTF_UP);
                    616:   if (error)
                    617:     printf("aa_addsingleroute: error %d\n", error);
                    618:   return(error);
                    619: }
                    620:
                    621: static int
                    622: aa_delsingleroute(struct ifaddr *ifa,
                    623:        struct at_addr *addr, struct at_addr *mask)
                    624: {
                    625:   int  error;
                    626:
                    627:   error = aa_dosingleroute(ifa, addr, mask, RTM_DELETE, 0);
                    628:   if (error)
                    629:        printf("aa_delsingleroute: error %d\n", error);
                    630:   return(error);
                    631: }
                    632:
                    633: static int
                    634: aa_dosingleroute(struct ifaddr *ifa,
                    635:        struct at_addr *at_addr, struct at_addr *at_mask, int cmd, int flags)
                    636: {
                    637:   struct sockaddr_at   addr, mask;
                    638:
                    639:   bzero(&addr, sizeof(addr));
                    640:   bzero(&mask, sizeof(mask));
                    641:   addr.sat_family = AF_APPLETALK;
                    642:   addr.sat_len = sizeof(struct sockaddr_at);
                    643:   addr.sat_addr.s_net = at_addr->s_net;
                    644:   addr.sat_addr.s_node = at_addr->s_node;
                    645:   mask.sat_family = AF_APPLETALK;
                    646:   mask.sat_len = sizeof(struct sockaddr_at);
                    647:   mask.sat_addr.s_net = at_mask->s_net;
                    648:   mask.sat_addr.s_node = at_mask->s_node;
                    649:   if (at_mask->s_node)
                    650:     flags |= RTF_HOST;
                    651:   return(rtrequest(cmd, (struct sockaddr *) &addr,
                    652:        (flags & RTF_HOST)?(ifa->ifa_dstaddr):(ifa->ifa_addr),
                    653:        (struct sockaddr *) &mask, flags, NULL, 0));
                    654: }

CVSweb