📄 muxtklib.c
字号:
if ((index = muxTkBibEntryGet (pEnd)) < 0) { if (muxTkDebug) logMsg ("muxTkBind: No more Bind entries", 1, 2, 3, 4, 5, 6); return (NULL); } else { tkFlag = TK_DRV_CHECK(&muxBindBase[index]); } /* Allocate a new protocol structure and bind the protocol to the END. */ pNewProto = (NET_PROTOCOL *)KHEAP_ALLOC(sizeof (NET_PROTOCOL)); if (pNewProto == NULL) { /* free BIB entry */ bzero ((void *)&muxBindBase[index], sizeof(MUX_BIND_ENTRY)); logMsg ("muxBind cannot allocate protocol node", 0, 0, 0, 0, 0, 0); errnoSet (S_muxLib_ALLOC_FAILED); return (NULL); } bzero ( (char *)pNewProto, sizeof(NET_PROTOCOL)); /* bind the protocol to the END */ if (type != MUX_PROTO_OUTPUT) { /* populate all fields in the new protocol node */ pNewProto->stackShutdownRtn = stackShutdownRtn; pNewProto->stackTxRestartRtn = stackTxRestartRtn; pNewProto->stackErrorRtn = stackErrorRtn; } pNewProto->type = type; /* Indicate that muxTkBind() was used. */ pNewProto->nptFlag = TRUE; if (tkFlag != TRUE && type != MUX_PROTO_OUTPUT) { /* Use a wrapper receive routine when sending data with END devices. */ pNewProto->stackRcvRtn = muxEndRcvRtn; } else { pNewProto->stackRcvRtn = stackRcvRtn; } /* * For all input protocols bound using muxTkBind, * install the BIB entry pointer as the call back ID. */ pNewProto->pSpare = &muxBindBase[index]; if (type != MUX_PROTO_OUTPUT) { /* copy the protocol name or generate one if not available */ if (pProtoName != NULL) { strncpy (pNewProto->name, pProtoName, 32); } else { sprintf (pNewProto->name, "Protocol %d", lstCount (&pEnd->protocols)); } } /* Insert the protocol in the END_OBJ protocol list */ switch (type) { case MUX_PROTO_OUTPUT: case MUX_PROTO_PROMISC: lstAdd (&pEnd->protocols, &pNewProto->node); break; default: /* Add a standard or snarf protocol after any existing ones. */ lstInsert(&pEnd->protocols, pFinal, &pNewProto->node); break; } if (type == MUX_PROTO_OUTPUT) { /* For an OUTPUT protocol place the filter in the END object itself. */ pEnd->outputFilter = pNewProto; pEnd->pOutputFilterSpare = pNetCallbackId; muxBindBase[index].pEnd->outputFilter->stackRcvRtn = muxEndRcvRtn; pEnd->outputFilter->stackRcvRtn = stackRcvRtn; } muxBindBase[index].netStackRcvRtn = stackRcvRtn; /* fill the rest of the BIB entry */ muxTkBibEntryFill (index, type, pNetCallbackId); if (type == MUX_PROTO_SNARF) /* Increase the count. */ (pEnd->snarfCount)++; pNewProto->pNptCookie = &muxBindBase[index]; return (&muxBindBase[index]); }/******************************************************************************* muxTkReceive - receive a packet from a NPT driver** This is the routine that the NPT driver calls to hand a packet to the MUX.* This routine forwards the received 'mBlk' chain to the network service* sublayer by calling its registered stackRcvRtn().** Typically, a driver includes an interrupt handling routine to process* received packets. It should keep processing to a minimum during interrupt* context and then arrange for processing of the received packet within* task context.** Once the frame has been validated, the driver should pass it to the MUX* with the 'receiveRtn' member of its END_OBJ structure. This routine has* the same prototype as (and typically is) muxTkReceive().** Depending on the protocol type (for example, MUX_PROTO_SNARF or* MUX_PROTO_PROMISC), this routine either forwards the received packet chain* unmodified or it changes the data pointer in the 'mBlk' to strip off the* frame header before forwarding the packet.** .IP <pCookie>* Expects the END_OBJ pointer returned by the driver's endLoad() or* nptLoad() function** .IP <pMblk>* Expects a pointer to the 'mBlk' structure containing the packet that has* been received** .IP <netSvcOffset>* Expects an offset into the frame to the point where the data field (the* network service layer header) begins** .IP <netSvcType>* Expects the network service type of the service for which the packet is* destined (typically this value can be found in the header of the received* frame)** .IP <uniPromiscuous>* Expects a boolean set to TRUE when driver is in promiscuous mode and* receives a unicast or a multicast packet not intended for this device.* When TRUE the packet is not handed over to network services other than* those registered as SNARF or PROMISCUOUS.** .IP <pSpareData>* Expects a pointer to any spare data the driver needs to pass up to the* network service layer, or NULL** RETURNS: OK or ERROR.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxTkReceive ( void * pCookie, /* cookie passed in endLoad() call */ M_BLK_ID pMblk, /* a buffer passed to us. */ long netSvcOffset, /* offset to network datagram in the packet */ long netSvcType, /* network service type */ BOOL uniPromiscuous, /* TRUE when driver is in promiscuous mode */ void * pSpareData /* out of band data */ ) { NET_PROTOCOL * pProto; END_OBJ * pEnd; long type; M_BLK_ID pMblkOrig; 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 (FALSE); } 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); } /* * 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. */ type = netSvcType; for (; pProto != NULL; pProto = (NET_PROTOCOL *)lstNext (&pProto->node)) { MUX_ID muxId = (MUX_ID)(pProto->pSpare); void * pNetCallbackId = NULL; if (pProto->type == MUX_PROTO_OUTPUT) continue; if (muxId) pNetCallbackId = muxId->pNetCallbackId; if (pProto->type == MUX_PROTO_SNARF) { if ((pProto->stackRcvRtn) && (*pProto->stackRcvRtn) (pNetCallbackId, type, pMblk, pSpareData) == TRUE) return (OK); } else if (pProto->type == type && !uniPromiscuous) { /* Make sure the entire Link Hdr is in the first M_BLK */ pMblkOrig = pMblk; if (pMblk->mBlkHdr.mLen < netSvcOffset && (pMblk = m_pullup (pMblk, netSvcOffset)) == NULL) { pMblk = pMblkOrig; break; } /* remove the MAC header and set the packet length accordingly */ pMblk->mBlkHdr.mData += netSvcOffset; pMblk->mBlkHdr.mLen -= netSvcOffset; pMblk->mBlkPktHdr.len -= netSvcOffset; if ((pProto->stackRcvRtn) && (((*pProto->stackRcvRtn) (pNetCallbackId, type, pMblk, pSpareData)) == TRUE)) { return (OK); } } else if (pProto->type == MUX_PROTO_PROMISC) { if ((pProto->stackRcvRtn) && (((*pProto->stackRcvRtn) (pNetCallbackId, type, pMblk, pSpareData)) == TRUE)) { return (OK); } } } /* if the flow comes here then pMblk is not freed */ if (pMblk) netMblkClChainFree (pMblk); return (OK); }/******************************************************************************* _muxTkSend - A private function common to both muxTkSend and muxTkPollSend** This routine does all of the processing required prior to a muxTkSend() or* muxTkPollSend() and calls the driver's send() or pollSend() routine; a* pointer to which is passed as the last argument. All other arguments are* the same as muxTkSend() or muxTkPollSend()** RETURNS: OK or ERROR** SEE ALSO: muxTkSend(), muxTkPollSend, muxSend(), muxPollSend** NOMANUAL */LOCAL STATUS _muxTkSend ( MUX_ID muxId, /* cookie returned by muxTkBind */ M_BLK_ID pNBuff, /* data to be sent */ char * dstMacAddr, /* destination MAC address */ USHORT netType, /* network protocol that is calling us: redundant? */ void * pSpareData, /* spare data passed on each send */ FUNCPTR sendRtn /* the driver's send routine: poll or regular */ ) { LL_HDR_INFO llHdrInfo; END_OBJ * pEnd = muxId->pEnd; NET_PROTOCOL * pOut = NULL; /* we need these two M_BLKs for endAddressForm */ M_BLK srcAddr = {{NULL,NULL,NULL,0,MT_IFADDR,0,0}, {NULL,0}, NULL}; M_BLK dstAddr = {{NULL,NULL,NULL,0,MT_IFADDR,0,0}, {NULL,0}, NULL}; if (pEnd == NULL) return (ERROR); /* bump MIB2 statistic */ 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 objects * M2_ID. */ } else /* (RFC1213 style counters supported) XXX */ { ++(pEnd->mib2Tbl.ifOutNUcastPkts); } } if (pEnd->outputFilter) { pOut = pEnd->outputFilter; if (pOut->stackRcvRtn (pEnd->pOutputFilterSpare, netType, pNBuff, pSpareData) == TRUE) { return (OK); } } if (!TK_DRV_CHECK(muxId)) { M_BLK_ID pSrcAddr = &srcAddr; M_BLK_ID pDstAddr = &dstAddr; M_BLK_ID pMacFrame = NULL; char srcMacAddr[64]; /* copy END MAC addr into a temporary buffer */ bzero (srcMacAddr, 64); if (pEnd->flags & END_MIB_2233) bcopy(END_ALT_HADDR(pEnd),srcMacAddr,END_ALT_HADDR_LEN(pEnd)); else bcopy(END_HADDR(pEnd),srcMacAddr,END_HADDR_LEN(pEnd)); pDstAddr->mBlkHdr.mData = dstMacAddr; pDstAddr->mBlkHdr.mLen = END_HADDR_LEN(pEnd); pDstAddr->mBlkHdr.reserved = netType; pSrcAddr->mBlkHdr.mData = srcMacAddr; pSrcAddr->mBlkHdr.mLen = END_HADDR_LEN(pEnd); if (pEnd->pFuncTable->formAddress && ((pMacFrame = pEnd->pFuncTable->formAddress (pNBuff, pSrcAddr, pDstAddr, FALSE)) != NULL)) { STATUS status; /* * if we get here, we send the fully formed MAC frame to * the END driver */ status = sendRtn (pEnd, pMacFrame); if (status != OK) { /* * resurrect the network layer packet */ if (pMacFrame == pNBuff) { if (pEnd->pFuncTable->packetDataGet (pNBuff, &llHdrInfo) == ERROR) { if (pNBuff) netMblkClChainFree (pNBuff); return ERROR; } /* point to the network pkt header, and adjust the length */ pNBuff->mBlkHdr.mData += llHdrInfo.dataOffset; pNBuff->mBlkHdr.mLen -= llHdrInfo.dataOffset; if(pNBuff->mBlkHdr.mFlags & M_PKTHDR) pNBuff->mBlkPktHdr.len -= llHdrInfo.dataOffset; #if 0 logMsg("_muxTkSendError\n",1,2,3,4,5,6); #endif } else { if(pMacFrame) { netMblkClFree(pMacFrame); } pNBuff->mBlkHdr.mFlags |= M_PKTHDR; } } return(status); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -