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

Cache object: 044070694c3a4f0447211d636b64f508


[ 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.