if_subr.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:34k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* if_subr.c - common routines for network interface drivers */
  2. /* Copyright 1990 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1989, 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_ethersubr.c 8.1 (Berkeley) 6/10/93
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01q,23may02,vvv  removed unnecessary m_copy from ether_output (SPR #77775)
  42. 01p,22apr02,wap  call ip_mloopback() rather than calling looutput() directly
  43.                  (SPR #72246)
  44. 01o,15apr02,wap  reinstate netJobAdd removal changes
  45. 01n,29mar02,wap  back out the previous change (needs more investigation)
  46. 01m,21mar02,rae  remove unecessary netJobAdd() SPR #
  47. 01l,21mar02,vvv  updated man page for copyFromMbufs (SPR #20787)
  48. 01k,01nov01,rae  fixed compile warnings, corrected WV event (SPR #71284)
  49. 01j,12oct01,rae  merge from truestack ver 01o, base 01h (SPR #69112 etc.)
  50. 01i,17oct00,spm  updated ether_attach to report memory allocation failures
  51. 01h,21aug98,n_s  updated if_omcast in ether_output () if_noproto in 
  52.                  do_protocol_with_type (). spr21074
  53. 01f,19sep97,vin  modified build_cluster to incorporate cluster blks,
  54.  removed pointers to refcounts.
  55. 01g,11aug97,vin  changed mBlkGet to use _pNetDpool.
  56. 01e,10jul97,vin  removed unsupported revarpinput() code.
  57. 01f,05jun97,vin  corrected processing for promiscuous interfaces in
  58.  ether_input.
  59. 01e,02jun97,spm  updated man page for bcopy_to_mbufs()
  60. 01d,15may97,vin  reworked ether_input, cleanup, added copyFromMbufs().
  61.  removed support for check_trailer().
  62. 01c,16dec96,vin  removed unnecessary ntohs(). 
  63. 01b,13nov96,vin  replaced m_gethdr with mBlkGet() in buildCluster.
  64. 01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02p of if_subr.c
  65. */
  66. #include "vxWorks.h"
  67. #include "stdlib.h"
  68. #include "stdio.h"
  69. #include "tickLib.h"
  70. #include "logLib.h"
  71. #include "errno.h"
  72. #include "netinet/in.h"
  73. #include "netinet/in_systm.h"
  74. #include "netinet/in_var.h"
  75. #include "netinet/ip.h"
  76. #include "net/if.h"
  77. #include "net/if_arp.h"
  78. #include "netinet/if_ether.h"
  79. #include "net/if_subr.h"
  80. #include "netinet/in_var.h"
  81. #include "netinet/ip_var.h"    /* for ipintr() prototype */
  82. #include "net/mbuf.h"
  83. #include "net/route.h"
  84. #include "net/if_llc.h"
  85. #include "net/if_dl.h"
  86. #include "net/if_types.h"
  87. #include "lstLib.h"
  88. #include "netLib.h"
  89. #include "muxLib.h"
  90. #include "memPartLib.h"
  91. #ifdef WV_INSTRUMENTATION
  92. #ifdef INCLUDE_WVNET
  93. #include "wvNetLib.h"
  94. #endif /* INCLUDE_WVNET */
  95. #endif
  96. #ifdef VIRTUAL_STACK
  97. #include "netinet/vsLib.h"
  98. #endif
  99. typedef struct net_type
  100.     {
  101.     NODE      node;
  102.     FUNCPTR     inputRtn;
  103.     int      etherType;
  104.     } NET_TYPE;
  105. #ifdef WV_INSTRUMENTATION
  106. #ifdef INCLUDE_WVNET
  107.     /* Set common fields of event identifiers for this module. */
  108. LOCAL UCHAR wvNetModuleId = WV_NET_IFSUBR_MODULE;   /* Value for if_subr.c */
  109. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  110. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  111. #endif    /* INCLUDE_WVNET */
  112. #endif
  113. /* externs */
  114. #ifndef VIRTUAL_STACK
  115. extern struct ifnet loif;
  116. extern  void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *,
  117.                           struct rtentry *rt);
  118. #endif /* VIRTUAL_STACK */
  119. u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  120. u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
  121. u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
  122. #define senderr(e) { error = (e); goto bad;}
  123. LOCAL LIST netTypeList;
  124. /*
  125.  * Ethernet output routine.
  126.  * Encapsulate a packet of type family for the local net.
  127.  * Use trailer local net encapsulation if enough data in first
  128.  * packet leaves a multiple of 512 bytes of data in remainder.
  129.  * Assumes that ifp is actually pointer to arpcom structure.
  130.  */
  131. int
  132. ether_output(ifp, m0, dst, rt0)
  133. register struct ifnet *ifp;
  134. struct mbuf *m0;
  135. struct sockaddr *dst;
  136. struct rtentry *rt0;
  137. {
  138. u_short etype;
  139. int s, error = 0;
  140.   u_char edst[6];
  141. register struct mbuf *m = m0;
  142. register struct rtentry *rt;
  143. register struct ether_header *eh;
  144. int off, len = m->m_pkthdr.len;
  145. struct arpcom *ac = (struct arpcom *)ifp;
  146. if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  147.             {
  148. #ifdef WV_INSTRUMENTATION
  149. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  150.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 2, 3,
  151.                             WV_NETEVENT_ETHEROUT_IFDOWN, WV_NET_SEND, ifp)
  152. #endif  /* INCLUDE_WVNET */
  153. #endif
  154.             senderr(ENETDOWN);
  155.             }
  156. ifp->if_lastchange = tickGet();
  157. if ((rt = rt0)) {
  158. if ((rt->rt_flags & RTF_UP) == 0) {
  159. if ((rt0 = rt = rtalloc1(dst, 1)))
  160. rt->rt_refcnt--;
  161. else {
  162. #ifdef WV_INSTRUMENTATION
  163. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  164.             WV_NET_DSTADDROUT_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 4, 5,
  165.                             ((struct sockaddr_in *)dst)->sin_addr.s_addr,
  166.                             WV_NETEVENT_ETHEROUT_NOROUTE, WV_NET_SEND,
  167.                             ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  168. #endif  /* INCLUDE_WVNET */
  169. #endif
  170.                              senderr(EHOSTUNREACH);
  171.                              }
  172. }
  173. if (rt->rt_flags & RTF_GATEWAY) {
  174. if (rt->rt_gwroute == 0)
  175. goto lookup;
  176. if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
  177. rtfree(rt); rt = rt0;
  178. lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
  179. if ((rt = rt->rt_gwroute) == 0) {
  180. #ifdef WV_INSTRUMENTATION
  181. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  182.             WV_NET_DSTADDROUT_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 4, 5,
  183.                        ((struct sockaddr_in *)rt->rt_gateway)->sin_addr.s_addr,
  184.                                     WV_NETEVENT_ETHEROUT_NOROUTE, WV_NET_SEND,
  185.                        ((struct sockaddr_in *)rt->rt_gateway)->sin_addr.s_addr)
  186. #endif  /* INCLUDE_WVNET */
  187. #endif
  188.                                     senderr(EHOSTUNREACH);
  189.                                 }
  190. }
  191. }
  192. if (rt->rt_flags & RTF_REJECT)
  193. if (rt->rt_rmx.rmx_expire == 0 ||
  194.     tickGet() < rt->rt_rmx.rmx_expire) {
  195. #ifdef WV_INSTRUMENTATION
  196. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  197.         WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_CRITICAL, 5, 6,
  198.                         WV_NETEVENT_ETHEROUT_RTREJECT, WV_NET_SEND)
  199. #endif  /* INCLUDE_WVNET */
  200. #endif
  201.                             senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  202.                             }
  203. }
  204. switch (dst->sa_family) {
  205. #ifdef INET
  206. case AF_INET:
  207. if (!arpresolve(ac, rt, m, dst, edst))
  208. return (0); /* if not yet resolved */
  209. /* If broadcasting on a simplex interface, loopback a copy */
  210. if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
  211. ip_mloopback (ifp, m, (struct sockaddr_in *)dst,
  212.       (struct rtentry*)rt);
  213. off = m->m_pkthdr.len - m->m_len;
  214. etype = ETHERTYPE_IP;
  215. break;
  216. #endif
  217. case AF_UNSPEC:
  218. eh = (struct ether_header *)dst->sa_data;
  219.   bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
  220. etype = eh->ether_type;
  221. break;
  222. default:
  223. printf("%s%d: can't handle af%dn", ifp->if_name, ifp->if_unit,
  224. dst->sa_family);
  225. #ifdef WV_INSTRUMENTATION
  226. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  227.                 WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_ERROR, 3, 7,
  228.                                 WV_NETEVENT_ETHEROUT_AFNOTSUPP, WV_NET_SEND,
  229.                                 dst->sa_family)
  230. #endif  /* INCLUDE_WVNET */
  231. #endif
  232. senderr(EAFNOSUPPORT);
  233. }
  234. /*
  235.  * Add local net header.  If no space in first mbuf,
  236.  * allocate another.
  237.  */
  238. M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
  239. if (m == 0)
  240.             {
  241. #ifdef WV_INSTRUMENTATION
  242. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  243.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 3, 4,
  244.                             WV_NETEVENT_ETHEROUT_NOBUFS, WV_NET_SEND, ifp)
  245. #endif  /* INCLUDE_WVNET */
  246. #endif
  247.             senderr(ENOBUFS);
  248.             }
  249. eh = mtod(m, struct ether_header *);
  250. etype = htons(etype);
  251. bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
  252. sizeof(eh->ether_type));
  253.   bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
  254.   bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
  255.     sizeof(eh->ether_shost));
  256. s = splimp();
  257. /*
  258.  * Queue message on interface, and start output if interface
  259.  * not yet active.
  260.  */
  261. if (IF_QFULL(&ifp->if_snd)) {
  262. IF_DROP(&ifp->if_snd);
  263. splx(s);
  264. #ifdef WV_INSTRUMENTATION
  265. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  266.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 3, 4,
  267.                             WV_NETEVENT_ETHEROUT_NOBUFS, WV_NET_SEND, ifp)
  268. #endif  /* INCLUDE_WVNET */
  269. #endif
  270. senderr(ENOBUFS);
  271. }
  272. IF_ENQUEUE(&ifp->if_snd, m);
  273. if ((ifp->if_flags & IFF_OACTIVE) == 0)
  274. (*ifp->if_start)(ifp);
  275. splx(s);
  276. ifp->if_obytes += len + sizeof (struct ether_header);
  277. if (m->m_flags & M_MCAST || m->m_flags & M_BCAST)
  278. ifp->if_omcasts++;
  279. #ifdef WV_INSTRUMENTATION
  280. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  281.         WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_NOTICE, 3, 12,
  282.                         WV_NETEVENT_ETHEROUT_FINISH, WV_NET_SEND, ifp, error)
  283. #endif  /* INCLUDE_WVNET */
  284. #endif
  285. return (error);
  286. bad:
  287. if (m)
  288. m_freem(m);
  289. return (error);
  290. }
  291. /*******************************************************************************
  292. *
  293. * do_protocol - check the link-level type field and process IP and ARP data
  294. *
  295. * This routine must not be called at interrupt level.
  296. * Process a received Ethernet packet;
  297. * the packet is in the mbuf chain m without
  298. * the ether header, which is provided separately.
  299. *
  300. * NOMANUAL
  301. */
  302. void
  303. ether_input(ifp, eh, m)
  304. struct ifnet *ifp;
  305. register struct ether_header *eh;
  306. struct mbuf *m;
  307. {
  308. u_short  etype;
  309. struct arpcom * ac = (struct arpcom *)ifp;
  310. #ifdef WV_INSTRUMENTATION
  311. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  312.         WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_NOTICE, 4, 13,
  313.                         WV_NETEVENT_ETHERIN_START, WV_NET_RECV, ifp)
  314. #endif  /* INCLUDE_WVNET */
  315. #endif
  316. if ((ifp->if_flags & IFF_UP) == 0) {
  317. m_freem(m);
  318. return;
  319. }
  320. ifp->if_lastchange = tickGet();
  321. ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
  322. if (eh->ether_dhost[0] & 1) {
  323. if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
  324.     sizeof(etherbroadcastaddr)) == 0)
  325. m->m_flags |= M_BCAST;
  326. else
  327. m->m_flags |= M_MCAST;
  328. ifp->if_imcasts++;
  329. }
  330.         if (ifp->if_flags & IFF_PROMISC)
  331.             {
  332.             /*
  333.              * do not hand over the non multicast packets to the ip stack
  334.              * if they are not destined to us, orelse it confuses the
  335.              * ip forwarding logic and keeps sending unnecessary redirects.
  336.              * If packets destined for other hosts have to be snooped they
  337.              * have to done through driver level hooks.
  338.              */
  339.             
  340.             if (!(m->m_flags & (M_BCAST | M_MCAST)))
  341.                 {
  342.                 if (bcmp ((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_dhost,
  343.                           sizeof(eh->ether_dhost)) != 0)
  344.                     {
  345.                     m_freem (m);  /* free the packet chain */
  346.                     return; 
  347.                     }
  348.                 }
  349.             }
  350.         
  351. etype = ntohs(eh->ether_type);
  352.         /* add code here to process IEEE802.3 LLC format, Hook!! */
  353.         /* demux the packet and hand off the ip layer */
  354.         do_protocol_with_type (etype, m , ac, m->m_pkthdr.len); 
  355. }
  356. /*
  357.  * Perform common duties while attaching to interface list
  358.  */
  359. void
  360. ether_ifattach(ifp)
  361. register struct ifnet *ifp;
  362. {
  363. register struct ifaddr *ifa;
  364. register struct sockaddr_dl *sdl;
  365. #ifdef WV_INSTRUMENTATION
  366. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  367.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 11, 14,
  368.                          WV_NETEVENT_ETHERIFATTACH_START, ifp)
  369. #endif  /* INCLUDE_WVNET */
  370. #endif
  371. ifp->if_type = IFT_ETHER;
  372. ifp->if_addrlen = 6;
  373. ifp->if_hdrlen = 14;
  374. ifp->if_mtu = ETHERMTU;
  375. for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  376. if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
  377.     sdl->sdl_family == AF_LINK) {
  378. sdl->sdl_type = IFT_ETHER;
  379. sdl->sdl_alen = ifp->if_addrlen;
  380. bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
  381.       LLADDR(sdl), ifp->if_addrlen);
  382. break;
  383. }
  384. }
  385. /*
  386.  * Add an Ethernet multicast address or range of addresses to the list for a
  387.  * given interface.
  388.  */
  389. int
  390. ether_addmulti(ifr, ac)
  391. struct ifreq *ifr;
  392. register struct arpcom *ac;
  393. {
  394. register struct ether_multi *enm;
  395. struct sockaddr_in *sin;
  396. u_char addrlo[6];
  397. u_char addrhi[6];
  398. int s = splimp();
  399. /*
  400.  * XXX - This event cannot currently occur: the ether_addmulti() routine
  401.  *       provides multicasting support which is not available for VxWorks
  402.  *       BSD Ethernet drivers.
  403. #ifdef WV_INSTRUMENTATION
  404. #ifdef INCLUDE_WVNET    /@ WV_NET_VERBOSE event @/
  405.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 12, 15,
  406.                          WV_NETEVENT_ADDMULT_START, ac->ac_if)
  407. #endif  /@ INCLUDE_WVNET @/
  408. #endif
  409.  * XXX - end of unused event
  410.  */
  411. switch (ifr->ifr_addr.sa_family) {
  412. case AF_UNSPEC:
  413. bcopy((char *)ifr->ifr_addr.sa_data, (char *)addrlo, 6);
  414. bcopy((char *) addrlo, (char *)addrhi, 6);
  415. break;
  416. #ifdef INET
  417. case AF_INET:
  418. sin = (struct sockaddr_in *)&(ifr->ifr_addr);
  419. if (sin->sin_addr.s_addr == INADDR_ANY) {
  420. /*
  421.  * An IP address of INADDR_ANY means listen to all
  422.  * of the Ethernet multicast addresses used for IP.
  423.  * (This is for the sake of IP multicast routers.)
  424.  */
  425. bcopy((char *)ether_ipmulticast_min, (char *)addrlo, 6);
  426. bcopy((char *)ether_ipmulticast_max, (char *)addrhi, 6);
  427. }
  428. else {
  429. ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
  430. bcopy((char *)addrlo, (char *)addrhi, 6);
  431. }
  432. break;
  433. #endif
  434. default:
  435. splx(s);
  436. #ifdef WV_INSTRUMENTATION
  437. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  438.                 WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 4, 8,
  439.                                 WV_NETEVENT_ADDMULT_AFNOTSUPP,
  440.                                 ifr->ifr_addr.sa_family) 
  441. #endif  /* INCLUDE_WVNET */
  442. #endif
  443. return (EAFNOSUPPORT);
  444. }
  445. /*
  446.  * Verify that we have valid Ethernet multicast addresses.
  447.  */
  448. if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
  449. splx(s);
  450. #ifdef WV_INSTRUMENTATION
  451. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  452.                 WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 5, 9,
  453.                                 WV_NETEVENT_ADDMULT_BADADDR,
  454.                                 ac->ac_if) 
  455. #endif  /* INCLUDE_WVNET */
  456. #endif
  457. return (EINVAL);
  458. }
  459. /*
  460.  * See if the address range is already in the list.
  461.  */
  462. ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  463. if (enm != NULL) {
  464. /*
  465.  * Found it; just increment the reference count.
  466.  */
  467. ++enm->enm_refcount;
  468. splx(s);
  469. return (0);
  470. }
  471. /*
  472.  * New address or range; malloc a new multicast record
  473.  * and link it into the interface's multicast list.
  474.  */
  475.         MALLOC (enm, struct ether_multi *, sizeof(*enm), MT_IFMADDR, 
  476. M_DONTWAIT);
  477. if (enm == NULL) {
  478. splx(s);
  479. #ifdef WV_INSTRUMENTATION
  480. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  481.                 WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 6, 1,
  482.                                  WV_NETEVENT_ADDMULT_NOBUFS)
  483. #endif  /* INCLUDE_WVNET */
  484. #endif
  485. return (ENOBUFS);
  486. }
  487. bcopy((char *)addrlo, (char *)enm->enm_addrlo, 6);
  488. bcopy((char *)addrhi, (char *)enm->enm_addrhi, 6);
  489. enm->enm_ac = ac;
  490. enm->enm_refcount = 1;
  491. enm->enm_next = ac->ac_multiaddrs;
  492. ac->ac_multiaddrs = enm;
  493. ac->ac_multicnt++;
  494. splx(s);
  495. /*
  496.  * Return ENETRESET to inform the driver that the list has changed
  497.  * and its reception filter should be adjusted accordingly.
  498.  */
  499. return (ENETRESET);
  500. }
  501. /*
  502.  * Delete a multicast address record.
  503.  */
  504. int
  505. ether_delmulti(ifr, ac)
  506. struct ifreq *ifr;
  507. register struct arpcom *ac;
  508. {
  509. register struct ether_multi *enm;
  510. register struct ether_multi **p;
  511. struct sockaddr_in *sin;
  512. u_char addrlo[6];
  513. u_char addrhi[6];
  514. int s = splimp();
  515. /*
  516.  * XXX - This event cannot currently occur: the ether_delmulti() routine
  517.  *       provides multicasting support which is not available for VxWorks
  518.  *       BSD Ethernet drivers.
  519. #ifdef WV_INSTRUMENTATION
  520. #ifdef INCLUDE_WVNET    /@ WV_NET_VERBOSE event @/
  521.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 13, 16,
  522.                             WV_NETEVENT_DELMULT_START, ac->ac_if)
  523. #endif  /@ INCLUDE_WVNET @/
  524. #endif
  525.  * XXX - end of unused event
  526.  */
  527. switch (ifr->ifr_addr.sa_family) {
  528. case AF_UNSPEC:
  529. bcopy((char *)ifr->ifr_addr.sa_data, (char *)addrlo, 6);
  530. bcopy((char *)addrlo, (char *)addrhi, 6);
  531. break;
  532. #ifdef INET
  533. case AF_INET:
  534. sin = (struct sockaddr_in *)&(ifr->ifr_addr);
  535. if (sin->sin_addr.s_addr == INADDR_ANY) {
  536. /*
  537.  * An IP address of INADDR_ANY means stop listening
  538.  * to the range of Ethernet multicast addresses used
  539.  * for IP.
  540.  */
  541. bcopy((char *)ether_ipmulticast_min, (char *)addrlo, 6);
  542. bcopy((char *)ether_ipmulticast_max, (char *)addrhi, 6);
  543. }
  544. else {
  545. ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
  546. bcopy((char *)addrlo, (char *)addrhi, 6);
  547. }
  548. break;
  549. #endif
  550. default:
  551. splx(s);
  552. #ifdef WV_INSTRUMENTATION
  553. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  554.                 WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 6, 10,
  555.                                  WV_NETEVENT_DELMULT_AFNOTSUPP,
  556.                                  ifr->ifr_addr.sa_family)
  557. #endif  /* INCLUDE_WVNET */
  558. #endif
  559. return (EAFNOSUPPORT);
  560. }
  561. /*
  562.  * Look up the address in our list.
  563.  */
  564. ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  565. if (enm == NULL) {
  566. splx(s);
  567. #ifdef WV_INSTRUMENTATION
  568. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  569.                 WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 7, 11,
  570.                                  WV_NETEVENT_DELMULT_BADADDR, ac->ac_if)
  571. #endif  /* INCLUDE_WVNET */
  572. #endif
  573. return (ENXIO);
  574. }
  575. if (--enm->enm_refcount != 0) {
  576. /*
  577.  * Still some claims to this record.
  578.  */
  579. splx(s);
  580. return (0);
  581. }
  582. /*
  583.  * No remaining claims to this record; unlink and free it.
  584.  */
  585. for (p = &enm->enm_ac->ac_multiaddrs;
  586.      *p != enm;
  587.      p = &(*p)->enm_next)
  588. continue;
  589. *p = (*p)->enm_next;
  590. FREE(enm, MT_IFMADDR);
  591. ac->ac_multicnt--;
  592. splx(s);
  593. /*
  594.  * Return ENETRESET to inform the driver that the list has changed
  595.  * and its reception filter should be adjusted accordingly.
  596.  */
  597. return (ENETRESET);
  598. }
  599. /*******************************************************************************
  600. *
  601. * check_trailer - check ethernet frames that have trailers following them
  602. *
  603. * Decypher the ethernet frames that are encoded via trailer protocol which
  604. * has a link level type field that contains a value which is an encoding of
  605. * the size of the data portion.  The original BSD 4.2 and 4.3 TCP/IP
  606. * implementations use the trailer protocol to accomplish more efficient
  607. * copying of data.  Basically the idea was to put the variable lenght protocol
  608. * headers (TCP, UDP, IP headers) at the end of a page aligned data and use
  609. * the link-level type field (ethernet type) to indicate both the use of a
  610. * specialized framing protocol as well as the length of the data following
  611. * the ethernet header.  The original link-level type field and the length
  612. * of the protocol headers following the data portion are attached between
  613. * the data portion (which should be of length multiple of 512 bytes) and
  614. * protocol headers.  (size of data portion == (type - 0x1000) * 415)
  615. *
  616. * Upon return, 'pOff' will contain NULL if trailer protocol is not being
  617. * used.  Otherwise, 'pOff' points to the trailer header and 'pLen'
  618. * will contain the size of the frame.
  619. *
  620. * NOMANUAL
  621. */
  622. void check_trailer (eh, pData, pLen, pOff, ifp)
  623.     FAST struct ether_header  *eh; /* ethernet header */
  624.     FAST unsigned char  *pData; /* data immediately after 'eh' */
  625.     FAST int  *pLen; /* value/result input data length */
  626.     FAST int  *pOff; /* result -- points to trailer header */
  627.     FAST struct ifnet  *ifp; /* network interface */
  628.     {
  629. #if 0 /* XXX No support for trailers in BSD44 vxWorks */    
  630.     FAST int resid;
  631.     eh->ether_type = ntohs((u_short)eh->ether_type);
  632.     if ((eh->ether_type >= ETHERTYPE_TRAIL)  &&
  633. (eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER))
  634. {
  635. *pOff = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
  636. if (*pOff >= ifp->if_mtu)
  637.     return; /* sanity */
  638. eh->ether_type = ntohs (*(u_short *) (pData + *pOff));
  639. resid          = ntohs (*(u_short *) (pData + *pOff + 2));
  640. if ((*pOff + resid) > *pLen)
  641.     return; /* sanity */
  642. *pLen = *pOff + resid;
  643. }
  644.     else
  645. *pOff = 0;
  646. #endif /* XXX No trailer support in BSD44 */    
  647.     }
  648. /*******************************************************************************
  649. *
  650. * bcopy_to_mbufs - copy data into mbuf chain
  651. *
  652. * Copies up to <totlen> bytes of data from <buf0> into a freshly allocated
  653. * mbuf. The <off0> parameter indicates the amount of trailer encapsulation,
  654. * which was formerly handled according to the trailer protocol described in
  655. * check_trailer(). Since trailer encapsulation is not supported in BSD 4.4,
  656. * that parameter is unused. The <width> argument supports machines which 
  657. * have special byte alignment requirements when copying data from device 
  658. * I/O buffers to main memory.  A macro function called 'copy_to_mbufs' is 
  659. * provided in the "mbuf.h" file for compatability with SunOS, which doesn't 
  660. * support the <width> parameter. This function uses mbuf clusters when possible
  661. * to enhance network throughput.
  662. *
  663. * RETURNS: first mbuf or 0 if error
  664. *
  665. * NOMANUAL
  666. */
  667. struct mbuf *bcopy_to_mbufs (buf0, totlen, off0, ifp, width)
  668.     u_char *buf0; /* buffer to be copied into mbufs */
  669.     int totlen; /* number of bytes to be copied */
  670.     int off0; /* trailer protocol indicative */
  671.     struct ifnet *ifp; /* network interface */
  672.     int width; /* copy data by this unit width */
  673.     {
  674.     return (m_devget ((char *) buf0, totlen, width, ifp, NULL));
  675.     }
  676. /*******************************************************************************
  677. * copyFromMbufs - copy data from an mbuf chain
  678. *
  679. * This routine copies data from an mbuf chain into a given buffer.
  680. * The length of the data copied from the mbuf chain is returned.
  681. * The argument width is provided for machines that have special byte alignment
  682. * requirements when copying data to an I/O buffer of the device from main
  683. * memory. This routine frees the mbuf chain passed to it. 
  684. *
  685. * This routine should not be used since it can cause unaligned memory accesses
  686. * resulting in target crashes.
  687. * RETURNS: length of data copied.
  688. *
  689. * NOMANUAL
  690. */
  691. int copyFromMbufs
  692.     (
  693.     char *  pIoBuf, /* buffer to copy mbufs into */
  694.     struct mbuf *  pMbuf, /* pointer to an mbuf chain */
  695.     int width /* width of the copy */
  696.     )
  697.     {
  698.     FAST char * pBuf = (char *) (pIoBuf);
  699.     FAST struct mbuf *  pMbufHead = pMbuf;
  700.     FAST char * adjBuf;
  701.     FAST int  adjLen;
  702.     FAST int  odd = 0;
  703.     FAST int  ix;
  704.     char  temp [4];
  705.     if (width == NONE)
  706.         {
  707.         for (; pMbuf != NULL; pBuf += pMbuf->m_len, pMbuf = pMbuf->m_next)
  708.             bcopy (mtod (pMbuf, char *), pBuf, pMbuf->m_len);
  709.         }
  710.     else if (width == 1)
  711.         {
  712. for (; pMbuf != NULL; pBuf += pMbuf->m_len, pMbuf = pMbuf->m_next)
  713.     bcopyBytes (mtod (pMbuf, char *), pBuf, pMbuf->m_len);
  714.         }
  715.     
  716.     else if (width == 2)
  717.         {
  718. for (; pMbuf != NULL; pMbuf = pMbuf->m_next)
  719.     {
  720.     adjLen = pMbuf->m_len;
  721.     adjBuf = mtod(pMbuf, char *);
  722.     if (odd > 0)
  723. {
  724. --pBuf;
  725. *((UINT16 *) temp) = *((UINT16 *) pBuf);
  726. temp [1] = *adjBuf++;
  727. --adjLen;
  728. *((UINT16 *) pBuf) = *((UINT16 *) temp);
  729. pBuf += 2;
  730. }
  731.     bcopyWords (adjBuf, pBuf, (adjLen + 1) >> 1);
  732.     pBuf += adjLen;
  733.             odd = adjLen & 0x1;
  734.     }
  735.         }
  736.     else if (width == 4)
  737.         {
  738. for (; pMbuf != NULL; pMbuf = pMbuf->m_next)
  739.     {
  740.     adjLen = pMbuf->m_len;
  741.     adjBuf = mtod(pMbuf, char *);
  742.     if (odd > 0)
  743. {
  744. pBuf -= odd;
  745. *((UINT32 *) temp) = *((UINT32 *) pBuf);
  746. for (ix = odd; ix < 4; ix++, adjBuf++, --adjLen)
  747.     temp [ix] = *adjBuf;
  748. *((UINT32 *) pBuf) = *((UINT32 *) temp);
  749. pBuf += 4;
  750. }
  751.     bcopyLongs (adjBuf, pBuf, (adjLen + 3) >> 2);
  752.     pBuf += adjLen;
  753.             odd = adjLen & 0x3;
  754.     }
  755.         }
  756.     else
  757.         {
  758.         panic ("copyFromMbufs");
  759.         }
  760.     m_freem (pMbufHead);  /* free the mbuf chain */
  761.     
  762.     return ((int) pBuf - (int) pIoBuf); /* return length copied */
  763.     }
  764. /*******************************************************************************
  765. *
  766. * build_cluster - encapsulate a passed buffer into a cluster mbuf.
  767. *
  768. * This routine is used to surround the passed buffer <buf0> with a
  769. * mbuf header and make it a pseudo cluster.  It is used primarily by the
  770. * network interface drivers to avoid copying large chunk of data incoming
  771. * from the network.  Network interface device drivers typically call this
  772. * routine with a pointer to the memory location where the IP data reside.
  773. * This buffer pointer is used as a cluster buffer pointer and inserted
  774. * into mbuf along with other relevant pieces information such as the
  775. * index into the reference count array, pointer to the reference count
  776. * array and the driver level free routine.
  777. *
  778. * RETURNS: NULL if unsuccessful, pointer to <struct mbuf> if successful.
  779. *
  780. * SEE ALSO: do_protocol_with_type(), uipc_mbuf.c
  781. *
  782. * NOMANUAL
  783. */
  784. struct mbuf *build_cluster (buf0, totlen, ifp, ctype, pRefCnt,
  785.     freeRtn, arg1, arg2, arg3)
  786.     u_char  *buf0; /* the buffer containing data */
  787.     int totlen; /* len of the buffer */
  788.     struct ifnet *ifp; /* network interface device pointer */
  789.     u_char ctype; /* type of this cluster being built */
  790.     u_char *pRefCnt; /* type-specific ref count array */
  791.     FUNCPTR freeRtn; /* driver level free callback routine */
  792.     int arg1; /* first argument to freeRtn() */
  793.     int arg2; /* second argument to freeRtn() */
  794.     int arg3; /* third argument to freeRtn() */
  795.     {
  796.     FAST struct mbuf    *m;
  797.     CL_BLK_ID pClBlk;
  798.     /* get an mbuf header, header will have ifp info in the packet header */
  799.     m = mBlkGet(_pNetDpool, M_DONTWAIT, MT_DATA);
  800.     if (m == NULL) /* out of mbufs! */
  801. return (NULL);
  802.     pClBlk = clBlkGet (_pNetDpool, M_DONTWAIT); 
  803.     
  804.     if (pClBlk == NULL) /* out of cl Blks */
  805.         {
  806.         m_free (m); 
  807. return (NULL);
  808.         }
  809.     /* intialize the header */
  810.     m->m_pkthdr.rcvif = ifp;
  811.     m->m_pkthdr.len = totlen;
  812.     m->m_data = (caddr_t) buf0; 
  813.     m->m_len = m->m_pkthdr.len;
  814.     m->m_flags = (M_EXT | M_PKTHDR) ;
  815.     m->pClBlk = pClBlk;
  816.     m->m_extBuf = (caddr_t) buf0;
  817.     m->m_extSize = m->m_pkthdr.len;
  818.     m->m_extFreeRtn = freeRtn;
  819.     m->m_extArg1 = arg1;
  820.     m->m_extArg2 = arg2;
  821.     m->m_extArg3 = arg3;
  822.     m->m_extRefCnt = 1;
  823.     return (m);
  824.     }
  825. /*******************************************************************************
  826. *
  827. * do_protocol_with_type - demultiplex incoming packet to the protocol handlers
  828. *
  829. * Demultiplexes the incoming packet to the associated protocol handler.  This
  830. * version supports IP, ARP, and a generic mechanism via an external lookup
  831. * table.
  832. *
  833. * This routine differs from do_protocol() in that the link-level frame type
  834. * is passed directly, instead of passing a pointer to an Ethernet header,
  835. * respectively.
  836. *
  837. * This routine must not be called interrupt level.
  838. *
  839. * NOMANUAL
  840. */
  841. void do_protocol_with_type
  842.     (
  843.     u_short         type, /* the frame type field */
  844.     struct mbuf * pMbuf, /* the frame data, in mbuf chain */
  845.     struct arpcom * pArpcom, /* the source interface information */
  846.     int len /* length of the mbuf data */
  847.     )
  848.     {
  849.     int s;
  850.     FAST struct ifqueue * inq;
  851.     FUNCPTR  pInputFunc;  /* message handler */
  852.     switch (type)
  853.         {
  854. case ETHERTYPE_IP:
  855.             ipintr(pMbuf);
  856.     return;
  857. case ETHERTYPE_ARP:
  858.             inq = &arpintrq;
  859.             pInputFunc = (FUNCPTR) arpintr;
  860.             break;
  861.         default:
  862.             {
  863.     /* No protocol. Drop packet */
  864.     
  865.     ((struct ifnet *) pArpcom)->if_noproto++;
  866.     m_freem (pMbuf); /* free the mbuf chain */
  867.     return;
  868.             }
  869.         }
  870.     s = splnet ();
  871.     if (IF_QFULL(inq))
  872.         {
  873.         IF_DROP (inq);
  874.         m_freem (pMbuf); /* free the mbuf chain */
  875. splx (s);
  876. }
  877.     else
  878.         {
  879.         IF_ENQUEUE (inq, pMbuf); /* put the mbuf chain in the packet queue */
  880. splx (s);
  881.         /* Schedule a new job to finish the handling of the IP or ARP data. */
  882. #ifdef VIRTUAL_STACK
  883.         netJobAdd (pInputFunc, pArpcom->ac_if.vsNum, 0, 0, 0, 0);
  884. #else
  885. arpintr();
  886. #endif /* VIRTUAL_STACK */
  887.         }
  888.     }
  889. /*******************************************************************************
  890. *
  891. * set_if_addr - handle SIOCSIFADDR ioctl
  892. *
  893. * Sets a protocol address associated with this network interface.
  894. * This function is called by various ioctl handlers in each of the network
  895. * interface drivers.
  896. *
  897. * RETURNS: 0 or appropriate errno
  898. *
  899. * NOMANUAL
  900. */
  901. int set_if_addr (ifp, data, enaddr)
  902.     struct ifnet  *ifp;   /* interface */
  903.     char  *data;  /* usually "struct ifaddr *" */
  904.     u_char  *enaddr;/* ethernet address */
  905.     {
  906.     int  error = 0;
  907.     FAST struct ifaddr *ifa = (struct ifaddr *) data;
  908.     ifp->if_flags |= IFF_UP;
  909.     if ((error = (*ifp->if_init) (ifp->if_unit)) != 0)
  910.         return (error);
  911.     switch (ifa->ifa_addr->sa_family)
  912.         {
  913. #ifdef  INET
  914.         case AF_INET:
  915.             ((struct arpcom *) ifp)->ac_ipaddr = IA_SIN (ifa)->sin_addr;
  916.             arpwhohas ((struct arpcom *) ifp, &IA_SIN (ifa)->sin_addr);
  917.             break;
  918. #endif /* INET */
  919. default:
  920.     logMsg ("eh: set_if_addr unknown family 0x%xn",
  921. ifa->ifa_addr->sa_family,0,0,0,0,0);
  922.     break;
  923.         }
  924.     return (0);
  925.     }
  926. /*******************************************************************************
  927. *
  928. * ether_attach - attach a new network interface to the network layer.
  929. *
  930. * Fill in the ifnet structure and pass it off to if_attach () routine
  931. * which will attach the network interface described in that structure
  932. * to the network layer software for future use in routing, packet reception,
  933. * and transmisison.
  934. *
  935. * NOMANUAL
  936. */
  937. STATUS ether_attach (ifp, unit, name, initRtn, ioctlRtn, outputRtn, resetRtn)
  938.     struct ifnet  *ifp; /* network interface data structure */
  939.     int  unit; /* unit number */
  940.     char  *name; /* name of the interface */
  941.     FUNCPTR  initRtn; /* initialization routine */
  942.     FUNCPTR  ioctlRtn; /* ioctl handler */
  943.     FUNCPTR  outputRtn; /* output routine */
  944.     FUNCPTR  resetRtn; /* reset routine */
  945.     {
  946. #ifdef WV_INSTRUMENTATION
  947. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  948.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 14, 17,
  949.                      WV_NETEVENT_ETHERATTACH_START, ifp)
  950. #endif  /* INCLUDE_WVNET */
  951. #endif
  952.     bzero ((char *) ifp, sizeof (*ifp));
  953.     ifp->if_unit   = unit;
  954.     ifp->if_name   = name;
  955.     ifp->if_mtu    = ETHERMTU;
  956.     ifp->if_init   = initRtn;
  957.     ifp->if_ioctl  = ioctlRtn;
  958.     ifp->if_output = outputRtn;
  959.     ifp->if_reset  = resetRtn;
  960.     ifp->if_flags  = IFF_BROADCAST;
  961.     return (if_attach (ifp));
  962.     }
  963. /*******************************************************************************
  964. *
  965. * netTypeAdd - add a network type to list of network types.
  966. *
  967. * RETURNS: OK if successful, otherwise ERROR.
  968. *
  969. * NOMANUAL
  970. */
  971. STATUS netTypeAdd (etherType, inputRtn)
  972.     int              etherType; /* ethernet type */
  973.     FUNCPTR             inputRtn; /* input routine */
  974.     {
  975.     NET_TYPE *          pType;
  976.     if ((pType = (NET_TYPE *) KHEAP_ALLOC(sizeof(NET_TYPE))) == NULL)
  977.         {
  978. #ifdef WV_INSTRUMENTATION
  979. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  980.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 7, 2,
  981.                          WV_NETEVENT_TYPEADD_FAIL, etherType)
  982. #endif  /* INCLUDE_WVNET */
  983. #endif
  984.         return (ERROR);
  985.         }
  986.     bzero((char *)pType, sizeof (NET_TYPE));
  987.     pType->etherType    = etherType;
  988.     pType->inputRtn     = inputRtn;
  989.     lstAdd (&netTypeList, &pType->node);
  990.     return (OK);
  991.     }
  992. /*******************************************************************************
  993. *
  994. * netTypeDelete - delete a network type from the list of network types.
  995. *
  996. * RETURNS: OK if successful, otherwise ERROR.
  997. *
  998. * NOMANUAL
  999. */
  1000. STATUS netTypeDelete (etherType)
  1001.     int etherType; /* ethernet type */
  1002.     {
  1003.     NET_TYPE * pType;
  1004.     for (pType = (NET_TYPE *) lstFirst (&netTypeList);
  1005.          pType != NULL; pType = (NET_TYPE *) lstNext (&pType->node))
  1006. {
  1007.         if (etherType == pType->etherType)
  1008.             {
  1009.             lstDelete (&netTypeList, &pType->node);
  1010.     KHEAP_FREE((caddr_t)pType);
  1011.             return (OK);
  1012.             }
  1013. }
  1014.     return (ERROR);
  1015.     }
  1016. /*******************************************************************************
  1017. *
  1018. * netTypeInit - initialize list of network types.
  1019. *
  1020. * RETURNS: N/A
  1021. *
  1022. * NOMANUAL
  1023. */
  1024. void netTypeInit ()
  1025.     {
  1026.     lstInit (&netTypeList);
  1027.     }