📄 muxlib.c
字号:
{ int error; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = ENETDOWN; } else { switch (cmd) { case EIOCMULTIADD: error = pEnd->pFuncTable->mCastAddrAdd(pEnd, (char *)data); break; case EIOCMULTIDEL: error = pEnd->pFuncTable->mCastAddrDel(pEnd, (char *)data); break; case EIOCMULTIGET: error = pEnd->pFuncTable->mCastAddrGet(pEnd, (MULTI_TABLE *)data); break; default: error = pEnd->pFuncTable->ioctl(pEnd, cmd, data); break; } } return (error); }/******************************************************************************** muxMCastAddrAdd - add a multicast address to multicast table for a device** This routine adds an address to the multicast table maintained for a device. * Internally, this function uses <pCookie> to find the device-specific * routine that handles adding an address to the device's multicast table. * * .IP <pCookie> 13* Expects the pointer returned as the function value of the muxBind() * call. This pointer identifies the device to which the MUX has bound this * protocol. * .IP <pAddress>* Expects a pointer to a character string containing the address you * want to add. * * RETURNS: OK, ENETDOWN if <pCookie> doesn't represent a valid device,* or ERROR if the device's endMCastAddrAdd() function fails.** ERRNO: ENOTSUP, S_muxLib_NO_DEVICE**/STATUS muxMCastAddrAdd ( void* pCookie, /* returned by the muxBind() call */ char *pAddress /* address to add to the table */ ) { int error; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = ENETDOWN; } else { error = pEnd->pFuncTable->mCastAddrAdd(pEnd, pAddress); } return (error); }/******************************************************************************** muxMCastAddrDel - delete a multicast address from a device's multicast table** This routine deletes an address from the multicast table maintained for a * device. Internally, this function uses <pCookie> to find the * device-specific routine that handles deleting an address from the * device's multicast table.** .IP <pCookie> 13* Expects the pointer returned as the function value of the muxBind() * call. This pointer identifies the device to which the MUX bound this * protocol. * .IP <pAddress>* Expects a pointer to a character string containing the address you * want to delete. ** RETURNS: OK, ENETDOWN if <pCookie> does not represent a valid driver,* or ERROR if the driver's registered endMCastAddrDel() function* fails.** ERRNO: ENOTSUP, EINVAL, S_muxLib_NO_DEVICE**/STATUS muxMCastAddrDel ( void* pCookie, /* Returned by the muxBind() call */ char* pAddress /* Address to delete from the table. */ ) { int error; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = ENETDOWN; } else { error = pEnd->pFuncTable->mCastAddrDel(pEnd, pAddress); } return (error); }/******************************************************************************** muxMCastAddrGet - get the multicast address table from the MUX/Driver** This routine expects a buffer into which it can write the list * of multicast addresses for the specified device. Internally, this* routine uses <pCookie> to access the device-specific routine needed* to retrieve the multicast address table. ** .IP <pCookie>* Expects the pointer returned as the function value of the muxBind() * call. This pointer identifies the device to which the MUX has bound this * protocol. * .IP <pTable>* Expects the pointer to a MULTI_TABLE structure. You must have allocated * this structure at some time before the call to muxMCastAddrGet(). * The MULTI_TABLE structure is defined in end.h as: * * .CS* typedef struct multi_table* {* int tableLen; /@ length of table in bytes @/* char *pTable; /@ pointer to entries @/* } MULTI_TABLE;* .CE** RETURNS: OK, ENETDOWN if <pCookie> does not represent a valid driver,* or ERROR if the driver's registered endMCastAddrGet() function fails.** ERRNO: S_muxLib_NO_DEVICE*/int muxMCastAddrGet ( void* pCookie, /* returned by the muxBind() call */ MULTI_TABLE *pTable /* pointer to a table to be filled and returned. */ ) { int error; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = ENETDOWN; } else { error = pEnd->pFuncTable->mCastAddrGet(pEnd, pTable); } return (error); }/******************************************************************************** muxUnbind - detach a protocol from the specified driver** This routine disconnects a protocol from the specified driver. ** .IP <pCookie> 15* Expects the pointer returned as the function value from the * muxBind() call. This pointer identifies the device to which the * MUX has bound this protocol. * .IP <type>* This is the type that you passed down in the muxBind() call.* .IP <stackRcvRtn>* Expects a pointer to the stack receive routine you specified when you * called muxBind() to bind the driver and protocol. ** RETURNS: OK, EINVAL if <pCookie> does not represent a valid driver or * the protocol is not attached, ERROR if muxUnbind() fails.* * ERRNO: EINVAL, S_muxLib_NO_DEVICE*/STATUS muxUnbind ( void* pCookie, /* pointer to identifier for device */ long type, /* device type passed in muxBind() call */ FUNCPTR stackRcvRtn /* pointer to stack receive routine */ ) { int error; END_OBJ* pEnd = (END_OBJ *)pCookie; NET_PROTOCOL* pNode; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = EINVAL; return error; } else { /* Special case for output protocols. */ if (type == MUX_PROTO_OUTPUT) { if (pEnd->outputFilter) { pEnd->outputFilter = NULL; return (OK); } else { errnoSet(EINVAL); return (ERROR); } } for (pNode = (NET_PROTOCOL *)lstFirst(&pEnd->protocols); pNode != NULL; pNode = (NET_PROTOCOL *)lstNext(&pNode->node)) { if (pNode->stackRcvRtn == stackRcvRtn && pNode->type == type) { if (pNode->type == MUX_PROTO_SNARF) pEnd->snarfProto = FALSE; lstDelete(&pEnd->protocols, &pNode->node); free(pNode); return (OK); } } } errnoSet(EINVAL); return (ERROR); } /******************************************************************************** muxDevUnload - remove a driver from the MUX** This routine unloads a driver from the MUX. This breaks any* network connections an application might have open. The* stackShutdownRtn() of each protocol bound to the END via* muxBind() will be called. Each stackShutdownRtn() is expected* to call muxUnbind() to detach from the END.** .IP <pName>* Expects a pointer to a string containing the name of the device, for example* 'ln' or 'ei'** .IP <unit>* Expects the unit number of the device indicated by <pName>** RETURNS: OK on success, EINVAL or ERROR if the device's registered* endUnload() function failed, if the specified device was not found,* or some other error occurred** ERRNO: S_muxLib_UNLOAD_FAILED, S_muxLib_NO_DEVICE**/STATUS muxDevUnload ( char *pName, /* a string containing the name of the device */ /* for example, ln or ei */ int unit /* the unit number */ ) { int error; END_OBJ* pEnd = NULL; NET_PROTOCOL* pNetNode; NET_PROTOCOL* pNetNodeNext; END_TBL_ROW* pNode; pEnd = endFindByName (pName, unit); if (pEnd != NULL) { semTake (muxLock, WAIT_FOREVER); /* * Find which row we're in. WE know it' shere because endFindByName * did not fail. */ for (pNode = (END_TBL_ROW *)lstFirst(&endList); pNode != NULL; pNode = (END_TBL_ROW *)lstNext(&pNode->node)) { if (STREQ(pNode->name, pName)) break; } /* First we shutdown all of the protocols. */ for (pNetNode = (NET_PROTOCOL *) lstFirst (&pEnd->protocols); pNetNode != NULL; pNetNode = pNetNodeNext) { /* Save pointer to next node as shutdown rtn will free pNetNode */ pNetNodeNext = (NET_PROTOCOL *) lstNext (&pNetNode->node); if (pNetNode->stackShutdownRtn != NULL) { /* * stackShutdownRtn () is expected to call muxUnbind () which * will free the NET_PROTOCOL node so it is not necessary here. */ pNetNode->stackShutdownRtn (pEnd, pNetNode->pSpare); } else { /* * If no shutdown rtn then muxUnbind () will not be called and * we need to free the pNetNode ourselves. */ lstDelete (&pEnd->protocols, &pNetNode->node); free (pNetNode); } } error = pEnd->pFuncTable->unload(pEnd); if (error != OK) { errnoSet(S_muxLib_UNLOAD_FAILED); semGive (muxLock); return (ERROR); } lstDelete(&pNode->units, &pEnd->node); free(pEnd->devObject.pDevice); /* Is this row empty? If so, remove it. */ if (lstCount(&pNode->units) == 0) { lstDelete (&endList, &pNode->node); free (pNode); } error = OK; semGive (muxLock); } else { errnoSet(S_muxLib_NO_DEVICE); error = ERROR; } return(error); }/******************************************************************************** muxAddressForm - form an address into a packet** This routine accepts the source and destination addressing information* through the <pSrcAddr> and <pDstAddr> mBlks and returns an M_BLK_ID that * points to the assembled link-level header. This routine prepends the * link-level header into <pMblk> if there is enough space available or it * allocates a new 'mBlk'-'clBlk'-cluster and prepends the new <mBlk> * to the 'mBlk' chain passed in <pMblk>. This routine returns a pointer to * an 'mBlk' that contains the link-level header information.** .IP <pCookie> 13* Expects the pointer returned from the muxBind(). This pointer * identifies the device to which the MUX has bound this protocol. * .IP <pMblk>* Expects a pointer to the 'mBlk' structure that contains the packet. * .IP <pSrcAddr>* Expects a pointer to the 'mBlk' that contains the source address.* .IP <pDstAddr>* Expects a pointer to the 'mBlk' that contains the destination address.** RETURNS: M_BLK_ID or NULL.** ERRNO: S_muxLib_NO_DEVICE*/M_BLK_ID muxAddressForm ( void* pCookie, /* cookie that identifies the device */ M_BLK_ID pMblk, /* structure to contain packet */ M_BLK_ID pSrcAddr, /* structure containing source address */ M_BLK_ID pDstAddr /* structure containing destination address */ ) { END_OBJ* pEnd; M_BLK_ID pMblkHdr = NULL; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); return (NULL); } if (pEnd->pFuncTable->formAddress != NULL) { pMblkHdr = pEnd->pFuncTable->formAddress (pMblk, pSrcAddr, pDstAddr); } else { switch (pEnd->mib2Tbl.ifType) { case M2_ifType_ethernet_csmacd: case M2_ifType_iso88023_csmacd: M_PREPEND(pMblk, ENET_HDR_REAL_SIZ, M_DONTWAIT); bcopy(pDstAddr->m_data, pMblk->m_data, pDstAddr->m_len); bcopy(pSrcAddr->m_data, pMblk->m_data + pDstAddr->m_len, pSrcAddr->m_len); ((ENET_HDR *)pMblk->m_data)->type = pDstAddr->mBlkHdr.reserved; pMblkHdr = pMblk; break; default: break; } } return (pMblkHdr); }/******************************************************************************** muxPacketDataGet - return the data from a packet** This routine copies the header information from the packet referenced in* <pMblk> into the LL_HDR_INFO structure referenced in <pLinkHdrInfo>.** .IP <pCookie>* Expects the cookie returned from the muxBind() call. This* cookie identifies the device to which the MUX bound this protocol.** .IP <pMblk>* Expects a pointer to an 'mBlk' or 'mBlk' cluster representing a packet* containing the data to be returned** .IP <pLinkHdrInfo>* Expects a pointer to an LL_HDR_INFO structure into which the packet header* information is copied from the incoming 'mBlk'* * RETURNS: OK or ERROR if the device type is not recognized.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxPacketDataGet ( void* pCookie, /* cookie that identifies the device */ M_BLK_ID pMblk, /* returns the packet data */ LL_HDR_INFO * pLinkHdrInfo /* the new data is returned here */ ) { int error = OK; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); return (ERROR); } if (pEnd->pFuncTable->packetDataGet != NULL) { error = pEnd->pFuncTable->packetDataGet(pMblk, pLinkHdrInfo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -