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

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

unix.superglobalmegacorp.com

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