📄 muxlib.c
字号:
/* Check to see if we have a valid device. */ pEnd = endFindByName(pName, unit); if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); return (NULL); } /* * Check to see if an output protocol already exists. */ if (type == MUX_PROTO_OUTPUT) { if (pEnd->outputFilter) { errnoSet(S_muxLib_ALREADY_BOUND); return (NULL); } } /* * Get the appropriate place in the protocol list if necessary. * For standard protocols, also check if the protocol number * is available. */ if (type != MUX_PROTO_PROMISC && type != MUX_PROTO_OUTPUT) { /* Get the first standard protocol and last snarf protocol, if any. */ if (pEnd->snarfCount) { pFinal = lstNth (&pEnd->protocols, pEnd->snarfCount); pNode = (NET_PROTOCOL *)lstNext (pFinal); } else pNode = (NET_PROTOCOL *)lstFirst (&pEnd->protocols); } if (type != MUX_PROTO_SNARF && type != MUX_PROTO_PROMISC && type != MUX_PROTO_OUTPUT) { for ( ; 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 *) KHEAP_ALLOC (sizeof (NET_PROTOCOL)); if (pNew == NULL) { if (muxLibState.debug) logMsg ("muxBind cannot allocate protocol node", 0, 0, 0, 0, 0, 0); errnoSet (S_muxLib_ALLOC_FAILED); return (NULL); } bzero ( (char *)pNew, sizeof (NET_PROTOCOL)); pNew->stackRcvRtn = stackRcvRtn; if (type != MUX_PROTO_OUTPUT) { pNew->stackShutdownRtn = stackShutdownRtn; pNew->stackTxRestartRtn = stackTxRestartRtn; pNew->stackErrorRtn = stackErrorRtn; } pNew->pEnd = pEnd; pNew->type = type; pNew->nptFlag = FALSE; /* Protocol uses original MUX prototypes. */ pNew->pSpare = pSpare; if (type != MUX_PROTO_OUTPUT) { if (pProtoName != NULL) { strncpy(pNew->name, pProtoName, 32); } else { sprintf(pNew->name, "Protocol %d", lstCount(&pEnd->protocols)); } } switch (type) { case MUX_PROTO_OUTPUT: case MUX_PROTO_PROMISC: lstAdd(&pEnd->protocols, &pNew->node); break; default: /* Add a standard or snarf protocol after any existing ones. */ if (pEnd->snarfCount) { lstInsert(&pEnd->protocols, pFinal, &pNew->node); } else { lstInsert(&pEnd->protocols, NULL, &pNew->node); } break; } /* update the BIB. */ if((pCookie = muxTkBindUpdate(pEnd,pNew)) == NULL) { /* unbind the protocol */ lstDelete(&pEnd->protocols, &pNew->node); KHEAP_FREE((char *)pNew); return (NULL); } else if (type == MUX_PROTO_SNARF) /* Increase the count. */ (pEnd->snarfCount)++; if (type == MUX_PROTO_OUTPUT) { pEnd->outputFilter = pNew; pEnd->pOutputFilterSpare = pSpare; } pNew->pNptCookie = pCookie; return (pCookie); }/****************************************************************************** * muxSend - send a packet out on a network interface** This routine transmits a packet for the service specified by <pCookie>.* You got this cookie from a previous bind call that bound the service to * a particular interface. This muxSend() call uses this bound interface to * transmit the packet.** .IP <pCookie>* Expects the cookie returned from muxBind(). This cookie identifies a* particular service-to-interface binding.* .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(). ** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call muxSend() from within the kernel * protection domain only, and the data referenced in the <pCookie> and * <pNBuff> parameters must reside in the kernel protection domain. * This restriction does not apply under non-AE versions of VxWorks. ** RETURNS: OK; ENETDOWN, if <pCookie> does not represent a valid binding;* or ERROR, if the driver's endSend() routine fails.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxSend ( void * pCookie, /* protocol/device binding from muxBind() */ M_BLK_ID pNBuff /* data to be sent */ ) { int error; END_OBJ * pEnd; LL_HDR_INFO llHdrInfo; long type; NET_PROTOCOL * pOut = NULL; pEnd = PCOOKIE_TO_ENDOBJ (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)) { if (pEnd->flags & END_MIB_2233) { /* * Do nothing as ifOutNUcastPkts is updated by the * m2PktCountRtn function specified in the END object's M2_ID. */ } else /* RFC1213 style counters supported) XXX */ { ++(pEnd->mib2Tbl.ifOutNUcastPkts); } } if (pEnd->outputFilter) { pOut = pEnd->outputFilter; if (muxPacketDataGet (pCookie, pNBuff, &llHdrInfo) == ERROR) return (ERROR); type = llHdrInfo.pktType; if (pOut->stackRcvRtn (pOut->pNptCookie, type, pNBuff, &llHdrInfo, pEnd->pOutputFilterSpare) == TRUE) { return (OK); } } error = pEnd->pFuncTable->send (pEnd, pNBuff); } return (error); }/****************************************************************************** * muxReceive - handle a packet from a device driver** An END calls this routine to transfer a packet to one or more bound* services.** NOTE: The stack receive routine installed by a protocol must not alter* the packet if it returns FALSE.** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call muxReceive() from within the kernel * protection domain only, and the data referenced in the <pCookie> and * <pMblk> parameters must reside in the kernel protection domain. * This restriction does not apply under non-AE versions of VxWorks. ** RETURNS: OK or ERROR.** ERRNO: S_muxLib_NO_DEVICE** NOMANUAL*/STATUS muxReceive ( void * pCookie, /* device identifier from driver's load routine */ M_BLK_ID pMblk /* buffer containing received frame */ ) { NET_PROTOCOL * pProto; END_OBJ * pEnd; long type; LL_HDR_INFO llHdrInfo; int count; 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. */ count = lstCount (&pEnd->protocols); if (count <= 0) { if (pMblk) netMblkClChainFree (pMblk); return (ERROR); } pProto = (NET_PROTOCOL *)lstFirst (&pEnd->protocols); if (pProto == NULL) { if (pMblk) netMblkClChainFree (pMblk); return (ERROR); } /* Ignore incoming data if an output protocol is the only entry. */ if (count == 1 && pProto->type == MUX_PROTO_OUTPUT) { if (pMblk) netMblkClChainFree (pMblk); return (ERROR); } if (muxPacketDataGet (pProto->pNptCookie, pMblk, &llHdrInfo) == ERROR) { if (pEnd->flags & END_MIB_2233) { if ((pEnd->pMib2Tbl != NULL) && (pEnd->pMib2Tbl->m2CtrUpdateRtn != NULL)) { pEnd->pMib2Tbl->m2CtrUpdateRtn(pEnd->pMib2Tbl, M2_ctrId_ifInErrors, 1); } } else /* (RFC1213 style of counters supported) */ { pEnd->mib2Tbl.ifInErrors++; } if (pMblk) netMblkClChainFree (pMblk); return (ERROR); } type = llHdrInfo.pktType; /* * Loop through the protocol list. * If a service's receive routine returns TRUE, it has consumed the * packet. The receive routine must return FALSE for other services * to see the packet. * * The order of services in the list (established during the bind) * determines their priority. SNARF services have the priority over * every other service type. PROMISC services have the lowest priority. * If multiple SNARF or PROMISC services exist, the order is first-come, * first-served, which could prevent some services from seeing matching * data if an earlier entry consumes it. */ for (;pProto != NULL; pProto = (NET_PROTOCOL *)lstNext (&pProto->node)) { if (pProto->type == MUX_PROTO_OUTPUT) /* Ignore output service. */ continue; /* * Handoff the data to any SNARF or promiscuous protocols, or to * a standard protocol which registered for the frame type. */ if (pProto->type == MUX_PROTO_SNARF || pProto->type == MUX_PROTO_PROMISC || pProto->type == type) { if ( (*pProto->stackRcvRtn) (pProto->pNptCookie, type, pMblk, &llHdrInfo, pProto->pSpare) == TRUE) return (OK); } } /* Unknown service. Free the packet. */ if (pEnd->flags & END_MIB_2233) { if ((pEnd->pMib2Tbl != NULL) && (pEnd->pMib2Tbl->m2CtrUpdateRtn != NULL)) { pEnd->pMib2Tbl->m2CtrUpdateRtn(pEnd->pMib2Tbl, M2_ctrId_ifInUnknownProtos, 1); } } else /* (RFC1213 style counters supported) XXX */ { pEnd->mib2Tbl.ifInUnknownProtos++; } if (pMblk) netMblkClChainFree (pMblk); return OK; }#endif /* STANDALONE_AGENT *//****************************************************************************** * muxPollSend - now 'deprecated', see muxTkPollSend()** This routine transmits a packet for the service specified by <pCookie>.* You got this cookie from a previous bind call that bound the service to * a particular interface. This muxPollSend() call uses this bound interface * to transmit the packet. The <pNBuff> argument is a buffer ('mBlk') chain * that contains the packet to be sent.** RETURNS: OK; ENETDOWN, if <pCookie> does not represent a valid device;* ERROR, if the device type is not recognized; or an error value from the * device's registered endPollSend() routine. ** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxPollSend ( void * pCookie, /* binding instance from muxBind() */ M_BLK_ID pNBuff /* data to be sent */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -