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

VxWorks

开发平台:

C/C++

  1. /* ipProto.c - an interface between the BSD IP protocol and the MUX */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 03k,15may02,tcr  Make WV_NETEVENT_ETHEROUT_NOBUFS match uses elsewhere
  7. 03j,24apr02,rae  Fixed muxTxRestart race condition (SPR #74565)
  8. 03i,19apr02,wap  call ip_mloopback() rather than calling looutput() directly
  9.                  (SPR #72246)
  10. 03h,26mar02,vvv  fixed proxy broadcast storm (SPR #74518)
  11. 03g,02jan02,vvv  changed ipAttach failure message when device not found
  12. 03f,01nov01,rae  ipError frees buffers on END_ERR_NO_BUF (SPR #70545)
  13. 03e,15oct01,rae  merge from truestack ver 03r, base 02r(1) (SPRs 69573, 69112,
  14.                  29668, ROUTER_STACK etc.)
  15. 03d,24jul01,r_s  changed code to be ANSI compatible so that it compiles with
  16.                  diab. made asm macro changes for diab
  17. 03f,12jun01,rae  ipDetach checks for npt
  18. 03e,01jun01,rae  fix problem with last checkin
  19. 03d,08may01,rae  limited ARP binding to appropriate device types (SPR #33657)
  20. 03c,07feb01,spm  fixed modification history for branches and merges
  21. 03b,22nov00,rae  fixed problem with zeros in ethernet address (SPR# 29152)
  22. 03a,14nov00,rae  fix SIOC[ADD,DEL]MULTI for non-ethernet devices (SPR# 35459)
  23. 02z,13nov00,niq  merged from version 03o of tor2_0.open_stack-f1 brranh:
  24.                  added RFC 2233 support
  25. 02y,10nov00,ham  enhanced sanity check for memory allocation (SPR #62262)
  26. 02x,07nov00,spm  moved nptFlag from END_OBJ for T2 END binary compatibility
  27. 02w,23oct00,spm  removed duplicate free (corrects SPR #22324 fix) (SPR #30465)
  28. 02v,17oct00,spm  removed modification history from tor2_0_0.toolkit branch;
  29.                  merged from ver. 02z of tor3_0_x branch (base 02t): corrected
  30.                  attach routine (SPR #31351), added backward compatibility for
  31.                  END devices, and included general code cleanup
  32. 02u,17oct00,spm  updated for new if_attach: reports memory allocation failures
  33. 02t,17mar99,spm  added support for identical unit numbers (SPR #20913)
  34. 02s,16mar99,spm  recovered orphaned code from version 02q of tor2_0_x branch
  35.                  (base version 02n) (SPR #25570)
  36. 02r,03mar99,spm  eliminated buffer overflow when attaching device (SPR #22679);
  37.                  cleaned up mod history list
  38. 02q,03mar99,pul  update the driver flag during ipAttach(), SPR# 24287
  39. 02p,02mar99,pul  update ifp->if_baudrate during ipAttach(): SPR# 24256
  40. 02o,25feb99,pul  fixed multicast mapping to invoke resolution func spr#24255
  41. 02n,08aug98,n_s  fixed ipReceiveRtn to handle M_BLK chains (SPR #22324)
  42. 02m,26aug98,fle  doc : put library description next line
  43. 02l,24aug98,ann  fixed copy of ifSpeed field in ipIoctl() spr # 22198
  44. 02k,21aug98,n_s  fixed if_omcast increment in ipOutout (). spr # 21074
  45. 02j,16jul98,n_s  fixed ipIoctl () SIOCSIFFLAGS. SPR 21124
  46. 02i,15jun98,n_s  seperated ipDetach () into ipShutdownRtn () and 
  47.                  arpShutdownRtn ().  spr # 21545
  48. 02h,11dec97,gnn  removed IFF_SCAT and IFF_LOAN references.
  49. 02g,08dec97,gnn  END code review fixes.
  50. 02f,17oct97,vin  changes reflecting protocol recieveRtn changes.
  51. 02e,09oct97,vin  added break statements to ipIoctl(). fixed ipReceive().
  52. 02d,03oct97,gnn  added an error routine
  53. 02c,25sep97,gnn  SENS beta feedback fixes
  54. 02b,03sep97,gnn  implemented dropping of packets if the queue is full
  55. 02a,29aug97,jag  fixed bad parameter causing failure in txRestart routine.
  56. 01z,25aug97,gnn  documentation fixes for mangen.
  57. 01y,25aug97,gnn  added a check for attached in the TxRestart routine.
  58. 01x,19aug97,gnn  changes due to new buffering scheme.
  59. 01w,12aug97,gnn  name change and changes necessitated by MUX/END update.
  60. 01v,06jun97,vin  made enhancements, fixed arpReceive for multiple units.
  61. 01u,02jun97,gnn  put in stuff to deal with memory widths.
  62. 01t,20may97,gnn  fixed SPR 8627 so that multiple units are possible.
  63. 01s,15may97,gnn  modified muxUnbind to follow new prototype.
  64. 01r,30apr97,gnn  put a logMsg behind a debug check.
  65.                  cleaned up warnings.
  66. 01q,25apr97,gnn  fixed SPR 8461 about SNMP ioctls.
  67. 01p,09apr97,gnn  pass through for IFFLAGS.
  68. 01o,20mar97,map  Fixed problems in buffer loaning.
  69.                  Added gratuitous arp on SIOCSIFADDR.
  70. 01n,03feb97,gnn  Changed the way in which muxBufAlloc is used.
  71. 01m,30jan97,gnn  Fixed a bug in the call to build_cluster.
  72. 01l,24jan97,gnn  Modified vector code to handle holes in mbuf chains.
  73. 01k,24jan97,gnn  Fixed the bug where we were not checking the length of
  74.                  data in an mbuf as well as the next pointer.
  75.                  Fixed a bug in initialising for buffer loaning.
  76. 01j,22jan97,gnn  Added new private flags that is seperate from if flags.
  77. 01i,21jan97,gnn  Added code to handle scatter/gather.
  78.                  Changed the way send is done to deal with freeing buffers.
  79.                  Made receive routines return a value for SNARFing.
  80. 01h,20dec96,vin  fixed problems in send (added semGive, m_freem) 
  81.                  and recv routines (cleaned up). cleanup ifdefs.
  82. 01j,17dec96,gnn  added new drvCtrl structures.
  83. 01i,27nov96,gnn  added MIB 2 if_type handling.
  84. 01h,07nov96,gnn  fixed the bug where we were getting the flags wrong.
  85. 01g,23oct96,gnn  removed bcopy hack in initialization.
  86. 01f,22oct96,gnn  name changes to follow coding standards.
  87.                  cleanup of some compilation warnings.
  88. 01e,22oct96,gnn  removed ENET_HDR definition.
  89. 01d,22oct96,gnn  Changed all netVectors to netBuffers.
  90.                  Removed all private buffer loaning stuff.  That's all now
  91.                  in the MUX.
  92. 01c,23sep96,gnn  Added new buffering scheme information.
  93. 01b,13sep96,vin  fixed a bug in ipEtherIoctl for SIOCADDMULTI & SIOCDELMULTI 
  94. 01a,16may96,gnn  written.
  95. */
  96.  
  97. /*
  98. DESCRIPTION
  99. This library provides an interface between the Berkeley protocol stack
  100. and the MUX interface for both NPT and END devices. The ipAttach() routine
  101. binds the IP protocol to a specific device. It is called automatically
  102. during network initialization if INCLUDE_END is defined. The ipDetach()
  103. routine removes an existing binding to an END device.
  104. NOTE: The library can only transmit data to link-level destination addresses
  105.       less than or equal to 64 bytes in length.
  106. INCLUDE FILES: end.h muxLib.h etherMultiLib.h sys/ioctl.h
  107. */
  108. /* includes */
  109. #include "vxWorks.h"
  110. #include "stdio.h"
  111. #include "logLib.h"
  112. #include "semLib.h"
  113. #include "errnoLib.h"
  114. #include "tickLib.h"
  115. #include "intLib.h"
  116. #include "m2Lib.h"
  117. #include "private/m2LibP.h"
  118. #include "end.h"
  119. #include "muxLib.h"
  120. #include "private/muxLibP.h"
  121. #include "muxTkLib.h"
  122. #include "etherMultiLib.h"
  123. #include "sys/ioctl.h"
  124. #include "net/protosw.h"
  125. #include "sys/socket.h"
  126. #include "errno.h"
  127. #include "netinet/in_systm.h"
  128. #include "netinet/in_var.h"
  129. #include "netinet/ip.h"
  130. #include "netinet/if_ether.h"
  131. #include "net/if_subr.h"
  132. #include "net/if_dl.h"
  133. #include "net/if_llc.h"
  134. #include "net/mbuf.h"
  135. #include "ipProto.h"
  136. #include "netinet/ip_var.h"
  137. #include "stdlib.h"
  138. #include "memPartLib.h"
  139. #ifdef VIRTUAL_STACK
  140. #include "netinet/vsLib.h"
  141. #endif /* VIRTUAL_STACK */
  142. #ifdef ROUTER_STACK
  143. #include "wrn/fastPath/fastPathLib.h"
  144. #endif /* ROUTER_STACK */
  145. #ifdef WV_INSTRUMENTATION
  146. #ifdef INCLUDE_WVNET
  147. #include "wvNetLib.h"
  148. #endif /* INCLUDE_WVNET */
  149. #endif /* WV_INSTRUMENTATION */
  150. #ifdef WV_INSTRUMENTATION
  151. #ifdef INCLUDE_WVNET
  152.     /* Set common fields of event identifiers for this module. */
  153. LOCAL UCHAR wvNetModuleId = WV_NET_IPPROTO_MODULE;   /* Value for ipProto.c */
  154. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  155. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  156. #endif    /* INCLUDE_WVNET */
  157. #endif   /* WV_INSTRUMENTATION */
  158. /* defines */
  159. #define MAX_ADDRLEN 64  /* Largest link-level destination for NPT devices. */
  160. #define senderr(e) { error = (e); goto bad;}
  161. /* typedefs */
  162. typedef struct arpcom IDR;
  163. typedef struct mbuf MBUF;
  164. typedef struct ifnet IFNET;                 /* real Interface Data Record */
  165. typedef struct sockaddr SOCK;
  166. /* externs */
  167. IMPORT void if_dettach(struct ifnet *ifp);
  168. IMPORT void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *,
  169.                     struct rtentry *rt);
  170. /* globals */
  171. #ifdef ROUTER_STACK
  172. /*
  173.  * Pointer to the Fastpath library function table. This is set to
  174.  * point to the function table inside of ffLibInit() when it is called
  175.  */
  176. FF_LIB_FUNCTIONS * pFFLibFuncs = NULL;
  177. #endif /* ROUTER_STACK */
  178. /* locals */
  179. /* forward declarations */
  180. LOCAL BOOL ipReceiveRtn (void * pCookie, long type, M_BLK_ID pBuff,
  181.                          LL_HDR_INFO * pLinkHdrInfo, void * pSpare);
  182. LOCAL BOOL ipTkReceiveRtn (void * callbackId ,long type, M_BLK_ID pBuff,
  183.                           void * pSpareData);
  184. LOCAL STATUS ipShutdownRtn (void * pCookie, void * pSpare);
  185. LOCAL STATUS ipTkShutdownRtn (void * callbackId);
  186. LOCAL STATUS arpShutdownRtn (void * pCookie, void * pSpare);
  187. LOCAL STATUS arpTkShutdownRtn (void * callbackId);
  188. LOCAL void ipTxStartup (IP_DRV_CTRL* pDrvCtrl);
  189. LOCAL int ipIoctl (IDR * ifp, int cmd, caddr_t data );
  190. LOCAL int ipTxRestart (void * pCookie, IP_DRV_CTRL* pDrvCtrl);
  191. LOCAL int ipTkTxRestart (void * pSpare);
  192. LOCAL int ipOutput (register struct ifnet *ifp, struct mbuf *m0,
  193.                         struct sockaddr *dst, struct rtentry *rt0);
  194. LOCAL void ipError (END_OBJ* pEnd, END_ERR* pError, void * pSpare);
  195. LOCAL int ipOutputResume (struct mbuf*, struct sockaddr*, void*, void*);
  196. LOCAL int ipMcastResume (struct mbuf* pMbuf, struct sockaddr* ipDstAddr,
  197.                              void* pIfp, void* rt);
  198. #ifdef IP_DEBUG
  199. int ipDebug  = FALSE;
  200. #endif
  201. /******************************************************************************
  202. *
  203. * ipReceiveRtn - Send a packet from the MUX to the Protocol
  204. * This routine deals with  calling the upper layer protocol.
  205. *
  206. * RETURNS: always TRUE.
  207. *
  208. * NOMANUAL
  209. */
  210. BOOL ipReceiveRtn
  211.     (
  212.     void *  pCookie,   /* protocol/device binding from muxBind() */
  213.     long                type,           /* Protocol type.  */
  214.     M_BLK_ID  pMblk,         /* The whole packet. */
  215.     LL_HDR_INFO * pLinkHdrInfo, /* pointer to link level header info */
  216.     void *  pSpare  /* ip Drv ctrl */
  217.     )
  218.     {
  219.     END_OBJ *  pEnd;
  220.     struct ifnet *  pIfp;
  221.     M_BLK_ID            pMblkOrig;
  222.     IP_DRV_CTRL *  pDrvCtrl = (IP_DRV_CTRL *)pSpare;
  223. #ifdef ROUTER_STACK
  224.     struct ip* pIpHdr;
  225.     ULONG ipAddr=0;
  226.     struct sockaddr_in dstIpAddr;
  227. #endif  /* ROUTER_STACK */
  228.     if (pDrvCtrl == NULL)
  229.         {
  230.         logMsg ("ipProto: unknown devicen", 0, 0, 0, 0, 0, 0);
  231.         goto ipReceiveError;
  232.         }
  233.     
  234.     pIfp = &pDrvCtrl->idr.ac_if;
  235. #ifdef WV_INSTRUMENTATION
  236. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  237.     WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_NOTICE, 4, 13,
  238.                     WV_NETEVENT_ETHERIN_START, WV_NET_RECV, pIfp)
  239. #endif  /* INCLUDE_WVNET */
  240. #endif
  241.     if ((pIfp->if_flags & IFF_UP) == 0)
  242.         {
  243.         pIfp->if_ierrors++;
  244.         goto ipReceiveError;
  245.         }
  246.     pIfp->if_ipackets++;          /* bump statistic */
  247.     pIfp->if_lastchange = tickGet();
  248.     pIfp->if_ibytes += pMblk->mBlkPktHdr.len;
  249.     /* Make sure the entire Link Hdr is in the first M_BLK */
  250.     pMblkOrig = pMblk;
  251.     if (pMblk->mBlkHdr.mLen < pLinkHdrInfo->dataOffset
  252.         && (pMblk = m_pullup (pMblk, pLinkHdrInfo->dataOffset)) == NULL)
  253.         {
  254.         pMblk = pMblkOrig;
  255.         goto ipReceiveError;
  256.         }
  257.     switch (pIfp->if_type)
  258.         {
  259.         case M2_ifType_ethernetCsmacd:
  260.         case M2_ifType_iso88023Csmacd:
  261.         case M2_ifType_iso88024_tokenBus:
  262.         case M2_ifType_iso88025_tokenRing:
  263.         case M2_ifType_iso88026_man:
  264.         case M2_ifType_fddi:                  
  265.             if (pMblk->mBlkHdr.mData[0] & 1)
  266.                 {
  267.                 if (bcmp((caddr_t)etherbroadcastaddr,
  268.                          (caddr_t)pMblk->mBlkHdr.mData,
  269.                          sizeof(etherbroadcastaddr)) == 0)
  270.                     pMblk->mBlkHdr.mFlags |= M_BCAST;
  271.                 else
  272.                     pMblk->mBlkHdr.mFlags |= M_MCAST;
  273.                 pIfp->if_imcasts++;
  274.                 }
  275.             
  276.             if (pIfp->if_flags & IFF_PROMISC)
  277.                 {
  278. #ifdef ROUTER_STACK /* UNNUMBERED_SUPPORT */
  279. /* No point to reject if we are on an unnumbered P2P network */
  280. if (pIfp->if_flags & IFF_UNNUMBERED)
  281.     break;
  282. #endif /* ROUTER_STACK */
  283.                 /*
  284.                  * do not hand over the non multicast packets to the ip stack
  285.                  * if they are not destined to us, orelse it confuses the
  286.                  * ip forwarding logic and keeps sending unnecessary redirects.
  287.                  * If packets destined for other hosts have to be snooped they
  288.                  * have to done through driver level hooks.
  289.                  */
  290.                 
  291.                 if (!(pMblk->mBlkHdr.mFlags & (M_BCAST | M_MCAST)))
  292.                     {
  293.                     pEnd = PCOOKIE_TO_ENDOBJ(pCookie);
  294.                     if (pEnd->flags & END_MIB_2233)
  295.                         {
  296.                         if (bcmp ((char *)END_ALT_HADDR (pEnd),
  297.                                   (caddr_t)pMblk->mBlkHdr.mData,
  298.                                   END_ALT_HADDR_LEN (pEnd)) != 0)
  299.                             goto ipReceiveError;
  300.                         }
  301.                     else /* (RFC1213 style of counters supported) XXX */
  302.                         {
  303.                         if (bcmp ((char *)END_HADDR (pEnd),
  304.                                   (caddr_t)pMblk->mBlkHdr.mData,
  305.                                   END_HADDR_LEN (pEnd)) != 0)
  306.                             goto ipReceiveError;
  307.                         }
  308.                     }
  309.                 }
  310.             break;
  311.         default:
  312.             break;
  313.         }
  314.     /* point to the ip header, and adjust the length */
  315.     pMblk->mBlkHdr.mData  += pLinkHdrInfo->dataOffset;
  316.     pMblk->mBlkHdr.mLen   -= pLinkHdrInfo->dataOffset;
  317.     pMblk->mBlkPktHdr.len    -= pLinkHdrInfo->dataOffset;
  318.     pMblk->mBlkPktHdr.rcvif  = &pDrvCtrl->idr.ac_if;
  319. #ifdef VIRTUAL_STACK
  320.      /* Set the virtual stack ID so the received packet
  321.       * will be processed by the correct stack.
  322.       */
  323.       virtualStackNumTaskIdSet(pMblk->mBlkPktHdr.rcvif->vsNum);
  324. #endif /* VIRTUAL_STACK */
  325. #ifdef ROUTER_STACK
  326.     /*
  327.      * The algorithm explained...
  328.      * Check if Fastpath is enabled and this is an Ip packet.
  329.      * If so hand the packet over to the Fastpath code.
  330.      * If Fastpath is not enabled or if the Fastpath packet send function
  331.      * returns false, hand over the packet to tNetTask for normal processing.
  332.      */
  333.     if (SHOULD_GIVE_PACKET_TO_FF (GET_IPV4_FF_ID, pIfp) && 
  334.         type == ETHERTYPE_IP)
  335.         {
  336.         pIpHdr=mtod(pMblk, struct ip*);
  337.         ipAddr=pIpHdr->ip_dst.s_addr;
  338.         bzero((char*)&dstIpAddr, sizeof(struct sockaddr_in));
  339.         dstIpAddr.sin_len = sizeof(struct sockaddr_in);
  340.         dstIpAddr.sin_family=AF_INET;
  341.         dstIpAddr.sin_addr.s_addr=(ipAddr);
  342.         if (FF_NC_CALL (GET_IPV4_FF_ID, ffPktSend, (GET_IPV4_FF_ID, (struct sockaddr*)&dstIpAddr, pMblk, ETHERTYPE_IP, pIfp)) == OK)
  343.             {
  344. #ifdef DEBUG
  345.             logMsg("ipReceiveRtn: packet forwarded by Fastpathn",0,0,0,0,0,0);
  346. #endif /* DEBUG */
  347.             return (TRUE);
  348.             }
  349.         }
  350. #endif /* ROUTER_STACK */
  351.     do_protocol_with_type (type, pMblk , &pDrvCtrl->idr, 
  352.                            pMblk->mBlkPktHdr.len);
  353.     return (TRUE);
  354. ipReceiveError:
  355.     if (pMblk != NULL)
  356.         netMblkClChainFree (pMblk);
  357.     return (TRUE);
  358.     }
  359. /******************************************************************************
  360. *
  361. * ipTkReceiveRtn - send a packet to the protocol from an NPT device
  362. *
  363. * This routine transfers data to IP when an NPT device receives a packet
  364. * from a toolkit driver. The data contained in the <pMblk> argument is an
  365. * IP packet (without a link-level header). A toolkit driver updates the
  366. * flags in the mBlk to indicate a multicast or broadcast link-level frame.
  367. *
  368. * RETURNS: TRUE, always.
  369. *
  370. * NOMANUAL
  371. */
  372. LOCAL BOOL ipTkReceiveRtn
  373.     (
  374.     void * ipCallbackId,      /* Sent down in muxTkBind call. */
  375.     long         type,        /* Protocol type.  */
  376.     M_BLK_ID     pMblk,       /* The whole packet. */
  377.     void *       pSpareData   /* out of band data */
  378.     )
  379.     {
  380.     IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)ipCallbackId;
  381.     struct ifnet *  pIfp;
  382. #ifdef ROUTER_STACK
  383.     struct ip* pIpHdr;
  384.     ULONG ipAddr=0;
  385.     struct sockaddr_in dstIpAddr;
  386. #endif  /* ROUTER_STACK */
  387.     if (pDrvCtrl == NULL)
  388.         {
  389.         logMsg ("ipProto: unknown devicen", 0, 0, 0, 0, 0, 0);
  390.         goto ipReceiveError;
  391.         }
  392. #ifdef IP_DEBUG
  393.     if (ipDebug)
  394.         logMsg("start of ipTkReceiveRtn!n", 0, 0, 0, 0, 0, 0);
  395. #endif /* IP_DEBUG */
  396.     pIfp = (struct ifnet *)&pDrvCtrl->idr;
  397.     if ((pIfp->if_flags & IFF_UP) == 0)
  398.         {
  399.         pIfp->if_ierrors++;
  400.         goto ipReceiveError;
  401.         }
  402.     /* bump statistic */
  403.     pIfp->if_ipackets++;        
  404.     pIfp->if_lastchange = tickGet();
  405.     pIfp->if_ibytes += pMblk->mBlkPktHdr.len;
  406.     if(pMblk->mBlkHdr.mFlags & M_MCAST)
  407.         pIfp->if_imcasts++;
  408.     pMblk->mBlkPktHdr.rcvif     = pIfp;
  409.     /* hand off the packet to ip layer */
  410. #ifdef ROUTER_STACK
  411.     /* Check to see if Fastpath is enabled on the received interface */
  412.     if (SHOULD_GIVE_PACKET_TO_FF (GET_IPV4_FF_ID, pIfp) && 
  413.         type == ETHERTYPE_IP)
  414.         {
  415.         pIpHdr=mtod(pMblk, struct ip*);
  416.         ipAddr=pIpHdr->ip_dst.s_addr;
  417.         bzero((char*)&dstIpAddr, sizeof(struct sockaddr_in));
  418.         dstIpAddr.sin_len = sizeof(struct sockaddr_in);
  419.         dstIpAddr.sin_family=AF_INET;
  420.         dstIpAddr.sin_addr.s_addr=NTOHL(ipAddr);
  421.         if (FF_NC_CALL (GET_IPV4_FF_ID, ffPktSend, 
  422.                         (GET_IPV4_FF_ID, (struct sockaddr*)&dstIpAddr, 
  423.                          pMblk, ETHERTYPE_IP, pIfp)) == OK)
  424.             {
  425. #ifdef DEBUG
  426.             logMsg("ipTkReceiveRtn: packet forwarded by Fastpathn",0,0,0,0,0,0);
  427. #endif /* DEBUG */
  428.             return (TRUE);
  429.             }
  430.         }
  431. #endif /* ROUTER_STACK */
  432.     do_protocol_with_type (type, pMblk , (struct arpcom* )pIfp, 
  433.                            pMblk->mBlkHdr.mLen);
  434.     return (TRUE);
  435.     ipReceiveError:
  436.          {
  437.          if (pMblk != NULL)
  438.              netMblkClChainFree (pMblk);
  439.          }
  440.     return (TRUE);
  441.     }
  442. /******************************************************************************
  443. *
  444. * ipShutdownRtn - Shutdown the NULL protocol stack gracefully.
  445. * This routine is called by the lower layer upon muxDevUnload or a similar
  446. * condition to tell the protocol to shut itself down.
  447. *
  448. * RETURNS: OK, or ERROR if muxUnbind routine fails.
  449. *
  450. * NOMANUAL
  451. */
  452. LOCAL STATUS ipShutdownRtn
  453.     (
  454.     void *  pCookie,  /* protocol/device binding from muxBind() */
  455.     void *  pSpare  /* spare pointer from muxBind() */
  456.     )
  457.     {
  458.     IP_DRV_CTRL *  pDrvCtrl = (IP_DRV_CTRL *)pSpare;
  459.     if (!pDrvCtrl->attached)
  460. return (ERROR);
  461.     if_dettach(&pDrvCtrl->idr.ac_if);
  462.     KHEAP_FREE(pDrvCtrl->idr.ac_if.if_name);
  463.     netMblkFree (_pNetDpool, pDrvCtrl->pSrc);
  464.     netClFree (_pNetDpool, pDrvCtrl->pDstAddr);
  465.     netMblkFree (_pNetDpool, pDrvCtrl->pDst);
  466.     if (muxUnbind (pDrvCtrl->pIpCookie, ETHERTYPE_IP, ipReceiveRtn) != OK)
  467. {
  468. logMsg ("Could not un-bind from the IP MUX!", 0, 0, 0, 0, 0, 0);
  469. return (ERROR);
  470. }
  471.     if (pDrvCtrl->pArpCookie == NULL)
  472.         {
  473.         pDrvCtrl->attached = FALSE;
  474.         }
  475.     pDrvCtrl->pIpCookie = NULL;
  476.     return (OK);
  477.     }
  478. /******************************************************************************
  479. *
  480. * arpShutdownRtn - Shutdown the NULL protocol stack gracefully.
  481. * This routine is called by the lower layer upon muxDevUnload or a similar
  482. * condition to tell the protocol to shut itself down.
  483. *
  484. * RETURNS: OK or ERROR.
  485. *
  486. * NOMANUAL
  487. */
  488. LOCAL STATUS arpShutdownRtn
  489.     (
  490.     void *  pCookie,  /* protocol/device binding from muxBind() */
  491.     void *  pSpare  /* spare pointer from muxBind() */
  492.     )
  493.     {
  494.     IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)pSpare;
  495.     if (pDrvCtrl == NULL)
  496.         return (ERROR);
  497.             
  498.     if (!pDrvCtrl->attached)
  499. return (ERROR);
  500.     if (muxUnbind (pDrvCtrl->pArpCookie, ETHERTYPE_ARP, ipReceiveRtn) != OK)
  501. {
  502. logMsg ("Could not un-bind from the ARP MUX!", 0, 0, 0, 0, 0, 0);
  503. return (ERROR);
  504. }
  505.     if (pDrvCtrl->pIpCookie == NULL)
  506.         {
  507.         pDrvCtrl->attached = FALSE;
  508.         }
  509.     pDrvCtrl->pArpCookie = NULL;
  510.     return (OK);
  511.     }
  512. /******************************************************************************
  513. *
  514. * ipTkShutdownRtn - Shutdown the protocol stack bound to a toolkit driver
  515. *
  516. * This routine is called by the lower layer upon muxDevUnload or a similar
  517. * condition to tell the protocol to shut itself down.
  518. *
  519. * RETURNS: OK or ERROR depending on ipDetach.
  520. *
  521. * NOMANUAL
  522. */
  523. LOCAL STATUS ipTkShutdownRtn
  524.     (
  525.     void * ipCallbackId       /* protocol/device binding from muxTkBind() */
  526.     )
  527.     {
  528.     IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)ipCallbackId;
  529.     if (pDrvCtrl == NULL)
  530.         return (ERROR);
  531.     
  532.     if (!pDrvCtrl->attached)
  533.         return (ERROR);
  534.     if_dettach(&pDrvCtrl->idr.ac_if);
  535.     KHEAP_FREE(pDrvCtrl->idr.ac_if.if_name);
  536.     netClFree (_pNetDpool, pDrvCtrl->pDstAddr);
  537.     if (muxUnbind(pDrvCtrl->pIpCookie, ETHERTYPE_IP, ipTkReceiveRtn) != OK)
  538.         {
  539.         logMsg("Could not un-bind from the IP MUX!", 1, 2, 3, 4, 5, 6);
  540.         return (ERROR);
  541.         }
  542.     if (pDrvCtrl->pArpCookie == NULL)
  543.         {
  544.         pDrvCtrl->attached = FALSE;
  545.         }
  546.     pDrvCtrl->pIpCookie=NULL;
  547.     return (OK);
  548.     }
  549. /******************************************************************************
  550. *
  551. * arpTkShutdownRtn - shutdown the protocol stack bound to a toolkit driver. 
  552. *
  553. * This routine is called by the lower layer upon muxDevUnload or a similar
  554. * condition to tell the protocol to shut itself down.
  555. *
  556. * RETURNS: OK or ERROR.
  557. *
  558. * NOMANUAL
  559. */
  560. LOCAL STATUS arpTkShutdownRtn
  561.     (
  562.     void * ipCallbackId       /* Sent down in muxTkBind call. */
  563.     )
  564.     {
  565.     IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)ipCallbackId;
  566.     if (pDrvCtrl == NULL)
  567.         return (ERROR);
  568.     if (!pDrvCtrl->attached)
  569.         return (ERROR);
  570.     if (muxUnbind(pDrvCtrl->pArpCookie, ETHERTYPE_ARP, ipTkReceiveRtn) != OK)
  571.         {
  572.         logMsg("Could not un-bind from the ARP MUX!", 1, 2, 3, 4, 5, 6);
  573.         return (ERROR);
  574.         }
  575.     if (pDrvCtrl->pIpCookie == NULL)
  576.         {
  577.         pDrvCtrl->attached = FALSE;
  578.         }
  579.     pDrvCtrl->pArpCookie=NULL;
  580.     return (OK);
  581.     }
  582. /******************************************************************************
  583. *
  584. * ipTkError - a routine to deal with toolkit device errors
  585. *
  586. * This routine is called by the lower layer to handle a toolkit device error.
  587. *
  588. * RETURNS: N/A
  589. *
  590. * NOMANUAL
  591. *
  592. */
  593. void ipTkError
  594.     (
  595.     void * ipCallbackId,  /* Sent down in muxTkBind call. */
  596.     END_ERR* pError       /* Error message */
  597.     )
  598.     {
  599.     IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)ipCallbackId;
  600.     END_OBJ * pEnd  = NULL;
  601.     if (pDrvCtrl)
  602.  pEnd = PCOOKIE_TO_ENDOBJ (pDrvCtrl->pIpCookie);
  603.     if (pDrvCtrl == NULL || pEnd == NULL)
  604.         return;
  605.     ipError (pEnd, pError, pDrvCtrl);
  606.     return;
  607.     }
  608. /******************************************************************************
  609. *
  610. * ipError - a routine to deal with device errors
  611. *
  612. * This routine handles all errors from NPT and END drivers.
  613. *
  614. * RETURNS: N/A
  615. *
  616. * NOMANUAL
  617. */
  618. LOCAL void ipError
  619.     (
  620.     END_OBJ *  pEnd,  /* END reporting the error */
  621.     END_ERR *  pError,  /* the error message */
  622.     void *  pSpare  /* spare pointer from muxBind() */
  623.     )
  624.     {
  625.     int s;
  626.     IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)pSpare;
  627.     struct ifnet * pIfp;
  628.     USHORT newFlags;
  629.     if (pEnd == NULL || pDrvCtrl == NULL)
  630.      return;
  631.     pIfp = (struct ifnet *)&pDrvCtrl->idr;
  632.     switch (pError->errCode)
  633.         {
  634. #ifdef IP_DEBUG
  635.         case END_ERR_INFO:
  636.             if (ipDebug && pError->pMesg != NULL)
  637.                 logMsg ("INFO: Device: %s Unit: %d Msg: %sn",
  638.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  639.                         (int)pError->pMesg, 0, 0, 0);
  640.                 break;
  641.         case END_ERR_WARN:
  642.             if (ipDebug && pError->pMesg != NULL)
  643.                 logMsg ("WARN: Device: %s Unit: %d Msg: %sn",
  644.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  645.                         (int)pError->pMesg, 0, 0, 0);
  646.                 break;
  647. #endif /* IP_DEBUG */
  648.         case END_ERR_RESET:
  649. #ifdef IP_DEBUG
  650.             if (ipDebug && pError->pMesg != NULL)
  651.                 logMsg ("RESET: Device: %s Unit: %d Msg: %sn",
  652.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  653.                         (int)pError->pMesg, 0, 0, 0);
  654. #endif /* IP_DEBUG */
  655.             pDrvCtrl->idr.ac_if.if_lastchange = tickGet();
  656.             break;
  657.         case END_ERR_UP:
  658. #ifdef IP_DEBUG
  659.             if (ipDebug && pError->pMesg != NULL)
  660.                 logMsg ("UP: Device: %s Unit: %d Msg: %sn",
  661.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  662.                         (int)pError->pMesg, 0, 0, 0);
  663. #endif /* IP_DEBUG */
  664.             if ( (pIfp->if_flags & IFF_UP) == 0)
  665.                 {
  666.                 s = splimp ();
  667.                 if_up (pIfp);
  668.                 splx (s);
  669.                 }
  670.             pDrvCtrl->idr.ac_if.if_lastchange = tickGet();
  671.             ((IFNET *)&pDrvCtrl->idr)->if_flags |= (IFF_UP| IFF_RUNNING);
  672.             break;
  673.         case END_ERR_DOWN:
  674. #ifdef IP_DEBUG
  675.             if (ipDebug && pError->pMesg != NULL)
  676.                 logMsg ("DOWN: Device: %s Unit: %d Msg: %sn",
  677.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  678.                         (int)pError->pMesg, 0, 0, 0);
  679. #endif /* IP_DEBUG */
  680.             if ( (pIfp->if_flags & IFF_UP))
  681.                 {
  682.                 s = splimp ();
  683.                 if_down (pIfp);
  684.                 splx (s);
  685.                 }
  686.             pDrvCtrl->idr.ac_if.if_lastchange = tickGet();
  687.             ((IFNET *)&pDrvCtrl->idr)->if_flags &= ~(IFF_UP| IFF_RUNNING);
  688.             break;
  689.         case END_ERR_FLAGS:
  690. #ifdef IP_DEBUG
  691.             if (ipDebug && pError->pMesg != NULL)
  692.                 logMsg ("ipError:Msg from device %s Unit: %d Msg: %sn",
  693.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  694.                         (int)pError->pMesg, 0, 0, 0);
  695. #endif /* IP_DEBUG */
  696.             newFlags = (USHORT) ( (UINT32)pError->pSpare);
  697.             if ( (pIfp->if_flags & IFF_UP) ^ (newFlags & IFF_UP))
  698.                 {
  699.                 s = splimp ();
  700.                 if ( (pIfp->if_flags & IFF_UP) == 0)
  701.                     if_up (pIfp);
  702.                 else
  703.                     if_down (pIfp);
  704.                 splx (s);
  705.                 }
  706.             /* Set interface flags to new values, if allowed. */
  707.             newFlags = newFlags & ~IFF_CANTCHANGE;
  708.             pIfp->if_flags &= IFF_CANTCHANGE;
  709.             pIfp->if_flags = pIfp->if_flags | newFlags;
  710.             break;
  711.         case END_ERR_NO_BUF:
  712. #ifdef IP_DEBUG
  713.             if (ipDebug && pError->pMesg != NULL)
  714.                 logMsg ("NO_BUF: Device: %s Unit: %d Msg: %sn",
  715.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  716.                         (int)pError->pMesg, 0, 0, 0);
  717. #endif /* IP_DEBUG */
  718.             ip_drain();                      /* empty the fragment Q */
  719.             break;
  720.         default:
  721. #ifdef IP_DEBUG
  722.             if (ipDebug && pError->pMesg != NULL)
  723.                 logMsg ("UNKOWN ERROR: Device: %s Unit: %d Msg: %sn",
  724.                         (int)pEnd->devObject.name, pEnd->devObject.unit,
  725.                         (int)pError->pMesg, 0, 0, 0);
  726. #endif /* IP_DEBUG */
  727.             
  728. break;
  729.         }
  730.     }
  731. /******************************************************************************
  732. *
  733. * ipAttach - a generic attach routine for the TCP/IP network stack
  734. *
  735. * This routine takes the unit number and device name of an END or NPT
  736. * driver (e.g., "ln0", "ei0", etc.) and attaches the IP protocol to
  737. * the corresponding device. Following a successful attachment IP will
  738. * begin receiving packets from the devices.
  739. *
  740. * RETURNS: OK or ERROR
  741. */
  742. int ipAttach
  743.     (
  744.     int unit,                   /* Unit number  */
  745.     char *pDevice /* Device name (i.e. ln, ei etc.). */
  746.     )
  747.     {
  748.     long flags;
  749.     M2_INTERFACETBL mib2Tbl;
  750.     M2_ID * pM2ID; 
  751.     IP_DRV_CTRL* pDrvCtrl;
  752. #ifndef VIRTUAL_STACK
  753.     IMPORT int          ipMaxUnits;
  754. #endif
  755.     struct ifnet* pIfp = NULL;
  756.     char *pName = NULL;
  757.     END_OBJ* pEnd;
  758.     struct ifaddr *pIfa;
  759.     struct sockaddr_dl *pSdl;
  760.     CL_POOL_ID pClPoolId;
  761.     int ifHdrLen;
  762.     
  763.     int count;
  764.     int limit = ipMaxUnits;
  765.     int freeslot = -1;
  766.     
  767.     pEnd = endFindByName (pDevice, unit);
  768.     if (pEnd == NULL)
  769.         {
  770.         logMsg ("ipAttach: Can't attach %s (unit %d). It is not an END device.n",
  771.                 (int)pDevice, unit, 0, 0, 0, 0);
  772.         return (ERROR);
  773.         }
  774.     
  775.     for (count = 0; count < limit; count++)
  776.         {
  777.         pDrvCtrl = &ipDrvCtrl [count];
  778.         
  779.         if (pDrvCtrl->attached)
  780.             {
  781.             /* Already attached to requested device? */
  782.             
  783.             if (PCOOKIE_TO_ENDOBJ (pDrvCtrl->pIpCookie) == pEnd)
  784.                 return (OK);
  785.             }
  786.         else if (freeslot == -1)
  787.             freeslot = count;
  788.         }
  789.     
  790.     if (freeslot == -1)
  791.         {
  792.         /* Too many attach attempts. */
  793.         
  794.         logMsg ("Protocol is out of space. Increase IP_MAX_UNITS.n",
  795.                 0, 0, 0, 0, 0, 0);
  796.         
  797.         return (ERROR);
  798.         }
  799.     
  800.     pDrvCtrl = &ipDrvCtrl [freeslot];
  801.     bzero ( (char *)pDrvCtrl, sizeof (IP_DRV_CTRL));
  802.     
  803.     /*
  804.      * Bind IP to the device using the appropriate routines for the driver
  805.      * type. NPT devices use a different receive routine since those drivers
  806.      * remove the link-level header before handing incoming data to the MUX
  807.      * layer.
  808.      */
  809.     
  810.     pDrvCtrl->nptFlag = FALSE;
  811.     
  812.     if (pEnd->pFuncTable->ioctl)
  813.         {
  814.         if ( (pEnd->pFuncTable->ioctl (pEnd, EIOCGNPT, NULL)) == OK)
  815.             {
  816.             /* NPT device. */
  817.             pDrvCtrl->nptFlag = TRUE;
  818.             }
  819.         }
  820.     
  821.     if (pDrvCtrl->nptFlag)
  822.         {
  823.         /* NPT device */
  824.         pDrvCtrl->pIpCookie = muxTkBind (pDevice, unit, ipTkReceiveRtn,
  825.                                          ipTkShutdownRtn, ipTkTxRestart,
  826.                                          ipTkError, ETHERTYPE_IP, 
  827.                                          "IP 4.4 TCP/IP",
  828.                                          pDrvCtrl, NULL, NULL);
  829.         
  830.         if (pDrvCtrl->pIpCookie == NULL)
  831.             {
  832.             logMsg ("TCP/IP could not bind to the MUX: muxTkBind! %s",
  833.                     (int)pDevice, 0, 0, 0, 0, 0);
  834.             goto ipAttachError;
  835.             }
  836.         }
  837.     else
  838.         {
  839.         /* END device */
  840.         pDrvCtrl->pIpCookie = muxBind (pDevice, unit, (FUNCPTR) ipReceiveRtn,
  841.                                        (FUNCPTR) ipShutdownRtn, 
  842.                                        (FUNCPTR) ipTxRestart,
  843.                                        (VOIDFUNCPTR) ipError, ETHERTYPE_IP,
  844.                                        "IP 4.4 TCP/IP", (void *) pDrvCtrl);
  845.         if (pDrvCtrl->pIpCookie == NULL)
  846.             {
  847.             logMsg ("TCP/IP could not bind to the MUX! %s", (int)pDevice,
  848.                     0, 0, 0, 0, 0);
  849.             goto ipAttachError;
  850.             }
  851.         
  852.         
  853.         /*
  854.          * END devices require additional memory to construct a
  855.          * link-level header for outgoing data.
  856.          */
  857.         
  858.         pDrvCtrl->pSrc = netMblkGet (_pNetDpool, M_DONTWAIT, MT_DATA);
  859.         if (pDrvCtrl->pSrc == NULL)
  860.             {
  861.             goto ipAttachError;
  862.             }
  863.         
  864.         pDrvCtrl->pDst = netMblkGet (_pNetDpool, M_DONTWAIT, MT_DATA);
  865.         if (pDrvCtrl->pDst == NULL)
  866.             {
  867.             goto ipAttachError;
  868.             }
  869.         }
  870.         
  871.     /* Get storage for link-level destination addresses. */
  872.     
  873.     pClPoolId = netClPoolIdGet (_pNetDpool, MAX_ADDRLEN, TRUE);
  874.     if (pClPoolId == NULL)
  875.         {
  876.         goto ipAttachError;
  877.         }
  878.     
  879.     pDrvCtrl->pDstAddr = netClusterGet (_pNetDpool, pClPoolId);
  880.     if (pDrvCtrl->pDstAddr == NULL)
  881.         {
  882.         goto ipAttachError;
  883.         }
  884.     
  885.     /* Set the internal mBlk to access the link-level information. */
  886.     
  887.     if (!pDrvCtrl->nptFlag)
  888.         pDrvCtrl->pDst->m_data = pDrvCtrl->pDstAddr;
  889.     
  890.     pName = KHEAP_ALLOC( (strlen (pDevice) + 1));    /* +1: EOS character */
  891.     if (pName == NULL)
  892.         {
  893.         goto ipAttachError;
  894.         }
  895.     bzero (pName, strlen (pDevice) + 1);
  896.     strcpy (pName, pDevice);
  897.     /* Get all necessary lower-level device information. */
  898.     
  899.     muxIoctl (pDrvCtrl->pIpCookie, EIOCGFLAGS, (caddr_t)&flags);
  900.     
  901.     if (pEnd->flags & END_MIB_2233)
  902.         {
  903.         if (muxIoctl(pDrvCtrl->pIpCookie, EIOCGMIB2233,
  904.                      (caddr_t)&pM2ID) == ERROR)
  905.     {
  906.     logMsg("ipAttach: could not get MIB2 Table for device %s #%dn",
  907.                    (int)pDevice,unit,3,4,5,6);
  908.             
  909.     goto ipAttachError;
  910.     }
  911.         
  912.         memcpy(&mib2Tbl, &(pM2ID->m2Data.mibIfTbl), sizeof(M2_INTERFACETBL));
  913.         }
  914.     else /* (RFC1213 style of counters supported) XXX */
  915.         {
  916.         if (muxIoctl(pDrvCtrl->pIpCookie, EIOCGMIB2,
  917.                      (caddr_t)&mib2Tbl) == ERROR)
  918.     {
  919.     logMsg("ipAttach: could not get MIB2 Table for device %s #%dn",
  920.                    (int)pDevice,unit,3,4,5,6);
  921.             
  922.     goto ipAttachError;
  923.     }
  924.         }
  925.     pIfp = (IFNET *)&pDrvCtrl->idr;
  926.     
  927.     /* Hook up the interface pointers etc. */
  928.     
  929. #ifdef WV_INSTRUMENTATION
  930. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  931.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 14, 17, 
  932.                      WV_NETEVENT_ETHERATTACH_START, pIfp)
  933. #endif  /* INCLUDE_WVNET */
  934. #endif
  935.         
  936.         bzero ((char *) pIfp, sizeof (*pIfp));
  937.     
  938. #ifdef VIRTUAL_STACK
  939.     virtualStackIdCheck();  /* make sure the myStackNum exists */
  940.     pIfp->vsNum = myStackNum;
  941. #endif /* VIRTUAL_STACK */
  942.     
  943.     pIfp->if_unit   = unit;
  944.     pIfp->if_name   = pName;
  945.     pIfp->if_mtu    = mib2Tbl.ifMtu;
  946.     pIfp->if_baudrate = mib2Tbl.ifSpeed;
  947.     pIfp->if_init   = NULL;
  948.     pIfp->if_ioctl  = (FUNCPTR) ipIoctl;
  949.     pIfp->if_output = ipOutput;
  950.     pIfp->if_reset  = NULL;
  951.     pIfp->if_resolve = muxAddrResFuncGet (mib2Tbl.ifType, ETHERTYPE_IP);
  952.     pIfp->if_flags  = flags;
  953.     pIfp->if_type = mib2Tbl.ifType;
  954.     pIfp->if_addrlen = mib2Tbl.ifPhysAddress.addrLength;
  955.     pIfp->pCookie = (void *)pDrvCtrl;
  956.     /*
  957.      * Store address information for supported devices (802.x addressing)
  958.      * and bind ARP to the device using the appropriate receive routine.
  959.      */
  960.     switch (mib2Tbl.ifType)
  961.         {
  962.         case M2_ifType_ethernet_csmacd:
  963.         case M2_ifType_iso88023_csmacd:
  964.         case M2_ifType_iso88024_tokenBus:
  965.         case M2_ifType_iso88025_tokenRing:
  966.         case M2_ifType_iso88026_man:
  967.         case M2_ifType_fddi:
  968.             bcopy (mib2Tbl.ifPhysAddress.phyAddress, pDrvCtrl->idr.ac_enaddr,
  969.                    pIfp->if_addrlen);
  970.             
  971.             if (pDrvCtrl->nptFlag)
  972.                 {
  973.                 pDrvCtrl->pArpCookie = muxTkBind (pDevice, unit,
  974.                                                   ipTkReceiveRtn,
  975.                                                   arpTkShutdownRtn,
  976.                                                   ipTkTxRestart,
  977.                                                   NULL, ETHERTYPE_ARP, 
  978.                                                   "IP 4.4 ARP",
  979.                                                   pDrvCtrl, NULL, NULL);
  980.                 if (pDrvCtrl->pArpCookie == NULL)
  981.                     {
  982.                     logMsg ("ARP could not bind to the MUX: muxTkBind! %s",
  983.                             (int)pDevice, 0, 0, 0, 0, 0);
  984.                     goto ipAttachError;
  985.                     }
  986.                 }
  987.             else     /* END device */
  988.                 {
  989.                 pDrvCtrl->pArpCookie = muxBind (pDevice, unit,
  990.                                                 (FUNCPTR) ipReceiveRtn,
  991.                                                 (FUNCPTR) arpShutdownRtn, 
  992.                                                 (FUNCPTR) ipTxRestart,
  993.                                                 NULL, ETHERTYPE_ARP, 
  994.                                                 "IP 4.4 ARP",
  995.                                                 pDrvCtrl);
  996.                 if (pDrvCtrl->pArpCookie == NULL)
  997.                     {
  998.                     logMsg ("ARP could not bind to the MUX! %s", (int)pDevice,
  999.                             0, 0, 0, 0, 0);
  1000.                     goto ipAttachError;
  1001.                     }
  1002.                 }
  1003.             break;
  1004.         default:
  1005.             break;
  1006.         }
  1007.     
  1008.     /* Get the length of the header. */
  1009.     if (muxIoctl (pDrvCtrl->pIpCookie, EIOCGHDRLEN, (caddr_t)&ifHdrLen) != OK)
  1010.         pIfp->if_hdrlen = 0;
  1011.     else
  1012.         pIfp->if_hdrlen = (short)ifHdrLen;
  1013.     
  1014.     /* Attach the interface. */
  1015.     /* NOTE: if_attach must come before "common duties" below.  see spr# 29152 */
  1016.     
  1017.     if (if_attach (pIfp) == ERROR)
  1018.         goto ipAttachError;
  1019.     
  1020.     /*
  1021.      * Perform common duties while attaching to interface list
  1022.      */
  1023.     for (pIfa = pIfp->if_addrlist; pIfa; pIfa = pIfa->ifa_next)
  1024.         {
  1025.         if ((pSdl = (struct sockaddr_dl *)pIfa->ifa_addr) &&
  1026.             pSdl->sdl_family == AF_LINK)
  1027.             {
  1028.             pSdl->sdl_type = pIfp->if_type;
  1029.             pSdl->sdl_alen = pIfp->if_addrlen;
  1030.             bcopy (mib2Tbl.ifPhysAddress.phyAddress,
  1031.                    LLADDR (pSdl), pSdl->sdl_alen);
  1032.             break;
  1033.             }
  1034.         }
  1035.     
  1036.     pIfp->if_start = (FUNCPTR)ipTxStartup;
  1037.     
  1038.     pDrvCtrl->attached = TRUE;
  1039.     
  1040.     return (OK);
  1041.     ipAttachError:
  1042.     
  1043.     /* Cleanup by removing any bound protocols and/or allocated memory. */
  1044.     
  1045.     if (pDrvCtrl->pDstAddr)
  1046.         netClFree (_pNetDpool, pDrvCtrl->pDstAddr);
  1047.     
  1048.     if (pDrvCtrl->nptFlag)
  1049.         {
  1050.         if (pDrvCtrl->pIpCookie)
  1051.             muxUnbind (pDrvCtrl->pIpCookie, ETHERTYPE_IP, ipTkReceiveRtn);
  1052.         
  1053.         if (pDrvCtrl->pArpCookie)
  1054.             muxUnbind (pDrvCtrl->pArpCookie, ETHERTYPE_IP, ipTkReceiveRtn);
  1055.         }
  1056.     else
  1057.         {
  1058.         if (pDrvCtrl->pIpCookie)
  1059.             muxUnbind (pDrvCtrl->pIpCookie, ETHERTYPE_IP, ipReceiveRtn);
  1060.         
  1061.         if (pDrvCtrl->pArpCookie)
  1062.             muxUnbind (pDrvCtrl->pArpCookie, ETHERTYPE_IP, ipReceiveRtn);
  1063.         }
  1064.     
  1065.     if (pDrvCtrl->pSrc)
  1066.         netMblkFree (_pNetDpool, pDrvCtrl->pSrc);
  1067.     
  1068.     if (pDrvCtrl->pDst)
  1069.         netMblkFree (_pNetDpool, pDrvCtrl->pDst);
  1070.     
  1071.     return (ERROR);
  1072.     }
  1073. /*******************************************************************************
  1074. *
  1075. * ipTxRestart - restart routine 
  1076. *
  1077. * NOMANUAL
  1078. */
  1079. LOCAL int ipTxRestart
  1080.     (
  1081.     void * pCookie, /* device identifier (from muxDevLoad) */
  1082.     IP_DRV_CTRL * pDrvCtrl
  1083.     )
  1084.     {
  1085.     if (pDrvCtrl == NULL)
  1086.         return (ERROR);
  1087.     
  1088.     ipTxStartup (pDrvCtrl);
  1089.     
  1090.     return (OK);
  1091.     }
  1092. /*******************************************************************************
  1093. *
  1094. * ipTkTxRestart - restart routine registered with a toolkit driver. 
  1095. *
  1096. * NOMANUAL
  1097. */
  1098. LOCAL int ipTkTxRestart
  1099.     (
  1100.     void * ipCallbackId       /* Sent down in muxTkBind call. */
  1101.     )
  1102.     {
  1103.     IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)ipCallbackId;
  1104.     if (pDrvCtrl == NULL)
  1105.         return (ERROR);
  1106.     ipTxStartup (pDrvCtrl);
  1107.     return (OK);
  1108.     }
  1109. /*******************************************************************************
  1110. *
  1111. * ipTxStartup - start output on the lower layer
  1112. *
  1113. * Looks for any action on the queue, and begins output if there is anything
  1114. * there.  This routine is called from several possible threads.  Each will be
  1115. * described below.
  1116. *
  1117. * The first, and most common thread, is when a user task requests the
  1118. * transmission of data.  This will cause muxSend() to be called, which will
  1119. * cause ether_output() to be called, which will cause this routine to be
  1120. * called (usually).  This routine will not be called if ether_output() finds
  1121. * that our interface output queue is full.  In this case, the outgoing data
  1122. * will be thrown out.
  1123. *
  1124. * The second, and most obscure thread, is when the reception of certain
  1125. * packets causes an immediate (attempted) response.  For example, ICMP echo
  1126. * packets (ping), and ICMP "no listener on that port" notifications.  All
  1127. * functions in this driver that handle the reception side are executed in the
  1128. * context of netTask().  Always.  So, in the case being discussed, netTask() 
  1129. * will receive these certain packets, cause IP to be stimulated, and cause the
  1130. * generation of a response to be sent.  We then find ourselves following the
  1131. * thread explained in the second example, with the important distinction that
  1132. * the context is that of netTask().
  1133. *
  1134. * This routine is also called from ipTxRestart() and ipTkTxRestart().
  1135. *
  1136. * NOMANUAL
  1137. */
  1138. void ipTxStartup
  1139.     (
  1140.     IP_DRV_CTRL * pDrvCtrl /* pointer to the drv control */
  1141.     )
  1142.     {
  1143.     M_BLK_ID      pMblk;
  1144.     STATUS        status = OK;
  1145.     struct ifnet *  pIf;
  1146.     BOOL  nptFlag;
  1147.     USHORT netType = 0;
  1148.     char dstAddrBuf [MAX_ADDRLEN];
  1149.     M_BLK_ID pNetPkt = NULL;
  1150.     int s;
  1151.     if (pDrvCtrl == NULL)
  1152.         return;
  1153.     if (!pDrvCtrl->attached)
  1154.         {
  1155. #ifdef IP_DEBUG
  1156.         if (ipDebug)
  1157.             logMsg ("ipTxStartup not attached!n", 0, 0, 0, 0, 0, 0);
  1158. #endif /* IP_DEBUG */
  1159.         return;
  1160.         }
  1161.     s = splnet();
  1162.     nptFlag = pDrvCtrl->nptFlag;
  1163.     pIf = (struct ifnet *)&pDrvCtrl->idr;
  1164.     /*
  1165.      * Loop until there are no more packets ready to send or we
  1166.      * have insufficient resources left to send another one.
  1167.      */
  1168.     while (pIf->if_snd.ifq_head)
  1169.         {
  1170.         /* Dequeue a packet. */
  1171.         IF_DEQUEUE (&pIf->if_snd, pMblk);  
  1172. #ifdef ETHER_OUTPUT_HOOKS
  1173.         if ((etherOutputHookRtn != NULL) &&
  1174.             (* etherOutputHookRtn)
  1175.           (&pDrvCtrl->idr, (struct ether_header *)pMblk->m_data,pMblk->m_len))
  1176.             {
  1177.             continue;
  1178.             }
  1179. #endif /* ETHER_OUTPUT_HOOKS */
  1180.         if (nptFlag)
  1181.             {
  1182.             /*
  1183.              * For NPT devices, the output processing adds the network packet
  1184.              * type (and the link-level destination address, if any) to the
  1185.              * start of the packet. Retrieve that information and pass it to
  1186.              * the NPT transmit routine.
  1187.              */
  1188.             netType = pMblk->mBlkHdr.reserved;
  1189.             bzero (dstAddrBuf, MAX_ADDRLEN);
  1190.             pNetPkt = pMblk;
  1191.             if (pIf->if_addrlen)
  1192.                 {
  1193.                 /* Save the dest. address to protect it from driver changes. */
  1194.                 bcopy (pMblk->mBlkHdr.mData, dstAddrBuf, pIf->if_addrlen);
  1195.                 /* Restore original network packet data pointers and length. */
  1196.                 m_adj (pMblk, pIf->if_addrlen);
  1197.                 if (pMblk->mBlkHdr.mLen == 0)
  1198.                     {
  1199.                     /*
  1200.                      * The destination address used a new mBlk in the chain.
  1201.                      * Access the next entry containing the network packet
  1202.                      * and restore the header flag setting.
  1203.                      */
  1204.                     pNetPkt = pMblk->mBlkHdr.mNext;
  1205.                     if (pMblk->mBlkHdr.mFlags & M_PKTHDR)
  1206.                         {
  1207.                         pNetPkt->mBlkHdr.mFlags |= M_PKTHDR;
  1208.                         }
  1209.                     }
  1210.                 }
  1211.             /* Attempt to send the packet. */
  1212.             status = muxTkSend (pDrvCtrl->pIpCookie, pNetPkt, dstAddrBuf,
  1213.                                 netType, NULL);
  1214.             }
  1215.         else
  1216.             {
  1217.             /*
  1218.              * For END devices, the transmit queue contains a complete
  1219.              * link-level frame. Attempt to send that data.
  1220.              */
  1221.             status = muxSend (pDrvCtrl->pIpCookie, pMblk);
  1222.             }
  1223.         if (status == END_ERR_BLOCK)
  1224.             {
  1225.             /*
  1226.              * The device is currently unable to transmit. Return the
  1227.              * packet or frame to the queue to retry later.
  1228.              */
  1229. #ifdef IP_DEBUG
  1230.             if (ipDebug)
  1231.                 logMsg ("Transmit error!n", 0, 0, 0, 0, 0, 0);
  1232. #endif /* IP_DEBUG */
  1233.             if (nptFlag && pIf->if_addrlen)
  1234.                 {
  1235.                 /*
  1236.                  * For NPT devices, restore the link-level destination
  1237.                  * address, in case the driver processing altered it.
  1238.                  */
  1239.                 if (pMblk == pNetPkt)
  1240.                     {
  1241.                     /*
  1242.                      * The destination address used the initial mBlk in the
  1243.                      * chain. Change the data pointer to provide copy space.
  1244.                      */
  1245.                     pMblk->mBlkHdr.mData -= pIf->if_addrlen;
  1246.                     }
  1247.                 bcopy (dstAddrBuf, pMblk->mBlkHdr.mData, pIf->if_addrlen);
  1248.                 pMblk->mBlkHdr.mLen += pIf->if_addrlen;
  1249.                 if (pMblk->mBlkHdr.mFlags & M_PKTHDR)
  1250.                     pMblk->mBlkPktHdr.len += pIf->if_addrlen;
  1251.                 }
  1252.     /* If we are transmitting make a new copy and PREPEND it. */
  1253.     if (IF_QFULL(&pDrvCtrl->idr.ac_if.if_snd))
  1254.         {
  1255.         IF_DROP(&pDrvCtrl->idr.ac_if.if_snd);
  1256.         netMblkClChainFree (pMblk);
  1257.         ++pDrvCtrl->idr.ac_if.if_oerrors;          
  1258.                 }
  1259.     else
  1260.         IF_PREPEND (&pDrvCtrl->idr.ac_if.if_snd, pMblk);
  1261.             break;
  1262.             }
  1263.         else     /* Successful handoff to driver for transmission. */
  1264.            {
  1265.            ++pDrvCtrl->idr.ac_if.if_opackets;
  1266.             /* For NPT devices, free any Mblk prepended for the link-level
  1267.              * destination address.  */
  1268.            if (nptFlag && (pMblk != pNetPkt))
  1269.                {
  1270.                netMblkClFree(pMblk);
  1271.                }
  1272.            }
  1273.         
  1274. #ifdef IP_DEBUG
  1275.         if (ipDebug)
  1276.             logMsg("ipTxStartup done!n", 0, 0, 0, 0, 0, 0);
  1277. #endif /* IP_DEBUG */
  1278.         }
  1279.     splx(s);
  1280.     }
  1281. /*******************************************************************************
  1282. *
  1283. * ipDetach - a generic detach routine for the TCP/IP network stack
  1284. *
  1285. * This routine removes the TCP/IP stack from the MUX. If completed
  1286. * successfully, the IP protocol will no longer receive packets
  1287. * from the named END driver. 
  1288. *
  1289. * RETURNS: OK or ERROR
  1290. */
  1291. STATUS ipDetach
  1292.     (
  1293.     int unit,                   /* Unit number  */
  1294.     char *pDevice /* Device name (i.e. ln, ei etc.). */
  1295.     )
  1296.     {
  1297.     END_OBJ *  pEnd;
  1298.     IP_DRV_CTRL* pDrvCtrl = NULL;
  1299.     int error;                 /* return error status */
  1300.     int count;
  1301. #ifndef VIRTUAL_STACK
  1302.     IMPORT int          ipMaxUnits;
  1303. #endif
  1304.     int limit = ipMaxUnits;
  1305.     char        ifName[IFNAMSIZ];               /* if name, e.g. "en0" */
  1306.     /* Check if device is valid. */
  1307.     pEnd = endFindByName (pDevice, unit);
  1308.     if (pEnd == NULL)
  1309.         return (ERROR);
  1310.     for (count = 0; count < limit; count++)
  1311.         {
  1312.         pDrvCtrl = &ipDrvCtrl [count];
  1313.         if (pDrvCtrl->attached &&
  1314.                 PCOOKIE_TO_ENDOBJ (pDrvCtrl->pIpCookie) == pEnd)
  1315.             break;
  1316.         }
  1317.     if (count == limit)
  1318.         {
  1319.         /* Device not attached. */
  1320.         return (ERROR);
  1321.         }
  1322.     /* Now bring down the interface */
  1323.  
  1324.     sprintf (ifName,"%s%d",pDevice, unit);
  1325.     ifFlagChange(ifName, IFF_UP, 0);
  1326.  
  1327.     /* Now remove the interface route */
  1328.  
  1329.     ifRouteDelete(pDevice, unit);
  1330.     
  1331.     if (pDrvCtrl->nptFlag)       /* npt device, call npt routines */
  1332.         {
  1333.         error = ipTkShutdownRtn (pDrvCtrl);
  1334.         if (pDrvCtrl->pArpCookie)
  1335.             error |= arpTkShutdownRtn (pDrvCtrl);
  1336.         }
  1337.     else
  1338.         {
  1339.         error = ipShutdownRtn (pDrvCtrl->pIpCookie, pDrvCtrl);
  1340.         if (pDrvCtrl->pArpCookie)
  1341.             error |= arpShutdownRtn (pDrvCtrl->pArpCookie, pDrvCtrl);
  1342.         }
  1343.     
  1344.     return (error);
  1345.     }
  1346. /*******************************************************************************
  1347. *
  1348. * ipIoctl - the IP I/O control routine
  1349. *
  1350. * Process an ioctl request.
  1351. *
  1352. * NOMANUAL
  1353. */
  1354. LOCAL int ipIoctl
  1355.     (
  1356.     IDR  *ifp,
  1357.     int            cmd,
  1358.     caddr_t        data
  1359.     )
  1360.     {
  1361.     int error = OK;
  1362.     struct ifreq *ifr;
  1363.     IP_DRV_CTRL* pDrvCtrl;
  1364.     register struct in_ifaddr* pIa = 0;
  1365.     M2_INTERFACETBL mib2Tbl;
  1366.     struct sockaddr* inetaddr;
  1367.     char   mapMCastBuff[128];
  1368.     long flagsMask;
  1369.     register M2_NETDRVCNFG *pm2DrvCnfg = (M2_NETDRVCNFG *)data;
  1370.     register M2_NETDRVCNTRS *pm2DrvCntr = (M2_NETDRVCNTRS *)data;
  1371.     u_long dt_saddr = ((struct in_ifaddr *)data)->ia_addr.sin_addr.s_addr;
  1372.     struct mBlk* pMblk;
  1373.     pDrvCtrl = (IP_DRV_CTRL *)(ifp->ac_if.pCookie);
  1374.     if (pDrvCtrl->pIpCookie == NULL)
  1375.         return (EINVAL);
  1376.     switch ((u_int) cmd)
  1377. {
  1378. case SIOCSIFADDR:
  1379. #ifdef VIRTUAL_STACK
  1380.             for (pIa = _in_ifaddr; pIa; pIa = pIa->ia_next)
  1381. #else
  1382.             for (pIa = in_ifaddr; pIa; pIa = pIa->ia_next)
  1383. #endif /* VIRTUAL_STACK */
  1384.                 if ((pIa->ia_ifp == (struct ifnet *)ifp) &&
  1385.                     (pIa->ia_addr.sin_addr.s_addr == dt_saddr))
  1386.                     break;
  1387.             /*
  1388.              * For devices with 802.x addressing, setup ARP processing
  1389.              * for the IP address.
  1390.              */
  1391.             switch (ifp->ac_if.if_type)
  1392.                 {
  1393.                 case M2_ifType_ethernet_csmacd:
  1394.                 case M2_ifType_iso88023_csmacd:
  1395.                 case M2_ifType_iso88024_tokenBus:
  1396.                 case M2_ifType_iso88025_tokenRing:
  1397.                 case M2_ifType_iso88026_man:
  1398.                 case M2_ifType_fddi:
  1399. #ifdef ROUTER_STACK /* UNNUMBERED_SUPPORT */ 
  1400.             if (pIa->ia_ifp->if_flags & IFF_UNNUMBERED)
  1401.         {
  1402.         pIa->ia_ifa.ifa_rtrequest = NULL;
  1403.         pIa->ia_ifa.ifa_flags &= ~RTF_CLONING;
  1404.         ifp->ac_ipaddr = IA_SIN (data)->sin_addr;
  1405.         break;
  1406.         }
  1407. #endif /* ROUTER_STACK */
  1408.                     pIa->ia_ifa.ifa_rtrequest = arp_rtrequest;
  1409.                     pIa->ia_ifa.ifa_flags |= RTF_CLONING;
  1410.                     ifp->ac_ipaddr = IA_SIN (data)->sin_addr;
  1411.                     /* Generate gratuitous ARP requests only for ethernet devices. */
  1412.                     arpwhohas ((struct arpcom*) ifp, &IA_SIN (data)->sin_addr);
  1413.                     break;
  1414.                 default:
  1415.                     break;
  1416.                 }
  1417.     break;
  1418.         case SIOCGMIB2CNFG:
  1419.     error = muxIoctl (pDrvCtrl->pIpCookie, EIOCGMIB2,
  1420.                               (caddr_t)&mib2Tbl);
  1421.             if (error != OK)
  1422.                 return (EINVAL);
  1423.             pm2DrvCnfg->ifType = mib2Tbl.ifType; /* ppp type */
  1424.             if (mib2Tbl.ifSpecific.idLength)
  1425.                 {
  1426.                 pm2DrvCnfg->ifSpecific.idLength = mib2Tbl.ifSpecific.idLength;
  1427.                 memcpy (&pm2DrvCnfg->ifSpecific.idArray[0],
  1428.                             &mib2Tbl.ifSpecific.idArray[0],
  1429.                             mib2Tbl.ifSpecific.idLength * sizeof (long));
  1430.                 }
  1431.             else
  1432.                 pm2DrvCnfg->ifSpecific.idLength = 0;
  1433.             break;
  1434.             
  1435.         case SIOCGMIB2CNTRS: /* fill in counters */
  1436.     error = muxIoctl (pDrvCtrl->pIpCookie, EIOCGMIB2,
  1437.                               (caddr_t)&mib2Tbl);
  1438.             if (error != OK)
  1439.                 return (EINVAL);
  1440.     pm2DrvCntr->ifSpeed = mib2Tbl.ifSpeed;
  1441.             pm2DrvCntr->ifInOctets = mib2Tbl.ifInOctets;
  1442.             pm2DrvCntr->ifInNUcastPkts = mib2Tbl.ifInNUcastPkts;
  1443.             pm2DrvCntr->ifInDiscards = mib2Tbl.ifInDiscards;
  1444.             pm2DrvCntr->ifInUnknownProtos = mib2Tbl.ifInUnknownProtos;
  1445.             pm2DrvCntr->ifOutOctets = mib2Tbl.ifOutOctets;
  1446.             pm2DrvCntr->ifOutNUcastPkts = mib2Tbl.ifOutNUcastPkts;
  1447.             pm2DrvCntr->ifOutDiscards = mib2Tbl.ifOutDiscards;
  1448.             break;
  1449.         case SIOCGMIB2233:
  1450.             error = muxIoctl (pDrvCtrl->pIpCookie, EIOCGMIB2233, data);
  1451.             if (error != OK)
  1452.                 return (EINVAL);
  1453.             break;
  1454.         case SIOCSMIB2233:
  1455.             error = muxIoctl (pDrvCtrl->pIpCookie, EIOCSMIB2233, data);
  1456.             if (error != OK)
  1457.                 return (EINVAL);
  1458.             break;
  1459.             
  1460.         case SIOCADDMULTI:
  1461.             /* Don't allow group membership on non-multicast
  1462.                interfaces. */
  1463.             if ((ifp->ac_if.if_flags & IFF_MULTICAST) == 0)
  1464.                 return EOPNOTSUPP;
  1465.             
  1466.             if (ifp->ac_if.if_resolve)
  1467.                 {
  1468.                 pDrvCtrl = (IP_DRV_CTRL*)ifp->ac_if.pCookie;
  1469.                 ifr = (struct ifreq *)data;
  1470.                 inetaddr = &ifr->ifr_addr;
  1471.                 pMblk = KHEAP_ALLOC(sizeof(M_BLK));
  1472.                 if (pMblk == NULL)
  1473.                     {
  1474.                     error = ENOBUFS;
  1475.                     break;
  1476.                     }
  1477.                 bzero ( (char *)pMblk, sizeof (M_BLK));
  1478.                 pMblk->mBlkHdr.mFlags |= M_MCAST;
  1479.                 /*
  1480.                  * call the registered address resolution function
  1481.                  * to do the mapping
  1482.                  */
  1483.                 if (ifp->ac_if.if_resolve (&ipMcastResume, pMblk, inetaddr,
  1484.                                            &ifp->ac_if, SIOCADDMULTI, &mapMCastBuff) == 0)
  1485.     {
  1486.     KHEAP_FREE( (char *)pMblk);
  1487.     break; /* not yet resolved */
  1488.     }
  1489.                 KHEAP_FREE( (char *)pMblk);
  1490.                 /* register the mapped multicast MAC address */
  1491.                 error = muxMCastAddrAdd (pDrvCtrl->pIpCookie,
  1492.                                          (char *)&mapMCastBuff);
  1493.                 }
  1494.             break;           /* if no resolve function, return OK */
  1495.         case SIOCDELMULTI:
  1496.             /* Don't allow group membership on non-multicast interfaces. */
  1497.             if ((ifp->ac_if.if_flags & IFF_MULTICAST) == 0)
  1498.                 return EOPNOTSUPP;
  1499.             
  1500.             if (ifp->ac_if.if_resolve)
  1501.                 {
  1502.                 pDrvCtrl = ifp->ac_if.pCookie;
  1503.                 ifr = (struct ifreq *)data;
  1504.                 inetaddr = (&ifr->ifr_addr);
  1505.                 
  1506.                 pMblk = KHEAP_ALLOC(sizeof (M_BLK));
  1507.                 if (pMblk == NULL)
  1508.                     {
  1509.                     error = ENOBUFS;
  1510.                     break;
  1511.                     }
  1512.                 bzero ( (char *)pMblk, sizeof (M_BLK));
  1513.                 pMblk->mBlkHdr.mFlags |= M_MCAST;
  1514.                 /*
  1515.                  * call the registered address resolution function to do
  1516.                  * the mapping
  1517.                  */
  1518.                 
  1519.                 if (ifp->ac_if.if_resolve (&ipMcastResume, pMblk, inetaddr,
  1520.                                      &ifp->ac_if, SIOCDELMULTI, &mapMCastBuff) == 0)
  1521.     {
  1522.     KHEAP_FREE( (char *)pMblk);
  1523.     break; /* not yet resolved */
  1524.     }
  1525. KHEAP_FREE( (char *)pMblk);
  1526.                 
  1527. /* delete the mapped multicast MAC address */
  1528.                 
  1529. error = muxMCastAddrDel (pDrvCtrl->pIpCookie,
  1530.                                          (char *)&mapMCastBuff);
  1531. }
  1532.             break;            /* if no resolve routine, return OK */
  1533.             
  1534. case SIOCGETMULTI:
  1535.     break;
  1536.             
  1537. case SIOCSIFFLAGS:
  1538.     ifr = (struct ifreq *) data;
  1539.     
  1540.     /* 
  1541.      * Turn off all flags that are disabled in the request 
  1542.      * correcting for the conversion from short to long 
  1543.      */
  1544.     
  1545.     flagsMask = (unsigned short) (~ ifr->ifr_flags);
  1546.     /* Two's complement used to disable flags by muxIoctl () */
  1547.     
  1548.     flagsMask = -flagsMask - 1;
  1549.     error = muxIoctl (pDrvCtrl->pIpCookie, EIOCSFLAGS,
  1550.                               (caddr_t) flagsMask);
  1551.     /* 
  1552.      * Next set all flags that are set in request correcting for 
  1553.      * the conversion from short to long. 
  1554.      */
  1555.     flagsMask = (unsigned short) ifr->ifr_flags;
  1556.     error |= muxIoctl (pDrvCtrl->pIpCookie, EIOCSFLAGS,
  1557.                                (caddr_t) flagsMask);
  1558.     break;
  1559.         case SIOCGMCASTLIST:
  1560.             error = muxIoctl (pDrvCtrl->pIpCookie, EIOCGMCASTLIST, data);
  1561.             if (error != OK)
  1562.                 return (EINVAL);
  1563.             break;
  1564. default:
  1565.     error = muxIoctl (pDrvCtrl->pIpCookie, cmd, data);
  1566.     break;
  1567. }
  1568.     return (error);
  1569.     }
  1570. /******************************************************************************
  1571. *
  1572. * ipOutput - transmit routine for IP packets using END or NPT devices.
  1573. *
  1574. * This routine handles the final processing before transferring a
  1575. * network packet (contained in the <m0> argument) to the transmit
  1576. * device.
  1577. *
  1578. * For END devices, it encapsulates a packet in the link-level frame
  1579. * before transferring it to the driver. The output processing constructs
  1580. * Ethernet frames unless the device provides a custom routine to form the
  1581. * appropriate frame header.
  1582. *
  1583. * For NPT devices, the routine just inserts the destination link-level
  1584. * address at the front of the mBlk chain. Later processing hands that
  1585. * address to the driver along with an mBlk chain containing the network
  1586. * packet (with no link-level header).
  1587. *
  1588. * NOTE: It assumes that ifp is actually a pointer to an arpcom structure.
  1589. *
  1590. * NOMANUAL
  1591. */
  1592. int ipOutput
  1593.     (
  1594.     register struct ifnet *ifp,
  1595.     struct mbuf *m0,
  1596.     struct sockaddr *dst,
  1597.     struct rtentry *rt0
  1598.     )
  1599.     {
  1600.     u_short etype = 0;
  1601.     int s, error = 0;
  1602.     register struct mbuf *m = m0;
  1603.     register struct rtentry *rt;
  1604.     int off;
  1605.     struct arpcom *ac = (struct arpcom *)ifp;
  1606.     struct ether_header* eh;
  1607.     IP_DRV_CTRL* pDrvCtrl;
  1608. #ifdef ROUTER_STACK
  1609.     struct ip* pIpHdr;
  1610.     END_OBJ* pEnd;
  1611.     struct sockaddr_in* pNetMask;
  1612. #endif  /* ROUTER_STACK */
  1613.  
  1614.     pDrvCtrl = (IP_DRV_CTRL *)ifp->pCookie;
  1615.     if (pDrvCtrl->pIpCookie == NULL)
  1616.         senderr (EINVAL);
  1617.     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  1618.         {
  1619. #ifdef WV_INSTRUMENTATION
  1620. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1621.         WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 2, 3, 
  1622.                         WV_NETEVENT_ETHEROUT_IFDOWN, WV_NET_SEND, ifp)
  1623. #endif  /* INCLUDE_WVNET */
  1624. #endif
  1625.         senderr(ENETDOWN);
  1626.         }
  1627.     ifp->if_lastchange = tickGet();
  1628.     if ((rt = rt0))
  1629.         {
  1630.         if ((rt->rt_flags & RTF_UP) == 0)
  1631.             {
  1632.             if ((rt0 = rt = rtalloc1(dst, 1)))
  1633.                 rt->rt_refcnt--;
  1634.             else
  1635.                 {
  1636. #ifdef WV_INSTRUMENTATION
  1637. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1638.                 WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 4, 5, 
  1639.                                 WV_NETEVENT_ETHEROUT_NOROUTE, WV_NET_SEND,
  1640.                                 ((struct sockaddr_in *)dst)->sin_addr.s_addr)
  1641. #endif  /* INCLUDE_WVNET */
  1642. #endif
  1643.                 senderr(EHOSTUNREACH);
  1644.                 }
  1645.             }
  1646.         if (rt->rt_flags & RTF_GATEWAY)
  1647.             {
  1648.             if (rt->rt_gwroute == 0)
  1649.                 goto lookup;
  1650.             if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0)
  1651.                 {
  1652.                 rtfree(rt); rt = rt0;
  1653.                 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
  1654.                 if ((rt = rt->rt_gwroute) == 0)
  1655.                     {
  1656. #ifdef WV_INSTRUMENTATION
  1657. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1658.                     WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 4, 5, 
  1659.                                     WV_NETEVENT_ETHEROUT_NOROUTE, WV_NET_SEND,
  1660.                      ((struct sockaddr_in *)rt->rt_gateway)->sin_addr.s_addr)
  1661. #endif  /* INCLUDE_WVNET */
  1662. #endif
  1663.                     senderr(EHOSTUNREACH);
  1664.                     }
  1665.                 }
  1666.             }
  1667.         if (rt->rt_flags & RTF_REJECT)
  1668.             {
  1669.             if (rt->rt_rmx.rmx_expire == 0 ||
  1670.                 tickGet() < rt->rt_rmx.rmx_expire)
  1671.                 {
  1672. #ifdef WV_INSTRUMENTATION
  1673. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1674.                 WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_CRITICAL, 5, 6, 
  1675.                                 WV_NETEVENT_ETHEROUT_RTREJECT, WV_NET_SEND)
  1676. #endif  /* INCLUDE_WVNET */
  1677. #endif
  1678.                 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
  1679.                 }
  1680.             }
  1681.         } /* if (rt = rt0) */
  1682.     switch (dst->sa_family)
  1683.         {
  1684.         case AF_INET:
  1685.             if (ifp->if_resolve != NULL)
  1686.                 if (!ifp->if_resolve (&ipOutputResume, m, dst, ifp, rt,
  1687.                                       pDrvCtrl->pDstAddr))
  1688.                     return (0); /* if not yet resolved */
  1689. #ifdef ROUTER_STACK
  1690.             if ((m->m_flags & M_FORWARD)) 
  1691.                 {
  1692.                 /*
  1693.                  * If we are forwarding this packet, and Fastpath is
  1694.                  * enabled both at the module and interface level,
  1695.                  * supply the Fastpath module with the additional
  1696.                  * forwarding information (the MAC address etc.)
  1697.                  */
  1698.                 if (SHOULD_MAKE_CALLS_TO_FF (GET_IPV4_FF_ID) && 
  1699.                     FF_MOD_ENABLED (GET_IPV4_FF_ID) &&
  1700.                     FF_INTF_ENABLED (GET_IPV4_FF_ID, ifp))
  1701.                     {
  1702.                     pEnd = PCOOKIE_TO_ENDOBJ(pDrvCtrl->pIpCookie);
  1703.                     pIpHdr= mtod(m, struct ip *);
  1704.                     pNetMask=(struct sockaddr_in*)(rt_mask(rt0));
  1705. #ifdef DEBUG
  1706.                     logMsg ("ipOutput: dst IP addr %xn", pIpHdr->ip_dst.s_addr,
  1707.                             0, 0, 0, 0, 0);
  1708.                     logMsg ("ipOutput: rt0 is %x. rt is %x.n", rt0, rt,
  1709.                             0, 0, 0, 0);
  1710. #endif /* DEBUG */
  1711.                     /*
  1712.                      * if indirect route pass the 'key' of the
  1713.                      * routing entry as the destination IP address.
  1714.                      * If not pass the host
  1715.                      * IP address as the destination IP address.
  1716.                      */
  1717.                     if (rt0->rt_flags & RTF_GATEWAY)
  1718.                         {
  1719.                         if (rt0->rt_flags & RTF_CLONED) 
  1720.                             rt0 = rt0->rt_parent;
  1721.                         if (rt0) 
  1722.                             FFL_CALL (ffLibRouteMoreInfo, 
  1723.                                       (GET_IPV4_FF_ID, rt_key(rt0), 
  1724.                                        rt_mask(rt0), rt0->rt_gateway, 
  1725.                                        pDrvCtrl->pDstAddr, ifp->if_addrlen, 
  1726.                                        rt0->rt_flags, ifp->if_mtu, 
  1727.                                        ifp->if_index, ifp));
  1728.                         }
  1729.                     else 
  1730.                         {
  1731.                         FFL_CALL (ffLibRouteMoreInfo, 
  1732.                                   (GET_IPV4_FF_ID, dst, 
  1733.                                    0, dst, 
  1734.                                    pDrvCtrl->pDstAddr, ifp->if_addrlen, 
  1735.                                    rt0->rt_flags, ifp->if_mtu, 
  1736.                                    ifp->if_index, ifp));
  1737.                         }
  1738.                     }
  1739.                 }
  1740. #endif /* ROUTER_STACK */
  1741.             /* If broadcasting on a simplex interface, loopback a copy */
  1742.             if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
  1743. !(m->m_flags & M_PROXY))
  1744.                 ip_mloopback (ifp, m, (struct sockaddr_in *)dst,
  1745.                               (struct rtentry*)rt);
  1746.             off = m->m_pkthdr.len - m->m_len;
  1747.             etype = ETHERTYPE_IP;
  1748.             break;
  1749.         case AF_UNSPEC:
  1750.             /*
  1751.              * WARNING: At the moment this code ONLY handles 14 byte
  1752.              * headers of the type like Ethernet.
  1753.              */
  1754.             switch (ifp->if_type)
  1755.                 {
  1756.                 case M2_ifType_ethernet_csmacd:
  1757.                 case M2_ifType_iso88023_csmacd:
  1758.                 case M2_ifType_iso88024_tokenBus:
  1759.                 case M2_ifType_iso88025_tokenRing:
  1760.                 case M2_ifType_iso88026_man:
  1761.                 case M2_ifType_fddi:
  1762.                     eh = (struct ether_header *)dst->sa_data;
  1763.     bcopy((caddr_t)eh->ether_dhost, 
  1764.           (caddr_t)pDrvCtrl->pDstAddr, ifp->if_addrlen);
  1765.                     etype = eh->ether_type;
  1766.                     break;
  1767.                 default:
  1768.                     error=ERROR;
  1769. }
  1770.              
  1771.              if(!error)
  1772.                  break;
  1773.              /* fall-through */
  1774.         default:
  1775.             logMsg ("%s%d: can't handle af%dn", (int)ifp->if_name,
  1776.                     ifp->if_unit, dst->sa_family, 0, 0, 0);
  1777. #ifdef WV_INSTRUMENTATION
  1778. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  1779.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_ERROR, 3, 7, 
  1780.                             WV_NETEVENT_ETHEROUT_AFNOTSUPP, WV_NET_SEND,
  1781.                             dst->sa_family)
  1782. #endif  /* INCLUDE_WVNET */
  1783. #endif
  1784.             senderr(EAFNOSUPPORT);
  1785.         }
  1786.     
  1787.     etype = htons(etype);
  1788.     if (pDrvCtrl->nptFlag)
  1789.         {
  1790.         /*
  1791.          * For NPT devices, insert the destination address (if any) and
  1792.          * network protocol type at the beginning of the network packet
  1793.          * for later use.
  1794.          */
  1795.         if (ifp->if_addrlen)
  1796.             {
  1797.             M_PREPEND(m, ifp->if_addrlen, M_DONTWAIT);
  1798.             if (m == NULL)
  1799.                 {
  1800.                 senderr(ENOBUFS);
  1801.                 }
  1802.             ((M_BLK_ID)m)->mBlkPktHdr.rcvif = 0;
  1803.             /* Store the destination address. */
  1804.             bcopy (pDrvCtrl->pDstAddr, m->m_data, ifp->if_addrlen);
  1805.             }
  1806.     
  1807.         /* Save the network protocol type. */
  1808.         ((M_BLK_ID)m)->mBlkHdr.reserved = etype;
  1809.         }
  1810.     else
  1811.         {
  1812.         /*
  1813.          * For END devices, build and prepend the complete frame instead.
  1814.          * NOTE: currently, the ac_enaddr field is only valid for specific
  1815.          * device types. (See the ipAttach routine).
  1816.          */
  1817.         pDrvCtrl->pSrc->m_data = (char *)&ac->ac_enaddr;
  1818.         pDrvCtrl->pDst->mBlkHdr.reserved = etype;
  1819.         pDrvCtrl->pSrc->mBlkHdr.reserved = etype;
  1820.         m = muxAddressForm (pDrvCtrl->pIpCookie, m,
  1821.                             pDrvCtrl->pSrc, pDrvCtrl->pDst);
  1822.         if (m == NULL)
  1823.             {
  1824. #ifdef WV_INSTRUMENTATION
  1825. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1826.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 3, 4, 
  1827.                             WV_NETEVENT_ETHEROUT_NOBUFS, WV_NET_SEND, ifp)
  1828. #endif  /* INCLUDE_WVNET */
  1829. #endif
  1830.             senderr(ENOBUFS);
  1831.             }
  1832.         }
  1833.     s = splimp();
  1834.     /*
  1835.      * Queue message on interface, and start output if interface
  1836.      * not yet active.
  1837.      */
  1838.     if (IF_QFULL(&ifp->if_snd))
  1839.         {
  1840.         IF_DROP(&ifp->if_snd);
  1841.         splx(s);
  1842. #ifdef WV_INSTRUMENTATION
  1843. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1844.         WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 3, 4, 
  1845.                         WV_NETEVENT_ETHEROUT_NOBUFS, WV_NET_SEND, ifp)
  1846. #endif  /* INCLUDE_WVNET */
  1847. #endif
  1848.         senderr(ENOBUFS);
  1849.         }
  1850.     IF_ENQUEUE(&ifp->if_snd, m);
  1851.     (*ifp->if_start)(ifp);
  1852.     splx(s);
  1853.     ifp->if_obytes += m->mBlkHdr.mLen;
  1854.     if (m->m_flags & M_MCAST || m->m_flags & M_BCAST)
  1855.         ifp->if_omcasts++;
  1856. #ifdef WV_INSTRUMENTATION
  1857. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  1858.     WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_NOTICE, 3, 12, 
  1859.                     WV_NETEVENT_ETHEROUT_FINISH, WV_NET_SEND, ifp, error)
  1860. #endif  /* INCLUDE_WVNET */
  1861. #endif
  1862.     return (error);
  1863.     
  1864.     bad:
  1865.     if (m)
  1866.         netMblkClChainFree(m);
  1867.     return (error);
  1868.     }
  1869. /*******************************************************************************
  1870. *
  1871. * ipOutputResume - transmit routine called after delayed address resolution
  1872. *
  1873. * When sending an IP packet, all address resolution functions responsible
  1874. * for converting an IP address to a link-layer address receive a pointer to
  1875. * this routine as their first argument. If a resolution routine is unable to
  1876. * supply the required link-level address immediately from a cache, it may 
  1877. * calls this routine after finishing the necessary network transactions (such
  1878. * as an ARP request and reply) to resume the transmit process.
  1879. *
  1880. * RETURNS: results of ipOutput() routine.
  1881. *
  1882. * INTERNAL
  1883. * This callback routine is actually never used. The ipOutput() routine is
  1884. * already capable of resuming the transmit process. The arpresolve() routine
  1885. * (which is the default resolution routine for this library) calls ipOutput
  1886. * directly. This callback routine is only included to comply with the existing
  1887. * NPT interface. The prototype for resolution routines should be changed to
  1888. * eliminate the callback method.
  1889. *
  1890. * NOMANUAL
  1891. */
  1892. int ipOutputResume
  1893.      (
  1894.      struct mbuf* pMBuf,
  1895.      struct sockaddr* ipDstAddr,
  1896.      void* ifp,
  1897.      void* rt
  1898.      )
  1899.      {
  1900.      return (
  1901.          ipOutput ( (struct ifnet*)ifp,
  1902.                    pMBuf, ipDstAddr, (struct rtentry*)rt)
  1903.             );
  1904.      }
  1905.  
  1906. /*******************************************************************************
  1907. *
  1908. * ipMcastResume - internal routine called after delayed mcast address mapping
  1909. *
  1910. * All IP multicast addresses also correspond to a particular link-level
  1911. * address.  The registered address resolution routine is responsible for
  1912. * performing that mapping.
  1913. *
  1914. * All address resolution routines receive a pointer to this routine as their
  1915. * first argument when determining a link-level multicast address. If the
  1916. * resolution routine is unable to determine the link-level address immediately,
  1917. * it calls this routine once the address is available.
  1918. *
  1919. * INTERNAL
  1920. * This callback routine is actually never used, which is fortunate since the
  1921. * <rt> parameter is not valid for the ipIoctl routine it executes.
  1922. * The multicast conversions for Ethernet addresses are statically mapped, so
  1923. * they are always available immediately and the arpresolve() routine (which
  1924. * is the default resolution routine for this library) does not require the
  1925. * callback argument. This callback routine is only included to comply with
  1926. * the existing NPT interface. The prototype for resolution routines should
  1927. * be changed to eliminate the callback method.
  1928. *
  1929. * RETURNS: results of ipIoctl routine
  1930. *
  1931. * NOMANUAL
  1932. */
  1933. LOCAL int ipMcastResume
  1934.     (
  1935.     struct mbuf* pMbuf,
  1936.     struct sockaddr* ipDstAddr,
  1937.     void* pIfp,
  1938.     void* rt
  1939.     )
  1940.     {
  1941.     struct ifreq ifr;
  1942.     bcopy(ipDstAddr->sa_data, ifr.ifr_addr.sa_data, ipDstAddr->sa_len);
  1943.     ifr.ifr_addr.sa_family=ipDstAddr->sa_family;
  1944.     return(ipIoctl ((IDR *) pIfp, (int) rt, (caddr_t) &ifr));
  1945.     }
  1946. /****************************************************************************
  1947. *
  1948. * ipMuxCookieGet - Given an interface index returns the MUX cookie
  1949. *
  1950. * This routine returns the MUX cookie associated with an interface described
  1951. * by the <ifIndex> parameter. <ifIndex> is the interface index.
  1952. * This routine is called by the Fastpath module to retrieve the MUX cookie
  1953. * needed for sending packets out if Fastpath is done in software.
  1954. *
  1955. * <ifIndex> specifies the interface index whose MUX cookie is being
  1956. * retrieved.
  1957. *
  1958. * RETURNS: The MUX cookie if the interface exists and is bound; NULL otherwise
  1959. *
  1960. * NOMANUAL
  1961. */
  1962. void * ipMuxCookieGet 
  1963.     (
  1964.     unsigned short  ifIndex /* Interface index whose MUX cookie */
  1965.      /* is being retrieved */
  1966.     )
  1967.     {
  1968.     FAST struct ifnet * ifp;
  1969.     if ((ifp = ifIndexToIfp (ifIndex)) == NULL)
  1970.         return (NULL);
  1971.     return (((IP_DRV_CTRL *)ifp->pCookie)->pIpCookie);
  1972.     }