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

VxWorks

开发平台:

C/C++

  1. /* wdbEndPktDrv.c - END based packet driver for lightweight UDP/IP */
  2. /* Copyright 1996-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 02c,10apr02,wap  Set the M_PKTHDR flag for mBlks which do in fact contain
  7.                  packet headers. (SPR #73331)
  8. 02b,30oct01,jhw  Copied version TOR3_1-RC-1. Fixed ARPOP_REPLY.
  9. 02a,11sep00,elg  Update documentation.
  10. 01z,20jul00,dbt  Fixed some error cases where mBlk were incorrectly freed.
  11. 01y,14jun00,dbt  Fixed problem with Little Endian targets.
  12. 01x,12jun00,ham  removed reference to etherLib.
  13. 01w,31may00,dbt  Modified wdbEndInt() to test if a packet is fragmented (SPR
  14.                  #30194).
  15. 01v,19apr00,ham  merged TOR2_0-NPT-FCS(01s,05mar99,sj-01u,20sep99,sj).
  16. 01t,13apr00,dbt  Adapted to new MUX layer.
  17. 01u,20sep99,sj   htons(ETHERTYPE_IP)
  18. 01t,29apr99,pul  Upgraded NPT phase3 code to tor2.0.0
  19. 01s,05mar99,sj   added support for NPT drivers
  20. 01s,02aug99,dbt  added support for standalone agent.
  21.  Added support for ARP requests (SPR #25685).
  22.  Added IP address verification (SPR #27815).
  23. 01r,02mar99,dbt  correctly initialize mBlkPktHdr.len field in send routine
  24.                  (SPR #25330).
  25. 01q,11dec97,vin  optimized some code and additional fixes to SPR9563.
  26. 01p,08dec97,gnn  fixed spr#9563 to get MBLK chains.
  27. 01o,25nov97,gnn  fixed spr#9620 polled mode receive
  28. 01n,19oct97,vin  fixed wdbEndInt, wdbEndPoll(), cleanup.
  29. 01m,17oct97,vin  changed wdbEndInt for muxPacketDataGet fixes.
  30. 01l,09oct97,vin  fixed wdbEndInt various error conditions, added htons
  31. 01k,03oct97,gnn  adjusted muxBind call to be in line with new prototype
  32. 01j,25sep97,gnn  SENS beta feedback fixes
  33. 01i,25aug97,gnn  fixed remaining polled mode problems.
  34. 01h,22aug97,gnn  changes due to new buffering scheme.
  35. 01g,12aug97,gnn  changes necessitated by MUX/END update.
  36. 01f,08apr97,map  Free mbuf cluster in wdbEndTx() when output is busy.
  37. 01e,21jan97,gnn  Added code to handle new addressles sending.
  38.                  Changed the way that transmit is done and free'd.
  39. 01d,22oct96,gnn  Name changes to follow the coding standards.
  40. 01c,22oct96,gnn  Removed netVectors and replaced with netBuffers.
  41.                  Replaced the 0 for promiscous protocol with a constant
  42.                  MUX_PROTO_PROMISC.
  43. 01b,23sep96,gnn  Added new buffering scheme information.
  44. 01a,1jul96,gnn   written.
  45. */
  46. /*
  47. DESCRIPTION
  48. This is an END based driver for the WDB system.  It uses the MUX and END
  49. based drivers to allow for interaction between the target and target
  50. server.
  51. USAGE
  52. The driver is typically only called only from the configlette wdbEnd.c.
  53. The only directly callable routine in this module is wdbEndPktDevInit().
  54. To use this driver, just select the component INCLUDE_WDB_COMM_END in the
  55. folder SELECT_WDB_COMM_TYPE. This is the default selection.
  56. To modify the MTU, change the value of parameter WDB_END_MTU in component
  57. INCLUDE_WDB_COMM_END.
  58. DATA BUFFERING
  59. The drivers only need to handle one input packet at a time because
  60. the WDB protocol only supports one outstanding host-request at a time.
  61. If multiple input packets arrive, the driver can simply drop them.
  62. The driver then loans the input buffer to the WDB agent, and the agent
  63. invokes a driver callback when it is done with the buffer.
  64. For output, the agent will pass the driver a chain of mbufs, which
  65. the driver must send as a packet. When it is done with the mbufs,
  66. it calls wdbMbufChainFree() to free them.
  67. The header file wdbMbufLib.h provides the calls for allocating, freeing,
  68. and initializing mbufs for use with the lightweight UDP/IP interpreter.
  69. It ultimately makes calls to the routines wdbMbufAlloc and wdbMbufFree, which
  70. are provided in source code in the configlette usrWdbCore.c.
  71. INCLUDE FILES: drv/wdb/wdbEndPktDrv.h
  72. */
  73. /* includes */
  74. #include "string.h"
  75. #include "stdio.h"
  76. #include "errno.h"
  77. #include "sioLib.h"
  78. #include "intLib.h"
  79. #include "logLib.h"
  80. #include "end.h"
  81. #include "muxLib.h"
  82. #include "muxTkLib.h"
  83. #include "endLib.h"
  84. #include "private/muxLibP.h"
  85. #include "stdlib.h"
  86. #include "wdb/wdbMbufLib.h"
  87. #include "drv/wdb/wdbEndPktDrv.h"
  88. #include "net/if.h"
  89. #include "net/if_llc.h"
  90. #include "netinet/ip.h"
  91. #include "netinet/udp.h"
  92. #include "netinet/if_ether.h"
  93. #include "inetLib.h"
  94. /* defines */
  95. #define IP_HDR_SIZE 20
  96. #define WDB_NPT_CAPABLE
  97. /* globals */
  98. WDB_END_PKT_DEV * pEndPktDev;
  99. int wdbEndDebug = 0;
  100. char *pInPkt;
  101. /* pseudo-macros */
  102. #define DRIVER_INIT_HARDWARE(pDev) {}
  103. #define DRIVER_MODE_SET(pDev, mode)
  104. #define DRIVER_PACKET_IS_READY(pDev) FALSE
  105. #define DRIVER_RESET_INPUT(pDev) {pDev->inputBusy=FALSE;}
  106. #define DRIVER_RESET_OUTPUT(pDev) {pDev->outputBusy=FALSE;}
  107. #define DRIVER_GET_INPUT_PACKET(pDev, pBuf) (50)
  108. #define DRIVER_DATA_FROM_MBUFS(pDev, pBuf) {}
  109. #define DRIVER_POLL_TX(pDev, pBuf) {}
  110. #define DRIVER_TX_START(pDev) {}
  111. /* forward declarations */
  112. LOCAL STATUS wdbEndPoll (void *pDev);
  113. LOCAL STATUS wdbEndTx   (void *pDev, struct mbuf * pMbuf);
  114. LOCAL STATUS wdbEndModeSet (void *pDev, uint_t newMode);
  115. LOCAL void wdbEndInputFree (void *pDev);
  116. LOCAL void wdbEndOutputFree (void *pDev);
  117. LOCAL M_BLK_ID wdbEndMblkClGet (END_OBJ * pEnd, int size);
  118. LOCAL int wdbEndInt (void* pCookie, long type, M_BLK_ID pMblk, 
  119. LL_HDR_INFO *, void * pNull);
  120. LOCAL BOOL wdbEndPollArpReply (struct mbuf * pMblk, void * pCookie);
  121. #ifdef WDB_NPT_CAPABLE
  122. int wdbNptInt ( void *, long type, M_BLK_ID pMblk, void *);
  123. void wdbNptShutdown ( void * callbackId );
  124. #endif WDB_NPT_CAPABLE
  125. /******************************************************************************
  126. *
  127. * wdbEndPktDevInit - initialize an END packet device
  128. *
  129. * This routine initializes an END packet device. It is typically called
  130. * from configlette wdbEnd.c when the WDB agent's lightweight END
  131. * communication path (INCLUDE_WDB_COMM_END) is selected.
  132. *
  133. * RETURNS: OK or ERROR
  134. */
  135. STATUS wdbEndPktDevInit
  136.     (
  137.     WDB_END_PKT_DEV * pPktDev, /* device structure to init */
  138.     void (*stackRcv) (), /* receive packet callback (udpRcv) */
  139.     char * pDevice, /* Device (ln, ie, etc.) that we */
  140.      /* wish to bind to. */
  141.     int          unit            /* unit number (0, 1, etc.) */
  142.     )
  143.     {
  144.     END_OBJ * pEnd;
  145.     char ifname [20];
  146.     char inetAdrs [24];
  147.     /* initialize the wdbDrvIf field with driver info */
  148.     pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_POLL| WDB_COMM_MODE_INT;
  149.     pPktDev->wdbDrvIf.mtu = WDB_END_PKT_MTU;
  150.     pPktDev->wdbDrvIf.stackRcv = stackRcv; /* udpRcv */
  151.     pPktDev->wdbDrvIf.devId = (WDB_END_PKT_DEV *)pPktDev;
  152.     pPktDev->wdbDrvIf.pollRtn = wdbEndPoll;
  153.     pPktDev->wdbDrvIf.pktTxRtn = wdbEndTx;
  154.     pPktDev->wdbDrvIf.modeSetRtn = wdbEndModeSet;
  155.     /* initialize the device specific fields in the driver structure */
  156.     pPktDev->inputBusy = FALSE;
  157.     pPktDev->outputBusy = FALSE;
  158. #ifndef STANDALONE_AGENT
  159.     /*
  160.      * Here is where we bind to the lower layer.
  161.      * We do not, as yet, provide for a shutdown routine, but perhaps
  162.      * later.
  163.      * We are a promiscous protocol.
  164.      * The Int routine a fakeout.  Interrupts are handled by the lower
  165.      * layer but we use a similar mechanism to check packets for 
  166.      * the proper type and hand them off to the WDB agent from
  167.      * the "interrupt" routine if it's appropriate to do so.
  168.      */
  169. #ifdef WDB_NPT_CAPABLE
  170.     if (muxTkDrvCheck (pDevice) == TRUE)
  171. {
  172. if ((pPktDev->pCookie = muxTkBind (pDevice, unit, wdbNptInt,
  173.    (FUNCPTR)wdbNptShutdown,
  174.                                            NULL, NULL, MUX_PROTO_SNARF,
  175.    "Wind Debug Agent",
  176.    NULL, NULL, NULL)) == NULL)
  177.     {
  178.     if (wdbEndDebug)
  179. logMsg ("Could not bind to NPT Device %s, loading...n",
  180. (int)pDevice, 2, 3, 4, 5, 6);
  181.     return (ERROR);
  182.     }
  183. }
  184.     else  /* END */
  185. {
  186. if (wdbEndDebug)
  187.     logMsg ("Not a NPT device! %sn", (int)pDevice,2,3,4,5,6);
  188. #endif /* WDB_NPT_CAPABLE */
  189. if ((pPktDev->pCookie = muxBind (pDevice, unit, wdbEndInt, NULL,
  190.  NULL, NULL, MUX_PROTO_SNARF,
  191.    "Wind Debug Agent", NULL)) == NULL)
  192.     {
  193.     if (wdbEndDebug)
  194. logMsg ("Could not bind to %s, loading...n",
  195. (int)pDevice, 2, 3, 4, 5, 6);
  196.     return (ERROR);
  197.     }
  198. #ifdef WDB_NPT_CAPABLE
  199. }
  200. #endif /* WDB_NPT_CAPABLE */
  201.     pEnd = PCOOKIE_TO_ENDOBJ(pPktDev->pCookie);
  202. #else /* STANDALONE_AGENT */
  203.     /*
  204.      * for standalone agent, we simply need to get the address of the 
  205.      * of the device.
  206.      */
  207.      if ((pPktDev->pCookie = endFindByName (pDevice, unit)) == NULL)
  208. return (ERROR); 
  209. #endif /* STANDALONE_AGENT */
  210.     /* build interface name */
  211.     sprintf (ifname, "%s%d", pDevice, unit);
  212.     /* get interface inet address */
  213.     if (ifAddrGet (ifname, inetAdrs) != OK)
  214.      {
  215. if (wdbEndDebug)
  216.     logMsg ("Could not get inet address of %s interface...n",
  217.      (int) ifname, 2, 3, 4, 5, 6);
  218. return (ERROR);
  219. }
  220.     pPktDev->ipAddr.s_addr = inet_addr (inetAdrs);
  221.     pEnd = PCOOKIE_TO_ENDOBJ(pPktDev->pCookie);
  222.     if ((pInPkt = memalign (4,pEnd->mib2Tbl.ifMtu)) == NULL)
  223.         return (ERROR);
  224.    
  225.     if ((pPktDev->pInBlk = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu))
  226.         == NULL)
  227. return (ERROR);
  228.     pPktDev->pInBlk->mBlkHdr.mFlags |= M_PKTHDR;
  229.     if ((pPktDev->pOutBlk = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu))
  230.         == NULL)
  231. return (ERROR);
  232.     pPktDev->pOutBlk->mBlkHdr.mFlags |= M_PKTHDR;
  233.     if ((pPktDev->lastHAddr = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu))
  234.         == NULL)
  235. return (ERROR);
  236.     if ((pPktDev->srcAddr = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu))
  237.         == NULL)
  238. return (ERROR);
  239.     /* Set the length to the size of the buffer just allocated. */
  240.     pPktDev->pInBlk->mBlkHdr.mLen = pPktDev->pInBlk->pClBlk->clSize;
  241.     pPktDev->lastHAddr->mBlkHdr.mLen = pEnd->mib2Tbl.ifPhysAddress.addrLength;
  242.     memset (pPktDev->lastHAddr->mBlkHdr.mData, 0xff,
  243.             pPktDev->lastHAddr->mBlkHdr.mLen);
  244.     /*
  245.      * Create a source address structure so we can send fully
  246.      * qualified packets.
  247.      */
  248.      
  249.     muxIoctl (pPktDev->pCookie, EIOCGADDR, pPktDev->srcAddr->mBlkHdr.mData);
  250.     
  251.     pEndPktDev = pPktDev;
  252.     return (OK);
  253.     }
  254. /******************************************************************************
  255. *
  256. * wdbEndInt - END driver interrupt handler
  257. *
  258. * This is really a MUX receive routine but we let it look like
  259. * an interrupt handler to make this interface look as much like the
  260. * template as possible.
  261. *
  262. * RETURNS: TRUE if the packet was for us, FALSE otherwise.
  263. *
  264. * NOMANUAL
  265. */
  266. int wdbEndInt
  267.     (
  268.     void *  pCookie,
  269.     long  type, 
  270.     M_BLK_ID  pMblk,
  271.     LL_HDR_INFO *  pLinkHdrInfo, 
  272.     void *  pMode
  273.     )
  274.     {
  275.     struct mbuf *  pMbuf;
  276.     int size;
  277.     struct udphdr *  pUdpHdr;
  278.     struct ip * pIpHdr;
  279.     WDB_END_PKT_DEV *  pPktDev = pEndPktDev;
  280.     /* input buffer already in use - drop this packet */
  281.     if (wdbEndDebug)
  282. logMsg ("Got a packet!n", 1, 2, 3, 4, 5, 6);
  283.     if (pPktDev->inputBusy)
  284. {
  285.         if (wdbEndDebug)
  286.     logMsg ("Input busy!n", 1, 2, 3, 4, 5, 6);
  287. /*
  288.  * free the packet only if the driver is in polling mode. If not, the
  289.  * packet will be freed by the MUX layer.
  290.  */
  291. if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL))
  292.      netMblkClFree (pMblk);
  293. return (FALSE);
  294. }
  295.     pPktDev->inputBusy = TRUE;
  296.     /* Check the type before doing anything expensive. */
  297.     if ((type == 0x806) && (pMode != NULL) &&
  298.      (*((int *)pMode) == WDB_COMM_MODE_POLL))
  299.      {
  300. /*
  301.  * In polling mode we need to answer ARP request so that
  302.  * communication becomes or remains possible.
  303.  */
  304.         if (wdbEndDebug)
  305.             logMsg ("Type == 0x806n", 1, 2, 3, 4, 5, 6);
  306. return (wdbEndPollArpReply (pMblk, pCookie));
  307. }
  308.     if (type != 0x800)
  309.         {
  310.         if (wdbEndDebug)
  311.             logMsg ("Type != 0x800 && Type!= 0x806n", 1, 2, 3, 4, 5, 6);
  312.         goto wdbEndIntError;
  313.         }
  314.     size = pLinkHdrInfo->dataOffset + IP_HDR_SIZE + sizeof(struct udphdr);
  315.     if (!(pMblk->mBlkHdr.mFlags & M_PKTHDR) || (pMblk->mBlkPktHdr.len <
  316.                                                 size))
  317.         {
  318.         goto wdbEndIntError; 
  319.         }
  320.     if (pMblk->mBlkHdr.mLen < size)
  321.         {
  322.         if (netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset, pInPkt,
  323.                                     size, NULL) == 0)
  324.             goto wdbEndIntError;
  325. pIpHdr = (struct ip *) pInPkt;
  326.         pUdpHdr = (struct udphdr *)(pInPkt + IP_HDR_SIZE);
  327.         }
  328.     else
  329.         {
  330. pIpHdr = (struct ip *) (pMblk->mBlkHdr.mData +
  331. pLinkHdrInfo->dataOffset);
  332.         pUdpHdr = (struct udphdr *)(pMblk->mBlkHdr.mData +
  333.                                     pLinkHdrInfo->dataOffset +
  334.                                     IP_HDR_SIZE);
  335.         }
  336.     /* If this packet is not for the agent, ignore it */
  337.     if ((pIpHdr->ip_p != IPPROTO_UDP) ||
  338. (pUdpHdr->uh_dport != htons(WDBPORT)))
  339.         goto wdbEndIntError;
  340.     if (pPktDev->ipAddr.s_addr != pIpHdr->ip_dst.s_addr)
  341.      goto wdbEndIntError;
  342.     /*
  343.      * Check to see whether the packet is fragmented.  WDB does not
  344.      * handle fragmented packets.
  345.      */
  346.     if (pIpHdr->ip_off & htons(IP_MF|IP_OFFMASK))
  347.      {
  348. if (wdbEndDebug)
  349.     logMsg ("Fragmented packetn", 0, 0, 0, 0, 0, 0);
  350. goto wdbEndIntError;
  351. }
  352.     if ((size = netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset,
  353.                                         pInPkt, M_COPYALL, NULL)) == 0)
  354.         goto wdbEndIntError;
  355.     
  356.     bcopy ((char *)pMblk->mBlkHdr.mData + pLinkHdrInfo->srcAddrOffset,
  357.           (char *)pPktDev->lastHAddr->mBlkHdr.mData, 
  358.           pLinkHdrInfo->srcSize);
  359.     /* We're always going to send an IP packet. */
  360.     pPktDev->lastHAddr->mBlkHdr.reserved = htons (0x800);
  361.     
  362.     /*
  363.      * Fill the input buffer with the packet. Use an mbuf cluster 
  364.      * to pass the packet on to the agent.
  365.      */
  366.     
  367.     pMbuf = wdbMbufAlloc ();
  368.     if (pMbuf == NULL)
  369.         goto wdbEndIntError;
  370.     wdbMbufClusterInit (pMbuf, pInPkt, size, (int (*)())wdbEndInputFree,
  371.                         (int)pPktDev);
  372.     if (wdbEndDebug)
  373.         logMsg ("Passing up a packet!n", 1, 2, 3, 4, 5, 6);
  374.     (*pPktDev->wdbDrvIf.stackRcv) (pMbuf);  /* invoke callback */
  375.     netMblkClFree (pMblk);
  376.     return (TRUE); 
  377.     wdbEndIntError:
  378.      {
  379.          /*
  380.           * drop all non wdb packets received through the poll routine
  381.           * When call from muxReceive pMode is actually the spare pointer
  382.           * which is initialized in the NET_PROTOCOL structure, the spare
  383.           * pointer is passed as the last argument to the stackRcvRtn.
  384.           * When called from wdbEndPoll it passes a mode in the void pointer
  385.           * This mode is used to find out whether this routine is called from
  386.           * wdbEndPoll or muxReceive. You will not be happy camper if the
  387.           * spare pointer is removed from NET_PROTOCOL or if the stackRcvRtn's
  388.           * API is changed.
  389.           */
  390.          if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL))
  391.      netMblkClFree (pMblk);
  392.          
  393.          DRIVER_RESET_INPUT(pPktDev);
  394.          return (FALSE); 
  395.          }
  396.     }
  397. /******************************************************************************
  398. *
  399. * wdbEndTx - transmit a packet.
  400. *
  401. * The packet is realy a chain of mbufs. We may have to just queue up
  402. * this packet is we are already transmitting.
  403. *
  404. * RETURNS: OK or ERROR
  405. *
  406. * NOMANUAL
  407. */
  408. STATUS wdbEndTx
  409.     (
  410.     void * pDev,
  411.     struct mbuf * pMbuf
  412.     )
  413.     {
  414.     WDB_END_PKT_DEV *pPktDev = pDev;
  415.     struct mbuf* pFirstMbuf = pMbuf;
  416. #ifdef WDB_NPT_CAPABLE
  417.     int sendStatus = 0;
  418.     char * dstMacAddr = NULL;
  419. #else
  420.     int len = 0;
  421. #endif WDB_NPT_CAPABLE
  422.     if (wdbEndDebug)
  423. logMsg ("entering sendn", 1, 2, 3, 4, 5, 6);
  424.     if (pMbuf == NULL)
  425. return (ERROR);
  426.     if (pPktDev->outputBusy)
  427.         {
  428.         wdbMbufChainFree (pFirstMbuf);
  429.         return (EAGAIN);
  430.         }
  431.     else
  432.         pPktDev->outputBusy = TRUE;
  433.     if (wdbEndDebug)
  434. logMsg ("About to enter the copy loop!n", 1, 2, 3, 4, 5, 6);
  435.     /* Make sure we know that the outgoing buffer is clean/empty */
  436.     pPktDev->pOutBlk->mBlkHdr.mLen  = 0;
  437.     pPktDev->pOutBlk->mBlkHdr.mData = pPktDev->pOutBlk->pClBlk->clNode.pClBuf;
  438.     /* increment the data pointer so that muxAddressForm can prepend header */
  439.     pPktDev->pOutBlk->mBlkHdr.mData += SIZEOF_ETHERHEADER;
  440. #ifndef WDB_NPT_CAPABLE
  441.     /* First place the addressing information into the packet. */
  442.     muxAddressForm (pPktDev->pCookie, pPktDev->pOutBlk,
  443.                     pPktDev->srcAddr, pPktDev->lastHAddr);
  444.     len = pPktDev->pOutBlk->mBlkHdr.mLen;
  445.     
  446.     if (wdbEndDebug)
  447. logMsg ("About to check length!n", 1, 2, 3, 4, 5, 6);
  448.     if (len == 0)
  449.         {
  450.         wdbMbufChainFree (pFirstMbuf);
  451.         pPktDev->outputBusy = FALSE;
  452.         if (wdbEndDebug)
  453.             logMsg ("Wrong length!n", 1, 2, 3, 4, 5, 6);
  454.         return (EAGAIN);
  455.         }
  456.     
  457.     if (wdbEndDebug)
  458.         logMsg ("hdr length:%dn", len, 2, 3, 4, 5, 6);
  459.     pPktDev->pOutBlk->mBlkHdr.mLen = len + 
  460.         netMblkToBufCopy (pMbuf, pPktDev->pOutBlk->mBlkHdr.mData + len, NULL);
  461.     pPktDev->pOutBlk->mBlkPktHdr.len = pPktDev->pOutBlk->mBlkHdr.mLen;
  462.     if (wdbEndDebug)
  463.         logMsg ("OutBlk: %x:%x:%x:%x:%x:%xn", 
  464.                 pPktDev->pOutBlk->mBlkHdr.mData[0],
  465.                 pPktDev->pOutBlk->mBlkHdr.mData[1],
  466.                 pPktDev->pOutBlk->mBlkHdr.mData[2],
  467.                 pPktDev->pOutBlk->mBlkHdr.mData[3],
  468.                 pPktDev->pOutBlk->mBlkHdr.mData[4],
  469.                 pPktDev->pOutBlk->mBlkHdr.mData[5]);
  470. #else
  471.     pPktDev->pOutBlk->mBlkHdr.mLen =
  472.         netMblkToBufCopy (pMbuf, pPktDev->pOutBlk->mBlkHdr.mData, NULL);
  473.     pPktDev->pOutBlk->mBlkPktHdr.len = pPktDev->pOutBlk->mBlkHdr.mLen;
  474. #endif /* WDB_NPT_CAPABLE */
  475.     if (wdbEndDebug)
  476.         logMsg ("Data copied !n", 1, 2, 3, 4, 5, 6);
  477.     wdbMbufChainFree (pFirstMbuf); 
  478.     
  479.     if (wdbEndDebug)
  480. logMsg ("About to send a packet!n", 1, 2, 3, 4, 5, 6);
  481. #ifdef WDB_NPT_CAPABLE
  482.     dstMacAddr = pPktDev->lastHAddr->mBlkHdr.mData;
  483. #endif /* WDB_NPT_CAPABLE */
  484. #ifndef STANDALONE_AGENT
  485.     /* if we are in polled mode, transmit the packet in a loop */
  486.     if (pPktDev->mode == WDB_COMM_MODE_POLL)
  487. {
  488. #ifndef WDB_NPT_CAPABLE
  489.         muxPollSend (pPktDev->pCookie, pPktDev->pOutBlk);
  490. #else
  491.         sendStatus = muxTkPollSend (pPktDev->pCookie, pPktDev->pOutBlk,
  492.             dstMacAddr, htons(ETHERTYPE_IP), NULL);
  493.         if (sendStatus != OK)
  494.     {
  495.     pPktDev->outputBusy = FALSE;
  496.     if (wdbEndDebug)
  497. logMsg ("Wrong length!n", 1, 2, 3, 4, 5, 6);
  498.     return (EAGAIN);
  499.     }
  500. #endif /* WDB_NPT_CAPABLE */
  501.         if (wdbEndDebug)
  502.             logMsg ("Sent polled packet!n", 1, 2, 3, 4, 5, 6);
  503. }
  504.     else
  505.         {
  506. #ifndef WDB_NPT_CAPABLE
  507.         if (muxSend (pPktDev->pCookie, pPktDev->pOutBlk) == OK)
  508. #else
  509.         if (muxTkSend (pPktDev->pCookie, pPktDev->pOutBlk, dstMacAddr,
  510.        htons(ETHERTYPE_IP), NULL) == OK)
  511. #endif /* WDB_NPT_CAPABLE */
  512.             {
  513.     END_OBJ * pEnd;
  514.             if (wdbEndDebug)
  515.                 logMsg ("Sent regular packet!n", 1, 2, 3, 4, 5, 6);
  516.             /*pEnd = (END_OBJ *)pPktDev->pCookie;*/
  517.     pEnd = PCOOKIE_TO_ENDOBJ(pPktDev->pCookie);
  518.             
  519.             if ((pPktDev->pOutBlk =
  520.                  wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu)) == NULL)
  521.                 return (ERROR);
  522.             pPktDev->pOutBlk->mBlkHdr.mFlags |= M_PKTHDR;
  523.             }
  524.         else
  525.             {
  526.             if (wdbEndDebug)
  527.                 logMsg ("Could not send regular packet!n", 1, 2, 3, 4, 5, 6);
  528.             }
  529.         }
  530. #else /* STANDALONE_AGENT */
  531.     if (muxPollSend (pPktDev->pCookie, pPktDev->pOutBlk) == ERROR)
  532.      {
  533.      if (wdbEndDebug);
  534.     logMsg ("Could not send regular packet!n", 1, 2, 3, 4, 5, 6);
  535. }
  536.     else
  537.      {
  538.         if (wdbEndDebug)
  539.             logMsg ("Sent polled packet!n", 1, 2, 3, 4, 5, 6);
  540. }
  541. #endif /* STANDALONE_AGENT */
  542.     
  543.     wdbEndOutputFree (pPktDev);
  544.     
  545.     return (OK);
  546.     }
  547. /******************************************************************************
  548. *
  549. * wdbEndOutputFree - free the output buffer
  550. *
  551. * This is the callback used to let us know the that the device is done with the
  552. * output buffer we loaned it.
  553. *
  554. * RETURNS: N/A
  555. *
  556. * NOMANUAL
  557. */
  558. LOCAL void wdbEndOutputFree
  559.     (
  560.     void * pDev
  561.     )
  562.     {
  563.     WDB_END_PKT_DEV * pPktDev = pDev;
  564.     DRIVER_RESET_OUTPUT(pPktDev);
  565.     }
  566. /******************************************************************************
  567. *
  568. * wdbEndInputFree- free the input buffer
  569. *
  570. * This is the callback used to let us know the agent is done with the
  571. * input buffer we loaded it.
  572. *
  573. * RETURNS: N/A
  574. *
  575. * NOMANUAL
  576. */
  577. LOCAL void wdbEndInputFree
  578.     (
  579.     void * pDev
  580.     )
  581.     {
  582.     WDB_END_PKT_DEV * pPktDev = pDev;
  583.     DRIVER_RESET_INPUT(pPktDev);
  584.     }
  585. /******************************************************************************
  586. *
  587. * wdbEndModeSet - switch driver modes
  588. *
  589. * RETURNS: OK for a supported mode, else ERROR
  590. *
  591. * NOMANUAL
  592. */
  593. LOCAL STATUS wdbEndModeSet
  594.     (
  595.     void * pDev,
  596.     uint_t newMode
  597.     )
  598.     {
  599.     WDB_END_PKT_DEV * pPktDev = pDev;
  600.     if (newMode == WDB_COMM_MODE_INT)
  601. {
  602. muxIoctl (pPktDev->pCookie, EIOCPOLLSTOP, NULL);
  603. pPktDev->mode = newMode;
  604. return (OK);
  605. }
  606.     else if (newMode == WDB_COMM_MODE_POLL)
  607. {
  608. muxIoctl (pPktDev->pCookie, EIOCPOLLSTART, NULL);
  609. pPktDev->mode = newMode;
  610. return (OK);
  611. }
  612.     else
  613. return (ERROR);
  614.     return (ERROR);
  615.     }
  616. /******************************************************************************
  617. *
  618. * wdbEndPollArpReply - END driver ARP reply handler
  619. *
  620. * WDB agent normally only manages IP packets that are sent to a dedicated
  621. * port. However it is the only protocol bound to the MUX, we must also reply
  622. * to ARP request so that communication becomes possible.
  623. *
  624. * RETURNS: TRUE if the packet was for us, FALSE otherwise.
  625. *
  626. * NOMANUAL
  627. */
  628. LOCAL BOOL wdbEndPollArpReply
  629.     (
  630.     struct mbuf * pMblk,
  631.     void * pCookie
  632.     )
  633.     {
  634.     struct ether_header * pEh;
  635.     struct ether_arp *   pEa;
  636.     WDB_END_PKT_DEV *    pPktDev = pEndPktDev;
  637.     int   op;
  638.     pEh = mtod(pMblk, struct ether_header *);
  639.     pEa = (struct ether_arp *) ((char *)pEh + sizeof (struct ether_header));
  640.     op = ntohs(pEa->arp_op);
  641.     /* test if the request is for us */
  642.     if ((bcmp ((caddr_t)&pPktDev->ipAddr.s_addr,
  643.      (caddr_t)&pEa->arp_tpa, pEa->arp_pln) == 0) &&
  644. (op == ARPOP_REQUEST))
  645. {
  646.         /* build the reply */
  647. /* fill the ethernet header */
  648. bcopy (pEh->ether_shost, pEh->ether_dhost, sizeof(pEh->ether_shost));
  649. bcopy (pPktDev->srcAddr->mBlkHdr.mData, pEh->ether_shost,
  650.                sizeof(pEh->ether_shost));
  651. /* fill the ARP Frame */
  652.         bcopy (pEh->ether_dhost, pEa->arp_tha, pEa->arp_hln);
  653. bcopy (pEa->arp_spa, pEa->arp_tpa, pEa->arp_pln);
  654. bcopy (pEh->ether_shost, pEa->arp_sha, pEa->arp_hln);
  655. bcopy ((char *)&pPktDev->ipAddr.s_addr, pEa->arp_spa, pEa->arp_pln);
  656. pEa->arp_op = htons (ARPOP_REPLY);
  657.         /* send the reply */
  658. muxPollSend (pCookie, pMblk);
  659. netMblkClFree (pMblk);
  660. DRIVER_RESET_INPUT(pPktDev);
  661. return (TRUE);
  662. }
  663.     netMblkClFree (pMblk);
  664.     DRIVER_RESET_INPUT(pPktDev);
  665.     return (FALSE);
  666.     }
  667. /******************************************************************************
  668. *
  669. * wdbEndPoll - poll for a packet
  670. *
  671. * This routine polls for a packet. If a packet has arrived it invokes
  672. * the agents callback.
  673. *
  674. * RETURNS: OK if a packet has arrived, else ERROR.
  675. *
  676. * NOMANUAL
  677. */ 
  678. LOCAL STATUS wdbEndPoll
  679.     (
  680.     void * pDev
  681.     )
  682.     {
  683.     long  type;
  684.     M_BLK_ID  pMblk;
  685.     WDB_END_PKT_DEV *  pPktDev = pDev;
  686.     LL_HDR_INFO   llHdrInfo;
  687.     int mode = WDB_COMM_MODE_POLL; 
  688.     END_OBJ *  pEnd = PCOOKIE_TO_ENDOBJ(pPktDev->pCookie);
  689.     /* Reset the size to the maximum. */
  690.     pPktDev->pInBlk->mBlkHdr.mLen = pPktDev->pInBlk->pClBlk->clSize;
  691.     pPktDev->pInBlk->mBlkHdr.mData = pPktDev->pInBlk->pClBlk->clNode.pClBuf;
  692. #ifdef WDB_NPT_CAPABLE
  693.     if (muxTkPollReceive (pPktDev->pCookie, pPktDev->pInBlk, NULL) == OK)
  694. #else
  695.     if (muxPollReceive (pPktDev->pCookie, pPktDev->pInBlk) == OK)
  696. #endif /* WDB_NPT_CAPABLE */
  697. {
  698.         if ((pMblk = mBlkGet (pEnd->pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
  699.             return (ERROR);
  700.         /* duplicate the received mBlk so that wdbEndInt can free it */
  701.         pMblk = netMblkDup (pPktDev->pInBlk, pMblk);
  702. #ifndef WDB_NPT_CAPABLE
  703.         if (muxPacketDataGet (pPktDev->pCookie, pMblk, &llHdrInfo) == ERROR)
  704.     {
  705.     return (ERROR);
  706.     }
  707. #else
  708. if ((pEnd->mib2Tbl.ifType == M2_ifType_ethernet_csmacd) ||
  709.     (pEnd->mib2Tbl.ifType == M2_ifType_iso88023_csmacd))
  710.     {
  711.     if (endEtherPacketDataGet (pMblk, &llHdrInfo) == ERROR)
  712. {
  713. return (ERROR);
  714. }
  715.     }
  716. else
  717.     return ERROR;
  718. #endif /* WDB_NPT_CAPABLE */
  719.         type = llHdrInfo.pktType;
  720.         if (wdbEndInt (pPktDev->pCookie, type, pMblk, &llHdrInfo,
  721.                        (void *)&mode) == TRUE)
  722.             return (OK);
  723.         return (ERROR);
  724.         }
  725.     else
  726.         {
  727.         return (ERROR);
  728.         }
  729.     }
  730. /*******************************************************************************
  731. * wdbEndMblkClGet - get an mBlk/clBlk/cluster 
  732. *
  733. * This routine returns an mBlk which points to a clBlk which points to a
  734. * cluster. This routine allocates the triplet from the pNetPool in the
  735. * end object.
  736. *
  737. * RETURNS: M_BLK_ID / NULL
  738. *
  739. * NOMANUAL
  740. */ 
  741. LOCAL M_BLK_ID wdbEndMblkClGet
  742.     (
  743.     END_OBJ *  pEnd, /* endobject in which the netpool belongs */
  744.     int size /* size of the cluster */
  745.     )
  746.     {
  747.     M_BLK_ID  pMblk;
  748.     if ((pMblk = netTupleGet (pEnd->pNetPool, size, M_DONTWAIT, MT_DATA,
  749.                               FALSE)) == NULL)
  750.         {
  751. if (wdbEndDebug)
  752.     logMsg ("wdbEndMblkClGet:Could not get mBlk...n",
  753.                    1, 2, 3, 4, 5, 6);
  754.         }
  755.     return (pMblk);
  756.     }
  757. #ifdef WDB_NPT_CAPABLE
  758. /******************************************************************************
  759. *
  760. * wdbNptInt - NPT driver interrupt handler
  761. *
  762. * This is really a MUX receive routine but we let it look like
  763. * an interrupt handler to make this interface look as much like the
  764. * template as possible.
  765. *
  766. * RETURNS: TRUE if the packet was for us, FALSE otherwise.
  767. *
  768. * NOMANUAL
  769. */
  770. int wdbNptInt
  771.     (
  772.     void *  callbackId,  /* call back Id supplied during muxTkBind */
  773.     long  type,  /* our network service type */
  774.     M_BLK_ID  pMblk, /* the packet */
  775.     void *  pSpareData /* any spare data; we ignore it */
  776.     )
  777.     {
  778.     END_OBJ * pEnd = PCOOKIE_TO_ENDOBJ(pEndPktDev->pCookie);
  779.     LL_HDR_INFO llHdrInfo;
  780.     switch (pEnd->mib2Tbl.ifType)
  781.         {
  782.         case M2_ifType_ethernet_csmacd:
  783.         case M2_ifType_iso88023_csmacd:
  784.     if (wdbEndDebug)
  785. logMsg ("wdbNptInt: Received an Ethernet packetn",1,2,3,4,5,6);
  786.     endEtherPacketDataGet (pMblk,&llHdrInfo);
  787.     return (wdbEndInt (pEndPktDev->pCookie, type, pMblk,
  788.                                &llHdrInfo,callbackId));
  789.     break;
  790. default:
  791.     if (wdbEndDebug)
  792. logMsg ("wdbNptInt: NOT an Ethernet packetn",1,2,3,4,5,6);
  793.     return (FALSE);
  794. }
  795.     }
  796. /********************************************************************************
  797. * wdbNptShutdown - dummy shutdown routine for muxTkBind 
  798. *
  799. * RETURNS: N/A
  800. *
  801. * NOMANUAL
  802. */
  803. void wdbNptShutdown
  804.     (
  805.     void *  callbackId  /* call back Id supplied during muxTkBind */
  806.     )
  807.     {
  808.     }
  809. #endif /* WDB_NPT_CAPABLE */