if_ether.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:47k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* if_ether.c - network Ethernet address resolution protocol */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1986, 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * @(#)if_ether.c 8.2 (Berkeley) 9/26/94
  37.  */
  38. /*
  39.  * Ethernet address resolution protocol.
  40.  * TODO:
  41.  * add "inuse/lock" bit (or ref. count) along with valid bit
  42.  */
  43. /*
  44. modification history
  45. --------------------
  46. 01u,24jun02,wap  optimize away some bcopy()s in arpresolve()
  47. 01t,21may02,vvv  fixed ARP timer overflow problem (SPR #63908)
  48. 01s,24jan02,vvv  fixed arpintr memory leak (SPR #72577)
  49. 01r,18dec01,vvv  fixed build error from previous check-in
  50. 01q,18dec01,vvv  fixed shared-memory booting problem (SPR #71023)
  51. 01p,10dec01,vvv  allow send to any address assigned to an interface (SPR #71836)
  52. 01o,01nov01,rae  compiler warnings, modified arpresolve error message (SPR #71242)
  53. 01n,12oct01,rae  merge from truestack ver 01z base 01j (SPRs 63006, 68954,
  54.                  69112 ... plus Fastpath, revarp, etc.)
  55. 01m,07feb01,spm  added merge record for 30jan01 update from version 01i of
  56.                  tor2_0_x branch (base 01h) and fixed modification history
  57. 01l,30jan01,ijm  merged SPR# 28602 fixes (proxy ARP services are obsolete);
  58.                  fixed deleting ARP entries when proxy flag set
  59. 01j,08nov99,pul  merging T2 cumulative patch 2
  60. 01k,08Nov98,pul  changed the argument ordering to ipEtherResolveRtn
  61. 01i,29apr99,pul  Upgraded NPT phase3 code to tor2.0.0
  62. 01h,10may99,spm  fixed SIOCSARP handling to support ATF_PUBL flag (SPR #24397)
  63. 01g,03sep98,n_s  fixed handling of IFF_NOARP flag in arpresolve. spr #22280
  64. 01g,13jul98,n_s  added arpRxmitTicks.  spr # 21577
  65. 01f,10jul97,vin  ifdefed revarp code, fixed warnings.
  66. 01e,23apr97,vin  fixed SPR8445, rt_expire for arp route entry being set to 0.
  67. 01d,29jan97,vin  fixed a bug in arpioctl(), sdl_alen field.
  68. 01c,16dec96,vin  removed unnecessary htons in arprequest() and arpinput().
  69. 01b,31oct96,vin  changed m_gethdr(..) to mHdrClGet(..).  
  70. 01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02n of if_ether.c
  71. */
  72. /*
  73.  * Ethernet address resolution protocol.
  74.  * TODO:
  75.  *      run at splnet (add ARP protocol intr.)
  76.  *      link entries onto hash chains, keep free list
  77.  *      add "inuse/lock" bit (or ref. count) along with valid bit
  78.  */
  79. #include "vxWorks.h"
  80. #include "logLib.h"
  81. #include "stdio.h"
  82. #include "net/mbuf.h"
  83. #include "sys/socket.h"
  84. #include "errno.h"
  85. #include "sys/ioctl.h"
  86. #include "net/if.h"
  87. #include "net/if_dl.h"
  88. #include "net/route.h"
  89. #include "netinet/in.h"
  90. #include "netinet/in_systm.h"
  91. #include "netinet/in_var.h"
  92. #include "netinet/ip.h"
  93. #include "netinet/if_ether.h"
  94. #include "wdLib.h"
  95. #include "tickLib.h"
  96. #include "net/systm.h"
  97. #ifdef VIRTUAL_STACK
  98. #include "netinet/vsLib.h"
  99. #endif /* VIRTUAL_STACK */
  100. #ifdef ROUTER_STACK
  101. #include "wrn/fastPath/fastPathLib.h"
  102. #include "wrn/fastPath/fastPathIpP.h"
  103. #endif /* ROUTER_STACK */
  104. #ifdef INET
  105. #ifdef WV_INSTRUMENTATION
  106. #ifdef INCLUDE_WVNET
  107. #include "wvNetLib.h"
  108. #endif /* INCLUDE_WVNET */
  109. #endif
  110. /* defines */
  111. /* defines */
  112. #define ENET_SIZE 6 /* Ethernet address size */
  113. #define DDB
  114. #define PROXY_HOOK /* include proxy hook code */
  115. #define SIN(s) ((struct sockaddr_in *)s)
  116. #define SDL(s) ((struct sockaddr_dl *)s)
  117. #define SRP(s) ((struct sockaddr_inarp *)s)
  118. /*
  119.  * ARP trailer negotiation.  Trailer protocol is not IP specific,
  120.  * but ARP request/response use IP addresses.
  121.  */
  122. #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
  123. #define rt_expire rt_rmx.rmx_expire
  124. #define ARP_RXMIT_TICKS_DFLT sysClkRateGet ()      /* Minimum number of ticks */
  125.            /* between retransmission  */
  126.    /* of ARP request          */
  127. #define TICK_GEQ(t1,t2) ((long)((t1) - (t2)) >= 0)
  128. /* externs */
  129. IMPORT STATUS netJobAdd (FUNCPTR, int, int, int, int, int);
  130. IMPORT int sysClkRateGet ();
  131. #ifndef VIRTUAL_STACK
  132. extern struct ifnet loif[];
  133. #endif /* VIRTUAL_STACK */
  134. extern  void _insque ();
  135. extern  void _remque ();
  136. int arpMaxEntries = 12;                      /* sensible default */
  137. /* globals */
  138. void arptfree (struct llinfo_arp *);
  139. #ifndef VIRTUAL_STACK
  140. struct llinfo_arp llinfo_arp = {&llinfo_arp, &llinfo_arp};
  141. int arp_inuse, arp_allocated, arp_intimer;
  142. int arpinit_done = 0;
  143. #endif /* VIRTUAL_STACK */
  144. struct ifqueue arpintrq = {0, 0, 0, 50};
  145. int useloopback = 1;
  146. int arp_maxtries = 5; /* use loopback interface for local traffic */
  147. /* timer values */
  148. int arpt_prune = (1*60); /* walk list every 1 minutes */
  149. int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
  150. int arpt_down = 20; /* once declared down, don't send for 20 secs */
  151. #ifndef VIRTUAL_STACK
  152. int arpRxmitTicks = -1;  /* Minimum number of ticks between */
  153. /* retranmission of ARP request    */
  154. #endif /* VIRTUAL_STACK */
  155. /* proxy arp hook */
  156. #ifdef PROXY_HOOK
  157. FUNCPTR  proxyArpHook = NULL;
  158. #endif
  159. /* locals */
  160. #ifndef VIRTUAL_STACK
  161. LOCAL WDOG_ID arptimerWd; /* watchdog timer for arptimer routine */
  162. #endif /* VIRTUAL_STACK */
  163. static char  digits[] = "0123456789abcdef";
  164. #ifdef WV_INSTRUMENTATION
  165. #ifdef INCLUDE_WVNET
  166.     /* Set common fields of event identifiers for this module. */
  167. LOCAL UCHAR wvNetModuleId = WV_NET_IFETHER_MODULE;   /* Value for if_ether.c */
  168. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;  /* Available event filter */
  169. LOCAL ULONG wvNetEventId; /* Event identifier: see wvNetLib.h */
  170. #endif    /* INCLUDE_WVNET */
  171. #endif
  172. /* forward declarations */
  173. #ifdef VIRTUAL_STACK
  174. void arptimer (int);
  175. #else
  176. static void arptimer (void *);
  177. #endif /* VIRTUAL_STACK */
  178. static void arprequest (struct arpcom *, u_long *, u_long *, u_char *);
  179. static struct llinfo_arp *arplookup (u_long, int, int);
  180. static void in_arpinput (struct mbuf *);
  181. static  void arpEntryDelete (void);
  182. /*
  183.  * Timeout routine.  Age arp_tab entries periodically.
  184.  */
  185. /* ARGSUSED */
  186. #ifdef VIRTUAL_STACK
  187. /* must have a helper routine because of argument limitations */
  188. /* in WdStart */
  189. void arptimerRestart
  190.     (
  191.     int stackNum
  192.     )
  193.     {
  194.     netJobAdd ((FUNCPTR)arptimer, stackNum, 0, 0, 0, 0);
  195.     }
  196. void arptimer
  197.     (
  198.     int stackNum    /* used to set the stack correctly in wd routine*/
  199.     )
  200.     {
  201.     int s;
  202.     register struct llinfo_arp *la;
  203.     virtualStackNumTaskIdSet(stackNum);
  204.     s = splnet();
  205.     la = _llinfo_arp.la_next;
  206.     wdStart (arptimerWd, arpt_prune * sysClkRateGet(),
  207.              (FUNCPTR) arptimerRestart, (int) stackNum);
  208.     while (la != &_llinfo_arp)
  209.         {
  210. register struct rtentry *rt = la->la_rt;
  211. la = la->la_next;
  212. if (rt->rt_expire && rt->rt_expire <= tickGet())
  213.     {
  214.     arptfree(la->la_prev); /* timer has expired; clear */
  215.     }
  216. }
  217.     splx (s);
  218.     }
  219. #else  /* just use original version */
  220. static void
  221. arptimer(arg)
  222. void *arg;
  223.     {
  224.     int s = splnet();
  225.     register struct llinfo_arp *la = llinfo_arp.la_next;
  226.     wdStart (arptimerWd, arpt_prune * sysClkRateGet(), (FUNCPTR) netJobAdd,
  227.      (int)arptimer);
  228.     while (la != &llinfo_arp) 
  229. {
  230. register struct rtentry *rt = la->la_rt;
  231. la = la->la_next;
  232. if (rt->rt_expire && TICK_GEQ (tickGet(), rt->rt_expire))
  233.     {
  234. #ifdef WV_INSTRUMENTATION
  235. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  236.             WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_INFO, 2, 15,
  237.                              WV_NETEVENT_ARPTIMER_FREE)
  238. #endif  /* INCLUDE_WVNET */
  239. #endif
  240.     arptfree(la->la_prev); /* timer has expired; clear */
  241.     }
  242. }
  243.     splx (s);
  244.     }
  245. #endif /* VIRTUAL_STACK */
  246. /* IP multicast address to Ethernet mulitcast address mapping */
  247. void ipToEtherMCastMap
  248.      ( 
  249.      struct in_addr * ipaddr,
  250.      u_char *         enaddr
  251.      )
  252.      {
  253.      enaddr[0] = 0x01;
  254.      enaddr[1] = 0x00;
  255.      enaddr[2] = 0x5e;
  256.      enaddr[3] = ((u_char *)ipaddr)[1] & 0x7f;
  257.      enaddr[4] = ((u_char *)ipaddr)[2];
  258.      enaddr[5] = ((u_char *)ipaddr)[3];
  259.      return;
  260.      }
  261. /* IP to Ethernet address resolution protocol. This is just a wrapper for arpresolve
  262. * being called from ipOutput. This routine calls arpresolve with the appropriate
  263. * set of arguments. 
  264. *
  265. * Returns 1 if the address is resolved and 0 if the address is not resolved.
  266. */
  267. int ipEtherResolvRtn
  268.     (
  269.     FUNCPTR           ipArpCallBackRtn,
  270.     struct mbuf *     pMbuf,
  271.     struct sockaddr * dstIpAddr,
  272.     struct ifnet *    ifp,
  273.     struct rtentry *  rt,
  274.     char *            dstBuff
  275.     )
  276.     {
  277.     return(arpresolve ((struct arpcom *)ifp, rt, pMbuf, dstIpAddr, dstBuff));
  278.     }
  279. /*
  280.  * Parallel to llc_rtrequest.
  281.  */
  282. void
  283. arp_rtrequest(req, rt, sa)
  284. int req;
  285. register struct rtentry *rt;
  286. struct sockaddr *sa;
  287. {
  288. register struct sockaddr *gate = rt->rt_gateway;
  289. register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
  290. static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
  291. struct ifaddr *ifAddr = NULL;
  292. #ifdef WV_INSTRUMENTATION
  293. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  294.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 7, 17,
  295.                          WV_NETEVENT_ARPRTREQ_START, req)
  296. #endif  /* INCLUDE_WVNET */
  297. #endif
  298. #ifndef VIRTUAL_STACK
  299. if (!arpinit_done) {
  300. /*
  301.  * if this routine is executed for the first time, then 
  302.  * create the watch dog timer and kick of the arp timer.
  303.  */
  304. arpinit_done = 1;
  305. arptimerWd = wdCreate ();
  306. netJobAdd ((FUNCPTR)arptimer, 0, 0, 0, 0, 0);
  307. }
  308. #endif /* VIRTUAL_STACK */
  309. if (rt->rt_flags & RTF_GATEWAY)
  310. return;
  311. switch (req) {
  312. case RTM_ADD:
  313. /*
  314.  * XXX: If this is a manually added route to interface
  315.  * such as older version of routed or gated might provide,
  316.  * restore cloning bit.
  317.  */
  318. if ((rt->rt_flags & RTF_HOST) == 0 &&
  319.     SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
  320. rt->rt_flags |= RTF_CLONING;
  321. if (rt->rt_flags & RTF_CLONING) {
  322. /*
  323.  * Case 1: This route should come from a route to iface.
  324.  */
  325. rt_setgate(rt, rt_key(rt),
  326. (struct sockaddr *)&null_sdl);
  327. gate = rt->rt_gateway;
  328. SDL(gate)->sdl_type = rt->rt_ifp->if_type;
  329. SDL(gate)->sdl_index = rt->rt_ifp->if_index;
  330. /*
  331.  * Give this route an expiration time, even though
  332.  * it's a "permanent" route, so that routes cloned
  333.  * from it do not need their expiration time set.
  334.  */
  335. rt->rt_expire = tickGet();
  336.                         /*
  337.                          * rt_expire could be zero if the interface is
  338.                          * initialized before the first tick of the system
  339.                          * typically 1/60th of a second.
  340.                          * All the arp routes cloned from this route will
  341.                          * inherit all the route metrics properties.
  342.                          * if rt_expire is 0 for an arp route entry,
  343.                          * it never kicks in arpwhohas () in arpresolve ().
  344.                          * This would result in not generating an arp request
  345.                          * for the host. This problem was seen on the MIPS
  346.                          * board p4000. --- Vinai. Fix for SPR 8445
  347.                          */
  348.                         if (rt->rt_expire == 0)
  349.                             rt->rt_expire++;
  350. break;
  351. }
  352. /* Announce a new entry if requested. */
  353. if (rt->rt_flags & RTF_ANNOUNCE)
  354. arprequest((struct arpcom *)rt->rt_ifp,
  355.     &SIN(rt_key(rt))->sin_addr.s_addr,
  356.     &SIN(rt_key(rt))->sin_addr.s_addr,
  357.     (u_char *)LLADDR(SDL(gate)));
  358. /*FALLTHROUGH*/
  359. case RTM_RESOLVE:
  360. if (gate->sa_family != AF_LINK ||
  361.     gate->sa_len < sizeof(null_sdl)) {
  362. #ifdef WV_INSTRUMENTATION
  363. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  364.                 WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_WARNING, 1, 8,
  365.                                  WV_NETEVENT_ARPRTREQ_BADGATE,
  366.                                  gate->sa_family, gate->sa_len)
  367. #endif  /* INCLUDE_WVNET */
  368. #endif
  369. logMsg("arp_rtrequest: bad gateway value",0,0,0,0,0,0);
  370. break;
  371. }
  372. SDL(gate)->sdl_type = rt->rt_ifp->if_type;
  373. SDL(gate)->sdl_index = rt->rt_ifp->if_index;
  374. if (la != 0)
  375. break; /* This happens on a route change */
  376. /*
  377.  * Case 2:  This route may come from cloning, or a manual route
  378.  * add with a LL address.
  379.  */
  380. if (arp_inuse >= arpMaxEntries) 
  381.                   arpEntryDelete ();
  382. R_Malloc(la, struct llinfo_arp *, sizeof(*la));
  383. rt->rt_llinfo = (caddr_t)la;
  384. if (la == 0) {
  385. #ifdef WV_INSTRUMENTATION
  386. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  387.             WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 1, 1,
  388.                              WV_NETEVENT_ARPRTREQ_FAIL)
  389. #endif  /* INCLUDE_WVNET */
  390. #endif
  391. logMsg("arp_rtrequest: malloc failedn",0,0,0,0,0,0);
  392. break;
  393. }
  394. arp_inuse++, arp_allocated++;
  395. Bzero(la, sizeof(*la));
  396. la->la_rt = rt;
  397. rt->rt_flags |= RTF_LLINFO;
  398. #ifdef VIRTUAL_STACK
  399. insque(la, &_llinfo_arp);
  400. #else
  401. insque(la, &llinfo_arp);
  402. #endif /* VIRTUAL_STACK */
  403. ifAddr = rt->rt_ifp->if_addrlist;
  404. /* 
  405.  * Find destination address in list of addresses assigned to
  406.  * interface.
  407.  */
  408. while (ifAddr)
  409.     {
  410.     if (SIN(rt_key(rt))->sin_addr.s_addr ==
  411.         (IA_SIN(ifAddr))->sin_addr.s_addr) 
  412. {
  413.     /*
  414.      * This test used to be
  415.      * if (loif.if_flags & IFF_UP)
  416.      * It allowed local traffic to be forced
  417.      * through the hardware by configuring the loopback down.
  418.      * However, it causes problems during network configuration
  419.      * for boards that can't receive packets they send.
  420.      * It is now necessary to clear "useloopback" and remove
  421.      * the route to force traffic out to the hardware.
  422.      */
  423. rt->rt_expire = 0;
  424. Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,
  425. LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6);
  426. if (useloopback)
  427. rt->rt_ifp = loif;
  428.                         break;
  429. }
  430.                     ifAddr = ifAddr->ifa_next;
  431.     }
  432. break;
  433. case RTM_DELETE:
  434. if (la == 0)
  435. break;
  436. arp_inuse--;
  437. remque(la);
  438. rt->rt_llinfo = 0;
  439. rt->rt_flags &= ~RTF_LLINFO;
  440. if (la->la_hold)
  441. m_freem(la->la_hold);
  442. Free((caddr_t)la);
  443. }
  444. }
  445. /*
  446.  * Broadcast an ARP packet, asking who has addr on interface ac.
  447.  */
  448. void
  449. arpwhohas(ac, addr)
  450. register struct arpcom *ac;
  451. register struct in_addr *addr;
  452. {
  453. arprequest(ac, &ac->ac_ipaddr.s_addr, &addr->s_addr, ac->ac_enaddr);
  454. }
  455. /*
  456.  * Broadcast an ARP request. Caller specifies:
  457.  * - arp header source ip address
  458.  * - arp header target ip address
  459.  * - arp header source ethernet address
  460.  */
  461. static void
  462. arprequest(ac, sip, tip, enaddr)
  463. register struct arpcom *ac;
  464. register u_long *sip, *tip;
  465. register u_char *enaddr;
  466. {
  467. register struct mbuf *m;
  468. register struct ether_header *eh;
  469. register struct ether_arp *ea;
  470. struct sockaddr sa;
  471. if ((m = mHdrClGet(M_DONTWAIT, MT_DATA, 
  472.    sizeof(*ea), TRUE)) == NULL)
  473.             {
  474. #ifdef WV_INSTRUMENTATION
  475. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  476.             WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 2, 2,
  477.                              WV_NETEVENT_ARPREQ_FAIL)
  478. #endif  /* INCLUDE_WVNET */
  479. #endif
  480.     return;
  481.             }
  482. m->m_len = sizeof(*ea);
  483. m->m_pkthdr.len = sizeof(*ea);
  484. MH_ALIGN(m, sizeof(*ea));
  485. ea = mtod(m, struct ether_arp *);
  486. eh = (struct ether_header *)sa.sa_data;
  487. bzero((caddr_t)ea, sizeof (*ea));
  488. bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
  489.     sizeof(eh->ether_dhost));
  490. eh->ether_type = ETHERTYPE_ARP; /* if_output will swap */
  491. ea->arp_hrd = htons(ARPHRD_ETHER);
  492. ea->arp_pro = htons(ETHERTYPE_IP);
  493. ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
  494. ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
  495. ea->arp_op = htons(ARPOP_REQUEST);
  496. bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));
  497. bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));
  498. bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));
  499. sa.sa_family = AF_UNSPEC;
  500. sa.sa_len = sizeof(sa);
  501. (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
  502. #ifdef WV_INSTRUMENTATION
  503. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  504.         WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 8, 18,
  505.                          WV_NETEVENT_ARPREQ_SEND)
  506. #endif  /* INCLUDE_WVNET */
  507. #endif
  508. }
  509. /*
  510.  * Resolve an IP address into an ethernet address.  If success,
  511.  * desten is filled in.  If there is no entry in arptab,
  512.  * set one up and broadcast a request for the IP address.
  513.  * Hold onto this mbuf and resend it once the address
  514.  * is finally resolved.  A return value of 1 indicates
  515.  * that desten has been filled in and the packet should be sent
  516.  * normally; a 0 return indicates that the packet has been
  517.  * taken over here, either now or for later transmission.
  518.  */
  519. int
  520. arpresolve(ac, rt, m, dst, desten)
  521. register struct arpcom *ac;
  522. register struct rtentry *rt;
  523. struct mbuf *m;
  524. register struct sockaddr *dst;
  525. register u_char *desten;
  526. {
  527. register struct llinfo_arp *la;
  528. struct sockaddr_dl *sdl;
  529. int alen;                          /* Length of MAC address */
  530. u_long lna;                        /* Host portion if IP address */
  531. struct ifnet *pIf = &ac->ac_if;
  532. USHORT *pSrc = NULL;
  533. USHORT *pDst = NULL;
  534. #ifdef WV_INSTRUMENTATION
  535. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  536.             WV_NET_DSTADDROUT_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 9, 19,
  537.                                ((struct sockaddr_in *)dst)->sin_addr.s_addr,
  538.                                         WV_NETEVENT_ARPRESOLV_START,
  539.                                ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  540. #endif  /* INCLUDE_WVNET */
  541. #endif
  542. if (m != NULL) /* check if mbuf is not null */
  543.     {
  544.     if (m->m_flags & M_BCAST)
  545. { /* broadcast */
  546. pDst = (USHORT *)desten;
  547. pDst[0] = 0xFFFF;
  548. pDst[1] = 0xFFFF;
  549. pDst[2] = 0xFFFF;
  550. return (1);
  551. }
  552.     if (m->m_flags & M_MCAST)
  553. { /* multicast */
  554. ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
  555. return(1);
  556. }
  557.     }
  558. if (rt)
  559. la = (struct llinfo_arp *)rt->rt_llinfo;
  560. else {
  561. if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)))
  562. rt = la->la_rt;
  563. }
  564. if (la == 0 || rt == 0) {
  565. #ifdef WV_INSTRUMENTATION
  566. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  567.             WV_NET_DSTADDROUT_EVENT_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 3, 3,
  568.                                ((struct sockaddr_in *)dst)->sin_addr.s_addr,
  569.                                     WV_NETEVENT_ARPLOOK_FAIL, WV_NET_SEND,
  570.                                ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  571. #endif  /* INCLUDE_WVNET */
  572. #endif
  573. logMsg ("arpresolve: lookup failed (resource shortage or n 
  574. network configuration error -- check netmask)n",0,0,0,0,0,0);
  575. m_freem(m);
  576. return (0);
  577. }
  578. sdl = SDL(rt->rt_gateway);
  579. /*
  580.  * Check the address family and length is valid, the address
  581.  * is resolved; otherwise, try to resolve.
  582.  */
  583. if ((rt->rt_expire == 0 || !TICK_GEQ (tickGet(), rt->rt_expire)) &&
  584.     sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
  585. pSrc = (USHORT *)LLADDR(sdl);
  586. pDst = (USHORT *)desten;
  587. pDst[0] = pSrc[0];
  588. pDst[1] = pSrc[1];
  589. pDst[2] = pSrc[2];
  590. return 1;
  591. }
  592.         /*
  593.  * For shared memory interface using a BSD driver, resolve using
  594.  * smNetAddrResolve. All other BSD drivers will have if_resolve
  595.  * equal to NULL.
  596.  */
  597. if ((pIf->pCookie == NULL) && (pIf->if_resolve) &&
  598.     ((*pIf->if_resolve) (pIf, (struct in_addr *) &(SIN(dst)->sin_addr),
  599.  desten, NULL) == 0))
  600.     return (1);
  601. /* If IFF_NOARP then make LL addr from IP host addr */
  602.  
  603. if (ac->ac_if.if_flags & IFF_NOARP) 
  604.     {
  605.     /* Set expiration of Route/ARP entry */
  606.     if (rt->rt_expire == 0)
  607. {
  608. rt->rt_expire = tickGet ();
  609. }
  610.     /* Set length of MAC address.  Default to Ethernet length. */
  611.     alen = (sdl->sdl_alen > 0 ? sdl->sdl_alen : 
  612.     sizeof (struct ether_addr));
  613.     if (alen < 3)
  614. {
  615. return (0);
  616. }
  617.     bcopy((caddr_t)ac->ac_enaddr, (char *)desten, alen - 3);
  618.     lna = in_lnaof(SIN(dst)->sin_addr);
  619.     desten[alen - 1]     = lna & 0xff;
  620.     desten[alen - 1 - 1] = (lna >> 8) & 0xff;
  621.     desten[alen - 1 - 2] = (lna >> 16) & 0x7f;
  622.     return (1);
  623.     }
  624. /*
  625.  * There is an arptab entry, but no ethernet address
  626.  * response yet.  Replace the held mbuf with this
  627.  * latest one.
  628.  */
  629. if (la->la_hold)
  630. m_freem(la->la_hold);
  631. la->la_hold = m;
  632. if (rt->rt_expire) {
  633. rt->rt_flags &= ~RTF_REJECT;
  634. if (arpRxmitTicks < 0)
  635.     arpRxmitTicks = ARP_RXMIT_TICKS_DFLT;
  636. if (la->la_asked == 0 || 
  637.     (tickGet () - rt->rt_expire >= arpRxmitTicks)) {
  638. rt->rt_expire = tickGet();
  639. if (la->la_asked++ < arp_maxtries)
  640. arpwhohas(ac, &(SIN(dst)->sin_addr));
  641. else {
  642. rt->rt_flags |= RTF_REJECT;
  643. rt->rt_expire += (sysClkRateGet() * arpt_down);
  644. la->la_asked = 0;
  645. }
  646. }
  647. }
  648. return (0);
  649. }
  650. /*
  651.  * Common length and type checks are done here,
  652.  * then the protocol-specific routine is called.
  653.  */
  654. #ifdef VIRTUAL_STACK
  655. void arpintr
  656.     (
  657.     int stackNum
  658.     )
  659. #else
  660. void arpintr()
  661. #endif /* VIRTUAL_STACK */
  662.     {
  663.     register struct mbuf *m;
  664.     register struct arphdr *ar;
  665.     int s;
  666. #ifdef WV_INSTRUMENTATION
  667. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  668.         WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 10, 20,
  669.                              WV_NETEVENT_ARPINTR_START)
  670. #endif  /* INCLUDE_WVNET */
  671. #endif
  672. #ifdef VIRTUAL_STACK
  673.     /* Set the correct virtual stack context for the input processing. */
  674.     virtualStackNumTaskIdSet (stackNum);
  675. #endif /* VIRTUAL_STACK */
  676.     s = splnet ();
  677.     while (arpintrq.ifq_head)
  678.         {
  679.         IF_DEQUEUE (&arpintrq, m);
  680.         if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
  681.             {
  682. #ifdef WV_INSTRUMENTATION
  683. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  684.             WV_NET_EVENT_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 4, 4,
  685.                             WV_NETEVENT_ARPINTR_FAIL, WV_NET_RECV)
  686. #endif  /* INCLUDE_WVNET */
  687. #endif
  688.             panic("arpintr");
  689.             }
  690. #ifdef VIRTUAL_STACK
  691.                 /*
  692.                  * (tNetTask) Set the virtual stack ID so the received
  693.                  * packet will be processed by the correct stack.
  694.                  */
  695.                 virtualStackNumTaskIdSet(m->m_pkthdr.rcvif->vsNum);
  696. #endif /* VIRTUAL_STACK */
  697.         if (m->m_len >= sizeof(struct arphdr) &&
  698.                 (ar = mtod(m, struct arphdr *)) &&
  699.                  ntohs(ar->ar_hrd) == ARPHRD_ETHER &&
  700.             m->m_len >= sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))
  701.             {
  702.             switch (ntohs(ar->ar_pro))
  703.                 {
  704.                 case ETHERTYPE_IP:
  705.                 case ETHERTYPE_IPTRAILERS:
  706. #ifdef PROXY_HOOK
  707.                     if (proxyArpHook == NULL ||
  708.                         (* proxyArpHook)
  709.                          ( (struct arpcom *)m->m_pkthdr.rcvif, m) == FALSE)
  710. #endif
  711.                         in_arpinput(m);
  712.                     continue;
  713.                 }
  714.             }
  715.         m_freem(m);
  716.         }
  717.     splx (s);
  718.     }
  719. /*
  720.  * ARP for Internet protocols on 10 Mb/s Ethernet.
  721.  * Algorithm is that given in RFC 826.
  722.  * In addition, a sanity check is performed on the sender
  723.  * protocol address, to catch impersonators.
  724.  * We no longer handle negotiations for use of trailer protocol:
  725.  * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
  726.  * along with IP replies if we wanted trailers sent to us,
  727.  * and also sent them in response to IP replies.
  728.  * This allowed either end to announce the desire to receive
  729.  * trailer packets.
  730.  * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
  731.  * but formerly didn't normally send requests.
  732.  */
  733. static void
  734. in_arpinput(m)
  735. struct mbuf *m;
  736. {
  737. register struct ether_arp *ea;
  738. register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
  739. struct ether_header *eh;
  740. register struct llinfo_arp *la = 0;
  741. register struct rtentry *rt;
  742. struct in_ifaddr *ia, *maybe_ia = 0;
  743. struct sockaddr_dl *sdl;
  744. struct sockaddr sa;
  745. struct in_addr isaddr, itaddr, myaddr;
  746. int op;
  747. #ifdef WV_INSTRUMENTATION
  748. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  749.         WV_NET_EVENT_0 (NET_AUX_EVENT, WV_NET_NOTICE, 0, 12,
  750.                          WV_NETEVENT_ARPIN_START, WV_NET_RECV)
  751. #endif  /* INCLUDE_WVNET */
  752. #endif
  753. ea = mtod(m, struct ether_arp *);
  754. op = ntohs(ea->arp_op);
  755. bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr));
  756. bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr));
  757. #ifdef VIRTUAL_STACK
  758. for (ia = _in_ifaddr; ia; ia = ia->ia_next)
  759. #else
  760. for (ia = in_ifaddr; ia; ia = ia->ia_next)
  761. #endif /* VIRTUAL_STACK */
  762. if (ia->ia_ifp == &ac->ac_if) {
  763. maybe_ia = ia;
  764. if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
  765.      (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
  766. break;
  767. }
  768. if (maybe_ia == 0)
  769. goto out;
  770. myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
  771. if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
  772.     sizeof (ea->arp_sha)))
  773. goto out; /* it's from me, ignore it. */
  774. if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
  775.     sizeof (ea->arp_sha))) {
  776. #ifdef WV_INSTRUMENTATION
  777. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  778.                 WV_NET_DSTADDRIN_EVENT_1 (NET_AUX_EVENT, WV_NET_WARNING, 2, 9,
  779.                                           isaddr.s_addr,
  780.                                        WV_NETEVENT_ARPIN_BADADDR, WV_NET_RECV,
  781.                                           isaddr.s_addr)
  782. #endif  /* INCLUDE_WVNET */
  783. #endif
  784. logMsg (
  785.     "arp: ether address is broadcast for IP address %x!n",
  786.     (int)ntohl(isaddr.s_addr), 0,0,0,0,0);
  787. goto out;
  788. }
  789. if (ETHER_MULTICAST(ea->arp_sha))
  790.     {
  791. #ifdef WV_INSTRUMENTATION
  792. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  793. WV_NET_DSTADDRIN_EVENT_1 (NET_AUX_EVENT, WV_NET_WARNING, 2, 9,
  794.   isaddr.s_addr,
  795.        WV_NETEVENT_ARPIN_BADADDR, WV_NET_RECV,
  796.   isaddr.s_addr)
  797. #endif  /* INCLUDE_WVNET */
  798. #endif
  799.      logMsg ("arp: ether address is multicast for IP address %x!n",
  800.      (int)ntohl (isaddr.s_addr), 0, 0, 0, 0, 0);
  801.      goto out;
  802.      }
  803. if (isaddr.s_addr == myaddr.s_addr) {
  804. #ifdef WV_INSTRUMENTATION
  805. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  806.                 WV_NET_DSTADDRIN_EVENT_1 (NET_AUX_EVENT, WV_NET_WARNING, 3, 10,
  807.                                           isaddr.s_addr,
  808.                                        WV_NETEVENT_ARPIN_BADADDR2, WV_NET_RECV,
  809.                                           isaddr.s_addr)
  810. #endif  /* INCLUDE_WVNET */
  811. #endif
  812. logMsg(
  813.    "duplicate IP address %08x sent from ethernet address %sn",
  814.    (int)ntohl(isaddr.s_addr), (int)ether_sprintf(ea->arp_sha),
  815.    0,0,0,0);
  816. itaddr = myaddr;
  817. goto reply;
  818. }
  819. la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
  820. if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
  821. if (sdl->sdl_alen &&
  822.     bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen))
  823.                     {
  824. #ifdef WV_INSTRUMENTATION
  825. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  826.                 WV_NET_DSTADDRIN_EVENT_1 (NET_AUX_EVENT, WV_NET_WARNING, 4, 11,
  827.                                           isaddr.s_addr,
  828.                                        WV_NETEVENT_ARPIN_BADADDR3, WV_NET_RECV,
  829.                                           isaddr.s_addr)
  830. #endif  /* INCLUDE_WVNET */
  831. #endif
  832. logMsg("arp info overwritten for %08x by %sn",
  833.     (int) ntohl(isaddr.s_addr), 
  834.     (int) ether_sprintf(ea->arp_sha),0,0,0,0);
  835.                     }
  836. bcopy((caddr_t)ea->arp_sha, LLADDR(sdl),
  837.     sdl->sdl_alen = sizeof(ea->arp_sha));
  838. if (rt->rt_expire)
  839. rt->rt_expire = tickGet() + (sysClkRateGet() * 
  840.      arpt_keep);
  841. rt->rt_flags &= ~RTF_REJECT;
  842. la->la_asked = 0;
  843. if (la->la_hold) {
  844. #ifdef WV_INSTRUMENTATION
  845. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  846.                    WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_NOTICE, 1, 13,
  847.                                    WV_NETEVENT_ARPIN_DELAYEDSEND, WV_NET_SEND,
  848.                                    isaddr.s_addr)
  849. #endif  /* INCLUDE_WVNET */
  850. #endif
  851. (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,
  852. rt_key(rt), rt);
  853. la->la_hold = 0;
  854. }
  855. }
  856. reply:
  857. if (op != ARPOP_REQUEST) {
  858. out:
  859. m_freem(m);
  860. return;
  861. }
  862. if (itaddr.s_addr == myaddr.s_addr) {
  863. /* I am the target */
  864. bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
  865.     sizeof(ea->arp_sha));
  866. bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
  867.     sizeof(ea->arp_sha));
  868. } else {
  869. la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
  870. if (la == 0)
  871. goto out;
  872. rt = la->la_rt;
  873. bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
  874.     sizeof(ea->arp_sha));
  875. sdl = SDL(rt->rt_gateway);
  876.                 /*
  877.                  * ARP entries added by a proxy server use a "wildcard"
  878.                  * hardware address (equal to the sending interface) to
  879.                  * support multiple proxy networks.
  880.                  */
  881.                 if (rt->rt_flags & RTF_PROTO1)
  882.                     bcopy ((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
  883.                            sizeof(ea->arp_sha));
  884.                 else
  885.                     bcopy (LLADDR(sdl), (caddr_t)ea->arp_sha,
  886.                            sizeof(ea->arp_sha));
  887. }
  888. bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa));
  889. bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));
  890. ea->arp_op = htons(ARPOP_REPLY);
  891. ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
  892. eh = (struct ether_header *)sa.sa_data;
  893. bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
  894.     sizeof(eh->ether_dhost));
  895. eh->ether_type = ETHERTYPE_ARP;
  896. sa.sa_family = AF_UNSPEC;
  897. sa.sa_len = sizeof(sa);
  898. #ifdef WV_INSTRUMENTATION
  899. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  900.         WV_NET_ADDROUT_EVENT_2 (NET_AUX_EVENT, WV_NET_NOTICE, 2, 14,
  901.                                 isaddr.s_addr, itaddr.s_addr,
  902.                                 WV_NETEVENT_ARPIN_REPLYSEND, WV_NET_SEND,
  903.                                 itaddr.s_addr, isaddr.s_addr)
  904. #endif  /* INCLUDE_WVNET */
  905. #endif
  906. (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
  907. return;
  908. }
  909. /*
  910.  * Free an arp entry.
  911.  */
  912. void
  913. arptfree(la)
  914. register struct llinfo_arp *la;
  915. {
  916. register struct rtentry *rt = la->la_rt;
  917. register struct sockaddr_dl *sdl;
  918. if (rt == 0)
  919.             {
  920. #ifdef WV_INSTRUMENTATION
  921. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  922.             WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 5, 5,
  923.                              WV_NETEVENT_ARPTFREE_PANIC)
  924. #endif  /* INCLUDE_WVNET */
  925. #endif
  926. panic("arptfree");
  927.             }
  928.         if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
  929.             sdl->sdl_family == AF_LINK) {
  930.                 sdl->sdl_alen = 0;
  931.                 la->la_asked = 0;
  932.                 rt->rt_flags |= RTF_REJECT;
  933.         }
  934.  
  935. #ifdef ROUTER_STACK
  936.         /* Let Fastpath know that the entry is being deleted */
  937.         FFL_CALL (ffLibMacEntryDeleted, 
  938.                   (GET_IPV4_FF_ID, rt_key(rt), rt->rt_gateway));
  939. #endif /* ROUTER_STACK */
  940. rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
  941.     0, (struct rtentry **)0);
  942. }
  943. /*
  944.  * Lookup or enter a new address in arptab.
  945.  */
  946. static struct llinfo_arp *
  947. arplookup(addr, create, proxy)
  948. u_long addr;
  949. int create, proxy;
  950. {
  951. register struct rtentry *rt;
  952. #ifndef VIRTUAL_STACK
  953. static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
  954. sin.sin_addr.s_addr = addr;
  955. sin.sin_other = proxy ? SIN_PROXY : 0;
  956. rt = rtalloc1((struct sockaddr *)&sin, create);
  957. #else
  958. arpSin.sin_len    = sizeof(arpSin);
  959.         arpSin.sin_family = AF_INET;
  960. arpSin.sin_addr.s_addr = addr;
  961. arpSin.sin_other = proxy ? SIN_PROXY : 0;
  962. rt = rtalloc1((struct sockaddr *)&arpSin, create);
  963. #endif /* VIRTUAL_STACK */
  964. if (rt == 0)
  965. return (0);
  966. rt->rt_refcnt--;
  967. if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
  968.     rt->rt_gateway->sa_family != AF_LINK) {
  969. if (create)
  970. logMsg("arptnew failed on %xn", (int)ntohl(addr),
  971. 0,0,0,0,0);
  972. return (0);
  973. }
  974. return ((struct llinfo_arp *)rt->rt_llinfo);
  975. }
  976. int arpioctl
  977.     (
  978.     int  cmd,
  979.     caddr_t data
  980.     )
  981.     {
  982.     register struct arpreq * ar = (struct arpreq *)data;
  983.     register struct sockaddr_in * soInAddr;
  984.     register struct llinfo_arp * la = NULL;
  985.     register struct rtentry * rt = NULL;
  986.     struct rtentry *  pNewRt;
  987.     struct sockaddr_dl *  sdl = NULL;
  988.     struct sockaddr_in  rtmask;
  989.     struct sockaddr_in *  pMask;
  990.     struct sockaddr_inarp  ipaddr;
  991.     struct sockaddr_dl  arpaddr;
  992.     int error = OK;
  993.     int flags = 0;
  994.     BOOL proxy = FALSE;
  995.     BOOL export = FALSE;
  996. #ifdef WV_INSTRUMENTATION
  997. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  998.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 3, 16,
  999.                      WV_NETEVENT_ARPIOCTL_START, cmd)
  1000. #endif  /* INCLUDE_WVNET */
  1001. #endif
  1002.     if (ar->arp_pa.sa_family != AF_INET ||
  1003. ar->arp_ha.sa_family != AF_UNSPEC)
  1004.         {
  1005. #ifdef WV_INSTRUMENTATION
  1006. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  1007.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 2, 7,
  1008.                          WV_NETEVENT_ARPIOCTL_NOTSUPP,
  1009.                          ar->arp_pa.sa_family, ar->arp_ha.sa_family)
  1010. #endif  /* INCLUDE_WVNET */
  1011. #endif
  1012. return (EAFNOSUPPORT);
  1013.         }
  1014.     soInAddr = (struct sockaddr_in *)&ar->arp_pa;
  1015.     switch ((u_int) cmd) 
  1016. {
  1017. case SIOCSARP:
  1018.             if (ar->arp_flags & ATF_PUBL)
  1019.                 {
  1020.                 flags |= RTF_ANNOUNCE;
  1021.                 proxy = TRUE;
  1022.                 }
  1023.             /* Use a "wildcard" hardware address for proxy server entries. */
  1024.             if (ar->arp_flags & ATF_PROXY)
  1025.                 flags |= RTF_PROTO1;
  1026.             /* Search for existing entry with same address. */
  1027.    
  1028.             bzero ( (char *)&ipaddr, sizeof (ipaddr));
  1029.             ipaddr.sin_len = sizeof (ipaddr);
  1030.             ipaddr.sin_family = AF_INET;
  1031.             ipaddr.sin_addr.s_addr = soInAddr->sin_addr.s_addr;
  1032.             rt = rtalloc1 ((struct sockaddr *)&ipaddr, 0);
  1033.     if (!rt)
  1034.                 {
  1035. #ifdef WV_INSTRUMENTATION
  1036. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1037.                 WV_NET_EVENT_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 1, 6,
  1038.                                 WV_NETEVENT_ARPIOCTL_SEARCHFAIL, WV_NET_SEND,
  1039.                                 cmd, soInAddr->sin_addr.s_addr)
  1040. #endif  /* INCLUDE_WVNET */
  1041. #endif
  1042.                 return (ENETUNREACH);
  1043.                 }
  1044.   
  1045.             if (rt && !(ar->arp_flags & ATF_INCOMPLETE)) 
  1046.                 {
  1047.                 rt->rt_refcnt--;
  1048.                 if (soInAddr->sin_addr.s_addr ==
  1049.                         ((struct sockaddr_in *)rt_key (rt))->sin_addr.s_addr)
  1050.                     {
  1051.                     /* Matching entry found. Check address type. */
  1052.                     if ( (rt->rt_flags & RTF_GATEWAY) || 
  1053.                               (rt->rt_flags & RTF_LLINFO) == 0 || 
  1054.                                      rt->rt_gateway->sa_family != AF_LINK)
  1055.                         {
  1056.                         /* Host entry found: must create proxy entry. */
  1057.                         if ( !(ar->arp_flags & ATF_PUBL))
  1058.                             return (EINVAL);
  1059.                         /* 
  1060.                          * Set flag to prevent replacement of current entry 
  1061.                          * by creating entry which includes SIN_PROXY flag.
  1062.                          */
  1063.                         export = TRUE;
  1064.                         }
  1065.                     }
  1066.                 /*
  1067.                  * For remote hosts or networks, the gateway's associated
  1068.                  * route entry contains the interface values.
  1069.                  */
  1070.                 if (rt->rt_flags & RTF_GATEWAY)
  1071.                     {
  1072.                     if (rt->rt_gwroute == 0)
  1073.                         return (EHOSTUNREACH);
  1074.                     else
  1075.                         sdl = SDL (rt->rt_gwroute->rt_gateway);
  1076.                     }
  1077.                 else
  1078.                     sdl = SDL (rt->rt_gateway);
  1079.                 if (sdl->sdl_family != AF_LINK)
  1080.                     return (EINVAL);
  1081.         }
  1082.             bzero ( (char *)&rtmask, sizeof (rtmask));
  1083.             rtmask.sin_len = 8;
  1084.             rtmask.sin_addr.s_addr = 0xffffffff;
  1085.             bzero ( (char *)&ipaddr, sizeof (ipaddr));
  1086.             ipaddr.sin_len = sizeof (ipaddr);
  1087.             ipaddr.sin_family = AF_INET;
  1088.             ipaddr.sin_addr.s_addr = soInAddr->sin_addr.s_addr;
  1089.             bzero ( (char *)&arpaddr, sizeof (arpaddr));
  1090.     arpaddr.sdl_len = sizeof (arpaddr);
  1091.             arpaddr.sdl_family = AF_LINK;
  1092.     
  1093.     if (ar->arp_flags & ATF_INCOMPLETE)
  1094.         {
  1095.         arpaddr.sdl_type = rt->rt_ifp->if_type;
  1096.         arpaddr.sdl_index = rt->rt_ifp->if_index;
  1097. }
  1098.     else
  1099. {
  1100.                 arpaddr.sdl_type = sdl->sdl_type;
  1101.                 arpaddr.sdl_index = sdl->sdl_index;
  1102. }
  1103.  
  1104.     bcopy ((caddr_t)ar->arp_ha.sa_data, LLADDR (&arpaddr),
  1105.   arpaddr.sdl_alen = sizeof (struct ether_addr)); 
  1106.             flags |= (RTF_HOST | RTF_STATIC);
  1107.             /* 
  1108.              * A netmask of 0 compares each route entry against the entire
  1109.              * key during lookups. If an overlapping network route already
  1110.              * exists, set it to all ones so that queries with SIN_PROXY set
  1111.              * will still succeed. If a matching host route exists, set the
  1112.              * SIN_PROXY flag in the new entry instead.
  1113.              */
  1114.             pMask = NULL;
  1115.             if (proxy)
  1116.                 {
  1117.                 if (export)
  1118.                     ipaddr.sin_other = SIN_PROXY;
  1119.                 else
  1120.                     {
  1121.                     pMask = &rtmask;
  1122.                     flags &= ~RTF_HOST;
  1123.                     }
  1124.                 }
  1125.     if (ar->arp_flags & ATF_INCOMPLETE)
  1126.         {
  1127.         pNewRt = rt;
  1128. /* The gateway entry needs to be converted to an AF_LINK type */
  1129.         error = rt_setgate (rt, (struct sockaddr *)&ipaddr, 
  1130.     (struct sockaddr *)&arpaddr);
  1131. if (error)
  1132.     break;
  1133. /* The llinfo_arp structure needs to be allocated */
  1134. if (rt->rt_ifa->ifa_rtrequest)
  1135.     rt->rt_ifa->ifa_rtrequest (RTM_RESOLVE, rt,
  1136. (struct sockaddr *)&arpaddr);
  1137. else
  1138.     arp_rtrequest (RTM_RESOLVE, rt,
  1139. (struct sockaddr *)&arpaddr);
  1140. }
  1141.     else
  1142.                 error = rtrequest (RTM_ADD, (struct sockaddr *)&ipaddr,
  1143.                                (struct sockaddr *)&arpaddr,
  1144.                                (struct sockaddr *)pMask, flags, &pNewRt);
  1145.             if (error == 0 && pNewRt)
  1146.                 {
  1147.         if (ar->arp_flags & ATF_PERM)
  1148.     pNewRt->rt_expire = 0; 
  1149.         else 
  1150.     pNewRt->rt_expire = tickGet() + (sysClkRateGet() *
  1151.                                                      arpt_keep);
  1152.                 pNewRt->rt_refcnt--;
  1153.                 }
  1154.     break;
  1155. case SIOCDARP: /* delete entry */
  1156.     if ((la = arplookup(soInAddr->sin_addr.s_addr, 0, 0)) == NULL)
  1157.                 {
  1158. #ifdef WV_INSTRUMENTATION
  1159. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1160.                 WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 1, 6,
  1161.                                  WV_NETEVENT_ARPIOCTL_SEARCHFAIL,
  1162.                                  cmd, soInAddr->sin_addr.s_addr)
  1163. #endif  /* INCLUDE_WVNET */
  1164. #endif
  1165. return (EADDRNOTAVAIL); 
  1166.                 }
  1167.     arptfree(la);
  1168.     break;
  1169. case SIOCGARP: /* get entry */
  1170.     if ((la = arplookup(soInAddr->sin_addr.s_addr, 0, 0)) == NULL)
  1171.                 {
  1172. #ifdef WV_INSTRUMENTATION
  1173. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1174.                 WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 1, 6,
  1175.                                  WV_NETEVENT_ARPIOCTL_SEARCHFAIL,
  1176.                                  cmd, soInAddr->sin_addr.s_addr)
  1177. #endif  /* INCLUDE_WVNET */
  1178. #endif
  1179. return (EADDRNOTAVAIL); 
  1180.                 }
  1181.     rt = la->la_rt; 
  1182.             sdl = SDL(rt->rt_gateway);
  1183.     ar->arp_flags = 0;  /* initialize the flags */
  1184.     if (sdl->sdl_alen)
  1185. {
  1186. bcopy(LLADDR(sdl), (caddr_t)ar->arp_ha.sa_data, sdl->sdl_alen);
  1187. ar->arp_flags |= ATF_COM; 
  1188. }
  1189.     else
  1190.                 {
  1191. #ifdef WV_INSTRUMENTATION
  1192. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1193.                 WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_CRITICAL, 1, 6,
  1194.                                  WV_NETEVENT_ARPIOCTL_SEARCHFAIL,
  1195.                                  cmd, soInAddr->sin_addr.s_addr)
  1196. #endif  /* INCLUDE_WVNET */
  1197. #endif
  1198. return (EADDRNOTAVAIL); 
  1199.                 }
  1200.     if (rt->rt_flags & RTF_UP)
  1201. ar->arp_flags |= ATF_INUSE; 
  1202.     if (rt->rt_flags & RTF_ANNOUNCE)
  1203. ar->arp_flags |= ATF_PUBL; 
  1204.             if (rt->rt_flags & RTF_PROTO1)
  1205.                 ar->arp_flags |= ATF_PROXY; 
  1206.     if (rt->rt_expire == 0) 
  1207. ar->arp_flags |= ATF_PERM;
  1208.     break;
  1209. default : 
  1210.     return (EINVAL); 
  1211. }
  1212.     return (error); 
  1213.     }
  1214. /*******************************************************************************
  1215. *
  1216. * _arpCmd - issues an internal ARP command
  1217. *
  1218. * This routine directly call the arpioctl call for an ARP command. Expected
  1219. * values for the <cmd> parameter are SIOCSARP, SIOCGARP, or SIOCDARP. 
  1220. * The <pIpAddr> parameter specifies the IP address of the host. The
  1221. * <pHwAddr> pointer provides the corresponding link-level address in
  1222. * binary form. That parameter is only used with SIOCSARP, and is limited
  1223. * to the 6-byte maximum required for Ethernet addresses. The <pFlags> 
  1224. * argument provides any flag settings for the entry.
  1225. *
  1226. * RETURNS: OK, or ERROR if unsuccessful.
  1227. *
  1228. * NOMANUAL
  1229. *
  1230. * INTERNAL
  1231. * This routine should be called from inside the stack as from the
  1232. * ifAllRoutesDelete() routine to delete ARP entries.
  1233. */
  1234. STATUS _arpCmd
  1235.     (
  1236.     int                 cmd, /* arp command */
  1237.     struct in_addr *    pIpAddr, /* ip address */
  1238.     u_char *            pHwAddr, /* hardware address */
  1239.     int *               pFlags /* arp flags  */
  1240.     )
  1241.     {
  1242.     struct arpreq       arpRequest; /* arp request struct */
  1243.     STATUS              status = ERROR; /* return status  */
  1244.     /* fill in arp request structure */
  1245.     bzero ((caddr_t) &arpRequest, sizeof (struct arpreq));
  1246.     arpRequest.arp_pa.sa_family = AF_INET;
  1247.     ((struct sockaddr_in *)
  1248. &(arpRequest.arp_pa))->sin_addr.s_addr = pIpAddr->s_addr;
  1249.     arpRequest.arp_ha.sa_family = AF_UNSPEC;
  1250.     if (pHwAddr != NULL)
  1251.         bcopy ((caddr_t) pHwAddr ,(caddr_t) arpRequest.arp_ha.sa_data,
  1252.        ENET_SIZE);
  1253.     if (pFlags != NULL)
  1254.      arpRequest.arp_flags = *pFlags;
  1255.     if ((status = arpioctl (cmd, (caddr_t) &arpRequest)) == OK)
  1256.         {
  1257.         if (pHwAddr != NULL)
  1258.             bcopy ((caddr_t) arpRequest.arp_ha.sa_data, (caddr_t) pHwAddr,
  1259.                     ENET_SIZE);
  1260.         if (pFlags != NULL)
  1261.             *pFlags = arpRequest.arp_flags;
  1262.         }
  1263.     return (status);
  1264.     }
  1265. /*****************************************************************************
  1266. *
  1267. * arpEntryDelete - delete the oldest entry in ARP table
  1268. *
  1269. * This routine deletes the oldest non-permanent entry in the ARP table
  1270. *
  1271. * RETURNS: N/A
  1272. *
  1273. * NOMANUAL
  1274. */
  1275. static void arpEntryDelete ()
  1276.     {
  1277.     register struct llinfo_arp *la;
  1278. #ifdef VIRTUAL_STACK
  1279.     la = _llinfo_arp.la_prev;
  1280. #else
  1281.     la = llinfo_arp.la_prev;
  1282. #endif
  1283. #ifdef VIRTUAL_STACK
  1284.     while (la != &_llinfo_arp)
  1285. #else
  1286.     while (la != &llinfo_arp)
  1287. #endif
  1288.         {
  1289.         register struct rtentry *rt = la->la_rt;
  1290.         if (rt->rt_expire)
  1291.             {
  1292.             arptfree (la);
  1293.             break;
  1294.             }
  1295.         la = la->la_prev;
  1296.         }
  1297.     }
  1298.     
  1299. /*
  1300.  * Convert Ethernet address to printable (loggable) representation.
  1301.  */
  1302. char *
  1303. ether_sprintf(ap)
  1304. register u_char *ap;
  1305. {
  1306. register int i;
  1307. #ifndef VIRTUAL_STACK
  1308. static char etherbuf[18];
  1309. #endif /* VIRTUAL_STACK */
  1310. register char *cp = etherbuf;
  1311. for (i = 0; i < 6; i++) {
  1312. *cp++ = digits[*ap >> 4];
  1313. *cp++ = digits[*ap++ & 0xf];
  1314. *cp++ = ':';
  1315. }
  1316. *--cp = 0;
  1317. return (etherbuf);
  1318. }
  1319. #define db_printf printf
  1320. void
  1321. db_print_sa(sa)
  1322. struct sockaddr *sa;
  1323. {
  1324. int len;
  1325. u_char *p;
  1326. if (sa == 0) {
  1327. db_printf("[NULL]n");
  1328. return;
  1329. }
  1330. p = (u_char*)sa;
  1331. len = sa->sa_len;
  1332. db_printf("[");
  1333. while (len > 0) {
  1334. db_printf("%d", *p);
  1335. p++; len--;
  1336. if (len) db_printf(",");
  1337. }
  1338. db_printf("]n");
  1339. }
  1340. #ifdef DDB
  1341. static void
  1342. db_print_ifa(ifa)
  1343. struct ifaddr *ifa;
  1344. {
  1345. if (ifa == 0)
  1346. return;
  1347. db_printf("  ifa_addr=");
  1348. db_print_sa(ifa->ifa_addr);
  1349. db_printf("  ifa_dsta=");
  1350. db_print_sa(ifa->ifa_dstaddr);
  1351. db_printf("  ifa_mask=");
  1352. db_print_sa(ifa->ifa_netmask);
  1353. db_printf("  flags=0x%x,refcnt=%d,metric=%dn",
  1354.   ifa->ifa_flags,
  1355.   ifa->ifa_refcnt,
  1356.   ifa->ifa_metric);
  1357. }
  1358. static void
  1359. db_print_llinfo(li)
  1360. caddr_t li;
  1361. {
  1362. struct llinfo_arp *la;
  1363. if (li == 0)
  1364. return;
  1365. la = (struct llinfo_arp *)li;
  1366. db_printf("  la_rt=0x%x la_hold=0x%x, la_asked=0x%lxn",
  1367.   (u_int) la->la_rt, (u_int) la->la_hold, la->la_asked);
  1368. }
  1369. /*
  1370.  * Function to pass to rn_walktree().
  1371.  * Return non-zero error to abort walk.
  1372.  */
  1373. static int
  1374. db_show_radix_node(rn, w)
  1375. struct radix_node *rn;
  1376. void *w;
  1377. {
  1378. struct rtentry *rt = (struct rtentry *)rn;
  1379. db_printf("rtentry=0x%x", (u_int) rt);
  1380. db_printf(" flags=0x%x refcnt=%d use=%ld expire=%ldn",
  1381.   rt->rt_flags, rt->rt_refcnt,
  1382.   rt->rt_use, rt->rt_expire);
  1383. db_printf(" key="); db_print_sa(rt_key(rt));
  1384. db_printf(" mask="); db_print_sa(rt_mask(rt));
  1385. db_printf(" gw="); db_print_sa(rt->rt_gateway);
  1386. db_printf(" ifp=0x%x ", (u_int) rt->rt_ifp);
  1387. if (rt->rt_ifp)
  1388. db_printf("(%s%d)",
  1389.   rt->rt_ifp->if_name,
  1390.   rt->rt_ifp->if_unit);
  1391. else
  1392. db_printf("(NULL)");
  1393. db_printf(" ifa=0x%xn", (u_int) rt->rt_ifa);
  1394. db_print_ifa(rt->rt_ifa);
  1395. db_printf(" genmask="); db_print_sa(rt->rt_genmask);
  1396. db_printf(" gwroute=0x%x llinfo=0x%xn",
  1397.   (u_int) rt->rt_gwroute, (u_int) rt->rt_llinfo);
  1398. db_print_llinfo(rt->rt_llinfo);
  1399. return (0);
  1400. }
  1401. /*
  1402.  * Internal Function to print the route tree.
  1403.  * Given the radix tree head.
  1404.  */
  1405. int
  1406. _db_show_arptab(struct radix_node_head *rnh)
  1407. {
  1408. db_printf("Route tree for AF_INETn");
  1409. if (rnh == NULL) {
  1410. db_printf(" (not initialized)n");
  1411. return (0);
  1412. }
  1413. rn_walktree(rnh, db_show_radix_node, NULL);
  1414. return (0);
  1415. }
  1416. /*
  1417.  * Function to print all the route trees.
  1418.  * Use this from ddb:  "call db_show_arptab"
  1419.  */
  1420. int
  1421. db_show_arptab()
  1422. {
  1423. struct radix_node_head *rnh;
  1424. rnh = rt_tables[AF_INET];
  1425. return _db_show_arptab(rnh);
  1426. }
  1427. #ifdef ROUTER_STACK
  1428. /*
  1429.  * Function to print all the route trees for the fast forwarder.
  1430.  * Use this from ddb:  "call db_show_arptab_ff"
  1431.  */
  1432. int
  1433. db_show_arptab_ff()
  1434. {
  1435. return _db_show_arptab ((struct radix_node_head *)(IPV4_FF_CACHE_COOKIE (GET_IPV4_FF_ID)));
  1436. }
  1437. #endif /* ROUTER_STACK */
  1438. #endif /* DDB */
  1439. #endif /* INET */