[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

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