Annotation of Net2/netinet/if_ether.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.2 ! root       33:  *     from: @(#)if_ether.c    7.13 (Berkeley) 10/31/90
        !            34:  *     if_ether.c,v 1.3 1993/06/27 06:02:37 andrew Exp
1.1       root       35:  */
                     36: 
                     37: /*
                     38:  * Ethernet address resolution protocol.
                     39:  * TODO:
                     40:  *     run at splnet (add ARP protocol intr.)
                     41:  *     link entries onto hash chains, keep free list
                     42:  *     add "inuse/lock" bit (or ref. count) along with valid bit
                     43:  */
                     44: 
                     45: #include "param.h"
                     46: #include "systm.h"
                     47: #include "malloc.h"
                     48: #include "mbuf.h"
                     49: #include "socket.h"
                     50: #include "time.h"
                     51: #include "kernel.h"
                     52: #include "errno.h"
                     53: #include "ioctl.h"
                     54: #include "syslog.h"
                     55: 
                     56: #include "../net/if.h"
                     57: #include "in.h"
                     58: #include "in_systm.h"
                     59: #include "in_var.h"
                     60: #include "ip.h"
                     61: #include "if_ether.h"
                     62: 
                     63: #ifdef GATEWAY
                     64: #define        ARPTAB_BSIZ     16              /* bucket size */
                     65: #define        ARPTAB_NB       37              /* number of buckets */
                     66: #else
                     67: #define        ARPTAB_BSIZ     9               /* bucket size */
                     68: #define        ARPTAB_NB       19              /* number of buckets */
                     69: #endif
                     70: #define        ARPTAB_SIZE     (ARPTAB_BSIZ * ARPTAB_NB)
                     71: struct arptab arptab[ARPTAB_SIZE];
                     72: int    arptab_size = ARPTAB_SIZE;      /* for arp command */
                     73: 
                     74: /*
                     75:  * ARP trailer negotiation.  Trailer protocol is not IP specific,
                     76:  * but ARP request/response use IP addresses.
                     77:  */
                     78: #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
                     79: 
                     80: #define        ARPTAB_HASH(a) \
                     81:        ((u_long)(a) % ARPTAB_NB)
                     82: 
                     83: #define        ARPTAB_LOOK(at,addr) { \
                     84:        register n; \
                     85:        at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \
                     86:        for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
                     87:                if (at->at_iaddr.s_addr == addr) \
                     88:                        break; \
                     89:        if (n >= ARPTAB_BSIZ) \
                     90:                at = 0; \
                     91: }
                     92: 
                     93: /* timer values */
                     94: #define        ARPT_AGE        (60*1)  /* aging timer, 1 min. */
                     95: #define        ARPT_KILLC      20      /* kill completed entry in 20 mins. */
                     96: #define        ARPT_KILLI      3       /* kill incomplete entry in 3 minutes */
                     97: 
                     98: extern struct ifnet loif;
                     99: 
                    100: /*
                    101:  * Timeout routine.  Age arp_tab entries once a minute.
                    102:  */
1.1.1.2 ! root      103: /* ARGSUSED */
        !           104: void
        !           105: arptimer(caddr_t arg)
1.1       root      106: {
                    107:        register struct arptab *at;
                    108:        register i;
                    109: 
                    110:        timeout(arptimer, (caddr_t)0, ARPT_AGE * hz);
                    111:        at = &arptab[0];
                    112:        for (i = 0; i < ARPTAB_SIZE; i++, at++) {
                    113:                if (at->at_flags == 0 || (at->at_flags & ATF_PERM))
                    114:                        continue;
                    115:                if (++at->at_timer < ((at->at_flags&ATF_COM) ?
                    116:                    ARPT_KILLC : ARPT_KILLI))
                    117:                        continue;
                    118:                /* timer has expired, clear entry */
                    119:                arptfree(at);
                    120:        }
                    121: }
                    122: 
                    123: /*
                    124:  * Broadcast an ARP packet, asking who has addr on interface ac.
                    125:  */
                    126: arpwhohas(ac, addr)
                    127:        register struct arpcom *ac;
                    128:        struct in_addr *addr;
                    129: {
                    130:        register struct mbuf *m;
                    131:        register struct ether_header *eh;
                    132:        register struct ether_arp *ea;
                    133:        struct sockaddr sa;
                    134: 
                    135:        if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
                    136:                return;
                    137:        m->m_len = sizeof(*ea);
                    138:        m->m_pkthdr.len = sizeof(*ea);
                    139:        MH_ALIGN(m, sizeof(*ea));
                    140:        ea = mtod(m, struct ether_arp *);
                    141:        eh = (struct ether_header *)sa.sa_data;
                    142:        bzero((caddr_t)ea, sizeof (*ea));
                    143:        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
                    144:            sizeof(eh->ether_dhost));
                    145:        eh->ether_type = ETHERTYPE_ARP;         /* if_output will swap */
                    146:        ea->arp_hrd = htons(ARPHRD_ETHER);
                    147:        ea->arp_pro = htons(ETHERTYPE_IP);
                    148:        ea->arp_hln = sizeof(ea->arp_sha);      /* hardware address length */
                    149:        ea->arp_pln = sizeof(ea->arp_spa);      /* protocol address length */
                    150:        ea->arp_op = htons(ARPOP_REQUEST);
                    151:        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
                    152:           sizeof(ea->arp_sha));
                    153:        bcopy((caddr_t)&ac->ac_ipaddr, (caddr_t)ea->arp_spa,
                    154:           sizeof(ea->arp_spa));
                    155:        bcopy((caddr_t)addr, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));
                    156:        sa.sa_family = AF_UNSPEC;
                    157:        sa.sa_len = sizeof(sa);
                    158:        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
                    159: }
                    160: 
                    161: int    useloopback = 1;        /* use loopback interface for local traffic */
                    162: 
                    163: /*
                    164:  * Resolve an IP address into an ethernet address.  If success, 
                    165:  * desten is filled in.  If there is no entry in arptab,
                    166:  * set one up and broadcast a request for the IP address.
                    167:  * Hold onto this mbuf and resend it once the address
                    168:  * is finally resolved.  A return value of 1 indicates
                    169:  * that desten has been filled in and the packet should be sent
                    170:  * normally; a 0 return indicates that the packet has been
                    171:  * taken over here, either now or for later transmission.
                    172:  *
                    173:  * We do some (conservative) locking here at splimp, since
                    174:  * arptab is also altered from input interrupt service (ecintr/ilintr
                    175:  * calls arpinput when ETHERTYPE_ARP packets come in).
                    176:  */
                    177: arpresolve(ac, m, destip, desten, usetrailers)
                    178:        register struct arpcom *ac;
                    179:        struct mbuf *m;
                    180:        register struct in_addr *destip;
                    181:        register u_char *desten;
                    182:        int *usetrailers;
                    183: {
                    184:        register struct arptab *at;
                    185:        struct sockaddr_in sin;
                    186:        register struct in_ifaddr *ia;
                    187:        u_long lna;
                    188:        int s;
                    189: 
                    190:        *usetrailers = 0;
                    191:        if (m->m_flags & M_BCAST) {     /* broadcast */
                    192:                bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
                    193:                    sizeof(etherbroadcastaddr));
                    194:                return (1);
                    195:        }
                    196:        lna = in_lnaof(*destip);
                    197:        /* if for us, use software loopback driver if up */
                    198:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
                    199:            if ((ia->ia_ifp == &ac->ac_if) &&
                    200:                (destip->s_addr == ia->ia_addr.sin_addr.s_addr)) {
                    201:                /*
                    202:                 * This test used to be
                    203:                 *      if (loif.if_flags & IFF_UP)
                    204:                 * It allowed local traffic to be forced
                    205:                 * through the hardware by configuring the loopback down.
                    206:                 * However, it causes problems during network configuration
                    207:                 * for boards that can't receive packets they send.
                    208:                 * It is now necessary to clear "useloopback"
                    209:                 * to force traffic out to the hardware.
                    210:                 */
                    211:                if (useloopback) {
                    212:                        sin.sin_family = AF_INET;
                    213:                        sin.sin_addr = *destip;
                    214:                        (void) looutput(&loif, m, (struct sockaddr *)&sin, 0);
                    215:                        /*
                    216:                         * The packet has already been sent and freed.
                    217:                         */
                    218:                        return (0);
                    219:                } else {
                    220:                        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten,
                    221:                            sizeof(ac->ac_enaddr));
                    222:                        return (1);
                    223:                }
                    224:        }
                    225:        s = splimp();
                    226:        ARPTAB_LOOK(at, destip->s_addr);
                    227:        if (at == 0) {                  /* not found */
                    228:                if (ac->ac_if.if_flags & IFF_NOARP) {
                    229:                        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3);
                    230:                        desten[3] = (lna >> 16) & 0x7f;
                    231:                        desten[4] = (lna >> 8) & 0xff;
                    232:                        desten[5] = lna & 0xff;
                    233:                        splx(s);
                    234:                        return (1);
                    235:                } else {
                    236:                        at = arptnew(destip);
                    237:                        if (at == 0)
                    238:                                panic("arpresolve: no free entry");
                    239:                        at->at_hold = m;
                    240:                        arpwhohas(ac, destip);
                    241:                        splx(s);
                    242:                        return (0);
                    243:                }
                    244:        }
                    245:        at->at_timer = 0;               /* restart the timer */
                    246:        if (at->at_flags & ATF_COM) {   /* entry IS complete */
                    247:                bcopy((caddr_t)at->at_enaddr, (caddr_t)desten,
                    248:                    sizeof(at->at_enaddr));
                    249:                if (at->at_flags & ATF_USETRAILERS)
                    250:                        *usetrailers = 1;
                    251:                splx(s);
                    252:                return (1);
                    253:        }
                    254:        /*
                    255:         * There is an arptab entry, but no ethernet address
                    256:         * response yet.  Replace the held mbuf with this
                    257:         * latest one.
                    258:         */
                    259:        if (at->at_hold)
                    260:                m_freem(at->at_hold);
                    261:        at->at_hold = m;
                    262:        arpwhohas(ac, destip);          /* ask again */
                    263:        splx(s);
                    264:        return (0);
                    265: }
                    266: 
                    267: /*
                    268:  * Called from 10 Mb/s Ethernet interrupt handlers
                    269:  * when ether packet type ETHERTYPE_ARP
                    270:  * is received.  Common length and type checks are done here,
                    271:  * then the protocol-specific routine is called.
                    272:  */
                    273: arpinput(ac, m)
                    274:        struct arpcom *ac;
                    275:        struct mbuf *m;
                    276: {
                    277:        register struct arphdr *ar;
                    278: 
                    279:        if (ac->ac_if.if_flags & IFF_NOARP)
                    280:                goto out;
                    281:        if (m->m_len < sizeof(struct arphdr))
                    282:                goto out;
                    283:        ar = mtod(m, struct arphdr *);
                    284:        if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)
                    285:                goto out;
                    286:        if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
                    287:                goto out;
                    288: 
                    289:        switch (ntohs(ar->ar_pro)) {
                    290: 
                    291:        case ETHERTYPE_IP:
                    292:        case ETHERTYPE_IPTRAILERS:
                    293:                in_arpinput(ac, m);
                    294:                return;
                    295: 
                    296:        default:
                    297:                break;
                    298:        }
                    299: out:
                    300:        m_freem(m);
                    301: }
                    302: 
                    303: /*
                    304:  * ARP for Internet protocols on 10 Mb/s Ethernet.
                    305:  * Algorithm is that given in RFC 826.
                    306:  * In addition, a sanity check is performed on the sender
                    307:  * protocol address, to catch impersonators.
                    308:  * We also handle negotiations for use of trailer protocol:
                    309:  * ARP replies for protocol type ETHERTYPE_TRAIL are sent
                    310:  * along with IP replies if we want trailers sent to us,
                    311:  * and also send them in response to IP replies.
                    312:  * This allows either end to announce the desire to receive
                    313:  * trailer packets.
                    314:  * We reply to requests for ETHERTYPE_TRAIL protocol as well,
                    315:  * but don't normally send requests.
                    316:  */
                    317: in_arpinput(ac, m)
                    318:        register struct arpcom *ac;
                    319:        struct mbuf *m;
                    320: {
                    321:        register struct ether_arp *ea;
                    322:        struct ether_header *eh;
                    323:        register struct arptab *at;  /* same as "merge" flag */
                    324:        register struct in_ifaddr *ia;
                    325:        struct in_ifaddr *maybe_ia = 0;
                    326:        struct mbuf *mcopy = 0;
                    327:        struct sockaddr_in sin;
                    328:        struct sockaddr sa;
                    329:        struct in_addr isaddr, itaddr, myaddr;
                    330:        int proto, op, s, completed = 0;
                    331: 
                    332:        ea = mtod(m, struct ether_arp *);
                    333:        proto = ntohs(ea->arp_pro);
                    334:        op = ntohs(ea->arp_op);
                    335:        bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr));
                    336:        bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr));
                    337:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
                    338:                if (ia->ia_ifp == &ac->ac_if) {
                    339:                        maybe_ia = ia;
                    340:                        if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
                    341:                             (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
                    342:                                break;
                    343:                }
                    344:        if (maybe_ia == 0)
                    345:                goto out;
                    346:        myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
                    347:        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
                    348:            sizeof (ea->arp_sha)))
                    349:                goto out;       /* it's from me, ignore it. */
                    350:        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
                    351:            sizeof (ea->arp_sha))) {
                    352:                log(LOG_ERR,
                    353:                    "arp: ether address is broadcast for IP address %x!\n",
                    354:                    ntohl(isaddr.s_addr));
                    355:                goto out;
                    356:        }
                    357:        if (isaddr.s_addr == myaddr.s_addr) {
                    358:                log(LOG_ERR,
                    359:                   "duplicate IP address %x!! sent from ethernet address: %s\n",
                    360:                   ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha));
                    361:                itaddr = myaddr;
                    362:                if (op == ARPOP_REQUEST)
                    363:                        goto reply;
                    364:                goto out;
                    365:        }
                    366:        s = splimp();
                    367:        ARPTAB_LOOK(at, isaddr.s_addr);
                    368:        if (at) {
                    369:                bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
                    370:                    sizeof(ea->arp_sha));
                    371:                if ((at->at_flags & ATF_COM) == 0)
                    372:                        completed = 1;
                    373:                at->at_flags |= ATF_COM;
                    374:                if (at->at_hold) {
                    375:                        sin.sin_family = AF_INET;
                    376:                        sin.sin_addr = isaddr;
                    377:                        (*ac->ac_if.if_output)(&ac->ac_if, at->at_hold,
                    378:                                (struct sockaddr *)&sin, (struct rtentry *)0);
                    379:                        at->at_hold = 0;
                    380:                }
                    381:        }
                    382:        if (at == 0 && itaddr.s_addr == myaddr.s_addr) {
                    383:                /* ensure we have a table entry */
                    384:                if (at = arptnew(&isaddr)) {
                    385:                        bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
                    386:                            sizeof(ea->arp_sha));
                    387:                        completed = 1;
                    388:                        at->at_flags |= ATF_COM;
                    389:                }
                    390:        }
                    391:        splx(s);
                    392: reply:
                    393:        switch (proto) {
                    394: 
                    395:        case ETHERTYPE_IPTRAILERS:
                    396:                /* partner says trailers are OK */
                    397:                if (at)
                    398:                        at->at_flags |= ATF_USETRAILERS;
                    399:                /*
                    400:                 * Reply to request iff we want trailers.
                    401:                 */
                    402:                if (op != ARPOP_REQUEST || ac->ac_if.if_flags & IFF_NOTRAILERS)
                    403:                        goto out;
                    404:                break;
                    405: 
                    406:        case ETHERTYPE_IP:
                    407:                /*
                    408:                 * Reply if this is an IP request,
                    409:                 * or if we want to send a trailer response.
                    410:                 * Send the latter only to the IP response
                    411:                 * that completes the current ARP entry.
                    412:                 */
                    413:                if (op != ARPOP_REQUEST &&
                    414:                    (completed == 0 || ac->ac_if.if_flags & IFF_NOTRAILERS))
                    415:                        goto out;
                    416:        }
                    417:        if (itaddr.s_addr == myaddr.s_addr) {
                    418:                /* I am the target */
                    419:                bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
                    420:                    sizeof(ea->arp_sha));
                    421:                bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
                    422:                    sizeof(ea->arp_sha));
                    423:        } else {
                    424:                ARPTAB_LOOK(at, itaddr.s_addr);
                    425:                if (at == NULL || (at->at_flags & ATF_PUBL) == 0)
                    426:                        goto out;
                    427:                bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
                    428:                    sizeof(ea->arp_sha));
                    429:                bcopy((caddr_t)at->at_enaddr, (caddr_t)ea->arp_sha,
                    430:                    sizeof(ea->arp_sha));
                    431:        }
                    432: 
                    433:        bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa,
                    434:            sizeof(ea->arp_spa));
                    435:        bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa,
                    436:            sizeof(ea->arp_spa));
                    437:        ea->arp_op = htons(ARPOP_REPLY); 
                    438:        /*
                    439:         * If incoming packet was an IP reply,
                    440:         * we are sending a reply for type IPTRAILERS.
                    441:         * If we are sending a reply for type IP
                    442:         * and we want to receive trailers,
                    443:         * send a trailer reply as well.
                    444:         */
                    445:        if (op == ARPOP_REPLY)
                    446:                ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
                    447:        else if (proto == ETHERTYPE_IP &&
                    448:            (ac->ac_if.if_flags & IFF_NOTRAILERS) == 0)
                    449:                mcopy = m_copy(m, 0, (int)M_COPYALL);
                    450:        eh = (struct ether_header *)sa.sa_data;
                    451:        bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
                    452:            sizeof(eh->ether_dhost));
                    453:        eh->ether_type = ETHERTYPE_ARP;
                    454:        sa.sa_family = AF_UNSPEC;
                    455:        sa.sa_len = sizeof(sa);
                    456:        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
                    457:        if (mcopy) {
                    458:                ea = mtod(mcopy, struct ether_arp *);
                    459:                ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
                    460:                (*ac->ac_if.if_output)(&ac->ac_if,
                    461:                                        mcopy, &sa, (struct rtentry *)0);
                    462:        }
                    463:        return;
                    464: out:
                    465:        m_freem(m);
                    466:        return;
                    467: }
                    468: 
                    469: /*
                    470:  * Free an arptab entry.
                    471:  */
                    472: arptfree(at)
                    473:        register struct arptab *at;
                    474: {
                    475:        int s = splimp();
                    476: 
                    477:        if (at->at_hold)
                    478:                m_freem(at->at_hold);
                    479:        at->at_hold = 0;
                    480:        at->at_timer = at->at_flags = 0;
                    481:        at->at_iaddr.s_addr = 0;
                    482:        splx(s);
                    483: }
                    484: 
                    485: /*
                    486:  * Enter a new address in arptab, pushing out the oldest entry 
                    487:  * from the bucket if there is no room.
                    488:  * This always succeeds since no bucket can be completely filled
                    489:  * with permanent entries (except from arpioctl when testing whether
                    490:  * another permanent entry will fit).
                    491:  * MUST BE CALLED AT SPLIMP.
                    492:  */
                    493: struct arptab *
                    494: arptnew(addr)
                    495:        struct in_addr *addr;
                    496: {
                    497:        register n;
                    498:        int oldest = -1;
                    499:        register struct arptab *at, *ato = NULL;
                    500:        static int first = 1;
                    501: 
                    502:        if (first) {
                    503:                first = 0;
                    504:                timeout(arptimer, (caddr_t)0, hz);
                    505:        }
                    506:        at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ];
                    507:        for (n = 0; n < ARPTAB_BSIZ; n++,at++) {
                    508:                if (at->at_flags == 0)
                    509:                        goto out;        /* found an empty entry */
                    510:                if (at->at_flags & ATF_PERM)
                    511:                        continue;
                    512:                if ((int) at->at_timer > oldest) {
                    513:                        oldest = at->at_timer;
                    514:                        ato = at;
                    515:                }
                    516:        }
                    517:        if (ato == NULL)
                    518:                return (NULL);
                    519:        at = ato;
                    520:        arptfree(at);
                    521: out:
                    522:        at->at_iaddr = *addr;
                    523:        at->at_flags = ATF_INUSE;
                    524:        return (at);
                    525: }
                    526: 
                    527: arpioctl(cmd, data)
                    528:        int cmd;
                    529:        caddr_t data;
                    530: {
                    531:        register struct arpreq *ar = (struct arpreq *)data;
                    532:        register struct arptab *at;
                    533:        register struct sockaddr_in *sin;
                    534:        int s;
                    535: 
                    536:        sin = (struct sockaddr_in *)&ar->arp_ha;
                    537: #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN
                    538:        if (sin->sin_family == 0 && sin->sin_len < 16)
                    539:                sin->sin_family = sin->sin_len;
                    540: #endif
                    541:        sin->sin_len = sizeof(ar->arp_ha);
                    542:        sin = (struct sockaddr_in *)&ar->arp_pa;
                    543: #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN
                    544:        if (sin->sin_family == 0 && sin->sin_len < 16)
                    545:                sin->sin_family = sin->sin_len;
                    546: #endif
                    547:        sin->sin_len = sizeof(ar->arp_pa);
                    548:        if (ar->arp_pa.sa_family != AF_INET ||
                    549:            ar->arp_ha.sa_family != AF_UNSPEC)
                    550:                return (EAFNOSUPPORT);
                    551:        s = splimp();
                    552:        ARPTAB_LOOK(at, sin->sin_addr.s_addr);
                    553:        if (at == NULL) {               /* not found */
                    554:                if (cmd != SIOCSARP) {
                    555:                        splx(s);
                    556:                        return (ENXIO);
                    557:                }
                    558:                if (ifa_ifwithnet(&ar->arp_pa) == NULL) {
                    559:                        splx(s);
                    560:                        return (ENETUNREACH);
                    561:                }
                    562:        }
                    563:        switch (cmd) {
                    564: 
                    565:        case SIOCSARP:          /* set entry */
                    566:                if (at == NULL) {
                    567:                        at = arptnew(&sin->sin_addr);
                    568:                        if (at == NULL) {
                    569:                                splx(s);
                    570:                                return (EADDRNOTAVAIL);
                    571:                        }
                    572:                        if (ar->arp_flags & ATF_PERM) {
                    573:                        /* never make all entries in a bucket permanent */
                    574:                                register struct arptab *tat;
                    575:                                
                    576:                                /* try to re-allocate */
                    577:                                tat = arptnew(&sin->sin_addr);
                    578:                                if (tat == NULL) {
                    579:                                        arptfree(at);
                    580:                                        splx(s);
                    581:                                        return (EADDRNOTAVAIL);
                    582:                                }
                    583:                                arptfree(tat);
                    584:                        }
                    585:                }
                    586:                bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->at_enaddr,
                    587:                    sizeof(at->at_enaddr));
                    588:                at->at_flags = ATF_COM | ATF_INUSE |
                    589:                        (ar->arp_flags & (ATF_PERM|ATF_PUBL|ATF_USETRAILERS));
                    590:                at->at_timer = 0;
                    591:                break;
                    592: 
                    593:        case SIOCDARP:          /* delete entry */
                    594:                arptfree(at);
                    595:                break;
                    596: 
                    597:        case SIOCGARP:          /* get entry */
                    598:        case OSIOCGARP:
                    599:                bcopy((caddr_t)at->at_enaddr, (caddr_t)ar->arp_ha.sa_data,
                    600:                    sizeof(at->at_enaddr));
                    601: #ifdef COMPAT_43
                    602:                if (cmd == OSIOCGARP)
                    603:                        *(u_short *)&ar->arp_ha = ar->arp_ha.sa_family;
                    604: #endif
                    605:                ar->arp_flags = at->at_flags;
                    606:                break;
                    607:        }
                    608:        splx(s);
                    609:        return (0);
                    610: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.