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

unix.superglobalmegacorp.com

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