[BACK]Return to if_ether.c CVS log [TXT][DIR] Up to [local] / sys / netinet

Annotation of sys/netinet/if_ether.c, Revision 1.1

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

CVSweb