The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/if_arp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_arp.c,v 1.103.2.1 2008/08/29 20:37:48 bouyer Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Public Access Networks Corporation ("Panix").  It was developed under
    9  * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * Copyright (c) 1982, 1986, 1988, 1993
   42  *      The Regents of the University of California.  All rights reserved.
   43  *
   44  * Redistribution and use in source and binary forms, with or without
   45  * modification, are permitted provided that the following conditions
   46  * are met:
   47  * 1. Redistributions of source code must retain the above copyright
   48  *    notice, this list of conditions and the following disclaimer.
   49  * 2. Redistributions in binary form must reproduce the above copyright
   50  *    notice, this list of conditions and the following disclaimer in the
   51  *    documentation and/or other materials provided with the distribution.
   52  * 3. Neither the name of the University nor the names of its contributors
   53  *    may be used to endorse or promote products derived from this software
   54  *    without specific prior written permission.
   55  *
   56  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   66  * SUCH DAMAGE.
   67  *
   68  *      @(#)if_ether.c  8.2 (Berkeley) 9/26/94
   69  */
   70 
   71 /*
   72  * Ethernet address resolution protocol.
   73  * TODO:
   74  *      add "inuse/lock" bit (or ref. count) along with valid bit
   75  */
   76 
   77 #include <sys/cdefs.h>
   78 __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.103.2.1 2008/08/29 20:37:48 bouyer Exp $");
   79 
   80 #include "opt_ddb.h"
   81 #include "opt_inet.h"
   82 
   83 #ifdef INET
   84 
   85 #include "bridge.h"
   86 
   87 #include <sys/param.h>
   88 #include <sys/systm.h>
   89 #include <sys/callout.h>
   90 #include <sys/malloc.h>
   91 #include <sys/mbuf.h>
   92 #include <sys/socket.h>
   93 #include <sys/time.h>
   94 #include <sys/kernel.h>
   95 #include <sys/errno.h>
   96 #include <sys/ioctl.h>
   97 #include <sys/syslog.h>
   98 #include <sys/proc.h>
   99 #include <sys/protosw.h>
  100 #include <sys/domain.h>
  101 #include <sys/sysctl.h>
  102 
  103 #include <net/ethertypes.h>
  104 #include <net/if.h>
  105 #include <net/if_dl.h>
  106 #include <net/if_token.h>
  107 #include <net/if_types.h>
  108 #include <net/route.h>
  109 
  110 #include <netinet/in.h>
  111 #include <netinet/in_systm.h>
  112 #include <netinet/in_var.h>
  113 #include <netinet/ip.h>
  114 #include <netinet/if_inarp.h>
  115 
  116 #include "arc.h"
  117 #if NARC > 0
  118 #include <net/if_arc.h>
  119 #endif
  120 #include "fddi.h"
  121 #if NFDDI > 0
  122 #include <net/if_fddi.h>
  123 #endif
  124 #include "token.h"
  125 
  126 #define SIN(s) ((struct sockaddr_in *)s)
  127 #define SDL(s) ((struct sockaddr_dl *)s)
  128 #define SRP(s) ((struct sockaddr_inarp *)s)
  129 
  130 /*
  131  * ARP trailer negotiation.  Trailer protocol is not IP specific,
  132  * but ARP request/response use IP addresses.
  133  */
  134 #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
  135 
  136 /* timer values */
  137 int     arpt_prune = (5*60*1);  /* walk list every 5 minutes */
  138 int     arpt_keep = (20*60);    /* once resolved, good for 20 more minutes */
  139 int     arpt_down = 20;         /* once declared down, don't send for 20 secs */
  140 int     arpt_refresh = (5*60);  /* time left before refreshing */
  141 #define rt_expire rt_rmx.rmx_expire
  142 #define rt_pksent rt_rmx.rmx_pksent
  143 
  144 static  void arprequest(struct ifnet *,
  145             struct in_addr *, struct in_addr *, u_int8_t *);
  146 static  void arptfree(struct llinfo_arp *);
  147 static  void arptimer(void *);
  148 static  struct llinfo_arp *arplookup(struct mbuf *, struct in_addr *,
  149                                           int, int);
  150 static  void in_arpinput(struct mbuf *);
  151 
  152 LIST_HEAD(, llinfo_arp) llinfo_arp;
  153 struct  ifqueue arpintrq = {0, 0, 0, 50};
  154 int     arp_inuse, arp_allocated, arp_intimer;
  155 int     arp_maxtries = 5;
  156 int     useloopback = 1;        /* use loopback interface for local traffic */
  157 int     arpinit_done = 0;
  158 
  159 struct  arpstat arpstat;
  160 struct  callout arptimer_ch;
  161 
  162 
  163 /* revarp state */
  164 static struct   in_addr myip, srv_ip;
  165 static int      myip_initialized = 0;
  166 static int      revarp_in_progress = 0;
  167 static struct   ifnet *myip_ifp = NULL;
  168 
  169 #ifdef DDB
  170 static void db_print_sa(const struct sockaddr *);
  171 static void db_print_ifa(struct ifaddr *);
  172 static void db_print_llinfo(caddr_t);
  173 static int db_show_radix_node(struct radix_node *, void *);
  174 #endif
  175 
  176 /*
  177  * this should be elsewhere.
  178  */
  179 
  180 static char *
  181 lla_snprintf(u_int8_t *, int);
  182 
  183 static char *
  184 lla_snprintf(u_int8_t *adrp, int len)
  185 {
  186 #define NUMBUFS 3
  187         static char buf[NUMBUFS][16*3];
  188         static int bnum = 0;
  189         static const char hexdigits[] = {
  190             '','1','2','3','4','5','6','7',
  191             '8','9','a','b','c','d','e','f'
  192         };
  193 
  194         int i;
  195         char *p;
  196 
  197         p = buf[bnum];
  198 
  199         *p++ = hexdigits[(*adrp)>>4];
  200         *p++ = hexdigits[(*adrp++)&0xf];
  201 
  202         for (i=1; i<len && i<16; i++) {
  203                 *p++ = ':';
  204                 *p++ = hexdigits[(*adrp)>>4];
  205                 *p++ = hexdigits[(*adrp++)&0xf];
  206         }
  207 
  208         *p = 0;
  209         p = buf[bnum];
  210         bnum = (bnum + 1) % NUMBUFS;
  211         return p;
  212 }
  213 
  214 DOMAIN_DEFINE(arpdomain);       /* forward declare and add to link set */
  215 
  216 const struct protosw arpsw[] = {
  217         { 0, &arpdomain, 0, 0,
  218           0, 0, 0, 0,
  219           0,
  220           0, 0, 0, arp_drain,
  221         }
  222 };
  223 
  224 
  225 struct domain arpdomain =
  226 {       PF_ARP,  "arp", 0, 0, 0,
  227         arpsw, &arpsw[sizeof(arpsw)/sizeof(arpsw[0])]
  228 };
  229 
  230 /*
  231  * ARP table locking.
  232  *
  233  * to prevent lossage vs. the arp_drain routine (which may be called at
  234  * any time, including in a device driver context), we do two things:
  235  *
  236  * 1) manipulation of la->la_hold is done at splnet() (for all of
  237  * about two instructions).
  238  *
  239  * 2) manipulation of the arp table's linked list is done under the
  240  * protection of the ARP_LOCK; if arp_drain() or arptimer is called
  241  * while the arp table is locked, we punt and try again later.
  242  */
  243 
  244 static int      arp_locked;
  245 static __inline int arp_lock_try(int);
  246 static __inline void arp_unlock(void);
  247 
  248 static __inline int
  249 arp_lock_try(int recurse)
  250 {
  251         int s;
  252 
  253         /*
  254          * Use splvm() -- we're blocking things that would cause
  255          * mbuf allocation.
  256          */
  257         s = splvm();
  258         if (!recurse && arp_locked) {
  259                 splx(s);
  260                 return (0);
  261         }
  262         arp_locked++;
  263         splx(s);
  264         return (1);
  265 }
  266 
  267 static __inline void
  268 arp_unlock(void)
  269 {
  270         int s;
  271 
  272         s = splvm();
  273         arp_locked--;
  274         splx(s);
  275 }
  276 
  277 #ifdef DIAGNOSTIC
  278 #define ARP_LOCK(recurse)                                               \
  279 do {                                                                    \
  280         if (arp_lock_try(recurse) == 0) {                               \
  281                 printf("%s:%d: arp already locked\n", __FILE__, __LINE__); \
  282                 panic("arp_lock");                                      \
  283         }                                                               \
  284 } while (/*CONSTCOND*/ 0)
  285 #define ARP_LOCK_CHECK()                                                \
  286 do {                                                                    \
  287         if (arp_locked == 0) {                                          \
  288                 printf("%s:%d: arp lock not held\n", __FILE__, __LINE__); \
  289                 panic("arp lock check");                                \
  290         }                                                               \
  291 } while (/*CONSTCOND*/ 0)
  292 #else
  293 #define ARP_LOCK(x)             (void) arp_lock_try(x)
  294 #define ARP_LOCK_CHECK()        /* nothing */
  295 #endif
  296 
  297 #define ARP_UNLOCK()            arp_unlock()
  298 
  299 /*
  300  * ARP protocol drain routine.  Called when memory is in short supply.
  301  * Called at splvm();
  302  */
  303 
  304 void
  305 arp_drain(void)
  306 {
  307         struct llinfo_arp *la, *nla;
  308         int count = 0;
  309         struct mbuf *mold;
  310 
  311         if (arp_lock_try(0) == 0) {
  312                 printf("arp_drain: locked; punting\n");
  313                 return;
  314         }
  315 
  316         for (la = LIST_FIRST(&llinfo_arp); la != 0; la = nla) {
  317                 nla = LIST_NEXT(la, la_list);
  318 
  319                 mold = la->la_hold;
  320                 la->la_hold = 0;
  321 
  322                 if (mold) {
  323                         m_freem(mold);
  324                         count++;
  325                 }
  326         }
  327         ARP_UNLOCK();
  328         arpstat.as_dfrdropped += count;
  329 }
  330 
  331 
  332 /*
  333  * Timeout routine.  Age arp_tab entries periodically.
  334  */
  335 /* ARGSUSED */
  336 static void
  337 arptimer(void *arg)
  338 {
  339         int s;
  340         struct llinfo_arp *la, *nla;
  341 
  342         s = splsoftnet();
  343 
  344         if (arp_lock_try(0) == 0) {
  345                 /* get it later.. */
  346                 splx(s);
  347                 return;
  348         }
  349 
  350         callout_reset(&arptimer_ch, arpt_prune * hz, arptimer, NULL);
  351         for (la = LIST_FIRST(&llinfo_arp); la != 0; la = nla) {
  352                 struct rtentry *rt = la->la_rt;
  353 
  354                 nla = LIST_NEXT(la, la_list);
  355                 if (rt->rt_expire == 0)
  356                         continue;
  357                 if ((rt->rt_expire - time.tv_sec) < arpt_refresh &&
  358                     rt->rt_pksent > (time.tv_sec - arpt_keep)) {
  359                         /*
  360                          * If the entry has been used during since last
  361                          * refresh, try to renew it before deleting.
  362                          */
  363                         arprequest(rt->rt_ifp,
  364                             &SIN(rt->rt_ifa->ifa_addr)->sin_addr,
  365                             &SIN(rt_key(rt))->sin_addr,
  366                             LLADDR(rt->rt_ifp->if_sadl));
  367                 } else if (rt->rt_expire <= time.tv_sec)
  368                         arptfree(la); /* timer has expired; clear */
  369         }
  370 
  371         ARP_UNLOCK();
  372 
  373         splx(s);
  374 }
  375 
  376 /*
  377  * Parallel to llc_rtrequest.
  378  */
  379 void
  380 arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
  381 {
  382         struct sockaddr *gate = rt->rt_gateway;
  383         struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
  384         static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
  385         size_t allocsize;
  386         struct mbuf *mold;
  387         int s;
  388         struct in_ifaddr *ia;
  389         struct ifaddr *ifa;
  390 
  391         if (!arpinit_done) {
  392                 arpinit_done = 1;
  393                 /*
  394                  * We generate expiration times from time.tv_sec
  395                  * so avoid accidently creating permanent routes.
  396                  */
  397                 if (time.tv_sec == 0) {
  398                         time.tv_sec++;
  399                 }
  400                 callout_init(&arptimer_ch);
  401                 callout_reset(&arptimer_ch, hz, arptimer, NULL);
  402         }
  403 
  404         if ((rt->rt_flags & RTF_GATEWAY) != 0) {
  405                 if (req != RTM_ADD)
  406                         return;
  407 
  408                 /*
  409                  * linklayers with particular link MTU limitation.
  410                  */
  411                 switch(rt->rt_ifp->if_type) {
  412 #if NFDDI > 0
  413                 case IFT_FDDI:
  414                         if (rt->rt_ifp->if_mtu > FDDIIPMTU)
  415                                 rt->rt_rmx.rmx_mtu = FDDIIPMTU;
  416                         break;
  417 #endif
  418 #if NARC > 0
  419                 case IFT_ARCNET:
  420                     {
  421                         int arcipifmtu;
  422 
  423                         if (rt->rt_ifp->if_flags & IFF_LINK0)
  424                                 arcipifmtu = arc_ipmtu;
  425                         else
  426                                 arcipifmtu = ARCMTU;
  427                         if (rt->rt_ifp->if_mtu > arcipifmtu)
  428                                 rt->rt_rmx.rmx_mtu = arcipifmtu;
  429                         break;
  430                     }
  431 #endif
  432                 }
  433                 return;
  434         }
  435 
  436         ARP_LOCK(1);            /* we may already be locked here. */
  437 
  438         switch (req) {
  439 
  440         case RTM_ADD:
  441                 /*
  442                  * XXX: If this is a manually added route to interface
  443                  * such as older version of routed or gated might provide,
  444                  * restore cloning bit.
  445                  */
  446                 if ((rt->rt_flags & RTF_HOST) == 0 &&
  447                     SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
  448                         rt->rt_flags |= RTF_CLONING;
  449                 if (rt->rt_flags & RTF_CLONING) {
  450                         /*
  451                          * Case 1: This route should come from a route to iface.
  452                          */
  453                         rt_setgate(rt, rt_key(rt),
  454                                         (struct sockaddr *)&null_sdl);
  455                         gate = rt->rt_gateway;
  456                         SDL(gate)->sdl_type = rt->rt_ifp->if_type;
  457                         SDL(gate)->sdl_index = rt->rt_ifp->if_index;
  458                         /*
  459                          * Give this route an expiration time, even though
  460                          * it's a "permanent" route, so that routes cloned
  461                          * from it do not need their expiration time set.
  462                          */
  463                         rt->rt_expire = time.tv_sec;
  464                         /*
  465                          * linklayers with particular link MTU limitation.
  466                          */
  467                         switch (rt->rt_ifp->if_type) {
  468 #if NFDDI > 0
  469                         case IFT_FDDI:
  470                                 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0 &&
  471                                     (rt->rt_rmx.rmx_mtu > FDDIIPMTU ||
  472                                      (rt->rt_rmx.rmx_mtu == 0 &&
  473                                       rt->rt_ifp->if_mtu > FDDIIPMTU)))
  474                                         rt->rt_rmx.rmx_mtu = FDDIIPMTU;
  475                                 break;
  476 #endif
  477 #if NARC > 0
  478                         case IFT_ARCNET:
  479                             {
  480                                 int arcipifmtu;
  481                                 if (rt->rt_ifp->if_flags & IFF_LINK0)
  482                                         arcipifmtu = arc_ipmtu;
  483                                 else
  484                                         arcipifmtu = ARCMTU;
  485 
  486                                 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0 &&
  487                                     (rt->rt_rmx.rmx_mtu > arcipifmtu ||
  488                                      (rt->rt_rmx.rmx_mtu == 0 &&
  489                                       rt->rt_ifp->if_mtu > arcipifmtu)))
  490                                         rt->rt_rmx.rmx_mtu = arcipifmtu;
  491                                 break;
  492                             }
  493 #endif
  494                         }
  495                         break;
  496                 }
  497                 /* Announce a new entry if requested. */
  498                 if (rt->rt_flags & RTF_ANNOUNCE)
  499                         arprequest(rt->rt_ifp,
  500                             &SIN(rt_key(rt))->sin_addr,
  501                             &SIN(rt_key(rt))->sin_addr,
  502                             (u_char *)LLADDR(SDL(gate)));
  503                 /*FALLTHROUGH*/
  504         case RTM_RESOLVE:
  505                 if (gate->sa_family != AF_LINK ||
  506                     gate->sa_len < sizeof(null_sdl)) {
  507                         log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n");
  508                         break;
  509                 }
  510                 SDL(gate)->sdl_type = rt->rt_ifp->if_type;
  511                 SDL(gate)->sdl_index = rt->rt_ifp->if_index;
  512                 if (la != 0)
  513                         break; /* This happens on a route change */
  514                 /*
  515                  * Case 2:  This route may come from cloning, or a manual route
  516                  * add with a LL address.
  517                  */
  518                 switch (SDL(gate)->sdl_type) {
  519 #if NTOKEN > 0
  520                 case IFT_ISO88025:
  521                         allocsize = sizeof(*la) + sizeof(struct token_rif);
  522                         break;
  523 #endif /* NTOKEN > 0 */
  524                 default:
  525                         allocsize = sizeof(*la);
  526                 }
  527                 R_Malloc(la, struct llinfo_arp *, allocsize);
  528                 rt->rt_llinfo = (caddr_t)la;
  529                 if (la == 0) {
  530                         log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
  531                         break;
  532                 }
  533                 arp_inuse++, arp_allocated++;
  534                 Bzero(la, allocsize);
  535                 la->la_rt = rt;
  536                 rt->rt_flags |= RTF_LLINFO;
  537                 LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
  538 
  539                 INADDR_TO_IA(SIN(rt_key(rt))->sin_addr, ia);
  540                 while (ia && ia->ia_ifp != rt->rt_ifp)
  541                         NEXT_IA_WITH_SAME_ADDR(ia);
  542                 if (ia) {
  543                         /*
  544                          * This test used to be
  545                          *      if (lo0ifp->if_flags & IFF_UP)
  546                          * It allowed local traffic to be forced through
  547                          * the hardware by configuring the loopback down.
  548                          * However, it causes problems during network
  549                          * configuration for boards that can't receive
  550                          * packets they send.  It is now necessary to clear
  551                          * "useloopback" and remove the route to force
  552                          * traffic out to the hardware.
  553                          *
  554                          * In 4.4BSD, the above "if" statement checked
  555                          * rt->rt_ifa against rt_key(rt).  It was changed
  556                          * to the current form so that we can provide a
  557                          * better support for multiple IPv4 addresses on a
  558                          * interface.
  559                          */
  560                         rt->rt_expire = 0;
  561                         Bcopy(LLADDR(rt->rt_ifp->if_sadl),
  562                             LLADDR(SDL(gate)),
  563                             SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen);
  564                         if (useloopback)
  565                                 rt->rt_ifp = lo0ifp;
  566                         /*
  567                          * make sure to set rt->rt_ifa to the interface
  568                          * address we are using, otherwise we will have trouble
  569                          * with source address selection.
  570                          */
  571                         ifa = &ia->ia_ifa;
  572                         if (ifa != rt->rt_ifa) {
  573                                 IFAFREE(rt->rt_ifa);
  574                                 IFAREF(ifa);
  575                                 rt->rt_ifa = ifa;
  576                         }
  577                 }
  578                 break;
  579 
  580         case RTM_DELETE:
  581                 if (la == 0)
  582                         break;
  583                 arp_inuse--;
  584                 LIST_REMOVE(la, la_list);
  585                 rt->rt_llinfo = 0;
  586                 rt->rt_flags &= ~RTF_LLINFO;
  587 
  588                 s = splnet();
  589                 mold = la->la_hold;
  590                 la->la_hold = 0;
  591                 splx(s);
  592 
  593                 if (mold)
  594                         m_freem(mold);
  595 
  596                 Free((caddr_t)la);
  597         }
  598         ARP_UNLOCK();
  599 }
  600 
  601 /*
  602  * Broadcast an ARP request. Caller specifies:
  603  *      - arp header source ip address
  604  *      - arp header target ip address
  605  *      - arp header source ethernet address
  606  */
  607 static void
  608 arprequest(struct ifnet *ifp,
  609     struct in_addr *sip, struct in_addr *tip, u_int8_t *enaddr)
  610 {
  611         struct mbuf *m;
  612         struct arphdr *ah;
  613         struct sockaddr sa;
  614 
  615         if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
  616                 return;
  617         MCLAIM(m, &arpdomain.dom_mowner);
  618         switch (ifp->if_type) {
  619         case IFT_IEEE1394:
  620                 m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) +
  621                     ifp->if_addrlen;
  622                 break;
  623         default:
  624                 m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) +
  625                     2 * ifp->if_addrlen;
  626                 break;
  627         }
  628         m->m_pkthdr.len = m->m_len;
  629         MH_ALIGN(m, m->m_len);
  630         ah = mtod(m, struct arphdr *);
  631         bzero((caddr_t)ah, m->m_len);
  632         switch (ifp->if_type) {
  633         case IFT_IEEE1394:      /* RFC2734 */
  634                 /* fill it now for ar_tpa computation */
  635                 ah->ar_hrd = htons(ARPHRD_IEEE1394);
  636                 break;
  637         default:
  638                 /* ifp->if_output will fill ar_hrd */
  639                 break;
  640         }
  641         ah->ar_pro = htons(ETHERTYPE_IP);
  642         ah->ar_hln = ifp->if_addrlen;           /* hardware address length */
  643         ah->ar_pln = sizeof(struct in_addr);    /* protocol address length */
  644         ah->ar_op = htons(ARPOP_REQUEST);
  645         bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln);
  646         bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln);
  647         bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln);
  648         sa.sa_family = AF_ARP;
  649         sa.sa_len = 2;
  650         m->m_flags |= M_BCAST;
  651         arpstat.as_sndtotal++;
  652         arpstat.as_sndrequest++;
  653         (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
  654 }
  655 
  656 /*
  657  * Resolve an IP address into an ethernet address.  If success,
  658  * desten is filled in.  If there is no entry in arptab,
  659  * set one up and broadcast a request for the IP address.
  660  * Hold onto this mbuf and resend it once the address
  661  * is finally resolved.  A return value of 1 indicates
  662  * that desten has been filled in and the packet should be sent
  663  * normally; a 0 return indicates that the packet has been
  664  * taken over here, either now or for later transmission.
  665  */
  666 int
  667 arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m,
  668     struct sockaddr *dst, u_char *desten)
  669 {
  670         struct llinfo_arp *la;
  671         struct sockaddr_dl *sdl;
  672         struct mbuf *mold;
  673         int s;
  674 
  675         if (rt)
  676                 la = (struct llinfo_arp *)rt->rt_llinfo;
  677         else {
  678                 if ((la = arplookup(m, &SIN(dst)->sin_addr, 1, 0)) != NULL)
  679                         rt = la->la_rt;
  680         }
  681         if (la == 0 || rt == 0) {
  682                 arpstat.as_allocfail++;
  683                 log(LOG_DEBUG,
  684                     "arpresolve: can't allocate llinfo on %s for %s\n",
  685                     ifp->if_xname, in_fmtaddr(SIN(dst)->sin_addr));
  686                 m_freem(m);
  687                 return (0);
  688         }
  689         sdl = SDL(rt->rt_gateway);
  690         /*
  691          * Check the address family and length is valid, the address
  692          * is resolved; otherwise, try to resolve.
  693          */
  694         if ((rt->rt_expire == 0 || rt->rt_expire > time.tv_sec) &&
  695             sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
  696                 bcopy(LLADDR(sdl), desten,
  697                     min(sdl->sdl_alen, ifp->if_addrlen));
  698                 rt->rt_pksent = time.tv_sec; /* Time for last pkt sent */
  699                 return 1;
  700         }
  701         /*
  702          * There is an arptab entry, but no ethernet address
  703          * response yet.  Replace the held mbuf with this
  704          * latest one.
  705          */
  706 
  707         arpstat.as_dfrtotal++;
  708         s = splnet();
  709         mold = la->la_hold;
  710         la->la_hold = m;
  711         splx(s);
  712 
  713         if (mold) {
  714                 arpstat.as_dfrdropped++;
  715                 m_freem(mold);
  716         }
  717 
  718         /*
  719          * Re-send the ARP request when appropriate.
  720          */
  721 #ifdef  DIAGNOSTIC
  722         if (rt->rt_expire == 0) {
  723                 /* This should never happen. (Should it? -gwr) */
  724                 printf("arpresolve: unresolved and rt_expire == 0\n");
  725                 /* Set expiration time to now (expired). */
  726                 rt->rt_expire = time.tv_sec;
  727         }
  728 #endif
  729         if (rt->rt_expire) {
  730                 rt->rt_flags &= ~RTF_REJECT;
  731                 if (la->la_asked == 0 || rt->rt_expire != time.tv_sec) {
  732                         rt->rt_expire = time.tv_sec;
  733                         if (la->la_asked++ < arp_maxtries)
  734                                 arprequest(ifp,
  735                                     &SIN(rt->rt_ifa->ifa_addr)->sin_addr,
  736                                     &SIN(dst)->sin_addr,
  737                                     LLADDR(ifp->if_sadl));
  738                         else {
  739                                 rt->rt_flags |= RTF_REJECT;
  740                                 rt->rt_expire += arpt_down;
  741                                 la->la_asked = 0;
  742                         }
  743                 }
  744         }
  745         return (0);
  746 }
  747 
  748 /*
  749  * Common length and type checks are done here,
  750  * then the protocol-specific routine is called.
  751  */
  752 void
  753 arpintr(void)
  754 {
  755         struct mbuf *m;
  756         struct arphdr *ar;
  757         int s;
  758         int arplen;
  759 
  760         while (arpintrq.ifq_head) {
  761                 s = splnet();
  762                 IF_DEQUEUE(&arpintrq, m);
  763                 splx(s);
  764                 if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
  765                         panic("arpintr");
  766 
  767                 MCLAIM(m, &arpdomain.dom_mowner);
  768                 arpstat.as_rcvtotal++;
  769 
  770                 /*
  771                  * First, make sure we have at least struct arphdr.
  772                  */
  773                 if (m->m_len < sizeof(struct arphdr) ||
  774                     (ar = mtod(m, struct arphdr *)) == NULL)
  775                         goto badlen;
  776 
  777                 switch (m->m_pkthdr.rcvif->if_type) {
  778                 case IFT_IEEE1394:
  779                         arplen = sizeof(struct arphdr) +
  780                             ar->ar_hln + 2 * ar->ar_pln;
  781                         break;
  782                 default:
  783                         arplen = sizeof(struct arphdr) +
  784                             2 * ar->ar_hln + 2 * ar->ar_pln;
  785                         break;
  786                 }
  787 
  788                 if (/* XXX ntohs(ar->ar_hrd) == ARPHRD_ETHER && */
  789                     m->m_len >= arplen)
  790                         switch (ntohs(ar->ar_pro)) {
  791                         case ETHERTYPE_IP:
  792                         case ETHERTYPE_IPTRAILERS:
  793                                 in_arpinput(m);
  794                                 continue;
  795                         default:
  796                                 arpstat.as_rcvbadproto++;
  797                         }
  798                 else {
  799 badlen:
  800                         arpstat.as_rcvbadlen++;
  801                 }
  802                 m_freem(m);
  803         }
  804 }
  805 
  806 /*
  807  * ARP for Internet protocols on 10 Mb/s Ethernet.
  808  * Algorithm is that given in RFC 826.
  809  * In addition, a sanity check is performed on the sender
  810  * protocol address, to catch impersonators.
  811  * We no longer handle negotiations for use of trailer protocol:
  812  * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
  813  * along with IP replies if we wanted trailers sent to us,
  814  * and also sent them in response to IP replies.
  815  * This allowed either end to announce the desire to receive
  816  * trailer packets.
  817  * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
  818  * but formerly didn't normally send requests.
  819  */
  820 static void
  821 in_arpinput(struct mbuf *m)
  822 {
  823         struct arphdr *ah;
  824         struct ifnet *ifp = m->m_pkthdr.rcvif;
  825         struct llinfo_arp *la = 0;
  826         struct rtentry  *rt;
  827         struct in_ifaddr *ia;
  828 #if NBRIDGE > 0
  829         struct in_ifaddr *bridge_ia = NULL;
  830 #endif
  831         struct sockaddr_dl *sdl;
  832         struct sockaddr sa;
  833         struct in_addr isaddr, itaddr, myaddr;
  834         int op;
  835         struct mbuf *mold;
  836         int s;
  837 
  838         ah = mtod(m, struct arphdr *);
  839         op = ntohs(ah->ar_op);
  840 
  841         /*
  842          * Fix up ah->ar_hrd if necessary, before using ar_tha() or
  843          * ar_tpa().
  844          */
  845         switch (ifp->if_type) {
  846         case IFT_IEEE1394:
  847                 if (ntohs(ah->ar_hrd) == ARPHRD_IEEE1394)
  848                         ;
  849                 else {
  850                         /* XXX this is to make sure we compute ar_tha right */
  851                         /* XXX check ar_hrd more strictly? */
  852                         ah->ar_hrd = htons(ARPHRD_IEEE1394);
  853                 }
  854                 break;
  855         default:
  856                 /* XXX check ar_hrd? */
  857                 break;
  858         }
  859 
  860         bcopy((caddr_t)ar_spa(ah), (caddr_t)&isaddr, sizeof (isaddr));
  861         bcopy((caddr_t)ar_tpa(ah), (caddr_t)&itaddr, sizeof (itaddr));
  862 
  863         if (m->m_flags & (M_BCAST|M_MCAST))
  864                 arpstat.as_rcvmcast++;
  865 
  866         /*
  867          * If the target IP address is zero, ignore the packet.
  868          * This prevents the code below from tring to answer
  869          * when we are using IP address zero (booting).
  870          */
  871         if (in_nullhost(itaddr)) {
  872                 arpstat.as_rcvzerotpa++;
  873                 goto out;
  874         }
  875 
  876         /*
  877          * If the source IP address is zero, this is most likely a
  878          * confused host trying to use IP address zero. (Windoze?)
  879          * XXX: Should we bother trying to reply to these?
  880          */
  881         if (in_nullhost(isaddr)) {
  882                 arpstat.as_rcvzerospa++;
  883                 goto out;
  884         }
  885 
  886         /*
  887          * Search for a matching interface address
  888          * or any address on the interface to use
  889          * as a dummy address in the rest of this function
  890          */
  891         INADDR_TO_IA(itaddr, ia);
  892         while (ia != NULL) {
  893                 if (ia->ia_ifp == m->m_pkthdr.rcvif)
  894                         break;
  895 
  896 #if NBRIDGE > 0
  897                 /*
  898                  * If the interface we received the packet on
  899                  * is part of a bridge, check to see if we need
  900                  * to "bridge" the packet to ourselves at this
  901                  * layer.  Note we still prefer a perfect match,
  902                  * but allow this weaker match if necessary.
  903                  */
  904                 if (m->m_pkthdr.rcvif->if_bridge != NULL &&
  905                     m->m_pkthdr.rcvif->if_bridge == ia->ia_ifp->if_bridge)
  906                         bridge_ia = ia;
  907 #endif /* NBRIDGE > 0 */
  908 
  909                 NEXT_IA_WITH_SAME_ADDR(ia);
  910         }
  911 
  912 #if NBRIDGE > 0
  913         if (ia == NULL && bridge_ia != NULL) {
  914                 ia = bridge_ia;
  915                 ifp = bridge_ia->ia_ifp;
  916         }
  917 #endif
  918 
  919         if (ia == NULL) {
  920                 INADDR_TO_IA(isaddr, ia);
  921                 while ((ia != NULL) && ia->ia_ifp != m->m_pkthdr.rcvif)
  922                         NEXT_IA_WITH_SAME_ADDR(ia);
  923 
  924                 if (ia == NULL) {
  925                         IFP_TO_IA(ifp, ia);
  926                         if (ia == NULL) {
  927                                 arpstat.as_rcvnoint++;
  928                                 goto out;
  929                         }
  930                 }
  931         }
  932 
  933         myaddr = ia->ia_addr.sin_addr;
  934 
  935         /* XXX checks for bridge case? */
  936         if (!bcmp((caddr_t)ar_sha(ah), LLADDR(ifp->if_sadl),
  937             ifp->if_addrlen)) {
  938                 arpstat.as_rcvlocalsha++;
  939                 goto out;       /* it's from me, ignore it. */
  940         }
  941 
  942         /* XXX checks for bridge case? */
  943         if (!bcmp((caddr_t)ar_sha(ah), (caddr_t)ifp->if_broadcastaddr,
  944             ifp->if_addrlen)) {
  945                 arpstat.as_rcvbcastsha++;
  946                 log(LOG_ERR,
  947                     "%s: arp: link address is broadcast for IP address %s!\n",
  948                     ifp->if_xname, in_fmtaddr(isaddr));
  949                 goto out;
  950         }
  951 
  952         if (in_hosteq(isaddr, myaddr)) {
  953                 arpstat.as_rcvlocalspa++;
  954                 log(LOG_ERR,
  955                    "duplicate IP address %s sent from link address %s\n",
  956                    in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln));
  957                 itaddr = myaddr;
  958                 goto reply;
  959         }
  960         la = arplookup(m, &isaddr, in_hosteq(itaddr, myaddr), 0);
  961         if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
  962                 if (sdl->sdl_alen &&
  963                     bcmp((caddr_t)ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) {
  964                         if (rt->rt_flags & RTF_STATIC) {
  965                                 arpstat.as_rcvoverperm++;
  966                                 log(LOG_INFO,
  967                                     "%s tried to overwrite permanent arp info"
  968                                     " for %s\n",
  969                                     lla_snprintf(ar_sha(ah), ah->ar_hln),
  970                                     in_fmtaddr(isaddr));
  971                                 goto out;
  972                         } else if (rt->rt_ifp != ifp) {
  973                                 arpstat.as_rcvoverint++;
  974                                 log(LOG_INFO,
  975                                     "%s on %s tried to overwrite "
  976                                     "arp info for %s on %s\n",
  977                                     lla_snprintf(ar_sha(ah), ah->ar_hln),
  978                                     ifp->if_xname, in_fmtaddr(isaddr),
  979                                     rt->rt_ifp->if_xname);
  980                                     goto out;
  981                         } else {
  982                                 arpstat.as_rcvover++;
  983                                 log(LOG_INFO,
  984                                     "arp info overwritten for %s by %s\n",
  985                                     in_fmtaddr(isaddr),
  986                                     lla_snprintf(ar_sha(ah), ah->ar_hln));
  987                         }
  988                 }
  989                 /*
  990                  * sanity check for the address length.
  991                  * XXX this does not work for protocols with variable address
  992                  * length. -is
  993                  */
  994                 if (sdl->sdl_alen &&
  995                     sdl->sdl_alen != ah->ar_hln) {
  996                         arpstat.as_rcvlenchg++;
  997                         log(LOG_WARNING,
  998                             "arp from %s: new addr len %d, was %d\n",
  999                             in_fmtaddr(isaddr), ah->ar_hln, sdl->sdl_alen);
 1000                 }
 1001                 if (ifp->if_addrlen != ah->ar_hln) {
 1002                         arpstat.as_rcvbadlen++;
 1003                         log(LOG_WARNING,
 1004                             "arp from %s: addr len: new %d, i/f %d (ignored)\n",
 1005                             in_fmtaddr(isaddr), ah->ar_hln,
 1006                             ifp->if_addrlen);
 1007                         goto reply;
 1008                 }
 1009 #if NTOKEN > 0
 1010                 /*
 1011                  * XXX uses m_data and assumes the complete answer including
 1012                  * XXX token-ring headers is in the same buf
 1013                  */
 1014                 if (ifp->if_type == IFT_ISO88025) {
 1015                         struct token_header *trh;
 1016 
 1017                         trh = (struct token_header *)M_TRHSTART(m);
 1018                         if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
 1019                                 struct token_rif        *rif;
 1020                                 size_t  riflen;
 1021 
 1022                                 rif = TOKEN_RIF(trh);
 1023                                 riflen = (ntohs(rif->tr_rcf) &
 1024                                     TOKEN_RCF_LEN_MASK) >> 8;
 1025 
 1026                                 if (riflen > 2 &&
 1027                                     riflen < sizeof(struct token_rif) &&
 1028                                     (riflen & 1) == 0) {
 1029                                         rif->tr_rcf ^= htons(TOKEN_RCF_DIRECTION);
 1030                                         rif->tr_rcf &= htons(~TOKEN_RCF_BROADCAST_MASK);
 1031                                         bcopy(rif, TOKEN_RIF(la), riflen);
 1032                                 }
 1033                         }
 1034                 }
 1035 #endif /* NTOKEN > 0 */
 1036                 bcopy((caddr_t)ar_sha(ah), LLADDR(sdl),
 1037                     sdl->sdl_alen = ah->ar_hln);
 1038                 if (rt->rt_expire)
 1039                         rt->rt_expire = time.tv_sec + arpt_keep;
 1040                 rt->rt_flags &= ~RTF_REJECT;
 1041                 la->la_asked = 0;
 1042 
 1043                 s = splnet();
 1044                 mold = la->la_hold;
 1045                 la->la_hold = 0;
 1046                 splx(s);
 1047 
 1048                 if (mold) {
 1049                         arpstat.as_dfrsent++;
 1050                         (*ifp->if_output)(ifp, mold, rt_key(rt), rt);
 1051                 }
 1052         }
 1053 reply:
 1054         if (op != ARPOP_REQUEST) {
 1055                 if (op == ARPOP_REPLY)
 1056                         arpstat.as_rcvreply++;
 1057         out:
 1058                 m_freem(m);
 1059                 return;
 1060         }
 1061         arpstat.as_rcvrequest++;
 1062         if (in_hosteq(itaddr, myaddr)) {
 1063                 /* I am the target */
 1064                 if (ar_tha(ah))
 1065                         bcopy((caddr_t)ar_sha(ah), (caddr_t)ar_tha(ah),
 1066                             ah->ar_hln);
 1067                 bcopy(LLADDR(ifp->if_sadl), (caddr_t)ar_sha(ah), ah->ar_hln);
 1068         } else {
 1069                 la = arplookup(m, &itaddr, 0, SIN_PROXY);
 1070                 if (la == 0)
 1071                         goto out;
 1072                 rt = la->la_rt;
 1073                 if (ar_tha(ah))
 1074                         bcopy((caddr_t)ar_sha(ah), (caddr_t)ar_tha(ah),
 1075                             ah->ar_hln);
 1076                 sdl = SDL(rt->rt_gateway);
 1077                 bcopy(LLADDR(sdl), (caddr_t)ar_sha(ah), ah->ar_hln);
 1078         }
 1079 
 1080         bcopy((caddr_t)ar_spa(ah), (caddr_t)ar_tpa(ah), ah->ar_pln);
 1081         bcopy((caddr_t)&itaddr, (caddr_t)ar_spa(ah), ah->ar_pln);
 1082         ah->ar_op = htons(ARPOP_REPLY);
 1083         ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */
 1084         switch (ifp->if_type) {
 1085         case IFT_IEEE1394:
 1086                 /*
 1087                  * ieee1394 arp reply is broadcast
 1088                  */
 1089                 m->m_flags &= ~M_MCAST;
 1090                 m->m_flags |= M_BCAST;
 1091                 m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + ah->ar_hln;
 1092                 break;
 1093 
 1094         default:
 1095                 m->m_flags &= ~(M_BCAST|M_MCAST); /* never reply by broadcast */
 1096                 m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln);
 1097                 break;
 1098         }
 1099         m->m_pkthdr.len = m->m_len;
 1100         sa.sa_family = AF_ARP;
 1101         sa.sa_len = 2;
 1102         arpstat.as_sndtotal++;
 1103         arpstat.as_sndreply++;
 1104         (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
 1105         return;
 1106 }
 1107 
 1108 /*
 1109  * Free an arp entry.
 1110  */
 1111 static void arptfree(struct llinfo_arp *la)
 1112 {
 1113         struct rtentry *rt = la->la_rt;
 1114         struct sockaddr_dl *sdl;
 1115 
 1116         ARP_LOCK_CHECK();
 1117 
 1118         if (rt == 0)
 1119                 panic("arptfree");
 1120         if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
 1121             sdl->sdl_family == AF_LINK) {
 1122                 sdl->sdl_alen = 0;
 1123                 la->la_asked = 0;
 1124                 rt->rt_flags &= ~RTF_REJECT;
 1125                 return;
 1126         }
 1127         rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
 1128             0, (struct rtentry **)0);
 1129 }
 1130 
 1131 /*
 1132  * Lookup or enter a new address in arptab.
 1133  */
 1134 static struct llinfo_arp *
 1135 arplookup(struct mbuf *m, struct in_addr *addr, int create, int proxy)
 1136 {
 1137         struct arphdr *ah;
 1138         struct ifnet *ifp = m->m_pkthdr.rcvif;
 1139         struct rtentry *rt;
 1140         static struct sockaddr_inarp sin;
 1141         const char *why = 0;
 1142 
 1143         ah = mtod(m, struct arphdr *);
 1144         sin.sin_len = sizeof(sin);
 1145         sin.sin_family = AF_INET;
 1146         sin.sin_addr = *addr;
 1147         sin.sin_other = proxy ? SIN_PROXY : 0;
 1148         rt = rtalloc1(sintosa(&sin), create);
 1149         if (rt == 0)
 1150                 return (0);
 1151         rt->rt_refcnt--;
 1152 
 1153         if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) == RTF_LLINFO &&
 1154             rt->rt_gateway->sa_family == AF_LINK)
 1155                 return ((struct llinfo_arp *)rt->rt_llinfo);
 1156 
 1157 
 1158 
 1159         if (create) {
 1160                 if (rt->rt_flags & RTF_GATEWAY)
 1161                         why = "host is not on local network";
 1162                 else if ((rt->rt_flags & RTF_LLINFO) == 0) {
 1163                         arpstat.as_allocfail++;
 1164                         why = "could not allocate llinfo";
 1165                 } else
 1166                         why = "gateway route is not ours";
 1167                 log(LOG_DEBUG, "arplookup: unable to enter address"
 1168                     " for %s@%s on %s (%s)\n",
 1169                     in_fmtaddr(*addr), lla_snprintf(ar_sha(ah), ah->ar_hln),
 1170                     (ifp) ? ifp->if_xname : 0, why);
 1171                 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_CLONED) != 0) {
 1172                         rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
 1173                             rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
 1174                 }
 1175         }
 1176         return (0);
 1177 }
 1178 
 1179 int
 1180 arpioctl(u_long cmd, caddr_t data)
 1181 {
 1182 
 1183         return (EOPNOTSUPP);
 1184 }
 1185 
 1186 void
 1187 arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
 1188 {
 1189         struct in_addr *ip;
 1190 
 1191         /*
 1192          * Warn the user if another station has this IP address,
 1193          * but only if the interface IP address is not zero.
 1194          */
 1195         ip = &IA_SIN(ifa)->sin_addr;
 1196         if (!in_nullhost(*ip))
 1197                 arprequest(ifp, ip, ip, LLADDR(ifp->if_sadl));
 1198 
 1199         ifa->ifa_rtrequest = arp_rtrequest;
 1200         ifa->ifa_flags |= RTF_CLONING;
 1201 }
 1202 
 1203 /*
 1204  * Called from 10 Mb/s Ethernet interrupt handlers
 1205  * when ether packet type ETHERTYPE_REVARP
 1206  * is received.  Common length and type checks are done here,
 1207  * then the protocol-specific routine is called.
 1208  */
 1209 void
 1210 revarpinput(struct mbuf *m)
 1211 {
 1212         struct arphdr *ar;
 1213 
 1214         if (m->m_len < sizeof(struct arphdr))
 1215                 goto out;
 1216         ar = mtod(m, struct arphdr *);
 1217 #if 0 /* XXX I don't think we need this... and it will prevent other LL */
 1218         if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)
 1219                 goto out;
 1220 #endif
 1221         if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))
 1222                 goto out;
 1223         switch (ntohs(ar->ar_pro)) {
 1224         case ETHERTYPE_IP:
 1225         case ETHERTYPE_IPTRAILERS:
 1226                 in_revarpinput(m);
 1227                 return;
 1228 
 1229         default:
 1230                 break;
 1231         }
 1232 out:
 1233         m_freem(m);
 1234 }
 1235 
 1236 /*
 1237  * RARP for Internet protocols on 10 Mb/s Ethernet.
 1238  * Algorithm is that given in RFC 903.
 1239  * We are only using for bootstrap purposes to get an ip address for one of
 1240  * our interfaces.  Thus we support no user-interface.
 1241  *
 1242  * Since the contents of the RARP reply are specific to the interface that
 1243  * sent the request, this code must ensure that they are properly associated.
 1244  *
 1245  * Note: also supports ARP via RARP packets, per the RFC.
 1246  */
 1247 void
 1248 in_revarpinput(struct mbuf *m)
 1249 {
 1250         struct ifnet *ifp;
 1251         struct arphdr *ah;
 1252         int op;
 1253 
 1254         ah = mtod(m, struct arphdr *);
 1255         op = ntohs(ah->ar_op);
 1256 
 1257         switch (m->m_pkthdr.rcvif->if_type) {
 1258         case IFT_IEEE1394:
 1259                 /* ARP without target hardware address is not supported */
 1260                 goto out;
 1261         default:
 1262                 break;
 1263         }
 1264 
 1265         switch (op) {
 1266         case ARPOP_REQUEST:
 1267         case ARPOP_REPLY:       /* per RFC */
 1268                 in_arpinput(m);
 1269                 return;
 1270         case ARPOP_REVREPLY:
 1271                 break;
 1272         case ARPOP_REVREQUEST:  /* handled by rarpd(8) */
 1273         default:
 1274                 goto out;
 1275         }
 1276         if (!revarp_in_progress)
 1277                 goto out;
 1278         ifp = m->m_pkthdr.rcvif;
 1279         if (ifp != myip_ifp) /* !same interface */
 1280                 goto out;
 1281         if (myip_initialized)
 1282                 goto wake;
 1283         if (bcmp(ar_tha(ah), LLADDR(ifp->if_sadl), ifp->if_sadl->sdl_alen))
 1284                 goto out;
 1285         bcopy((caddr_t)ar_spa(ah), (caddr_t)&srv_ip, sizeof(srv_ip));
 1286         bcopy((caddr_t)ar_tpa(ah), (caddr_t)&myip, sizeof(myip));
 1287         myip_initialized = 1;
 1288 wake:   /* Do wakeup every time in case it was missed. */
 1289         wakeup((caddr_t)&myip);
 1290 
 1291 out:
 1292         m_freem(m);
 1293 }
 1294 
 1295 /*
 1296  * Send a RARP request for the ip address of the specified interface.
 1297  * The request should be RFC 903-compliant.
 1298  */
 1299 void
 1300 revarprequest(struct ifnet *ifp)
 1301 {
 1302         struct sockaddr sa;
 1303         struct mbuf *m;
 1304         struct arphdr *ah;
 1305 
 1306         if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
 1307                 return;
 1308         MCLAIM(m, &arpdomain.dom_mowner);
 1309         m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) +
 1310             2*ifp->if_addrlen;
 1311         m->m_pkthdr.len = m->m_len;
 1312         MH_ALIGN(m, m->m_len);
 1313         ah = mtod(m, struct arphdr *);
 1314         bzero((caddr_t)ah, m->m_len);
 1315         ah->ar_pro = htons(ETHERTYPE_IP);
 1316         ah->ar_hln = ifp->if_addrlen;           /* hardware address length */
 1317         ah->ar_pln = sizeof(struct in_addr);    /* protocol address length */
 1318         ah->ar_op = htons(ARPOP_REVREQUEST);
 1319 
 1320         bcopy(LLADDR(ifp->if_sadl), (caddr_t)ar_sha(ah), ah->ar_hln);
 1321         bcopy(LLADDR(ifp->if_sadl), (caddr_t)ar_tha(ah), ah->ar_hln);
 1322 
 1323         sa.sa_family = AF_ARP;
 1324         sa.sa_len = 2;
 1325         m->m_flags |= M_BCAST;
 1326         (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
 1327 
 1328 }
 1329 
 1330 /*
 1331  * RARP for the ip address of the specified interface, but also
 1332  * save the ip address of the server that sent the answer.
 1333  * Timeout if no response is received.
 1334  */
 1335 int
 1336 revarpwhoarewe(struct ifnet *ifp, struct in_addr *serv_in,
 1337     struct in_addr *clnt_in)
 1338 {
 1339         int result, count = 20;
 1340 
 1341         myip_initialized = 0;
 1342         myip_ifp = ifp;
 1343 
 1344         revarp_in_progress = 1;
 1345         while (count--) {
 1346                 revarprequest(ifp);
 1347                 result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2);
 1348                 if (result != EWOULDBLOCK)
 1349                         break;
 1350         }
 1351         revarp_in_progress = 0;
 1352 
 1353         if (!myip_initialized)
 1354                 return ENETUNREACH;
 1355 
 1356         bcopy((caddr_t)&srv_ip, serv_in, sizeof(*serv_in));
 1357         bcopy((caddr_t)&myip, clnt_in, sizeof(*clnt_in));
 1358         return 0;
 1359 }
 1360 
 1361 
 1362 
 1363 #ifdef DDB
 1364 
 1365 #include <machine/db_machdep.h>
 1366 #include <ddb/db_interface.h>
 1367 #include <ddb/db_output.h>
 1368 
 1369 static void
 1370 db_print_sa(const struct sockaddr *sa)
 1371 {
 1372         int len;
 1373         u_char *p;
 1374 
 1375         if (sa == 0) {
 1376                 db_printf("[NULL]");
 1377                 return;
 1378         }
 1379 
 1380         p = (u_char*)sa;
 1381         len = sa->sa_len;
 1382         db_printf("[");
 1383         while (len > 0) {
 1384                 db_printf("%d", *p);
 1385                 p++; len--;
 1386                 if (len) db_printf(",");
 1387         }
 1388         db_printf("]\n");
 1389 }
 1390 
 1391 static void
 1392 db_print_ifa(struct ifaddr *ifa)
 1393 {
 1394         if (ifa == 0)
 1395                 return;
 1396         db_printf("  ifa_addr=");
 1397         db_print_sa(ifa->ifa_addr);
 1398         db_printf("  ifa_dsta=");
 1399         db_print_sa(ifa->ifa_dstaddr);
 1400         db_printf("  ifa_mask=");
 1401         db_print_sa(ifa->ifa_netmask);
 1402         db_printf("  flags=0x%x,refcnt=%d,metric=%d\n",
 1403                           ifa->ifa_flags,
 1404                           ifa->ifa_refcnt,
 1405                           ifa->ifa_metric);
 1406 }
 1407 
 1408 static void
 1409 db_print_llinfo(caddr_t li)
 1410 {
 1411         struct llinfo_arp *la;
 1412 
 1413         if (li == 0)
 1414                 return;
 1415         la = (struct llinfo_arp *)li;
 1416         db_printf("  la_rt=%p la_hold=%p, la_asked=0x%lx\n",
 1417                           la->la_rt, la->la_hold, la->la_asked);
 1418 }
 1419 
 1420 /*
 1421  * Function to pass to rn_walktree().
 1422  * Return non-zero error to abort walk.
 1423  */
 1424 static int
 1425 db_show_radix_node(struct radix_node *rn, void *w)
 1426 {
 1427         struct rtentry *rt = (struct rtentry *)rn;
 1428 
 1429         db_printf("rtentry=%p", rt);
 1430 
 1431         db_printf(" flags=0x%x refcnt=%d use=%ld expire=%ld\n",
 1432                           rt->rt_flags, rt->rt_refcnt,
 1433                           rt->rt_use, rt->rt_expire);
 1434 
 1435         db_printf(" key="); db_print_sa(rt_key(rt));
 1436         db_printf(" mask="); db_print_sa(rt_mask(rt));
 1437         db_printf(" gw="); db_print_sa(rt->rt_gateway);
 1438 
 1439         db_printf(" ifp=%p ", rt->rt_ifp);
 1440         if (rt->rt_ifp)
 1441                 db_printf("(%s)", rt->rt_ifp->if_xname);
 1442         else
 1443                 db_printf("(NULL)");
 1444 
 1445         db_printf(" ifa=%p\n", rt->rt_ifa);
 1446         db_print_ifa(rt->rt_ifa);
 1447 
 1448         db_printf(" genmask="); db_print_sa(rt->rt_genmask);
 1449 
 1450         db_printf(" gwroute=%p llinfo=%p\n",
 1451                           rt->rt_gwroute, rt->rt_llinfo);
 1452         db_print_llinfo(rt->rt_llinfo);
 1453 
 1454         return (0);
 1455 }
 1456 
 1457 /*
 1458  * Function to print all the route trees.
 1459  * Use this from ddb:  "show arptab"
 1460  */
 1461 void
 1462 db_show_arptab(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
 1463 {
 1464         struct radix_node_head *rnh;
 1465         rnh = rt_tables[AF_INET];
 1466         db_printf("Route tree for AF_INET\n");
 1467         if (rnh == NULL) {
 1468                 db_printf(" (not initialized)\n");
 1469                 return;
 1470         }
 1471         rn_walktree(rnh, db_show_radix_node, NULL);
 1472         return;
 1473 }
 1474 #endif
 1475 
 1476 SYSCTL_SETUP(sysctl_net_inet_arp_setup, "sysctl net.inet.arp subtree setup")
 1477 {
 1478         struct sysctlnode *node;
 1479 
 1480         sysctl_createv(clog, 0, NULL, NULL,
 1481                         CTLFLAG_PERMANENT,
 1482                         CTLTYPE_NODE, "net", NULL,
 1483                         NULL, 0, NULL, 0,
 1484                         CTL_NET, CTL_EOL);
 1485         sysctl_createv(clog, 0, NULL, NULL,
 1486                         CTLFLAG_PERMANENT,
 1487                         CTLTYPE_NODE, "inet", NULL,
 1488                         NULL, 0, NULL, 0,
 1489                         CTL_NET, PF_INET, CTL_EOL);
 1490         sysctl_createv(clog, 0, NULL, &node,
 1491                         CTLFLAG_PERMANENT,
 1492                         CTLTYPE_NODE, "arp",
 1493                         SYSCTL_DESCR("Address Resolution Protocol"),
 1494                         NULL, 0, NULL, 0,
 1495                         CTL_NET, PF_INET, CTL_CREATE, CTL_EOL);
 1496 
 1497         sysctl_createv(clog, 0, NULL, NULL,
 1498                         CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1499                         CTLTYPE_INT, "prune",
 1500                         SYSCTL_DESCR("ARP cache pruning interval"),
 1501                         NULL, 0, &arpt_prune, 0,
 1502                         CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL);
 1503 
 1504         sysctl_createv(clog, 0, NULL, NULL,
 1505                         CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1506                         CTLTYPE_INT, "keep",
 1507                         SYSCTL_DESCR("Valid ARP entry lifetime"),
 1508                         NULL, 0, &arpt_keep, 0,
 1509                         CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL);
 1510 
 1511         sysctl_createv(clog, 0, NULL, NULL,
 1512                         CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1513                         CTLTYPE_INT, "down",
 1514                         SYSCTL_DESCR("Failed ARP entry lifetime"),
 1515                         NULL, 0, &arpt_down, 0,
 1516                         CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL);
 1517 
 1518         sysctl_createv(clog, 0, NULL, NULL,
 1519                         CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1520                         CTLTYPE_INT, "refresh",
 1521                         SYSCTL_DESCR("ARP entry refresh interval"),
 1522                         NULL, 0, &arpt_refresh, 0,
 1523                         CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL);
 1524 }
 1525 
 1526 #endif /* INET */

Cache object: dbec5a93eb4389a86b7d49d27e26a0c7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.