Annotation of cci/sys/netinet/if_ether.c, revision 1.1.1.1

1.1       root        1: /*     if_ether.c      6.2     83/08/28        */
                      2: 
                      3: /*
                      4:  * Ethernet address resolution protocol.
                      5:  */
                      6: 
                      7: #include "../h/param.h"
                      8: #include "../h/systm.h"
                      9: #include "../h/mbuf.h"
                     10: #include "../h/socket.h"
                     11: #include "../h/time.h"
                     12: #include "../h/kernel.h"
                     13: #include "../h/errno.h"
                     14: 
                     15: #include "../net/if.h"
                     16: #include "../netinet/in.h"
                     17: #include "../netinet/if_ether.h"
                     18: 
                     19: /*
                     20:  * changes:
                     21:  *
                     22:  *     . always return 0 after calling looutput().
                     23:  *
                     24:  *     . forces messages going to net if flag gotoether is set.
                     25:  *       (set this flag through "adb" for debugging purposes).
                     26:  *
                     27:  *     . add symbolic return code to arpresolve(). See comments in 
                     28:  *       arpresolve().
                     29:  */
                     30: 
                     31: /*
                     32:  * Internet to ethernet address resolution table.
                     33:  */
                     34: struct arptab {
                     35:        struct  in_addr at_iaddr;       /* internet address */
                     36:        u_char  at_enaddr[6];           /* ethernet address */
                     37:        struct  mbuf *at_hold;          /* last packet until resolved/timeout */
                     38:        u_char  at_timer;               /* minutes since last reference */
                     39:        u_char  at_flags;               /* flags */
                     40: };
                     41: /* at_flags field values */
                     42: #define        ATF_INUSE       1               /* entry in use */
                     43: #define ATF_COM                2               /* completed entry (enaddr valid) */
                     44: 
                     45: #define        ARPTAB_BSIZ     5               /* bucket size */
                     46: #define        ARPTAB_NB       19              /* number of buckets */
                     47: #define        ARPTAB_SIZE     (ARPTAB_BSIZ * ARPTAB_NB)
                     48: struct arptab arptab[ARPTAB_SIZE];
                     49: 
                     50: #define        ARPTAB_HASH(a) \
                     51:        ((short)((((a) >> 16) ^ (a)) & 0x7fff) % ARPTAB_NB)
                     52: 
                     53: #define        ARPTAB_LOOK(at,addr) { \
                     54:        register n; \
                     55:        at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \
                     56:        for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
                     57:                if (at->at_iaddr.s_addr == addr) \
                     58:                        break; \
                     59:        if (n >= ARPTAB_BSIZ) \
                     60:                at = 0; }
                     61: 
                     62: struct arpcom *arpcom;         /* chain of active ether interfaces */
                     63: int    arpt_age;               /* aging timer */
                     64: int    gotoether;              /* force traffic to Ethernet; no software
                     65:                                   loopback */
                     66: 
                     67: /* timer values */
                     68: #define        ARPT_AGE        (60*1)  /* aging timer, 1 min. */
                     69: #define        ARPT_KILLC      20      /* kill completed entry in 20 mins. */
                     70: #define        ARPT_KILLI      3       /* kill incomplete entry in 3 minutes */
                     71: 
                     72: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
                     73: extern struct ifnet loif;
                     74: 
                     75: /*------------- debug tools ---------------*/
                     76: #ifdef ARPPRINTFS
                     77:        int     arpprintfs;
                     78: #      define ARPTRACE(X)      {if (arpprintfs) X }
                     79: #else  ARPPRINTFS
                     80: #      define ARPTRACE(X)
                     81: #endif ARPPRINTFS
                     82: 
                     83: /*
                     84:  * Local addresses in the range oldmap to infinity are
                     85:  * mapped according to the old mapping scheme.  That is,
                     86:  * mapping of Internet to Ethernet addresses is performed
                     87:  * by taking the high three bytes of the network interface's
                     88:  * address and the low three bytes of the local address part.
                     89:  * This only allows boards from the same manufacturer to
                     90:  * communicate unless the on-board address is overridden
                     91:  * (not possible in many manufacture's hardware).
                     92:  *
                     93:  * NB: setting oldmap to zero completely disables ARP
                     94:  *     (i.e. identical to setting IFF_NOARP with an ioctl).
                     95:  */
                     96: int    oldmap = 0xffffff;
                     97: 
                     98: /*
                     99:  * Attach an ethernet interface to the list "arpcom" where
                    100:  * arptimer() can find it.  If first time 
                    101:  * initialization, start arptimer().
                    102:  */
                    103: arpattach(ac)
                    104:        register struct arpcom *ac;
                    105: {
                    106:        register struct arpcom *acp;
                    107: 
                    108:        for (acp = arpcom; acp != (struct arpcom *)0; acp = acp->ac_ac)
                    109:                if (acp == ac)          /* if already on list */
                    110:                        return;
                    111:        ac->ac_ac = arpcom;
                    112:        arpcom = ac;
                    113:        if (arpcom->ac_ac == 0)         /* very first time */
                    114:                arptimer();
                    115: }
                    116: 
                    117: /*
                    118:  * Timeout routine.  Age arp_tab entries once a minute.
                    119:  */
                    120: arptimer()
                    121: {
                    122:        register struct arptab *at;
                    123:        register i;
                    124: 
                    125:        timeout(arptimer, (caddr_t)0, hz);
                    126: #ifdef notdef
                    127:        if (++arpt_sanity > ARPT_SANITY) {
                    128:                register struct arpcom *ac;
                    129: 
                    130:                /*
                    131:                 * Randomize sanity timer based on my host address.
                    132:                 * Ask who has my own address;  if someone else replies,
                    133:                 * then they are impersonating me.
                    134:                 */
                    135:                arpt_sanity = arpcom->ac_enaddr[5] & 0x3f;
                    136:                for (ac = arpcom; ac != (struct arpcom *)-1; ac = ac->ac_ac)
                    137:                        arpwhohas(ac, &((struct sockaddr_in *)
                    138:                            &ac->ac_if.if_addr)->sin_addr);
                    139:        }
                    140: #endif
                    141:        if (++arpt_age > ARPT_AGE) {
                    142:                arpt_age = 0;
                    143:                at = &arptab[0];
                    144:                for (i = 0; i < ARPTAB_SIZE; i++, at++) {
                    145:                        if (at->at_flags == 0)
                    146:                                continue;
                    147:                        if (++at->at_timer < ((at->at_flags&ATF_COM) ?
                    148:                            ARPT_KILLC : ARPT_KILLI))
                    149:                                continue;
                    150:                        /* timer has expired, clear entry */
                    151:                        arptfree(at);
                    152:                }
                    153:        }
                    154: }
                    155: 
                    156: /*
                    157:  * Broadcast an ARP packet, asking who has addr on interface ac.
                    158:  */
                    159: arpwhohas(ac, addr)
                    160:        register struct arpcom *ac;
                    161:        struct in_addr *addr;
                    162: {
                    163:        register struct mbuf *m;
                    164:        register struct ether_header *eh;
                    165:        register struct ether_arp *ea;
                    166:        struct sockaddr sa;
                    167: 
                    168:        m = m_get(M_DONTWAIT, MT_DATA);
                    169:        MBUFNULL(5,m);                  /* for debugging */
                    170:        if (m == NULL)
                    171:                return;
                    172:        m->m_len = sizeof *ea + SIZEOF_ETHEADER;
                    173:        m->m_off = MMAXOFF - m->m_len;
                    174:        ea = mtod(m, struct ether_arp *);
                    175:        eh = (struct ether_header *)sa.sa_data;
                    176:        bzero((caddr_t)ea, sizeof (*ea));
                    177:        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
                    178:           sizeof (etherbroadcastaddr));
                    179:        eh->ether_type = ETHERPUP_ARPTYPE;      /* if_output will swap */
                    180:        ea->arp_hrd = htons(ARPHRD_ETHER);
                    181:        ea->arp_pro = htons(ETHERPUP_IPTYPE);
                    182:        ea->arp_hln = sizeof ea->arp_sha;       /* hardware address length */
                    183:        ea->arp_pln = sizeof ea->arp_spa;       /* protocol address length */
                    184:        ea->arp_op = htons(ARPOP_REQUEST);
                    185:        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
                    186:           sizeof (ea->arp_sha));
                    187:        bcopy((caddr_t)&((struct sockaddr_in *)&ac->ac_if.if_addr)->sin_addr,
                    188:           (caddr_t)ea->arp_spa, sizeof (ea->arp_spa));
                    189:        bcopy((caddr_t)addr, (caddr_t)ea->arp_tpa, sizeof (ea->arp_tpa));
                    190:        sa.sa_family = AF_UNSPEC;
                    191:        ARPTRACE(printf("arpwhohas:broadcast through %s%d for addr %lx\n",
                    192:                ac->ac_if.if_name, ac->ac_if.if_unit, addr->s_addr);)
                    193:        (void) (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
                    194: }
                    195: 
                    196: /*
                    197:  *
                    198:  * Resolve an IP address into an ethernet address.  If success, 
                    199:  * desten is filled in and 1 is returned.  If there is no entry
                    200:  * in arptab, set one up and broadcast a request 
                    201:  * for the IP address;  return 0.  Hold onto this mbuf and 
                    202:  * resend it once the address is finally resolved.
                    203:  *
                    204:  * We do some (conservative) locking here at splimp, since
                    205:  * arptab is also altered from input interrupt service (ecintr/ilintr
                    206:  * calls arpinput when ETHERPUP_ARPTYPE packets come in).
                    207:  *
                    208:  * Returns:
                    209:  *
                    210:  * ARPRESOLVE_WILLSEND
                    211:  *             arpresolve() cannot resolve the address. It will send the
                    212:  *             packet when it the address is resolved. However, if the 
                    213:  *             destination is same as origination, arpresolve() does not
                    214:  *             resolve address, it routes the packet to software loopback.
                    215:  *
                    216:  * ARPRESOLVE_OK
                    217:  *             arpresolve() successfully resolves the address. The calling
                    218:  *             routine is responsible for sending out the packet. Address
                    219:  *             is not a wild-card (not broadcast).
                    220:  *
                    221:  * ARPRESOLVE_BROADCAST
                    222:  *             arpresovle() successfully resolves the address which is
                    223:  *             a wildcard. If the controller is NOT capable of listening to
                    224:  *             its own broadcast, the device driver is responsible for
                    225:  *             routing a copy of the packet to the software loopback.
                    226:  *
                    227:  */
                    228: arpresolve(ac, m, destip, desten)
                    229:        register struct arpcom *ac;
                    230:        struct mbuf *m;
                    231:        register struct in_addr *destip;
                    232:        register u_char *desten;
                    233: {
                    234:        register struct arptab *at;
                    235:        register struct ifnet *ifp;
                    236:        struct sockaddr_in sin;
                    237:        int s, lna;
                    238: 
                    239:        lna = in_lnaof(*destip);
                    240:        if (lna == INADDR_ANY) {        /* broadcast address */
                    241:                bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
                    242:                   sizeof (etherbroadcastaddr));
                    243:                return (ARPRESOLVE_BROADCAST);
                    244:        }
                    245:        ifp = &ac->ac_if;
                    246:        /* if for us, then use software loopback driver */
                    247:        if ((destip->s_addr ==
                    248:            ((struct sockaddr_in *)&ifp->if_addr)-> sin_addr.s_addr) &&
                    249:            (gotoether==0)) {
                    250:                sin.sin_family = AF_INET;
                    251:                sin.sin_addr = *destip;
                    252:                looutput(&loif, m, (struct sockaddr *)&sin);
                    253:                return(ARPRESOLVE_WILLSEND);
                    254:        }
                    255:        if ((ifp->if_flags & IFF_NOARP) || lna >= oldmap) {
                    256:                bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3);
                    257:                desten[3] = (lna >> 16) & 0x7f;
                    258:                desten[4] = (lna >> 8) & 0xff;
                    259:                desten[5] = lna & 0xff;
                    260:                return (ARPRESOLVE_OK);
                    261:        }
                    262:        s = splimp();
                    263:        ARPTAB_LOOK(at, destip->s_addr);
                    264:        if (at == 0) {                  /* not found */
                    265:                at = arptnew(destip);
                    266:                ARPTRACE(printf("arpresolve(%s%d) (m=%lx), arptab empty\n",
                    267:                        ac->ac_if.if_name, ac->ac_if.if_unit, m);)
                    268: 
                    269:                ARPTRACE(if (at->at_hold)
                    270:                                printf("arpresolve: LOOSE mbuf %lx\n",m);)
                    271:                at->at_hold = m;
                    272:                arpwhohas(ac, destip);
                    273:                splx(s);
                    274:                return (ARPRESOLVE_WILLSEND);
                    275:        }
                    276:        at->at_timer = 0;               /* restart the timer */
                    277:        if (at->at_flags & ATF_COM) {   /* entry IS complete */
                    278:                bcopy((caddr_t)at->at_enaddr, (caddr_t)desten, 6);
                    279:                splx(s);
                    280:                return (ARPRESOLVE_OK);
                    281:        }
                    282:        /*
                    283:         * There is an arptab entry, but no ethernet address
                    284:         * response yet.  Replace the held mbuf with this
                    285:         * latest one.
                    286:         */
                    287:        ARPTRACE(printf("arpresolve(%s%d) (m=%lx), arptab not completed\n",
                    288:                ac->ac_if.if_name, ac->ac_if.if_unit, m);)
                    289:        if (at->at_hold)
                    290:                m_freem(at->at_hold);
                    291:        at->at_hold = m;
                    292:        arpwhohas(ac, destip);          /* ask again */
                    293:        splx(s);
                    294:        return (ARPRESOLVE_WILLSEND);
                    295: }
                    296: 
                    297: /*
                    298:  * Find my own IP address.  It will either be waiting for us in
                    299:  * monitor RAM, or can be obtained via broadcast to the file/boot
                    300:  * server (not necessarily using the ARP packet format).
                    301:  *
                    302:  * Unimplemented at present, return 0 and assume that the host
                    303:  * will set his own IP address via the SIOCSIFADDR ioctl.
                    304:  */
                    305: /*ARGSUSED*/
                    306: struct in_addr
                    307: arpmyaddr(ac)
                    308:        register struct arpcom *ac;
                    309: {
                    310:        static struct in_addr addr;
                    311: 
                    312: #ifdef lint
                    313:        ac = ac;
                    314: #endif
                    315:        addr.s_addr = 0;
                    316:        return (addr);
                    317: }
                    318: 
                    319: /*
                    320:  * Called from ecintr/ilintr when ether packet type ETHERPUP_ARP
                    321:  * is received.  Algorithm is exactly that given in RFC 826.
                    322:  * In addition, a sanity check is performed on the sender
                    323:  * protocol address, to catch impersonators.
                    324:  */
                    325: arpinput(ac, m)
                    326:        register struct arpcom *ac;
                    327:        struct mbuf *m;
                    328: {
                    329:        register struct ether_arp *ea;
                    330:        struct ether_header *eh;
                    331:        register struct arptab *at = 0;  /* same as "merge" flag */
                    332:        struct sockaddr_in sin;
                    333:        struct sockaddr sa;
                    334:        struct mbuf *mhold;
                    335:        struct in_addr isaddr,itaddr,myaddr;
                    336: 
                    337:        ARPTRACE(printf("arpinput through %s%d (m=%lx)\n",
                    338:                ac->ac_if.if_name, ac->ac_if.if_unit, m);)
                    339: 
                    340:        if (m->m_len < sizeof *ea)
                    341:                goto out;
                    342: 
                    343:        myaddr = ((struct sockaddr_in *)&ac->ac_if.if_addr)->sin_addr;
                    344:        ea = mtod(m, struct ether_arp *);
                    345:        if (ntohs(ea->arp_pro) != ETHERPUP_IPTYPE)
                    346:                goto out;
                    347:        bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr.s_addr,
                    348:                sizeof (ea->arp_spa));
                    349: /*     isaddr.s_addr = ((struct in_addr *)ea->arp_spa)->s_addr;*/
                    350:        bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr.s_addr,
                    351:                sizeof (ea->arp_spa));
                    352: /*     itaddr.s_addr = ((struct in_addr *)ea->arp_tpa)->s_addr;*/
                    353:        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
                    354:          sizeof (ac->ac_enaddr)))
                    355:                goto out;       /* it's from me, ignore it. */
                    356: 
                    357:        ARPTRACE(printf("\tarpinput (%s%d) sender: %lx, %x.%x.%x.%x.%x.%x, target: %lx, %x.%x.%x.%x.%x.%x\n",
                    358:                ac->ac_if.if_name, ac->ac_if.if_unit,
                    359:                isaddr.s_addr, 
                    360:                ea->arp_sha[0] & 0xff, ea->arp_sha[1] & 0xff,
                    361:                ea->arp_sha[2] & 0xff, ea->arp_sha[3] & 0xff,
                    362:                ea->arp_sha[4] & 0xff, ea->arp_sha[5] & 0xff,
                    363:                itaddr.s_addr, 
                    364:                ea->arp_tha[0] & 0xff, ea->arp_tha[1] & 0xff,
                    365:                ea->arp_tha[2] & 0xff, ea->arp_tha[3] & 0xff,
                    366:                ea->arp_tha[4] & 0xff, ea->arp_tha[5] & 0xff);)
                    367:                
                    368:        if (isaddr.s_addr == myaddr.s_addr) {
                    369:                printf("duplicate IP address!! sent from ethernet address: ");
                    370:                printf("%x %x %x %x %x %x\n", ea->arp_sha[0], ea->arp_sha[1],
                    371:                    ea->arp_sha[2], ea->arp_sha[3],
                    372:                    ea->arp_sha[4], ea->arp_sha[5]);
                    373:                if (ntohs(ea->arp_op) == ARPOP_REQUEST)
                    374:                        goto reply;
                    375:                goto out;
                    376:        }
                    377:        ARPTAB_LOOK(at, isaddr.s_addr);
                    378:        if (at) {
                    379:                bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
                    380:                   sizeof (ea->arp_sha));
                    381:                ARPTRACE(printf("\tarpinput(%s%d). Update sender addr\n",
                    382:                        ac->ac_if.if_name, ac->ac_if.if_unit);)
                    383:        
                    384:                at->at_flags |= ATF_COM;
                    385:                if (at->at_hold) {
                    386:                        mhold = at->at_hold;
                    387:                        at->at_hold = 0;
                    388:                        sin.sin_family = AF_INET;
                    389:                        sin.sin_addr = isaddr;
                    390:                        (*ac->ac_if.if_output)(&ac->ac_if, 
                    391:                            mhold, (struct sockaddr *)&sin);
                    392:                }
                    393:        }
                    394:        if (itaddr.s_addr != myaddr.s_addr) {
                    395:                ARPTRACE(printf("\tarpinput(%s%d) Iam not the target\n",
                    396:                        ac->ac_if.if_name, ac->ac_if.if_unit);)
                    397:                goto out;       /* if I am not the target */
                    398:        }
                    399:        if (at == 0) {          /* ensure we have a table entry */
                    400:                ARPTRACE(printf("\tarpinput(%s%d). New entry for sender addr\n",
                    401:                        ac->ac_if.if_name, ac->ac_if.if_unit);)
                    402:                at = arptnew(&isaddr);
                    403:                bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
                    404:                   sizeof (ea->arp_sha));
                    405:                at->at_flags |= ATF_COM;
                    406:        }
                    407:        if (ntohs(ea->arp_op) != ARPOP_REQUEST)
                    408:                goto out;
                    409: reply:
                    410:        bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
                    411:           sizeof (ea->arp_sha));
                    412:        bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa,
                    413:           sizeof (ea->arp_spa));
                    414:        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
                    415:           sizeof (ea->arp_sha));
                    416:        bcopy((caddr_t)&myaddr, (caddr_t)ea->arp_spa,
                    417:           sizeof (ea->arp_spa));
                    418:        ea->arp_op = htons(ARPOP_REPLY);
                    419:        eh = (struct ether_header *)sa.sa_data;
                    420:        bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
                    421:           sizeof (eh->ether_dhost));
                    422:        eh->ether_type = ETHERPUP_ARPTYPE;
                    423:        sa.sa_family = AF_UNSPEC;
                    424: 
                    425:        ARPTRACE(bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr.s_addr,
                    426:                sizeof (ea->arp_tpa));)
                    427:        ARPTRACE(printf("\tarpinput(%s%d). Send reply to %lx\n",
                    428:                ac->ac_if.if_name, ac->ac_if.if_unit,itaddr.s_addr);)
                    429: 
                    430:        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
                    431:        return;
                    432: out:
                    433:        m_freem(m);
                    434:        return;
                    435: }
                    436: 
                    437: /*
                    438:  * Free an arptab entry.
                    439:  */
                    440: arptfree(at)
                    441:        register struct arptab *at;
                    442: {
                    443:        int s = splimp();
                    444: 
                    445:        if (at->at_hold)
                    446:                m_freem(at->at_hold);
                    447:        at->at_hold = 0;
                    448:        at->at_timer = at->at_flags = 0;
                    449:        at->at_iaddr.s_addr = 0;
                    450:        splx(s);
                    451: }
                    452: 
                    453: /*
                    454:  * Enter a new address in arptab, pushing out the oldest entry 
                    455:  * from the bucket if there is no room.
                    456:  */
                    457: struct arptab *
                    458: arptnew(addr)
                    459:        struct in_addr *addr;
                    460: {
                    461:        register n;
                    462:        int oldest = 0;
                    463:        register struct arptab *at, *ato;
                    464: 
                    465:        ato = at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ];
                    466:        for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) {
                    467:                if (at->at_flags == 0)
                    468:                        goto out;        /* found an empty entry */
                    469:                if (at->at_timer > oldest) {
                    470:                        oldest = at->at_timer;
                    471:                        ato = at;
                    472:                }
                    473:        }
                    474:        at = ato;
                    475:        arptfree(at);
                    476: out:
                    477:        at->at_iaddr = *addr;
                    478:        at->at_flags = ATF_INUSE;
                    479:        return (at);
                    480: }
                    481: 
                    482: arpremove(addr)
                    483: struct sockaddr *addr;
                    484: {
                    485:        register struct arptab *at;
                    486:        struct in_addr *idst;
                    487:        register long x;
                    488: 
                    489:        idst = &((struct sockaddr_in *)addr)->sin_addr;
                    490:        x = splimp();
                    491:        ARPTAB_LOOK(at, idst->s_addr);
                    492:        if (at) arptfree(at);
                    493:        splx(x);
                    494: }
                    495: 

unix.superglobalmegacorp.com

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