Annotation of kernel/bsd/netinet/if_ether.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1982, 1986, 1988, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  *
                     30:  * Redistribution and use in source and binary forms, with or without
                     31:  * modification, are permitted provided that the following conditions
                     32:  * are met:
                     33:  * 1. Redistributions of source code must retain the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer.
                     35:  * 2. Redistributions in binary form must reproduce the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer in the
                     37:  *    documentation and/or other materials provided with the distribution.
                     38:  * 3. All advertising materials mentioning features or use of this software
                     39:  *    must display the following acknowledgement:
                     40:  *     This product includes software developed by the University of
                     41:  *     California, Berkeley and its contributors.
                     42:  * 4. Neither the name of the University nor the names of its contributors
                     43:  *    may be used to endorse or promote products derived from this software
                     44:  *    without specific prior written permission.
                     45:  *
                     46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     56:  * SUCH DAMAGE.
                     57:  *
                     58:  *     @(#)if_ether.c  8.2 (Berkeley) 9/26/94
                     59:  */
                     60: 
                     61: /*
                     62:  * Ethernet address resolution protocol.
                     63:  * TODO:
                     64:  *     add "inuse/lock" bit (or ref. count) along with valid bit
                     65:  */
                     66: 
                     67: 
                     68: #include <sys/param.h>
                     69: #include <sys/systm.h>
                     70: #include <sys/malloc.h>
                     71: #include <sys/mbuf.h>
                     72: #include <sys/socket.h>
                     73: #include <sys/time.h>
                     74: #include <sys/kernel.h>
                     75: #include <sys/errno.h>
                     76: #include <sys/ioctl.h>
                     77: #include <sys/syslog.h>
                     78: 
                     79: #include <net/if.h>
                     80: #include <net/if_dl.h>
                     81: #include <net/route.h>
                     82: 
                     83: #include <netinet/in.h>
                     84: #include <netinet/in_systm.h>
                     85: #include <netinet/in_var.h>
                     86: #include <netinet/ip.h>
                     87: #include <netinet/if_ether.h>
                     88: 
                     89: #if INET
                     90: 
                     91: struct ifqueue arpintrq;
                     92: 
                     93: struct llinfo_arp llinfo_arp;          /* head of the llinfo queue */
                     94: 
                     95: #define SIN(s) ((struct sockaddr_in *)s)
                     96: #define SDL(s) ((struct sockaddr_dl *)s)
                     97: #define SRP(s) ((struct sockaddr_inarp *)s)
                     98: 
                     99: /*
                    100:  * ARP trailer negotiation.  Trailer protocol is not IP specific,
                    101:  * but ARP request/response use IP addresses.
                    102:  */
                    103: #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
                    104: 
                    105: /* timer values */
                    106: int    arpt_prune = (5*60*1);  /* walk list every 5 minutes */
                    107: int    arpt_keep = (20*60);    /* once resolved, good for 20 more minutes */
                    108: int    arpt_down = 20;         /* once declared down, don't send for 20 secs */
                    109: #define        rt_expire rt_rmx.rmx_expire
                    110: 
                    111: static void arprequest __P((struct arpcom *, u_long *, u_long *, u_char *));
                    112: static void arptfree __P((struct llinfo_arp *));
                    113: static void arptimer __P((void *));
                    114: static struct llinfo_arp *arplookup __P((u_long, int, int));
                    115: static void in_arpinput __P((struct mbuf *));
                    116: 
                    117: extern struct ifnet loif;
                    118: struct llinfo_arp llinfo_arp = {&llinfo_arp, &llinfo_arp};
                    119: struct ifqueue arpintrq = {0, 0, 0, 50};
                    120: int    arp_inuse, arp_allocated, arp_intimer;
                    121: int    arp_maxtries = 5;
                    122: int    useloopback = 1;        /* use loopback interface for local traffic */
                    123: int    arpinit_done = 0;
                    124: 
                    125: /* revarp state */
                    126: static struct  in_addr myip, srv_ip;
                    127: static int     myip_initialized = 0;
                    128: static int     revarp_in_progress = 0;
                    129: static struct  ifnet *myip_ifp = NULL;
                    130: 
                    131: /* Should be in spl.h */
                    132: int splimp(void);
                    133: int splnet(void);
                    134: int splx(int);
                    135: 
                    136: /*
                    137:  * Timeout routine.  Age arp_tab entries periodically.
                    138:  */
                    139: /* ARGSUSED */
                    140: static void
                    141: arptimer(arg)
                    142:        void *arg;
                    143: {
                    144:        int s;
                    145:        register struct llinfo_arp *la = llinfo_arp.la_next;
                    146: 
                    147:        s = splnet();
                    148:        while (la != &llinfo_arp) {
                    149:                register struct rtentry *rt = la->la_rt;
                    150:                la = la->la_next;
                    151:                if (rt->rt_expire && rt->rt_expire <= time.tv_sec)
                    152:                        arptfree(la->la_prev); /* timer has expired; clear */
                    153:        }
                    154:        timeout(arptimer, NULL, arpt_prune * hz);
                    155:        splx(s);
                    156: 
                    157: }
                    158: 
                    159: /*
                    160:  * Parallel to llc_rtrequest.
                    161:  */
                    162: void
                    163: arp_rtrequest(req, rt, sa)
                    164:        int req;
                    165:        register struct rtentry *rt;
                    166:        struct sockaddr *sa;
                    167: {
                    168:        register struct sockaddr *gate = rt->rt_gateway;
                    169:        register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
                    170:        static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
                    171: 
                    172:        if (!arpinit_done) {
                    173:                arpinit_done = 1;
                    174:                timeout(arptimer, (caddr_t)0, hz);
                    175:        }
                    176:        if (rt->rt_flags & RTF_GATEWAY)
                    177:                return;
                    178:        switch (req) {
                    179: 
                    180:        case RTM_ADD:
                    181:                /*
                    182:                 * XXX: If this is a manually added route to interface
                    183:                 * such as older version of routed or gated might provide,
                    184:                 * restore cloning bit.
                    185:                 */
                    186:                if ((rt->rt_flags & RTF_HOST) == 0 &&
                    187:                    SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
                    188:                        rt->rt_flags |= RTF_CLONING;
                    189:                if (rt->rt_flags & RTF_CLONING) {
                    190:                        /*
                    191:                         * Case 1: This route should come from a route to iface.
                    192:                         */
                    193:                        rt_setgate(rt, rt_key(rt),
                    194:                                        (struct sockaddr *)&null_sdl);
                    195:                        gate = rt->rt_gateway;
                    196:                        SDL(gate)->sdl_type = rt->rt_ifp->if_type;
                    197:                        SDL(gate)->sdl_index = rt->rt_ifp->if_index;
                    198:                        /*
                    199:                         * Give this route an expiration time, even though
                    200:                         * it's a "permanent" route, so that routes cloned
                    201:                         * from it do not need their expiration time set.
                    202:                         */
                    203:                        rt->rt_expire = time.tv_sec;
                    204:                        break;
                    205:                }
                    206:                /* Announce a new entry if requested. */
                    207:                if (rt->rt_flags & RTF_ANNOUNCE)
                    208:                        arprequest((struct arpcom *)rt->rt_ifp,
                    209:                            &SIN(rt_key(rt))->sin_addr.s_addr,
                    210:                            &SIN(rt_key(rt))->sin_addr.s_addr,
                    211:                            (u_char *)LLADDR(SDL(gate)));
                    212:                /*FALLTHROUGH*/
                    213:        case RTM_RESOLVE:
                    214:                if (gate->sa_family != AF_LINK ||
                    215:                    gate->sa_len < sizeof(null_sdl)) {
                    216:                        log(LOG_DEBUG, "arp_rtrequest: bad gateway value");
                    217:                        break;
                    218:                }
                    219:                SDL(gate)->sdl_type = rt->rt_ifp->if_type;
                    220:                SDL(gate)->sdl_index = rt->rt_ifp->if_index;
                    221:                if (la != 0)
                    222:                        break; /* This happens on a route change */
                    223:                /*
                    224:                 * Case 2:  This route may come from cloning, or a manual route
                    225:                 * add with a LL address.
                    226:                 */
                    227:                R_Malloc(la, struct llinfo_arp *, sizeof(*la));
                    228:                rt->rt_llinfo = (caddr_t)la;
                    229:                if (la == 0) {
                    230:                        log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
                    231:                        break;
                    232:                }
                    233:                arp_inuse++, arp_allocated++;
                    234:                Bzero(la, sizeof(*la));
                    235:                la->la_rt = rt;
                    236:                rt->rt_flags |= RTF_LLINFO;
                    237:                insque((queue_t)la, (queue_t)&llinfo_arp);
                    238:                if (SIN(rt_key(rt))->sin_addr.s_addr ==
                    239:                    (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) {
                    240:                    /*
                    241:                     * This test used to be
                    242:                     *  if (loif.if_flags & IFF_UP)
                    243:                     * It allowed local traffic to be forced
                    244:                     * through the hardware by configuring the loopback down.
                    245:                     * However, it causes problems during network configuration
                    246:                     * for boards that can't receive packets they send.
                    247:                     * It is now necessary to clear "useloopback" and remove
                    248:                     * the route to force traffic out to the hardware.
                    249:                     */
                    250:                        rt->rt_expire = 0;
                    251:                        Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,
                    252:                                LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6);
                    253:                        if (useloopback)
                    254:                                rt->rt_ifp = &loif;
                    255: 
                    256:                }
                    257:                break;
                    258: 
                    259:        case RTM_DELETE:
                    260:                if (la == 0)
                    261:                        break;
                    262:                arp_inuse--;
                    263:                remque((queue_t)la);
                    264:                rt->rt_llinfo = 0;
                    265:                rt->rt_flags &= ~RTF_LLINFO;
                    266:                if (la->la_hold)
                    267:                        m_freem(la->la_hold);
                    268:                Free((caddr_t)la);
                    269:        }
                    270: }
                    271: 
                    272: /*
                    273:  * Broadcast an ARP packet, asking who has addr on interface ac.
                    274:  */
                    275: void
                    276: arpwhohas(ac, addr)
                    277:        register struct arpcom *ac;
                    278:        register struct in_addr *addr;
                    279: {      struct ifnet *ifp = (struct ifnet *)ac;
                    280:        struct ifaddr *ifa = ifp->if_addrlist;
                    281: 
                    282:        while (ifa)
                    283:        {       if (ifa->ifa_addr->sa_family == AF_INET)
                    284:                {       arprequest(ac, &SIN(ifa->ifa_addr)->sin_addr.s_addr, &addr->s_addr, ac->ac_enaddr);
                    285:                        return;
                    286:                }
                    287:                ifa = ifa->ifa_next;
                    288:        }
                    289:        return; /* XXX */
                    290: }
                    291: 
                    292: /*
                    293:  * Broadcast an ARP request. Caller specifies:
                    294:  *     - arp header source ip address
                    295:  *     - arp header target ip address
                    296:  *     - arp header source ethernet address
                    297:  */
                    298: static void
                    299: arprequest(ac, sip, tip, enaddr)
                    300:        register struct arpcom *ac;
                    301:        register u_long *sip, *tip;
                    302:        register u_char *enaddr;
                    303: {
                    304:        register struct mbuf *m;
                    305:        register struct ether_header *eh;
                    306:        register struct ether_arp *ea;
                    307:        struct sockaddr sa;
                    308: 
                    309:        if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
                    310:                return;
                    311:        m->m_len = sizeof(*ea);
                    312:        m->m_pkthdr.len = sizeof(*ea);
                    313:        MH_ALIGN(m, sizeof(*ea));
                    314:        ea = mtod(m, struct ether_arp *);
                    315:        eh = (struct ether_header *)sa.sa_data;
                    316:        bzero((caddr_t)ea, sizeof (*ea));
                    317:        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
                    318:            sizeof(eh->ether_dhost));
                    319:        eh->ether_type = htons(ETHERTYPE_ARP);
                    320:        ea->arp_hrd = htons(ARPHRD_ETHER);
                    321:        ea->arp_pro = htons(ETHERTYPE_IP);
                    322:        ea->arp_hln = sizeof(ea->arp_sha);      /* hardware address length */
                    323:        ea->arp_pln = sizeof(ea->arp_spa);      /* protocol address length */
                    324:        ea->arp_op = htons(ARPOP_REQUEST);
                    325:        bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));
                    326:        bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));
                    327:        bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));
                    328:        sa.sa_family = AF_UNSPEC;
                    329:        sa.sa_len = sizeof(sa);
                    330:        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
                    331: }
                    332: 
                    333: /*
                    334:  * Resolve an IP address into an ethernet address.  If success,
                    335:  * desten is filled in.  If there is no entry in arptab,
                    336:  * set one up and broadcast a request for the IP address.
                    337:  * Hold onto this mbuf and resend it once the address
                    338:  * is finally resolved.  A return value of 1 indicates
                    339:  * that desten has been filled in and the packet should be sent
                    340:  * normally; a 0 return indicates that the packet has been
                    341:  * taken over here, either now or for later transmission.
                    342:  */
                    343: int
                    344: arpresolve(ac, rt, m, dst, desten)
                    345:        register struct arpcom *ac;
                    346:        register struct rtentry *rt;
                    347:        struct mbuf *m;
                    348:        register struct sockaddr *dst;
                    349:        register u_char *desten;
                    350: {
                    351:        register struct llinfo_arp *la;
                    352:        struct sockaddr_dl *sdl;
                    353: 
                    354:        if (m->m_flags & M_BCAST) {     /* broadcast */
                    355:                bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
                    356:                    sizeof(etherbroadcastaddr));
                    357:                return (1);
                    358:        }
                    359:        if (m->m_flags & M_MCAST) {     /* multicast */
                    360:                ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
                    361:                return(1);
                    362:        }
                    363:        if (rt)
                    364:                la = (struct llinfo_arp *)rt->rt_llinfo;
                    365:        else {
                    366:                if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)))
                    367:                        rt = la->la_rt;
                    368:        }
                    369:        if (la == 0 || rt == 0) {
                    370:                log(LOG_DEBUG, "arpresolve: can't allocate llinfo");
                    371:                m_freem(m);
                    372:                return (0);
                    373:        }
                    374:        sdl = SDL(rt->rt_gateway);
                    375:        /*
                    376:         * Check the address family and length is valid, the address
                    377:         * is resolved; otherwise, try to resolve.
                    378:         */
                    379:        if ((rt->rt_expire == 0 || rt->rt_expire > time.tv_sec) &&
                    380:            sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
                    381:                bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
                    382: 
                    383:                return 1;
                    384:        }
                    385:        /*
                    386:         * There is an arptab entry, but no ethernet address
                    387:         * response yet.  Replace the held mbuf with this
                    388:         * latest one.
                    389:         */
                    390:        if (la->la_hold)
                    391:                m_freem(la->la_hold);
                    392:        la->la_hold = m;
                    393:        /*
                    394:         * Re-send the ARP request when appropriate.
                    395:         */
                    396: #if    DIAGNOSTIC
                    397:        if (rt->rt_expire == 0) {
                    398:                /* This should never happen. (Should it? -gwr) */
                    399:                printf("arpresolve: unresolved and rt_expire == 0\n");
                    400:                /* Set expiration time to now (expired). */
                    401:                rt->rt_expire = time.tv_sec;
                    402:        }
                    403: #endif
                    404:        if (rt->rt_expire) {
                    405:                rt->rt_flags &= ~RTF_REJECT;
                    406:                if (la->la_asked == 0 || rt->rt_expire != time.tv_sec) {
                    407:                        rt->rt_expire = time.tv_sec;
                    408:                        if (la->la_asked++ < arp_maxtries)
                    409:                                arpwhohas(ac, &(SIN(dst)->sin_addr));
                    410:                        else {
                    411:                                rt->rt_flags |= RTF_REJECT;
                    412:                                rt->rt_expire += arpt_down;
                    413:                                la->la_asked = 0;
                    414:                        }
                    415:                }
                    416:        }
                    417:        return (0);
                    418: }
                    419: 
                    420: /*
                    421:  * Common length and type checks are done here,
                    422:  * then the protocol-specific routine is called.
                    423:  */
                    424: void
                    425: arpintr()
                    426: {
                    427:        register struct mbuf *m;
                    428:        register struct arphdr *ar;
                    429:        int s;
                    430: 
                    431:        while (arpintrq.ifq_head) {
                    432:                s = splimp();
                    433:                IF_DEQUEUE(&arpintrq, m);
                    434:                splx(s);
                    435:                if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
                    436:                        panic("arpintr");
                    437:                if (m->m_len >= sizeof(struct arphdr) &&
                    438:                    (ar = mtod(m, struct arphdr *)) &&
                    439:                    ntohs(ar->ar_hrd) == ARPHRD_ETHER &&
                    440:                    m->m_len >=
                    441:                      sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))
                    442:                        switch (ntohs(ar->ar_pro)) {
                    443: 
                    444:                        case ETHERTYPE_IP:
                    445:                        case ETHERTYPE_IPTRAILERS:
                    446:                                in_arpinput(m);
                    447:                                continue;
                    448:                        }
                    449: 
                    450:                m_freem(m);
                    451:        }
                    452: }
                    453: 
                    454: /*
                    455:  * ARP for Internet protocols on 10 Mb/s Ethernet.
                    456:  * Algorithm is that given in RFC 826.
                    457:  * In addition, a sanity check is performed on the sender
                    458:  * protocol address, to catch impersonators.
                    459:  * We no longer handle negotiations for use of trailer protocol:
                    460:  * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
                    461:  * along with IP replies if we wanted trailers sent to us,
                    462:  * and also sent them in response to IP replies.
                    463:  * This allowed either end to announce the desire to receive
                    464:  * trailer packets.
                    465:  * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
                    466:  * but formerly didn't normally send requests.
                    467:  */
                    468: static void
                    469: in_arpinput(m)
                    470:        struct mbuf *m;
                    471: {
                    472:        register struct ether_arp *ea;
                    473:        register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
                    474:        struct ether_header *eh;
                    475:        register struct llinfo_arp *la = 0;
                    476:        register struct rtentry *rt;
                    477:        struct in_ifaddr *ia, *maybe_ia = 0;
                    478:        struct sockaddr_dl *sdl;
                    479:        struct sockaddr sa;
                    480:        struct in_addr isaddr, itaddr, myaddr;
                    481:        int op;
                    482:        extern void kprintf( const char *, ...);
                    483: 
                    484:        ea = mtod(m, struct ether_arp *);
                    485:        op = ntohs(ea->arp_op);
                    486:        bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr));
                    487:        bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr));
                    488:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
                    489:                if (ia->ia_ifp == &ac->ac_if) {
                    490:                        maybe_ia = ia;
                    491:                        if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
                    492:                             (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
                    493:                                break;
                    494:                }
                    495:        if (maybe_ia == 0)
                    496:                goto out;
                    497:        myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
                    498: #if 0
                    499:        /*
                    500:         * In order to support BlueBox networking, we need to allow
                    501:         *   "self-addressed" stamped envelopes
                    502:         */
                    503:        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
                    504:            sizeof (ea->arp_sha)))
                    505:                goto out;       /* it's from me, ignore it. */
                    506: #endif
                    507:        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
                    508:            sizeof (ea->arp_sha))) {
                    509:                log(LOG_ERR,
                    510:                    "arp: ether address is broadcast for IP address %x!\n",
                    511:                    ntohl(isaddr.s_addr));
                    512:                goto out;
                    513:        }
                    514:        if (isaddr.s_addr == myaddr.s_addr) {
                    515:                log(LOG_ERR,
                    516:                   "duplicate IP address %08x sent from ethernet address %s\n",
                    517:                   ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha));
                    518:                itaddr = myaddr;
                    519:                goto reply;
                    520:        }
                    521:        la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
                    522:        if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
                    523:                if (sdl->sdl_alen &&
                    524:                    bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen))
                    525:                        log(LOG_INFO, "arp info overwritten for %08x by %s\n",
                    526:                            ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha));
                    527:                bcopy((caddr_t)ea->arp_sha, LLADDR(sdl),
                    528:                            sdl->sdl_alen = sizeof(ea->arp_sha));
                    529:                if (rt->rt_expire)
                    530:                        rt->rt_expire = time.tv_sec + arpt_keep;
                    531:                rt->rt_flags &= ~RTF_REJECT;
                    532:                la->la_asked = 0;
                    533:                if (la->la_hold) {
                    534:                        (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,
                    535:                                rt_key(rt), rt);
                    536:                        la->la_hold = 0;
                    537:                }
                    538:        }
                    539: reply:
                    540:        if (op != ARPOP_REQUEST) {
                    541:        out:
                    542:                m_freem(m);
                    543:                return;
                    544:        }
                    545:        if (itaddr.s_addr == myaddr.s_addr) {
                    546:                /* I am the target */
                    547:                bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
                    548:                    sizeof(ea->arp_sha));
                    549:                bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
                    550:                    sizeof(ea->arp_sha));
                    551:        } else {
                    552:                la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
                    553:                if (la == NULL)
                    554:                        goto out;
                    555:                rt = la->la_rt;
                    556:                bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
                    557:                    sizeof(ea->arp_sha));
                    558:                sdl = SDL(rt->rt_gateway);
                    559:                bcopy(LLADDR(sdl), (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));
                    560:        }
                    561: 
                    562:        bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa));
                    563:        bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));
                    564:        ea->arp_op = htons(ARPOP_REPLY);
                    565:        ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
                    566:        eh = (struct ether_header *)sa.sa_data;
                    567:        bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
                    568:            sizeof(eh->ether_dhost));
                    569:        eh->ether_type = htons(ETHERTYPE_ARP);
                    570:        sa.sa_family = AF_UNSPEC;
                    571:        sa.sa_len = sizeof(sa);
                    572:        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
                    573:        return;
                    574: }
                    575: 
                    576: /*
                    577:  * Free an arp entry.
                    578:  */
                    579: static void
                    580: arptfree(la)
                    581:        register struct llinfo_arp *la;
                    582: {
                    583:        register struct rtentry *rt = la->la_rt;
                    584:        register struct sockaddr_dl *sdl;
                    585: 
                    586:        if (rt == 0)
                    587:                panic("arptfree");
                    588:        if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
                    589:            sdl->sdl_family == AF_LINK) {
                    590:                sdl->sdl_alen = 0;
                    591:                la->la_asked = 0;
                    592:                rt->rt_flags &= ~RTF_REJECT;
                    593:                return;
                    594:        }
                    595:        rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
                    596:            0, (struct rtentry **)0);
                    597: }
                    598: 
                    599: /*
                    600:  * Lookup or enter a new address in arptab.
                    601:  */
                    602: static struct llinfo_arp *
                    603: arplookup(addr, create, proxy)
                    604:        u_long addr;
                    605:        int create, proxy;
                    606: {
                    607:        register struct rtentry *rt;
                    608:        static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
                    609: 
                    610:        sin.sin_addr.s_addr = addr;
                    611:        sin.sin_other = proxy ? SIN_PROXY : 0;
                    612:        rt = rtalloc1((struct sockaddr *)&sin, create);
                    613:        if (rt == 0)
                    614:                return (0);
                    615:        rt->rt_refcnt--;
                    616:        if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
                    617:            rt->rt_gateway->sa_family != AF_LINK) {
                    618:                if (create)
                    619:                        log(LOG_DEBUG, "arplookup: unable to enter address for %x\n", ntohl(addr));
                    620:                return (0);
                    621:        }
                    622:        return ((struct llinfo_arp *)rt->rt_llinfo);
                    623: }
                    624: 
                    625: int
                    626: arpioctl(cmd, data)
                    627:        u_long cmd;
                    628:        caddr_t data;
                    629: {
                    630: 
                    631:        return (EOPNOTSUPP);
                    632: }
                    633: 
                    634: void
                    635: arp_ifinit(ac, ifa)
                    636:        struct arpcom *ac;
                    637:        struct ifaddr *ifa;
                    638: {
                    639:        ac->ac_ipaddr = IA_SIN(ifa)->sin_addr;
                    640:        /* Warn the user if another station has this IP address. */
                    641:        arpwhohas(ac, &ac->ac_ipaddr);
                    642:        ifa->ifa_rtrequest = arp_rtrequest;
                    643:        ifa->ifa_flags |= RTF_CLONING;
                    644: }
                    645: 
                    646: /*
                    647:  * Called from 10 Mb/s Ethernet interrupt handlers
                    648:  * when ether packet type ETHERTYPE_REVARP
                    649:  * is received.  Common length and type checks are done here,
                    650:  * then the protocol-specific routine is called.
                    651:  */
                    652: void
                    653: revarpinput(m)
                    654:        struct mbuf *m;
                    655: {
                    656:        struct arphdr *ar;
                    657:        extern int in_revarpinput(struct mbuf *);
                    658: 
                    659:        if (m->m_len < sizeof(struct arphdr)) {
                    660:                goto out;
                    661:        }
                    662:        ar = mtod(m, struct arphdr *);
                    663:        if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) {
                    664:                goto out;
                    665:        }
                    666:        if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) {
                    667:                goto out;
                    668:        }
                    669:        switch (ntohs(ar->ar_pro)) {
                    670: 
                    671:        case ETHERTYPE_IP:
                    672:        case ETHERTYPE_IPTRAILERS:
                    673:                in_revarpinput(m);
                    674:                return;
                    675: 
                    676:        default:
                    677:                break;
                    678:        }
                    679: out:
                    680:        m_freem(m);
                    681: }
                    682: 
                    683: /*
                    684:  * RARP for Internet protocols on 10 Mb/s Ethernet.
                    685:  * Algorithm is that given in RFC 903.
                    686:  * We are only using for bootstrap purposes to get an ip address for one of
                    687:  * our interfaces.  Thus we support no user-interface.
                    688:  *
                    689:  * Since the contents of the RARP reply are specific to the interface that
                    690:  * sent the request, this code must ensure that they are properly associated.
                    691:  *
                    692:  * Note: also supports ARP via RARP packets, per the RFC.
                    693:  */
                    694: int
                    695: in_revarpinput(m)
                    696:        struct mbuf *m;
                    697: {
                    698:        struct ifnet *ifp;
                    699:        struct ether_arp *ar;
                    700:        int op;
                    701:        extern void wakeup (void *);
                    702: 
                    703:        ar = mtod(m, struct ether_arp *);
                    704:        op = ntohs(ar->arp_op);
                    705:        switch (op) {
                    706:        case ARPOP_REQUEST:
                    707:        case ARPOP_REPLY:       /* per RFC */
                    708:                in_arpinput(m);
                    709:                return(0);
                    710:        case ARPOP_REVREPLY:
                    711:                break;
                    712:        case ARPOP_REVREQUEST:  /* handled by rarpd(8) */
                    713:        default:
                    714:                goto out;
                    715:        }
                    716:        if (!revarp_in_progress)
                    717:                goto out;
                    718:        ifp = m->m_pkthdr.rcvif;
                    719:        if (ifp != myip_ifp) /* !same interface */
                    720:                goto out;
                    721:        if (myip_initialized)
                    722:                goto wake;
                    723:        if (bcmp(ar->arp_tha, ((struct arpcom *)ifp)->ac_enaddr,
                    724:            sizeof(ar->arp_tha)))
                    725:                goto out;
                    726:        bcopy((caddr_t)ar->arp_spa, (caddr_t)&srv_ip, sizeof(srv_ip));
                    727:        bcopy((caddr_t)ar->arp_tpa, (caddr_t)&myip, sizeof(myip));
                    728:        myip_initialized = 1;
                    729: wake:  /* Do wakeup every time in case it was missed. */
                    730:        wakeup((caddr_t)&myip);
                    731: 
                    732: out:
                    733:        m_freem(m);
                    734:        return(0);
                    735: }
                    736: 
                    737: /*
                    738:  * Send a RARP request for the ip address of the specified interface.
                    739:  * The request should be RFC 903-compliant.
                    740:  */
                    741: void
                    742: revarprequest(ifp)
                    743:        struct ifnet *ifp;
                    744: {
                    745:        struct sockaddr sa;
                    746:        struct mbuf *m;
                    747:        struct ether_header *eh;
                    748:        struct ether_arp *ea;
                    749:        struct arpcom *ac = (struct arpcom *)ifp;
                    750: 
                    751:        if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
                    752:                return;
                    753:        m->m_len = sizeof(*ea);
                    754:        m->m_pkthdr.len = sizeof(*ea);
                    755:        MH_ALIGN(m, sizeof(*ea));
                    756:        ea = mtod(m, struct ether_arp *);
                    757:        eh = (struct ether_header *)sa.sa_data;
                    758:        bzero((caddr_t)ea, sizeof(*ea));
                    759:        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
                    760:            sizeof(eh->ether_dhost));
                    761:        eh->ether_type = htons(ETHERTYPE_REVARP);
                    762:        ea->arp_hrd = htons(ARPHRD_ETHER);
                    763:        ea->arp_pro = htons(ETHERTYPE_IP);
                    764:        ea->arp_hln = sizeof(ea->arp_sha);      /* hardware address length */
                    765:        ea->arp_pln = sizeof(ea->arp_spa);      /* protocol address length */
                    766:        ea->arp_op = htons(ARPOP_REVREQUEST);
                    767:        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
                    768:           sizeof(ea->arp_sha));
                    769:        bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_tha,
                    770:           sizeof(ea->arp_tha));
                    771:        sa.sa_family = AF_UNSPEC;
                    772:        sa.sa_len = sizeof(sa);
                    773:        ifp->if_output(ifp, m, &sa, (struct rtentry *)0);
                    774: }
                    775: 
                    776: /*
                    777:  * RARP for the ip address of the specified interface, but also
                    778:  * save the ip address of the server that sent the answer.
                    779:  * Timeout if no response is received.
                    780:  */
                    781: int
                    782: revarpwhoarewe(ifp, serv_in, clnt_in)
                    783:        struct ifnet *ifp;
                    784:        struct in_addr *serv_in;
                    785:        struct in_addr *clnt_in;
                    786: {
                    787:        int result, count = 20;
                    788:        extern int tsleep(void *, int, char *, int);
                    789:        
                    790:        if (myip_initialized) 
                    791:                return EIO;
                    792: 
                    793:        myip_ifp = ifp;
                    794:        revarp_in_progress = 1;
                    795:        while (count--) {
                    796:                revarprequest(ifp);
                    797:                result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2);
                    798:                if (result != EWOULDBLOCK)
                    799:                        break;
                    800:        }
                    801:        revarp_in_progress = 0;
                    802:        if (!myip_initialized)
                    803:                return ENETUNREACH;
                    804:        
                    805:        bcopy((caddr_t)&srv_ip, serv_in, sizeof(*serv_in));
                    806:        bcopy((caddr_t)&myip, clnt_in, sizeof(*clnt_in));
                    807:        return 0;
                    808: }
                    809: 
                    810: /* For compatibility: only saves interface address. */
                    811: int
                    812: revarpwhoami(in, ifp)
                    813:        struct in_addr *in;
                    814:        struct ifnet *ifp;
                    815: {
                    816:        struct in_addr server;
                    817:        return (revarpwhoarewe(ifp, &server, in));
                    818: }
                    819: 
                    820: 
                    821: #ifdef DDB
                    822: static void
                    823: db_print_sa(sa)
                    824:        struct sockaddr *sa;
                    825: {
                    826:        int len;
                    827:        u_char *p;
                    828: 
                    829:        if (sa == 0) {
                    830:                db_printf("[NULL]");
                    831:                return;
                    832:        }
                    833: 
                    834:        p = (u_char*)sa;
                    835:        len = sa->sa_len;
                    836:        db_printf("[");
                    837:        while (len > 0) {
                    838:                db_printf("%d", *p);
                    839:                p++; len--;
                    840:                if (len) db_printf(",");
                    841:        }
                    842:        db_printf("]\n");
                    843: }
                    844: static void
                    845: db_print_ifa(ifa)
                    846:        struct ifaddr *ifa;
                    847: {
                    848:        if (ifa == 0)
                    849:                return;
                    850:        db_printf("  ifa_addr=");
                    851:        db_print_sa(ifa->ifa_addr);
                    852:        db_printf("  ifa_dsta=");
                    853:        db_print_sa(ifa->ifa_dstaddr);
                    854:        db_printf("  ifa_mask=");
                    855:        db_print_sa(ifa->ifa_netmask);
                    856:        db_printf("  flags=0x%x,refcnt=%d,metric=%d\n",
                    857:                          ifa->ifa_flags,
                    858:                          ifa->ifa_refcnt,
                    859:                          ifa->ifa_metric);
                    860: }
                    861: static void
                    862: db_print_llinfo(li)
                    863:        caddr_t li;
                    864: {
                    865:        struct llinfo_arp *la;
                    866: 
                    867:        if (li == 0)
                    868:                return;
                    869:        la = (struct llinfo_arp *)li;
                    870:        db_printf("  la_rt=0x%x la_hold=0x%x, la_asked=0x%x\n",
                    871:                          la->la_rt, la->la_hold, la->la_asked);
                    872: }
                    873: /*
                    874:  * Function to pass to rn_walktree().
                    875:  * Return non-zero error to abort walk.
                    876:  */
                    877: static int
                    878: db_show_radix_node(rn, w)
                    879:        struct radix_node *rn;
                    880:        void *w;
                    881: {
                    882:        struct rtentry *rt = (struct rtentry *)rn;
                    883: 
                    884:        db_printf("rtentry=0x%x", rt);
                    885: 
                    886:        db_printf(" flags=0x%x refcnt=%d use=%d expire=%d\n",
                    887:                          rt->rt_flags, rt->rt_refcnt,
                    888:                          rt->rt_use, rt->rt_expire);
                    889: 
                    890:        db_printf(" key="); db_print_sa(rt_key(rt));
                    891:        db_printf(" mask="); db_print_sa(rt_mask(rt));
                    892:        db_printf(" gw="); db_print_sa(rt->rt_gateway);
                    893: 
                    894:        db_printf(" ifp=0x%x ", rt->rt_ifp);
                    895:        if (rt->rt_ifp)
                    896:                db_printf("(%s%d)",
                    897:                                  rt->rt_ifp->if_name,
                    898:                                  rt->rt_ifp->if_unit);
                    899:        else
                    900:                db_printf("(NULL)");
                    901: 
                    902:        db_printf(" ifa=0x%x\n", rt->rt_ifa);
                    903:        db_print_ifa(rt->rt_ifa);
                    904: 
                    905:        db_printf(" genmask="); db_print_sa(rt->rt_genmask);
                    906: 
                    907:        db_printf(" gwroute=0x%x llinfo=0x%x\n",
                    908:                          rt->rt_gwroute, rt->rt_llinfo);
                    909:        db_print_llinfo(rt->rt_llinfo);
                    910: 
                    911:        return (0);
                    912: }
                    913: /*
                    914:  * Function to print all the route trees.
                    915:  * Use this from ddb:  "call db_show_arptab"
                    916:  */
                    917: db_show_arptab()
                    918: {
                    919:        struct radix_node_head *rnh;
                    920:        rnh = rt_tables[AF_INET];
                    921:        db_printf("Route tree for AF_INET\n");
                    922:        if (rnh == NULL) {
                    923:                db_printf(" (not initialized)\n");
                    924:                return (0);
                    925:        }
                    926:        rn_walktree(rnh, db_show_radix_node, NULL);
                    927:        return (0);
                    928: }
                    929: #endif
                    930: #endif /* INET */

unix.superglobalmegacorp.com

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