Annotation of 43BSDTahoe/sys/netinet/if_ether.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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