muxTkLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:53k
开发平台:

MultiPlatform

  1. /* muxTkLib.c - MUX toolkit Network Interface Library */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 02k,05nov01,vvv  fixed compilation warning
  7. 02j,15oct01,rae  merge from truestack ver 02m, base 02i (SPR #70512 etc)
  8. 02i,09nov00,spm  removed pNptCookie from END_OBJ for binary compatibility;
  9.                  fixed handling of output protocols
  10. 02h,29oct00,ham  doc: removed reference to old SENS docs(SPR #35134).
  11. 02h,24oct00,niq  Merging in RFC2233 changes from tor2_0.open_stack-f1 branch
  12.                  02f,18oct00,ann  applyingthe fix for Jitterbug #25 regarding
  13.                  mac address not being filled correctly
  14.                  02e,16may00,ann merging from post R1 on openstack branch to
  15.                  incorporate RFC2233 implementation
  16.                  02c,10mar00,ead fixed MIB-2 counter updates to use new
  17.                  RFC 2233 m2IfLib
  18. 02g,18oct00,niq  Correct the order in which protocols are inserted in the
  19.                  muxTkBind call
  20. 02f,16oct00,spm  merged version 02g from tor3_0_x branch (base version 02b):
  21.                  adds multiple SNARF protocol support, code cleanup, and
  22.                  backward compatibility fixes; overrides 02d and 02e changes
  23. 02e,25apr00,pul  fixing SPR 30584
  24. 02d,17apr00,pul  fixed TSR 153280, TSR 156655 which are part of the NPT patch
  25. 02c,12apr00,pul  modified _muxTkSend() to free an MBlk that could be allocated
  26.                  by the addressForm() routine when the driver send() routine
  27.                  returns an error
  28. 02b,06oct99,pul  removing references to mCastMapFunc and rtRequestFunc
  29. 02a,04oct99,pul  adding a new semaphore to protect the Bib entry traversal 
  30.    + fixed SPR # 28427
  31. 01z,07jul99,pul  To modify description for man page generation
  32. 01y,07jun99,sj   resurrect network layer pkt in _muxTkSend if endSend fails 
  33. 01x,29apr99,pul  Upgraded NPT phase3 code to tor2.0.0
  34. 01w,29mar99,pul  altered bind query, member name
  35. 01v,29mar99,pul  altered muxTkPollReceive to return correct error.
  36. 01u,26mar99,pul  removed all muxSvcFunc related stuff.
  37. 01t,25mar99,sj   muxEndRcvRtn undoes MAC header strip after calling outputFilter
  38. 01s,24mar99,sj   MUX_ID is installed as pSpare by muxTkBind + hook re-org
  39. 01r,19mar99,sj   copy protocol type in to the BIB in muxTkBindUpdate
  40. 01q,18mar99,sj   some clean up: collocated future release code at the end 
  41. 01p,09mar99,sj   muxTkBind can bind to ENDs
  42. 01o,05mar99,sj   eliminated hooks; not cleanly though. next version will do that
  43. 01n,22feb99,sj   added muxTkSend and muxTkPollSend and muxTkPollReceive
  44. 01m,26jan99,sj   moved BIB entry definition from here to muxLibP.h
  45. 01l,10Nov98,sj   more doc fixes
  46. 01k,09Nov98,sj   made logMsgs in muxTkLibInit conditional on muxTkDebug
  47. 01j,09Nov98,sj   return OK from muxTkLibInit
  48. 01i,08Nov98,sj   populate hooks only if not done already
  49. 01h,06Nov98,sj   forward declaration for nptHookRtn
  50. 01g,03Nov98,pul  modified muxMCastMapFuncGet to accept net svc type and net
  51.                  drv type 
  52. 01f,03Nov98,pul  added muxMCastMapFuncGet, muxMCastMapFuncDel and comments
  53. 01e,03Nov98,pul  moved definition of MUX_BIND_ENTRY and MUX_SVC_FUNCS here.
  54.  modified muxTkLibInit to populate nptHook. Allocated
  55.                  muxBindBase array during muxTkBibInit().
  56. 01d,02Nov98,sj   doc update
  57. 01c,27Oct98,pul  removed muxTkSend for future release 
  58. 01b,10Oct98,pul  Introduced hooks for ipProto module
  59. 01a,05Oct98,pul  Written
  60. */
  61. /*
  62. DESCRIPTION
  63. This library provides additional APIs offered by the Network Protocol
  64. Toolkit (NPT) architecture.  These APIs extend the original release of
  65. the MUX interface.
  66. A NPT driver is an enhanced END but retains all of the END's functionality.
  67. NPT also introduces the term "network service sublayer" or simply "service
  68. sublayer" which is the component that interfaces between the network service
  69. (or network protocol) and the MUX.  This service sublayer may be built in
  70. to the network service or protocol rather than being a separate component.
  71. INTERNAL
  72. The muxLib routines for binding protocols to END drivers also use certain
  73. routines from this library so that the BIB accurately reflects all bindings
  74. between protocols and drivers. Since all information in the BIB is also
  75. stored elsewhere, the BIB array should be removed to avoid the predefined
  76. limit it imposes on the number of active bindings.
  77. INCLUDE FILES: vxWorks.h, taskLib.h, stdio.h, errno.herrnoLib.h, lstlib.h,
  78. logLib.h, string.h, m2Lib.h, net/if.h, bufLib.h, semlib.h, end.h, muxLib.h,
  79. muxTkLib.h, netinet/if_ether.h, net/mbuf.h
  80. */
  81. /* includes */
  82. #include "vxWorks.h"
  83. #include "taskLib.h"
  84. #include "stdio.h"
  85. #include "errno.h"
  86. #include "errnoLib.h"
  87. #include "lstLib.h"
  88. #include "logLib.h"
  89. #include "string.h"
  90. #include "m2Lib.h"
  91. #include "net/if.h"             /* Needed for IFF_LOAN flag. */
  92. #include "bufLib.h"
  93. #include "semLib.h"
  94. #include "end.h" /* Necessary for any END as well as the MUX */
  95. #include "muxLib.h"
  96. #include "private/muxLibP.h"
  97. #include "muxTkLib.h"
  98. #include "netinet/if_ether.h"
  99. #include "net/mbuf.h"
  100. #include "memPartLib.h"
  101. #ifdef VIRTUAL_STACK
  102. #include "netinet/vsLib.h"
  103. #endif    /* VIRTUAL_STACK */
  104. /* defines */
  105. #define STREQ(A, B) (strcmp ( (A), (B)) == 0)
  106. #define TK_DRV_CHECK(pBib) ((((MUX_ID)pBib)->flags & BIB_TK_DRV) ? TRUE : FALSE)
  107. #define TK_DRV_SET(pBib)   (((MUX_ID)pBib)->flags |= BIB_TK_DRV)
  108. #define TK_DRV_CLEAR(pBib) (((MUX_ID)pBib)->flags &= ~BIB_TK_DRV)
  109. #define DRV_ENTRY_CHECK(pBib) ((((MUX_ID)pBib)->flags & BIB_DRV_ENTRY) ? TRUE :
  110.     FALSE)
  111. #define PROTO_ENTRY_CHECK(pBib) ((((MUX_ID)pBib)->flags & BIB_PROTO_ENTRY) ?
  112. TRUE : FALSE)
  113. /* externs */
  114. /* globals */
  115. SEM_ID muxBibLock = NULL; /* To protect the traversal of Bib entries */
  116. int muxTkDebug = 0;
  117. int muxMaxBinds = 8;    /* Default (unless overridden by project facility). */
  118. /* locals */
  119. LOCAL MUX_ID muxBindBase;
  120. /* forward declarations */
  121. LOCAL int  muxTkBibEntryGet (END_OBJ * pEnd);
  122. LOCAL void muxTkBibEntryFill (int index, int netSvcType, void * netCallbackId);
  123. LOCAL void muxTkBibEntryFree (MUX_ID muxId);
  124. LOCAL int  muxEndRcvRtn (void *, long, M_BLK_ID, LL_HDR_INFO *, void *);
  125. /*****************************************************************************
  126. *
  127. * muxTkDrvCheck - checks if the device is an NPT or an END interface
  128. *
  129. * This function returns 1 if the driver indicated by <pDevName> is of the
  130. * Toolkit (NPT) paradigm, and 0 (zero) if it is an END.  This routine is
  131. * called by the network service sublayer so that it can discover the driver
  132. * type before it binds to it via the MUX.
  133. *
  134. * INTERNAL:
  135. * All network drivers having the same device name but different unit numbers
  136. * are of the same type (NPT or END), so passing just the device name as an
  137. * argument is sufficient
  138. *
  139. * .IP <pDevName>
  140. * Expects a pointer to a string containing the name of the device
  141. *
  142. * RETURNS: 1 for an NPT driver, 0 for an END or other driver, or ERROR (-1) 
  143. * if no device is found with the given name
  144. *
  145. * SEE ALSO: muxTkBind(), muxBind()
  146. */
  147. int muxTkDrvCheck
  148.     (
  149.     char * pDevName /* device name */
  150.     )
  151.     {
  152.     int    count;
  153.     BOOL   found = FALSE;
  154.     /* find the BIB entry for the device and return the tkFlag status */
  155.     semTake (muxBibLock, WAIT_FOREVER);
  156.     for (count = 0; count < muxMaxBinds; count++)
  157.         {
  158.         if (STREQ(muxBindBase[count].devName, pDevName))
  159.     {
  160.     found = TRUE;
  161.             break;
  162.     }
  163.         }
  164.     semGive (muxBibLock);
  165.     if (found)
  166. return (TK_DRV_CHECK(&muxBindBase[count]));
  167.     else
  168. return (ERROR);
  169.     }
  170. /*****************************************************************************
  171. *
  172. * muxTkCookieGet - returns the cookie for a device
  173. *
  174. * This routine returns the cookie for a device.
  175. *
  176. * RETURNS: a cookie to the device or NULL if unsuccessful
  177. *
  178. */
  179. void *muxTkCookieGet
  180.     (
  181.     char *pName, /* Device Name */
  182.     int unit /* Device Unit */
  183.     )
  184.     {
  185.     int    count = 0;
  186.     END_OBJ *pEnd;
  187.     pEnd = endFindByName (pName, unit);
  188.     if (pEnd == NULL)
  189. {
  190. errnoSet (S_muxLib_NO_DEVICE);
  191. return (NULL);
  192. }
  193.     /* find the BIB entry for the device */
  194.     for (; (count < muxMaxBinds) && (muxBindBase[count].pEnd != pEnd); count++);
  195.     /* if there is a match, return it */
  196.     if (muxBindBase[count].pEnd == pEnd)
  197. return (&muxBindBase[count]);
  198.     return (NULL);
  199.     }
  200.   
  201. /******************************************************************************
  202. *
  203. * muxTkBind - bind an NPT protocol to a driver
  204. *
  205. * A network protocol, network service, or service sublayer uses this routine
  206. * to bind to a specific driver.  This bind routine is valid both for END and
  207. * NPT drivers, but the specified stack routine parameters must use the NPT
  208. * function prototypes, and are somewhat different from those used with
  209. * muxBind().
  210. *
  211. * The driver is specified by the <pName> and <unit> arguments, (for example,
  212. * ln and 0, ln and 1, or ei and 0).
  213. *
  214. * .IP <pName> 20
  215. * Expects a pointer to a character string that contains the name of the
  216. * device that this network service wants to use to send and receive packets.
  217. * .IP <unit>
  218. * Expects the unit number of the device of the type indicated by <pName>.
  219. * .IP <stackRcvRtn>
  220. * Expects a pointer to the function that the MUX will call when it
  221. * wants to pass a packet up to the network service.  For a description of
  222. * how to write this routine, see the  
  223. * .I "WindNet TCP/IP Network Programmer's Guide"
  224. * .IP <stackShutdownRtn>
  225. * Expects a pointer to the function that the MUX will call to
  226. * shutdown the network service.  For a description of how to write such
  227. * a routine, see the 
  228. * .I "WindNet TCP/IP Network Programmer's Guide"
  229. * .IP <stackTxRestartRtn>
  230. * Expects a pointer to the function that the MUX will call after packet
  231. * transmission has been suspended, to tell the network service that it can
  232. * continue transmitting packets.  For a description of how to write this
  233. * routine, see the 
  234. * .I "WindNet TCP/IP Network Programmer's Guide"
  235. * .IP <stackErrorRtn>
  236. * Expects a pointer to the function that the MUX will call to give errors
  237. * to the network service.  For a description of how to write this routine,
  238. * see the section
  239. * .I "WindNet TCP/IP Network Programmer's Guide"
  240. * .IP <type>
  241. * Expects a value that indicates the protocol type.  The MUX uses this type
  242. * to prioritize a network service as well as to modify its capabilities.  For
  243. * example, a network service of type MUX_PROTO_SNARF has the highest priority
  244. * (see the description of protocol prioritizing provided in
  245. * .I "WindNet TCP/IP Network Programmer's Guide."
  246. * Aside from MUX_PROTO_SNARF and MUX_PROTO_PROMISC, valid network service
  247. * types include any of the values specified in RFC 1700, or can be
  248. * user-defined.
  249. *
  250. * The <stackRcvRtn> is called whenever the MUX has a packet of the specified
  251. * type.  If the type is MUX_PROTO_PROMISC, the protocol is considered
  252. * promiscuous and will get all of the packets that have not been consumed
  253. * by any other protocol.  If the type is MUX_PROTO_SNARF, it will get all of
  254. * the packets that the MUX sees.
  255. *
  256. * If the type is MUX_PROTO_OUTPUT, this network service is an output protocol
  257. * and all packets that are to be output on this device are first passed to
  258. * <stackRcvRtn> routine rather than being sent to the device.  This can be
  259. * used by a network service that needs to send packets directly to another
  260. * network service, or in a loop-back test.  If the <stackRcvRtn> returns OK,
  261. * the packet is consumed and as no longer available.  The <stackRcvRtn> for an
  262. * output protocol may return ERROR to indicate that it wants to look at the
  263. * packet without consuming it.
  264. * .IP <pProtoName>
  265. * Expects a pointer to a character string for the name of this
  266. * network service.  This string can be NULL, in which case a network service
  267. * name is assigned internally.
  268. * .IP <pNetCallbackId>
  269. * Expects a pointer to a structure defined by the protocol.  This argument
  270. * is passed up to the protocol as the first argument of all the callbacks.
  271. * This argument corresponds to the <pSpare> argument in muxBind()
  272. * .IP <pNetSvcInfo>
  273. * Reference to an optional structure specifying network service layer
  274. * information needed by the driver
  275. * .IP <pNetDrvInfo>
  276. * Reference to an optional structure specifying network driver information
  277. * needed by the network protocol, network service, or service sublayer
  278. *
  279. * RETURNS: A cookie that uniquely represents the binding instance, or NULL
  280. * if the bind fails.
  281. *
  282. * ERRNO: S_muxLib_NO_DEVICE, S_muxLib_END_BIND_FAILED, S_muxLib_NO_TK_DEVICE,
  283. * S_muxLib_NOT_A_TK_DEVICE, S_muxLib_ALREADY_BOUND, S_muxLib_ALLOC_FAILED
  284. *
  285. * SEE ALSO: muxBind()
  286. *
  287. */
  288. void * muxTkBind
  289.     (
  290.     char * pName, /* interface name, for example, ln, ei,... */
  291.     int    unit, /* unit number */
  292.     BOOL   (*stackRcvRtn) (void*,long, M_BLK_ID, void *),
  293.                                 /* receive function to be called. */
  294.     STATUS (*stackShutdownRtn) (void *),
  295.                                 /* routine to call to shutdown the stack */
  296.     STATUS (*stackTxRestartRtn) (void *),
  297.                                 /* routine to tell the stack it can transmit */
  298.     void   (*stackErrorRtn) (void*, END_ERR*),
  299.                                 /* routine to call on an error. */
  300.     long   type, /* protocol type from RFC1700 and many */
  301.                                 /* other sources (for example, 0x800 is IP) */
  302.     char * pProtoName,          /* string name for protocol  */
  303.     void * pNetCallbackId,      /* returned to network service sublayer during recv */
  304.     void * pNetSvcInfo,         /* reference to netSrvInfo structure */
  305.     void * pNetDrvInfo          /* reference to netDrvInfo structure */
  306.     )
  307.     {
  308.     NET_PROTOCOL * pNewProto = NULL;
  309.     NET_PROTOCOL * pNode = NULL;
  310.     NODE *         pFinal = NULL;    /* Last snarf protocol, if any. */
  311.     END_OBJ *      pEnd;
  312.     int            index = 0;
  313.     FUNCPTR        ioctlRtn = NULL;
  314.     BOOL           tkFlag = FALSE;
  315.     if (muxTkDebug)
  316. logMsg ("Start of muxTkBindn", 1, 2, 3, 4, 5, 6);
  317.     /* Check to see if we have a valid device. */
  318.     pEnd = endFindByName (pName, unit);
  319.     if (pEnd == NULL)
  320.         {
  321.         errnoSet (S_muxLib_NO_DEVICE);
  322.         return (NULL);
  323.         }
  324.     if (muxTkDebug)
  325. logMsg ("Found the END objectn", 1, 2, 3, 4, 5, 6);
  326.     /*
  327.      * Query for the END bind routine and call it if available;
  328.      * if the driver rejects the bind there's no need to proceed
  329.      */
  330.     if((ioctlRtn = pEnd->pFuncTable->ioctl) != NULL)
  331.         {
  332. FUNCPTR   bindRtn = NULL;
  333. END_QUERY endQuery = {END_BIND_QUERY, 4, {0,0,0,0} };
  334. if ((*ioctlRtn) (pEnd,EIOCQUERY, &endQuery) == OK)
  335.     {
  336.     bindRtn = *(FUNCPTR *)endQuery.queryData;
  337.     if ((*bindRtn) (pEnd, pNetSvcInfo,
  338.     pNetDrvInfo, type) == ERROR)
  339. {
  340. if (muxTkDebug)
  341.     logMsg ("muxTkBind: EndBind failedn", 1, 2, 3, 4, 5, 6);
  342. return (NULL);
  343. }
  344.     }
  345. }
  346.     /* check if we are allowed to continue with this protocol type */
  347.     if (type == MUX_PROTO_OUTPUT)
  348. {
  349. /*
  350.  * Check to see if this is an OUTPUT protocol and allow only
  351.  * one output filter per END
  352.  */
  353.         if (pEnd->outputFilter)
  354.             {
  355.             errnoSet (S_muxLib_ALREADY_BOUND);
  356.             return (NULL);
  357.             }
  358. }
  359.     else
  360. {
  361.         /*
  362.          * Get the appropriate place in the protocol list if necessary.
  363.          * For standard protocols, also check if the protocol number
  364.          * is available.
  365.          */
  366.  
  367.         if (type != MUX_PROTO_PROMISC)
  368.             {
  369.             /* Get the first standard protocol and last snarf protocol, if any. */
  370.             if (pEnd->snarfCount)
  371.                 {
  372.                 pFinal = lstNth (&pEnd->protocols, pEnd->snarfCount);
  373.                 pNode = (NET_PROTOCOL *)lstNext (pFinal);
  374.                 }
  375.             else
  376.                 pNode = (NET_PROTOCOL *)lstFirst (&pEnd->protocols);
  377.             }
  378.         if (type != MUX_PROTO_SNARF && type != MUX_PROTO_PROMISC)
  379.             {
  380.             for ( ; pNode != NULL;
  381.                   pNode = (NET_PROTOCOL *)lstNext (&pNode->node) )
  382.                 {
  383.                 if (pNode->type == type)
  384.                     {
  385.                     errnoSet (S_muxLib_ALREADY_BOUND);
  386.                     return (NULL);
  387.                     }
  388.                 }
  389.             }
  390. }
  391.    /* find an empty slot in the BIB */
  392.    if ((index = muxTkBibEntryGet (pEnd)) < 0)
  393.         {
  394. if (muxTkDebug)
  395.     logMsg ("muxTkBind: No more Bind entries", 1, 2, 3, 4, 5, 6);
  396. return (NULL);
  397.         }
  398.     else
  399. {
  400.         tkFlag = TK_DRV_CHECK(&muxBindBase[index]);
  401. }
  402.     /* Allocate a new protocol structure and bind the protocol to the END. */
  403.     pNewProto = (NET_PROTOCOL *)KHEAP_ALLOC(sizeof (NET_PROTOCOL));
  404.     if (pNewProto == NULL)
  405.         {
  406.         /* free BIB entry */
  407.         bzero ((void *)&muxBindBase[index], sizeof(MUX_BIND_ENTRY));
  408.         logMsg ("muxBind cannot allocate protocol node", 0, 0, 0, 0, 0, 0);
  409.         errnoSet (S_muxLib_ALLOC_FAILED);
  410.         return (NULL);
  411.         }
  412.     bzero ( (char *)pNewProto, sizeof(NET_PROTOCOL));
  413.     /* bind the protocol to the END */
  414.     if (type != MUX_PROTO_OUTPUT)
  415. {
  416. /* populate all fields in the new protocol node */
  417. pNewProto->stackShutdownRtn = stackShutdownRtn;
  418. pNewProto->stackTxRestartRtn = stackTxRestartRtn;
  419. pNewProto->stackErrorRtn = stackErrorRtn;
  420.         }
  421.     pNewProto->type = type;
  422.     /* Indicate that muxTkBind() was used. */
  423.     pNewProto->nptFlag = TRUE;
  424.     if (tkFlag != TRUE && type != MUX_PROTO_OUTPUT)
  425.         {
  426.         /* Use a wrapper receive routine when sending data with END devices. */
  427.         pNewProto->stackRcvRtn = muxEndRcvRtn;
  428.         }
  429.     else
  430.         {
  431.         pNewProto->stackRcvRtn = stackRcvRtn;
  432.         }
  433.     /*
  434.      * For all input protocols bound using muxTkBind,
  435.      * install the BIB entry pointer as the call back ID.
  436.      */
  437.     pNewProto->pSpare = &muxBindBase[index];
  438.     if (type != MUX_PROTO_OUTPUT)
  439.         {
  440. /* copy the protocol name or generate one if not available */
  441. if (pProtoName != NULL)
  442.     {
  443.     strncpy (pNewProto->name, pProtoName, 32);
  444.     }
  445. else
  446.     {
  447.     sprintf (pNewProto->name, "Protocol %d",
  448.      lstCount (&pEnd->protocols));
  449.     }
  450.         }
  451.     /* Insert the protocol in the END_OBJ protocol list */
  452.     switch (type)
  453.         {
  454.         case MUX_PROTO_OUTPUT:
  455.         case MUX_PROTO_PROMISC:
  456.             lstAdd (&pEnd->protocols, &pNewProto->node);
  457.             break;
  458.         default:
  459.             /* Add a standard or snarf protocol after any existing ones. */
  460.             lstInsert(&pEnd->protocols, pFinal, &pNewProto->node);
  461.             break;
  462.         }
  463.     if (type == MUX_PROTO_OUTPUT)
  464. {
  465. /* For an OUTPUT protocol place the filter in the END object itself. */
  466.         pEnd->outputFilter = pNewProto;
  467.         pEnd->pOutputFilterSpare = pNetCallbackId;
  468. muxBindBase[index].pEnd->outputFilter->stackRcvRtn = muxEndRcvRtn;
  469. pEnd->outputFilter->stackRcvRtn = stackRcvRtn;
  470. }
  471.     muxBindBase[index].netStackRcvRtn = stackRcvRtn;
  472.     /* fill the rest of the BIB entry */
  473.     muxTkBibEntryFill (index, type, pNetCallbackId);
  474.     if (type == MUX_PROTO_SNARF)     /* Increase the count. */
  475. (pEnd->snarfCount)++;
  476.     pNewProto->pNptCookie = &muxBindBase[index];
  477.     return (&muxBindBase[index]);
  478.     }
  479. /*****************************************************************************
  480. *
  481. * muxTkReceive - receive a packet from a NPT driver
  482. *
  483. * This is the routine that the NPT driver calls to hand a packet to the MUX.
  484. * This routine forwards the received 'mBlk' chain to the network service
  485. * sublayer by calling its registered stackRcvRtn().
  486. *
  487. * Typically, a driver includes an interrupt handling routine to process
  488. * received packets.  It should keep processing to a minimum during interrupt
  489. * context and then arrange for processing of the received packet within
  490. * task context.
  491. *
  492. * Once the frame has been validated, the driver should pass it to the MUX
  493. * with the 'receiveRtn' member of its END_OBJ structure.  This routine has
  494. * the same prototype as (and typically is) muxTkReceive().
  495. *
  496. * Depending on the protocol type (for example, MUX_PROTO_SNARF or
  497. * MUX_PROTO_PROMISC), this routine either forwards the received packet chain
  498. * unmodified or it changes the data pointer in the 'mBlk' to strip off the
  499. * frame header before forwarding the packet.
  500. *
  501. * .IP <pCookie>
  502. * Expects the END_OBJ pointer returned by the driver's endLoad() or
  503. * nptLoad() function
  504. *
  505. * .IP <pMblk>
  506. * Expects a pointer to the 'mBlk' structure containing the packet that has
  507. * been received
  508. *
  509. * .IP <netSvcOffset>
  510. * Expects an offset into the frame to the point where the data field (the
  511. * network service layer header) begins
  512. *
  513. * .IP <netSvcType>
  514. * Expects the network service type of the service for which the packet is
  515. * destined (typically this value can be found in the header of the received
  516. * frame)
  517. *
  518. * .IP <uniPromiscuous>
  519. * Expects a boolean set to TRUE when driver is in promiscuous mode and
  520. * receives a unicast or a multicast packet not intended for this device.
  521. * When TRUE the packet is not handed over to network services other than
  522. * those registered as SNARF or PROMISCUOUS.
  523. *
  524. * .IP <pSpareData>
  525. * Expects a pointer to any spare data the driver needs to pass up to the
  526. * network service layer, or NULL
  527. *
  528. * RETURNS: OK or ERROR.
  529. *
  530. * ERRNO: S_muxLib_NO_DEVICE
  531. */
  532. STATUS muxTkReceive
  533.     (
  534.     void *    pCookie, /* cookie passed in endLoad() call */
  535.     M_BLK_ID  pMblk, /* a buffer passed to us. */
  536.     long      netSvcOffset, /* offset to network datagram in the packet */
  537.     long      netSvcType, /* network service type */
  538.     BOOL      uniPromiscuous, /* TRUE when driver is in promiscuous mode */ 
  539.     void *    pSpareData /* out of band data */
  540.     )
  541.     {
  542.     NET_PROTOCOL *      pProto;
  543.     END_OBJ *           pEnd;
  544.     long                type;
  545.     M_BLK_ID            pMblkOrig;
  546.     int  count;
  547.     pEnd = (END_OBJ *)pCookie;
  548.     if (pEnd == NULL)
  549.         {
  550.         errnoSet (S_muxLib_NO_DEVICE);
  551.         if (pMblk)
  552.             netMblkClChainFree (pMblk);
  553.         return (ERROR);
  554.         }
  555.     /* Grab a new block and parse out the header information. */
  556.     count = lstCount (&pEnd->protocols);
  557.     if (count <= 0)
  558.         {
  559.         if (pMblk)
  560.             netMblkClChainFree (pMblk);
  561.         return (FALSE);
  562.         }
  563.     pProto = (NET_PROTOCOL *)lstFirst (&pEnd->protocols);
  564.     if (pProto == NULL)
  565.         {
  566.         if (pMblk)
  567.             netMblkClChainFree (pMblk);
  568.         return (ERROR);
  569.         }
  570.     /* Ignore incoming data if an output protocol is the only entry. */
  571.     if (count == 1 && pProto->type == MUX_PROTO_OUTPUT)
  572.         {
  573.         if (pMblk)
  574.             netMblkClChainFree (pMblk);
  575.         return (ERROR);
  576.         }
  577.     /*
  578.      * Loop through the protocol list.
  579.      * If a protocol's receive routine returns TRUE, that means it has
  580.      * consumed the packet.
  581.      * The protocol's receive routine should always return FALSE if other
  582.      * protocols have to see the packet.
  583.      * SNARF protocols have the priority over every other protocol.
  584.      * PROMISC protocols have the least priority.
  585.      */
  586.     type = netSvcType;
  587.     for (; pProto != NULL; pProto = (NET_PROTOCOL *)lstNext (&pProto->node))
  588.         {
  589.         MUX_ID muxId = (MUX_ID)(pProto->pSpare);
  590. void * pNetCallbackId = NULL;
  591.         if (pProto->type == MUX_PROTO_OUTPUT)
  592.             continue;
  593.         if (muxId)
  594.             pNetCallbackId = muxId->pNetCallbackId;
  595.         if (pProto->type == MUX_PROTO_SNARF)
  596.             {
  597.             if ((pProto->stackRcvRtn) && (*pProto->stackRcvRtn) 
  598.  (pNetCallbackId, type, pMblk, pSpareData) == TRUE)
  599.                 return (OK);
  600.             }
  601.         else if (pProto->type == type && !uniPromiscuous)
  602.             {
  603.             /* Make sure the entire Link Hdr is in the first M_BLK */
  604.             pMblkOrig = pMblk;
  605.             if (pMblk->mBlkHdr.mLen < netSvcOffset &&
  606.                 (pMblk = m_pullup (pMblk, netSvcOffset)) == NULL)
  607.                 {
  608.                 pMblk = pMblkOrig;
  609.                 break;
  610.                 }
  611.   
  612.             /* remove the MAC header and set the packet length accordingly */ 
  613.             pMblk->mBlkHdr.mData += netSvcOffset;
  614.             pMblk->mBlkHdr.mLen  -= netSvcOffset;
  615.             pMblk->mBlkPktHdr.len  -= netSvcOffset;
  616.             if ((pProto->stackRcvRtn) &&
  617.                 (((*pProto->stackRcvRtn) (pNetCallbackId, type, pMblk,
  618.                                           pSpareData)) == TRUE))
  619.                 {
  620.                 return (OK);
  621.                 }
  622.             }
  623.         else if (pProto->type == MUX_PROTO_PROMISC)
  624.             {
  625.             if ((pProto->stackRcvRtn) &&
  626.                 (((*pProto->stackRcvRtn) (pNetCallbackId, type, pMblk,
  627.                                           pSpareData)) == TRUE))
  628.                 {
  629.                 return (OK);
  630.                 }
  631.             }
  632.         }
  633.     /* if the flow comes here then pMblk is not freed */
  634.     if (pMblk)
  635.         netMblkClChainFree (pMblk);
  636.     return (OK);
  637.     }
  638. /*****************************************************************************
  639. *
  640. * _muxTkSend - A private function common to both muxTkSend and muxTkPollSend
  641. *
  642. * This routine does all of the processing required prior to a muxTkSend() or
  643. * muxTkPollSend() and calls the driver's send() or pollSend() routine; a
  644. * pointer to which is passed as the last argument. All other arguments are
  645. * the same as muxTkSend() or muxTkPollSend()
  646. *
  647. * RETURNS: OK or ERROR
  648. *
  649. * SEE ALSO: muxTkSend(), muxTkPollSend, muxSend(), muxPollSend
  650. *
  651. * NOMANUAL 
  652. */
  653. LOCAL STATUS _muxTkSend
  654.     (
  655.     MUX_ID    muxId, /* cookie returned by muxTkBind */
  656.     M_BLK_ID  pNBuff, /* data to be sent */
  657.     char *    dstMacAddr, /* destination MAC address */
  658.     USHORT    netType, /* network protocol that is calling us: redundant? */
  659.     void *    pSpareData, /* spare data passed on each send */
  660.     FUNCPTR   sendRtn /* the driver's send routine: poll or regular */
  661.     )
  662.     {
  663.     LL_HDR_INFO    llHdrInfo; 
  664.     END_OBJ *      pEnd = muxId->pEnd;
  665.     NET_PROTOCOL * pOut = NULL;
  666.     /* we need these two M_BLKs for endAddressForm */
  667.     M_BLK srcAddr = {{NULL,NULL,NULL,0,MT_IFADDR,0,0}, {NULL,0}, NULL};
  668.     M_BLK dstAddr = {{NULL,NULL,NULL,0,MT_IFADDR,0,0}, {NULL,0}, NULL};
  669.     if (pEnd == NULL)
  670.         return (ERROR);
  671.     /* bump MIB2 statistic */
  672.     if (pNBuff != NULL &&
  673.            (pNBuff->mBlkHdr.mFlags & M_BCAST ||
  674.               pNBuff->mBlkHdr.mFlags & M_MCAST))
  675.         {
  676.         if (pEnd->flags & END_MIB_2233)
  677.             {
  678.             /*
  679.              * Do nothing as ifOutNUcastPkts is updated by the
  680.              * m2PktCountRtn function specified in the END objects
  681.              * M2_ID.
  682.              */
  683.             }
  684.         else /* (RFC1213 style counters supported) XXX */
  685.             {
  686.             ++(pEnd->mib2Tbl.ifOutNUcastPkts);
  687.             }
  688.         }
  689.     if (pEnd->outputFilter)
  690.         {
  691.         pOut = pEnd->outputFilter;
  692.         if (pOut->stackRcvRtn (pEnd->pOutputFilterSpare, netType, pNBuff, 
  693.                                pSpareData) == TRUE)
  694.             {
  695.             return (OK);
  696.             }
  697.         }
  698.     if (!TK_DRV_CHECK(muxId))
  699. {
  700. M_BLK_ID  pSrcAddr = &srcAddr;
  701. M_BLK_ID  pDstAddr = &dstAddr;
  702. M_BLK_ID  pMacFrame = NULL;
  703. char      srcMacAddr[64];
  704.         /* copy END MAC addr into a temporary buffer */
  705.         bzero (srcMacAddr, 64);
  706.         if (pEnd->flags & END_MIB_2233)
  707.             bcopy(END_ALT_HADDR(pEnd),srcMacAddr,END_ALT_HADDR_LEN(pEnd));
  708.         else
  709.             bcopy(END_HADDR(pEnd),srcMacAddr,END_HADDR_LEN(pEnd));
  710. pDstAddr->mBlkHdr.mData = dstMacAddr;
  711. pDstAddr->mBlkHdr.mLen = END_HADDR_LEN(pEnd);
  712. pDstAddr->mBlkHdr.reserved = netType;
  713. pSrcAddr->mBlkHdr.mData = srcMacAddr; 
  714. pSrcAddr->mBlkHdr.mLen = END_HADDR_LEN(pEnd);
  715. if (pEnd->pFuncTable->formAddress &&
  716.     ((pMacFrame = pEnd->pFuncTable->formAddress (pNBuff, pSrcAddr,
  717.  pDstAddr, FALSE))
  718.       != NULL))
  719.     {
  720.     STATUS status;
  721.     /*
  722.      * if we get here, we send the fully formed MAC frame to 
  723.      * the END driver
  724.      */
  725.     status = sendRtn (pEnd, pMacFrame);
  726.     if (status != OK)
  727. {
  728. /*
  729.  * resurrect the network layer packet
  730.  */
  731. if (pMacFrame == pNBuff)
  732.     {
  733.     if (pEnd->pFuncTable->packetDataGet (pNBuff, &llHdrInfo)
  734. == ERROR)
  735.                         {
  736.                         if (pNBuff)
  737.                             netMblkClChainFree (pNBuff);
  738.                         return ERROR;
  739.                         }
  740.     /* point to the network pkt header, and adjust the length */
  741.     pNBuff->mBlkHdr.mData += llHdrInfo.dataOffset;
  742.     pNBuff->mBlkHdr.mLen  -= llHdrInfo.dataOffset;
  743.     if(pNBuff->mBlkHdr.mFlags & M_PKTHDR)
  744. pNBuff->mBlkPktHdr.len -= llHdrInfo.dataOffset;
  745.     #if 0
  746.     logMsg("_muxTkSendErrorn",1,2,3,4,5,6);
  747.     #endif
  748.     }
  749.                 else
  750.     {
  751.     if(pMacFrame)
  752. {
  753. netMblkClFree(pMacFrame);
  754. }
  755.                     pNBuff->mBlkHdr.mFlags |= M_PKTHDR;
  756.                     }
  757. }
  758.     return(status);
  759.     }
  760. else
  761.             {
  762.             if (pNBuff)
  763.                 netMblkClChainFree (pNBuff);
  764.             return ERROR;
  765.             }
  766. }
  767.     else /* NPT driver */
  768. {
  769. /* if we get here we send the packet to the driver */
  770. return (sendRtn (pEnd, pNBuff, dstMacAddr, netType, pSpareData));
  771. }
  772.     }
  773. /*****************************************************************************
  774. *
  775. * muxTkSend - send a packet out on a Toolkit or END network interface
  776. *
  777. * This routine uses <pCookie> to find a specific network interface and
  778. * uses that driver's send routine to transmit a packet.
  779. * The transmit entry point for an NPT driver uses the following prototype:
  780. * .CS
  781. * STATUS nptSend
  782. *     (
  783. *     END_OBJ * pEND,          /@ END object @/
  784. *     M_BLK_ID  pPkt,  /@ network packet to transmit @/
  785. *     char *  pDstAddr,  /@ destination MAC address @/
  786. *     int  netType  /@ network service type @/
  787. *     void *  pSpareData  /@ optional network service data @/
  788. *     )
  789. * .CE
  790. *
  791. * The transmit entry point for an END driver the following prototype:
  792. * .CS
  793. * STATUS endSend
  794. *     (
  795. *     void *  pEND,  /@ END object @/
  796. *     M_BLK_ID  pPkt, /@ Network packet to transmit @/
  797. *     )
  798. * .CE
  799. *
  800. * An END driver must continue to provide the addressForm() entry point to
  801. * construct the appropriate link-level header. The <pDst> and <pSrc> M_BLK
  802. * arguments to that routine supply the link-level addresses with the
  803. * 'mData' and 'mLen' fields. The reserved field of the destination M_BLK
  804. * contains the network service type. Both arguments f2mustfP
  805. * be treated as read-only.
  806. *
  807. * To send a fully formed physical layer frame to a device using an NPT
  808. * driver (which typically forms the frame itself), set the M_L2HDR flag
  809. * in the 'mBlk' header.
  810. *
  811. * A driver may be written so that it returns the error END_ERR_BLOCK if
  812. * the driver has insufficient resources to transmit data.  The network
  813. * service sublayer can use this feedback to establish a flow control
  814. * mechanism by holding off on making any further calls to muxTkSend()
  815. * until the device is ready to restart transmission, at which time the
  816. * device should call muxTxRestart() which will call the service sublayer's
  817. * stackRestartRtn() that was registered for the interface at bind time.
  818. *
  819. * .IP <pCookie>
  820. * Expects the cookie returned from muxTkBind().  This Cookie
  821. * identifies the device to which the MUX has bound this protocol.
  822. *
  823. * .IP <pNBuff>
  824. * The network packet to be sent, formed into an 'mBlk' chain.
  825. *
  826. * .IP <dstMacAddr>
  827. * Destination MAC address to which packet is to be sent, determined
  828. * perhaps by calling the address resolution function that was registered
  829. * for this service/device interface.
  830. *
  831. * .IP <netType>
  832. * Network service type of the sending service.  This will be used to
  833. * identify the payload type in the MAC frame.
  834. *
  835. * .IP <pSpareData>
  836. * Reference to any additional data the network service wants to pass to the
  837. * driver during the send operation.
  838. *
  839. * NOTE: A driver may return END_ERR_BLOCK if it is temporarily unable
  840. * to complete the send, and then call muxTxRestart() to indicate that it
  841. * is again able to send data.  If the driver has been written in this way,
  842. * muxTkSend() will pass the ERR_END_BLOCK back as its own return value and
  843. * the service can wait for its stackRestartRtn() callback routine to be
  844. * called before trying the send operation again.
  845. *
  846. * RETURNS: OK; ENETDOWN, if <pCookie> doesn't represent a valid device;
  847. * or an error, if the driver's send() routine fails.
  848. *
  849. * ERRNO: S_muxLib_NO_DEVICE
  850. */
  851. STATUS muxTkSend
  852.     (
  853.     void *    pCookie, /* returned by muxTkBind()*/
  854.     M_BLK_ID  pNBuff, /* data to be sent */
  855.     char *    dstMacAddr, /* destination MAC address */
  856.     USHORT    netType, /* network protocol that is calling us */
  857.                                 /** is netType redundant? **/
  858.     void *    pSpareData /* spare data passed on each send */
  859.     )
  860.     {
  861.     MUX_ID    muxId = (MUX_ID)pCookie;
  862.     END_OBJ * pEnd = muxId->pEnd;
  863.     if (pEnd == NULL)
  864.         {
  865.         errnoSet (S_muxLib_NO_DEVICE);
  866.         if (pNBuff)
  867.             netMblkClChainFree (pNBuff);
  868.         return (ENETDOWN);
  869.         }
  870.     else
  871.         {
  872. FUNCPTR sendRtn = pEnd->pFuncTable->send;
  873. return (_muxTkSend (muxId, pNBuff, dstMacAddr, netType, pSpareData,
  874.     sendRtn));
  875.         }
  876.     }
  877. /*****************************************************************************
  878. *
  879. * muxTkPollSend - send a packet out in polled mode to an END or NPT interface
  880. *
  881. * This routine uses <pCookie> to find a specific network interface and
  882. * use that driver's pollSend() routine to transmit a packet.
  883. *
  884. * This routine replaces the muxPollSend() routine for both END and NPT
  885. * drivers.
  886. *
  887. * When using this routine, the driver does not need to call muxAddressForm()
  888. * to complete the packet, nor does it need to prepend an 'mBlk' of type
  889. * MF_IFADDR containing the destination address.
  890. *
  891. * An NPT driver's pollSend() entry point is called based on this prototype:
  892. * .CS
  893. * STATUS nptPollSend
  894. *     (
  895. *     END_OBJ * pEND,          /@ END object @/
  896. *     M_BLK_ID  pPkt,  /@ network packet to transmit @/
  897. *     char *  pDstAddr,  /@ destination MAC address @/
  898. *     long  netType  /@ network service type @/
  899. *     void *  pSpareData  /@ optional network service data @/
  900. *     )
  901. * .CE
  902. *
  903. * The pollSend() entry point for an END uses this prototype:
  904. * .CS
  905. * STATUS endPollSend
  906. *     (
  907. *     END_OBJ * pEND,  /@ END object @/
  908. *     M_BLK_ID  pPkt,  /@ network packet to transmit @/
  909. *     )
  910. * .CE
  911. *
  912. * An END driver must provide the addressForm() entry point to
  913. * construct the appropriate link-level header. The <pDst> and <pSrc> M_BLK
  914. * arguments to that routine supply the link-level addresses with the
  915. * mData and mLen fields. The reserved field of the destination M_BLK
  916. * contains the network service type. Both arguments f2mustfP be treated as
  917. * read-only.
  918. *
  919. * .IP <pCookie>
  920. * Expects the cookie returned from muxBind() or muxTkBind().  This cookie
  921. * identifies the device to which the MUX has bound this protocol.
  922. *
  923. * .IP <pNBuff>
  924. * The network packet to be sent.
  925. *
  926. * .IP <dstMacAddr>
  927. * Destination MAC address to which packet is to be sent
  928. *
  929. * .IP <netType>
  930. * Network service type that will be used to identify the payload data in
  931. * the MAC frame.
  932. *
  933. * .IP <pSpareData>
  934. * Reference to any additional data the network service wants to pass to the
  935. * driver during the send operation.
  936. *
  937. * RETURNS: OK, ENETDOWN if <pCookie> doesn't represent a valid device,
  938. * or an error if the driver's pollSend() routine fails.
  939. *
  940. * ERRNO: S_muxLib_NO_DEVICE
  941. */
  942. STATUS muxTkPollSend
  943.     (
  944.     void *    pCookie, /* returned by muxTkBind()*/
  945.     M_BLK_ID  pNBuff, /* data to be sent */
  946.     char *    dstMacAddr, /* destination MAC address */
  947.     USHORT    netType, /* network protocol that is calling us */
  948.                                 /** is netType redundant? **/
  949.     void *    pSpareData /* spare data passed on each send */
  950.     )
  951.     {
  952.     MUX_ID    muxId = (MUX_ID)pCookie;
  953.     END_OBJ * pEnd = muxId->pEnd;
  954.     if (pEnd == NULL)
  955.         {
  956.         if (pNBuff)
  957.             netMblkClChainFree (pNBuff);
  958.         errnoSet (S_muxLib_NO_DEVICE);
  959.         return (ENETDOWN);
  960.         }
  961.     else
  962.         {
  963. FUNCPTR sendRtn = pEnd->pFuncTable->pollSend;
  964. return (_muxTkSend (muxId, pNBuff, dstMacAddr, netType,
  965.     pSpareData, sendRtn));
  966.         }
  967.     }
  968. /*****************************************************************************
  969. * muxTkPollReceive - poll for a packet from a NPT or END driver
  970. *
  971. * This is the routine that an upper layer can call to poll for a packet.
  972. * Any service type retrieved from the MAC frame is passed via the reserved
  973. * member of the M_BLK header.
  974. *
  975. * This API effectively replaces muxPollReceive() for both END and NPT drivers.
  976. *
  977. * For an NPT driver its pollReceive() entry point is called based on the new
  978. * prototype:
  979. * .CS
  980. * STATUS nptPollReceive
  981. *     (
  982. *     END_OBJ * pEND,          /@ END object @/
  983. *     M_BLK_ID  pPkt,  /@ network packet buffer @/
  984. *     long *  pNetSvc,  /@ service type from MAC frame @/
  985. *     long *  pNetOffset,  /@ offset to network packet @/
  986. *     void *  pSpareData  /@ optional network service data @/
  987. *     )
  988. * .CE
  989. *
  990. * The pollReceive() entry point for an END driver uses the original prototype:
  991. * .CS
  992. * STATUS endPollRcv
  993. *     (
  994. *     END_OBJ * pEND,  /@ END object @/
  995. *     M_BLK_ID  pPkt,  /@ network packet buffer @/
  996. *     )
  997. * .CE
  998. *
  999. * An END driver must continue to provide the packetDataGet() entry point
  1000. *
  1001. * .IP <pCookie>
  1002. * Expects the cookie that was returned from muxBind() or muxTkBind().
  1003. * This "cookie" identifies the driver. 
  1004. *
  1005. * .IP <pNBuff>
  1006. * Expects a pointer to a buffer chain into which incoming data will be put.
  1007. *
  1008. * .IP <pSpareData>
  1009. * A pointer to any optional spare data provided by a NPT driver. Always
  1010. * NULL with an END driver.
  1011. *
  1012. * RETURNS: OK; EAGAIN, if no packet was available; ENETDOWN, if the 'pCookie'
  1013. * does not represent a loaded driver; or an error value returned from the 
  1014. * driver's registered pollReceive() function.
  1015. *
  1016. * ERRNO: S_muxLib_NO_DEVICE
  1017. */
  1018. STATUS muxTkPollReceive
  1019.     (
  1020.     void *    pCookie, /* cookie from muxTkBind routine */
  1021.     M_BLK_ID  pNBuff, /* a vector of buffers passed to us */
  1022.     void *    pSpare /* a reference to  spare data is returned here */
  1023.     )
  1024.     {
  1025.     int          error        = OK;
  1026.     MUX_ID       muxId        = (MUX_ID)pCookie;
  1027.     END_OBJ *    pEnd         = muxId->pEnd;
  1028.     FUNCPTR      pollRcvRtn;
  1029.     LL_HDR_INFO  llHdrInfo; 
  1030.     int          netPktOffset = 0;
  1031.     int          netSvcType   = 0;
  1032.     if (pEnd == NULL)
  1033. {
  1034.         errnoSet (S_muxLib_NO_DEVICE);
  1035. return (ENETDOWN);
  1036. }
  1037.     pollRcvRtn = pEnd->pFuncTable->pollRcv;
  1038.     if (!TK_DRV_CHECK(muxId))
  1039. {
  1040. /* call END poll receive routine */
  1041. if ((error = pollRcvRtn (pEnd, pNBuff)) == OK)
  1042.     {
  1043.     if (pEnd->pFuncTable->packetDataGet (pNBuff,&llHdrInfo) == ERROR)
  1044. return (ERROR);
  1045.     }
  1046. netPktOffset = llHdrInfo.dataOffset;
  1047. netSvcType = llHdrInfo.pktType;
  1048. if (pSpare)
  1049.     *(UINT32 *)pSpare = (UINT32)NULL;
  1050. }
  1051.     else
  1052. {
  1053. error = pollRcvRtn (pEnd, pNBuff,&netSvcType,
  1054.     &netPktOffset, pSpare);
  1055.         if (error != OK)
  1056.     return error;
  1057. }
  1058.     /* restore the network layer packet for a non SNARF protocol */
  1059.     if (muxId->netSvcType != MUX_PROTO_SNARF)
  1060. {
  1061. pNBuff->mBlkHdr.mData += netPktOffset;
  1062. pNBuff->mBlkHdr.mLen -= netPktOffset;
  1063. }
  1064.     /* Save the service type returned by the driver in the reserved field. */
  1065.     pNBuff->mBlkHdr.reserved = (USHORT)netSvcType;
  1066.     return (error);
  1067.     }
  1068. /******************************************************************************
  1069. *
  1070. * muxTkPollReceive2 - muxTkPollReceive + muxTkReceive
  1071. *
  1072. * Combines muxTkPollReceive and muxTkReceive.
  1073. *
  1074. * RETURNS: OK if the packet is passed up the stack
  1075. * NOMANUAL
  1076. */
  1077. STATUS muxTkPollReceive2
  1078.     (
  1079.     void *    pCookie,  /* cookie from muxTkBind routine */
  1080.     M_BLK_ID  pNBuff
  1081.     )
  1082.     {
  1083.     MUX_ID       muxId        = (MUX_ID)pCookie;
  1084.     END_OBJ *    pEnd         = muxId->pEnd;
  1085.     FUNCPTR      pollRcvRtn;
  1086.     int          netPktOffset = 0;
  1087.     int          netSvcType   = 0;
  1088.     
  1089.     pollRcvRtn = pEnd->pFuncTable->pollRcv;
  1090.     if (pollRcvRtn (pEnd, pNBuff, &netSvcType, &netPktOffset, NULL) == ERROR)
  1091. return (ERROR);
  1092.     
  1093.     /* restore the network layer packet for a non SNARF protocol */
  1094.     if (((MUX_ID)pCookie)->netSvcType != MUX_PROTO_SNARF)
  1095. {
  1096. pNBuff->mBlkHdr.mData += netPktOffset;
  1097. pNBuff->mBlkHdr.mLen -= netPktOffset;
  1098. }
  1099.     /* Save the service type returned by the driver in the reserved field. */
  1100.     pNBuff->mBlkHdr.reserved = (USHORT)netSvcType;
  1101.     muxTkReceive (pCookie, pNBuff, netPktOffset, netSvcType,
  1102. ((END_OBJ *)pCookie)->flags & IFF_PROMISC, NULL);
  1103.     return (OK);
  1104.     }
  1105. /******************************************************************************
  1106. *
  1107. * muxEndRcvRtn - wrapper stack receive routine for END drivers
  1108. * This routine is installed as the stackRcvRoutine() for all END drivers bound
  1109. * to with the muxTkBind() call. This allows muxTkBind() to support both END
  1110. * and NPT drivers and thus eliminates the need to call muxTkDrvCheck().
  1111. *
  1112. * For incoming data, the <pCookie> argument is equal to the value from the
  1113. * muxBind() routine (if it had been used). For an NPT output filter bound
  1114. * to an END device, the <pCookie> argument is equal to NULL.
  1115. *
  1116. * The <pSpare> argument is equal to the address of the BIB entry for the
  1117. * protocol/device binding.
  1118. *
  1119. * RETURNS: OK or ERROR
  1120. *
  1121. * NOMANUAL
  1122. */
  1123. int muxEndRcvRtn
  1124.     (
  1125.     void *        pCookie,        /* muxReceive cookie, or NULL */
  1126.     long          type, /* network service type */
  1127.     M_BLK_ID      pMblk, /* MAC frame */
  1128.     LL_HDR_INFO * pLinkHdrInfo, /* link level information */
  1129.     void *        pSpare /* pSpare argument (from muxBind) */
  1130.     )
  1131.     {
  1132.     BOOL      retVal = FALSE;
  1133.     MUX_ID    muxId  = (MUX_ID) pSpare;
  1134.     END_OBJ * pEnd   = muxId->pEnd;
  1135.     if (pLinkHdrInfo == NULL || pEnd == NULL)
  1136. return ERROR;
  1137.     /* point to network packet and adjust the length */
  1138.     pMblk->mBlkHdr.mData        += pLinkHdrInfo->dataOffset;
  1139.     pMblk->mBlkHdr.mLen         -= pLinkHdrInfo->dataOffset;
  1140.     pMblk->mBlkPktHdr.len       -= pLinkHdrInfo->dataOffset;
  1141.     /* call the registered network service's stack recv routine */
  1142.     retVal = muxId->netStackRcvRtn (muxId->pNetCallbackId,type,pMblk,NULL);
  1143.     if (muxId->netSvcType == MUX_PROTO_OUTPUT && retVal == FALSE)
  1144. {
  1145. /*
  1146.  * if we are called via the output filter mechanism and the
  1147.  * filter does not consume the packet we need to undo the stripping
  1148.  * of the MAC header
  1149.  */
  1150. pMblk->mBlkHdr.mData        -= pLinkHdrInfo->dataOffset;
  1151. pMblk->mBlkHdr.mLen         += pLinkHdrInfo->dataOffset;
  1152. pMblk->mBlkPktHdr.len       += pLinkHdrInfo->dataOffset;
  1153. }
  1154.     return (retVal);
  1155.     }
  1156. /******************************************************************************
  1157. *
  1158. * muxTkBibEntryGet - find the next available slot in the BIB 
  1159. *
  1160. * This is a internal function called to find the next available entry in
  1161. * the BIB. For the first protocol that binds to a particular device the
  1162. * entry that was partially filled at the time of driver load, using
  1163. * muxDevLoad(), is used. For the second protocol onwards a new entry is
  1164. * claimed
  1165. *
  1166. * RETURNS : muxId or NULL.
  1167. * NOMANUAL
  1168. */
  1169. int muxTkBibEntryGet
  1170.     (
  1171.     END_OBJ * pEnd /* the END the protocol is trying to bind to */
  1172.     )
  1173.     {
  1174.     int            multBinds = 0;
  1175.     int            count = 0;
  1176.     int            index = -1;
  1177.     NET_PROTOCOL * pProto;
  1178.    /*
  1179.     * mutual exclusion begins here and we keep it till we have a valid
  1180.     * BIB index 
  1181.     */
  1182.     if (semTake (muxBibLock, WAIT_FOREVER) == ERROR)
  1183.        return (-1);
  1184.     /* are one or more protocols already bound to this device ? */
  1185.     multBinds = lstCount (&pEnd->protocols); 
  1186.     /*
  1187.      * KLUDGE to accomodate muxBind
  1188.      */
  1189.      if (multBinds == 1)
  1190.  {
  1191.  pProto = (NET_PROTOCOL *)lstFirst (&pEnd->protocols);
  1192.  if (! pProto->nptFlag)
  1193.      multBinds = 0;
  1194.  }
  1195.     /*
  1196.      * if this is the first protocol being registered with this device,
  1197.      * we simply use search for and use the BIB slot in which the driver
  1198.      * was loaded using muxDevLoad(); else we find the next available slot
  1199.      * in the BIB
  1200.      */  
  1201.     if (!multBinds)
  1202. {
  1203. for (count = 0; count < muxMaxBinds; count++)
  1204.     {
  1205.     if (STREQ(muxBindBase[count].devName, pEnd->devObject.name) &&
  1206. muxBindBase[count].unitNo == pEnd->devObject.unit)
  1207.        {
  1208.        index = count;
  1209.        break;
  1210.        }
  1211.     }
  1212. }
  1213.     else
  1214.         {
  1215.         for (count = 0; (count < muxMaxBinds) && 
  1216.     (muxBindBase[count].pEnd != NULL); count++)
  1217.     ;
  1218. /*
  1219.  * these fields in the BIB entry need to be filled only when 
  1220.  * more than one protocol is bound to the same device
  1221.  */
  1222. if (count < muxMaxBinds)
  1223.     {
  1224.     index = count;
  1225.     /* reserve this slot for us */
  1226.     muxBindBase[index].pEnd = pEnd;
  1227.     muxBindBase[index].unitNo = pEnd->devObject.unit;
  1228.     strcpy(muxBindBase[count].devName, pEnd->devObject.name);
  1229.     if ((END_IOCTL(pEnd)(pEnd, EIOCGNPT, NULL)) == OK)
  1230. {
  1231. TK_DRV_SET(&muxBindBase[count]);
  1232. }
  1233.     else
  1234. {
  1235. TK_DRV_CLEAR(&muxBindBase[count]);
  1236. }
  1237.     }
  1238.         }
  1239.     /* say that a protocol has taken this slot */
  1240.     muxBindBase[index].flags |= BIB_PROTO_ENTRY;
  1241.     /* we have the BIB index and we are clear to release muxLock */
  1242.     semGive (muxBibLock);
  1243.     return (index);
  1244.     }
  1245. /******************************************************************************
  1246. *
  1247. * muxTkBibEntryFill - fill and complete the BIB entry
  1248. *
  1249. * This is a internal function called to complete the BIB entry that was
  1250. * claimed using muxTkBibEntryGet()
  1251. *
  1252. * RETURNS : muxId or NULL.
  1253. * NOMANUAL
  1254. */
  1255. void muxTkBibEntryFill
  1256.     (
  1257.     int    index, /* BIB entry pointer */
  1258.     int    netSvcType, /* protocol that is being bound */
  1259.     void * pNetCallbackId /* protocols callback Id */
  1260.     )
  1261.     {
  1262.     M2_INTERFACETBL mib2Tbl;
  1263.     M2_ID * pM2ID;
  1264.     long            netDrvType = 0;
  1265.     /* get the MAC type from the END MIB table */
  1266.     if (muxBindBase[index].pEnd->flags & END_MIB_2233)
  1267.         {
  1268.         muxIoctl(&muxBindBase[index], EIOCGMIB2233, (caddr_t)&pM2ID);
  1269.         netDrvType = pM2ID->m2Data.mibIfTbl.ifType;
  1270.         }
  1271.     else /* (RFC1213 style counters supported) XXX */
  1272.         {
  1273.         muxIoctl(&muxBindBase[index], EIOCGMIB2, (caddr_t)&mib2Tbl);
  1274.         netDrvType = mib2Tbl.ifType;
  1275.         }
  1276.     /* populate the rest of the BIB entry */
  1277.     muxBindBase[index].netSvcType = netSvcType;
  1278.     muxBindBase[index].netDrvType = netDrvType;
  1279.     muxBindBase[index].pNetCallbackId = pNetCallbackId;
  1280.     /* populate the BIB entry with the registered network service functions */
  1281.     muxBindBase[index].addrResFunc = muxAddrResFuncGet (netDrvType,netSvcType);
  1282.     }
  1283. /******************************************************************************
  1284. *
  1285. * muxTkBibEntryFree - free the BIB entry
  1286. *
  1287. * This is a internal function called to free the said BIB entry
  1288. *
  1289. * RETURNS : N/A
  1290. * NOMANUAL
  1291. */
  1292. LOCAL void muxTkBibEntryFree
  1293.     (
  1294.     MUX_ID muxId /* BIB entry pointer */
  1295.     )
  1296.     {
  1297.     if (muxId == NULL)
  1298. return;
  1299.     /*
  1300.      * we bzero the entry if it is a driver load entry and no protocols
  1301.      * are bound OR if it is not a driver load entry and a protocol is
  1302.      * bound at this entry
  1303.      */
  1304.     if (((DRV_ENTRY_CHECK(muxId) == TRUE) &&
  1305.  (PROTO_ENTRY_CHECK(muxId)== FALSE)) ||
  1306.         ((DRV_ENTRY_CHECK(muxId) == FALSE) &&
  1307.  (PROTO_ENTRY_CHECK(muxId)== TRUE)))
  1308. {
  1309. bzero ((void *)muxId, sizeof(MUX_BIND_ENTRY));
  1310. }
  1311.     else if ((PROTO_ENTRY_CHECK(muxId) == TRUE) && 
  1312.      (DRV_ENTRY_CHECK(muxId) == TRUE))
  1313. {
  1314. /* here we simply clean up the protocol information */
  1315.      muxId->flags &= ~BIB_PROTO_ENTRY;
  1316. muxId->addrResFunc = NULL;
  1317. muxId->netSvcType = 0;
  1318. muxId->netDrvType = 0;
  1319. muxId->pNetCallbackId = NULL;
  1320. }
  1321.     }
  1322. /******************************************************************************
  1323. *
  1324. * muxTkBibShow - show the BIB entries
  1325. *
  1326. * This is an unpublished BIB show routine 
  1327. *
  1328. * RETURNS : N/A
  1329. * NOMANUAL
  1330. */
  1331. void muxTkBibShow (void)
  1332.     {
  1333.     int    i;
  1334.     int    count = 0;
  1335.     MUX_ID muxId = NULL;
  1336.     for (i = 0; i < muxMaxBinds; i++)
  1337. {
  1338. if (muxBindBase[i].pEnd == NULL)
  1339.     {
  1340.     continue;
  1341.     }
  1342. else if (++count == 1)
  1343.     {
  1344.     /* print banner */
  1345.     printf("n%5s   %8s  %8s  %8s  %8s n", "Slot#",
  1346.     "Svc Type", "Drv Name", "Drv Unit", "DRV_ENT");
  1347.     printf("%4s   %8s  %8s  %8s  %8s nn", "----",
  1348.     "--------", "--------", "--------", "--------");
  1349.     }
  1350. muxId = &muxBindBase[i];
  1351. printf ("%5d  0x%x  %8s  %8d  %8s n", i,
  1352.         (UINT)muxId->netSvcType, muxId->devName, muxId->unitNo,
  1353.         (char *)(DRV_ENTRY_CHECK(muxId) ? "DRV_ENTRY" : "    "));
  1354. }
  1355.     }
  1356. /*
  1357.  * The functions below are called by the SENS MUX API implementation to upgrade
  1358.  * to NPT infrastructure using the BIB
  1359.  */
  1360. /******************************************************************************
  1361. *
  1362. * muxTkBibInit - Initialize the BIB
  1363. *
  1364. * This initializes the MUX BIB used by NPT to store binding information. This
  1365. * routine also initializes the list to store the MUX service functions. 
  1366. *
  1367. * Note: This routine is called by muxLibInit()
  1368. *
  1369. * RETURNS: OK  or ERROR
  1370. * NOMANUAL
  1371. */
  1372. STATUS muxTkBibInit (void)
  1373.     {
  1374.     int count;
  1375.     if (muxBibLock != NULL)
  1376. return (OK);
  1377.     muxBibLock = semBCreate (SEM_Q_PRIORITY, SEM_FULL);
  1378.     if (muxBibLock == NULL)
  1379. return (ERROR);
  1380.     /* allocate the BIB table */
  1381.     muxBindBase = (MUX_ID) KHEAP_ALLOC(muxMaxBinds * sizeof (MUX_BIND_ENTRY));
  1382.     if (muxBindBase == NULL)
  1383. return (ERROR);
  1384.     /* Initialize the BIB table */
  1385.     for (count = 0; count < muxMaxBinds; count++)
  1386.         bzero ((char*) &muxBindBase[count], sizeof(MUX_BIND_ENTRY));
  1387.     return (OK);
  1388.     }
  1389. /*******************************************************************************
  1390. *
  1391. * muxTkDevLoadUpdate - Hook routine called from muxDevLoad
  1392. *
  1393. * This is called from muxDevLoad() to load the driver into the BIB.
  1394. * The driver is queried for NPT/END mode of operation and the receive
  1395. * routine in the END_OBJ is set accordingly.
  1396. *
  1397. * RETURNS: muxId or NULL.
  1398. * NOMANUAL
  1399. */
  1400. void * muxTkDevLoadUpdate
  1401.     (
  1402.     END_OBJ * pEnd
  1403.     )
  1404.     {
  1405.     int count = 0;  /* index for BIB */
  1406.     if (pEnd == NULL)
  1407.         return (NULL);
  1408.     /* Take the Bib semaphore and create an Entry in the BIB table */
  1409.     semTake (muxBibLock, WAIT_FOREVER);
  1410.     while ( (muxBindBase[count].pEnd != NULL) && (count < muxMaxBinds))
  1411. {
  1412. count++;
  1413. }
  1414.     semGive (muxBibLock);
  1415.     if (count == muxMaxBinds)
  1416.         return (NULL);
  1417.     muxBindBase[count].unitNo = pEnd->devObject.unit;
  1418.     strcpy (muxBindBase[count].devName, pEnd->devObject.name);
  1419.     muxBindBase[count].pEnd = pEnd;
  1420.     muxBindBase[count].flags = BIB_DRV_ENTRY;
  1421.     /* set the toolkit flag and the MUX receive routine  */
  1422.     if ((END_IOCTL(pEnd)(pEnd, EIOCGNPT, NULL)) == OK)
  1423.         {
  1424.         TK_DRV_SET(&muxBindBase[count]);
  1425.         pEnd->receiveRtn = (FUNCPTR)muxTkReceive;
  1426.         }
  1427.     else
  1428.         {
  1429.         TK_DRV_CLEAR(&muxBindBase[count]);
  1430.         pEnd->receiveRtn = (FUNCPTR)muxReceive;
  1431.         }
  1432.     return (&muxBindBase[count]);
  1433.     }
  1434. /*******************************************************************************
  1435. *
  1436. * muxTkUnbindUpdate - free the BIB entry upon unbind
  1437. *
  1438. * This routine is called by muxUnbind()
  1439. *
  1440. * RETURNS : N/A
  1441. * NOMANUAL
  1442. */
  1443. void muxTkUnbindUpdate
  1444.     (
  1445.     void * pCookie /* bind cookie */
  1446.     )
  1447.     {
  1448.     MUX_ID muxId = (MUX_ID) pCookie;
  1449.     muxTkBibEntryFree (muxId);
  1450.     }
  1451. /*******************************************************************************
  1452. *
  1453. * muxTkBindUpdate - Hook routine is called from muxBind
  1454. *
  1455. * This hook is called from muxBind() to update the BIB introduced by NPT
  1456. * Finds an entry in the mux BIB and fills in the relevant information
  1457. *
  1458. * RETURNS : muxId or NULL.
  1459. * NOMANUAL
  1460. */
  1461. void * muxTkBindUpdate
  1462.     (
  1463.     END_OBJ *      pEnd, /* the END being bound to */
  1464.     NET_PROTOCOL * pProto /* the protocol node added to the END */
  1465.     )
  1466.     {
  1467.     int    index          = -1;
  1468.     BOOL   tkFlag         = FALSE;
  1469.     int    netSvcType     = 0;
  1470.     void * pNetCallbackId = NULL;
  1471.     if (pEnd == NULL)
  1472.         return (NULL);
  1473.     /* find and get a BIB entry */
  1474.     if ((index = muxTkBibEntryGet (pEnd)) < 0)
  1475. return (NULL);
  1476.     else
  1477. {
  1478. if ((tkFlag = TK_DRV_CHECK(&muxBindBase[index])) == TRUE)
  1479.     {
  1480.     /*
  1481.      * cannot bind to a NPT driver using muxBind; free BIB entry
  1482.      * and return
  1483.      */
  1484.             muxTkBibEntryFree (&muxBindBase[index]);
  1485.     return (NULL);
  1486.     }
  1487. }
  1488.     if (pProto != NULL)
  1489. {
  1490. netSvcType = pProto->type;
  1491. pNetCallbackId = pProto->pSpare;
  1492. muxBindBase[index].netStackRcvRtn = pProto->stackRcvRtn;
  1493. }
  1494.     /* complete the BIB entry */
  1495.     muxTkBibEntryFill (index, netSvcType,pNetCallbackId);
  1496.     return (&muxBindBase[index]);
  1497.     }
  1498. /******************************************************************************
  1499. *
  1500. * muxTkUnloadUpdate - delete the entries in the BIB
  1501. *
  1502. * This hook is called from muxDevUnload() when a device is being unloaded and
  1503. * the corresponding entry in the BIB is to be removed
  1504. *
  1505. * RETURNS STATUS
  1506. * NOMANUAL
  1507. */
  1508. STATUS muxTkUnloadUpdate
  1509.     (
  1510.     END_OBJ * pEnd
  1511.     )
  1512.     {
  1513.     int  count = 0;     /* index */
  1514.     BOOL error = FALSE;
  1515.     /* delete the corresponding entry in the BIB table */
  1516.     semTake (muxBibLock, WAIT_FOREVER); 
  1517.     for (count = 0; count < muxMaxBinds; count++)
  1518.         {
  1519.         /* commented out since T2 NPT
  1520. if (STREQ(muxBindBase[count].devName, pEnd->devObject.name) &&
  1521.     muxBindBase[count].unitNo==pEnd->devObject.unit &&
  1522.     (DRV_ENTRY_CHECK(&muxBindBase[count]) == TRUE))
  1523. */
  1524. if (muxBindBase[count].pEnd == pEnd)
  1525.     {
  1526.     if (muxBindBase[count].netSvcType == MUX_PROTO_OUTPUT)
  1527. muxTkBibEntryFree(&muxBindBase[count]);
  1528.     if (DRV_ENTRY_CHECK(&muxBindBase[count]) == TRUE)
  1529. {
  1530. muxTkBibEntryFree (&muxBindBase[count]);
  1531. error = TRUE;
  1532. }
  1533.     }
  1534.         }
  1535.  
  1536.     semGive (muxBibLock);
  1537.     return (error);
  1538.     }