📄 muxlib.c
字号:
}/******************************************************************************** muxBind - bind a protocol to the MUX given a driver name ** A protocol uses this routine to bind to a specific driver.* The driver is specified by the <pName> and <unit> arguments* (for example, ln and 0, ln and 1, ei and 0, ...).* The <stackRcvRtn> is called whenever the MUX has a packet of the specified * type. If the type is MUX_PROTO_PROMISC, the protocol is considered * promiscuous and will get all of the packets that the MUX sees.* * .IP <pName> 20 * Expects a pointer to a character string that contains the name * of the device to which this protocol wants to use to send and * receive packets. * .IP <unit>* Expects a number which is the unit of the device of the type indicated* by <pName>.* .IP <stackRcvRtn> * Expects a pointer function that the MUX can call when it * wants to pass a packet up to the protocol. For a description of * how you should write this routine, * see the description of a stackRcvRtn()* provided in * .I "Network Protocol Toolkit User's Guide."* .IP <stackShutdownRtn> * Expects a pointer to the function that the MUX can call to * shutdown the protocol. For a description of how to write such * a routine, see stackShutdownRtn() see the description of a stackRcvRtn()* provided in * .I "Network Protocol Toolkit User's Guide."* .IP <stackErrorRtn>* Expects a pointer to the function that the MUX can call to give errors* to the protocol.* .IP <type> * Expects a value that indicates the protocol type. The MUX * uses this type to prioritize the protocol. For example, a * protocol of type MUX_PROTO_SNARF has the highest priority * (see the description of protocol prioritizing provided in * .I "Network Protocol Toolkit User's Guide: Writing an NPT Protocol."* Aside from MUX_PROTO_SNARF and MUX_PROTO_PROMISC, valid protocol * types include any of the values specified in RFC1700. * If the type is MUX_PROTO_OUTPUT, this protocol is an output protocol and all* packets that are going to be output on this device are passed to the* stackRcvRtn() routine before actually being sent down to the device. This* would be useful, for instance, for a network service that needs to send* packets directly to another network service, or for loop-back testing.* If the stackRcvRtn() returns OK, the packet is considered to have been* consumed and is no longer available. An output protocol may return ERROR* from its stackRcvRtn() in order to look at the packet without consuming it.* .IP <pProtoName> * Expects a pointer to a character string for the name of this * protocol. This string can be NULL, in which case a protocol name is* assigned internally.* .IP <pSpare>* Expects a pointer to a structure defined by the protocol. This argument* is passed up to the protocol with each received packet.* * RETURNS: A cookie identifying the network driver to which the mux has* bound the protocol.** ERRNO: S_muxLib_NO_DEVICE, S_muxLib_ALREADY_BOUND, S_muxLib_ALLOC_FAILED*/END_OBJ* muxBind ( char * pName, /* interface name, for example, ln, ei,... */ int unit, /* unit number */ BOOL (*stackRcvRtn) (void*, long, M_BLK_ID, LL_HDR_INFO *, void*), /* receive function to be called. */ STATUS (*stackShutdownRtn) (void*, void*), /* routine to call to shutdown the stack */ STATUS (*stackTxRestartRtn) (void*, void*), /* routine to tell the stack it can transmit */ void (*stackErrorRtn) (END_OBJ*, END_ERR*, void*), /* routine to call on an error. */ long type, /* protocol type from RFC1700 and many */ /* other sources (for example, 0x800 is IP) */ char* pProtoName, /* string name for protocol */ void* pSpare /* per protocol spare pointer */ ) { NET_PROTOCOL* pNew; NET_PROTOCOL* pNode; END_OBJ* pEnd; /* Check to see if we have a valid device. */ pEnd = endFindByName(pName, unit); if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); return (pEnd); } /* if we already have a snarf protcol then return NULL. */ if (type == MUX_PROTO_SNARF && pEnd->snarfProto) return (NULL); /* * Check to see if this is an OUTPUT protocol. * If this is the case then that filter is placed into the * device object itself. */ if (type == MUX_PROTO_OUTPUT) { if (pEnd->outputFilter) { errnoSet(S_muxLib_ALREADY_BOUND); return (NULL); } else { pEnd->outputFilter = stackRcvRtn; pEnd->pOutputFilterSpare = pSpare; return (pEnd); } } /* Check to see if this protocol number is already taken. */ for (pNode = (NET_PROTOCOL *)lstFirst(&pEnd->protocols); pNode != NULL; pNode = (NET_PROTOCOL *)lstNext(&pNode->node)) { if (pNode->type == type) { errnoSet(S_muxLib_ALREADY_BOUND); return (NULL); } } /* Now we can allocate a new protocol structure. */ pNew = (NET_PROTOCOL *)malloc(sizeof(NET_PROTOCOL)); if (pNew == NULL) { logMsg ("muxBind cannot allocate protocol node", 1, 2, 3, 4, 5, 6); errnoSet (S_muxLib_ALLOC_FAILED); return (NULL); } bzero((char *)pNew, sizeof(NET_PROTOCOL)); pNew->stackRcvRtn = stackRcvRtn; pNew->stackShutdownRtn = stackShutdownRtn; pNew->stackTxRestartRtn = stackTxRestartRtn; pNew->stackErrorRtn = stackErrorRtn; pNew->type = type; pNew->flags = 0; pNew->pSpare = pSpare; if (pProtoName != NULL) { strncpy(pNew->name, pProtoName, 32); } else { sprintf(pNew->name, "Protocol %d", lstCount(&pEnd->protocols)); } switch (type) { case MUX_PROTO_PROMISC: lstAdd(&pEnd->protocols, &pNew->node); break; case MUX_PROTO_SNARF: lstInsert(&pEnd->protocols, NULL, &pNew->node); pEnd->snarfProto = TRUE; break; default: if (pEnd->snarfProto) { lstInsert(&pEnd->protocols, lstFirst(&pEnd->protocols), &pNew->node); } else { lstInsert(&pEnd->protocols, NULL, &pNew->node); } break; } return (pEnd); }/****************************************************************************** * muxSend - send a packet out on a network interface** This routine uses the <pCookie> value returned during the bind to identify* the network interface through which the packet is to be transmitted.** .IP <pCookie>* Expects the pointer returned from muxBind(). This pointer * identifies the device to which the MUX has bound this protocol. * .IP <pNBuff>* Expects a pointer to the buffer that contains the packet you want * to transmit. Before you call muxSend(), you need to put the * addressing information at the head of the buffer. To do this, call * muxAddressForm(). ** Also, the buffer should probably be reserved from the MUX-* managed memory pool. To reserve a buffer from this pool, the * protocol should call muxBufAlloc(). ** RETURNS: OK, ENETDOWN if <pCookie> does not represent a valid interface,* or ERROR if the driver's endSend() routine fails.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxSend ( void* pCookie, /* cookie that identifies a network interface */ /* (returned by muxBind() */ M_BLK_ID pNBuff /* data to be sent */ ) { int error; END_OBJ* pEnd; LL_HDR_INFO llHdrInfo; long type; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = ENETDOWN; } else { if (pNBuff != NULL && (pNBuff->mBlkHdr.mFlags & M_BCAST || pNBuff->mBlkHdr.mFlags & M_MCAST)) { ++(pEnd->mib2Tbl.ifOutNUcastPkts); } if (pEnd->outputFilter) { if (muxPacketDataGet(pCookie, pNBuff, &llHdrInfo) == ERROR) return (ERROR); type = llHdrInfo.pktType; if (pEnd->outputFilter(pEnd->devObject.pDevice, type, pNBuff, &llHdrInfo, pEnd->pOutputFilterSpare) == TRUE) { return (OK); } } error = pEnd->pFuncTable->send(pEnd, pNBuff); } return (error); }/****************************************************************************** * muxReceive - Receive a packet from a device driver.** This is the routine that the driver calls when it wishes to hand a* packet to the MUX.** RETURNS: OK or ERROR.** ERRNO: S_muxLib_NO_DEVICE** NOMANUAL*/STATUS muxReceive ( void* pCookie, /* Cookie passed in endLoad call */ M_BLK_ID pMblk /* A buffer passed to us. */ ) { NET_PROTOCOL * pProto; END_OBJ * pEnd; long type; LL_HDR_INFO llHdrInfo; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); if (pMblk) netMblkClChainFree (pMblk); return (ERROR); } /* Grab a new block and parse out the header information. */ if (lstCount (&pEnd->protocols) <= 0) { if (pMblk) netMblkClChainFree (pMblk); return (FALSE); } /* * Loop through the protocol list. * If a protocol's receive routine returns TRUE, that means it has * consumed the packet. * The protocol's receive routine should always return FALSE if other * protocols have to see the packet. * SNARF protocols have the priority over every other protocol. * PROMISC protocols have the least priority. */ for (pProto = (NET_PROTOCOL *)lstFirst(&pEnd->protocols); pProto != NULL; pProto = (NET_PROTOCOL *)lstNext(&pProto->node)) { if (muxPacketDataGet(pCookie, pMblk, &llHdrInfo) == ERROR) { pEnd->mib2Tbl.ifInErrors++; break; } type = llHdrInfo.pktType; if (pProto->type == MUX_PROTO_SNARF) { if ((*pProto->stackRcvRtn) (pCookie, type, pMblk, &llHdrInfo, pProto->pSpare) == TRUE) return (OK); } else if (pProto->type == type) { if ((*pProto->stackRcvRtn) (pCookie, type, pMblk, &llHdrInfo, pProto->pSpare) == TRUE) return (OK); } else if (pProto->type == MUX_PROTO_PROMISC) { if ((*pProto->stackRcvRtn) (pCookie, type, pMblk, NULL, pProto->pSpare) == TRUE) return (OK); } } /* if the flow comes here then pMblk is not freed */ pEnd->mib2Tbl.ifInUnknownProtos++; if (pMblk) netMblkClChainFree (pMblk); return OK; }/****************************************************************************** * muxPollSend - send a packet on a network interface** This routine takes a cookie which was returned by muxBind()* and uses it to determine which network interface driver* should be used in transmitting the data. The routine takes the data* pointed to by <pNBuff> and sends it to the destination specified by calling* the functions in that driver.** .IP <pCookie>* Expects the cookie returned from muxBind(). This Cookie* identifies the device to which the MUX has bound the protocol calling* muxPollSend().** .IP <pNBuff>* Expects a pointer to the buffer('mBlk') chain that contains the packet to be* transmitted.** RETURNS: OK, ENETDOWN if <pCookie> doesn't represent a valid device,* or ERROR if the device type is not recognized or if the* endPollSend() routine for the driver fails.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxPollSend ( void* pCookie, /* cookie the protocol got from muxBind() */ M_BLK_ID pNBuff /* data to be sent */ ) { int error; END_OBJ* pEnd; LL_HDR_INFO llHdrInfo; long type; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet (S_muxLib_NO_DEVICE); error = ENETDOWN; } else { if (pEnd->outputFilter) { if (muxPacketDataGet(pCookie, pNBuff, &llHdrInfo) == ERROR) return (ERROR); type = llHdrInfo.pktType; if (pEnd->outputFilter(pEnd->devObject.pDevice, type, pNBuff, &llHdrInfo, pEnd->pOutputFilterSpare) == OK) return (OK); } error = pEnd->pFuncTable->pollSend(pEnd, pNBuff); } return (error); }/****************************************************************************** * muxPollReceive - poll for a packet from a device driver** This is the routine that an upper layer can call to poll for a packet.** .IP <pCookie>* Expects the cookie that was returned from muxBind().* This "cookie" is an identifier for the driver.** .IP <pNBuff>* Expects a pointer to a buffer chain into which incoming data will be put.** RETURNS: OK, ENETDOWN if the pCookie* does not represent a loaded driver, or an error value returned* from the driver's registered endPollReceive() function.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxPollReceive ( void* pCookie, /* cookie passed in endLoad call */ M_BLK_ID pNBuff /* a vector of buffers passed to us */ ) { int error; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = ENETDOWN; } else { error = pEnd->pFuncTable->pollRcv(pEnd, pNBuff); } return (error); }/******************************************************************************** muxIoctl - send control information to the MUX or to a device** This routine gives the protocol access to the network driver's control * functions. The MUX itself can implement some of the standard control* functions, so not all commands necessarily pass down to the device. * Otherwise, both command and data pass down to the device unmolested.** This routine also lets the protocol change the routine that the MUX uses * to pass data up to the protocol as well as the routine that the MUX uses * to shutdown the protocol. ** .IP <pCookie>* Expects the pointer returned as the function value of muxBind(). The * pointer identifies the device to which this protocol is bound. * .IP <cmd>* Expects a value indicating the control command you want to execute. * For valid <cmd> values, see the description of the endIoctl() routine* provided in * .I "Network Protocol Toolkit User's Guide".* .IP <data>* Expects the data or a pointer to the data needed to * carry out the command specified in <cmd>. * * RETURNS: OK, ENETDOWN if pCookie does not represent a bound device,* or ERROR if the command fails.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxIoctl ( void* pCookie, /* cookie identifying the device to access */ int cmd, /* command to pass to ioctl */ caddr_t data /* data need for command in cmd */ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -