📄 wdbendpktdrv.c
字号:
/* wdbEndPktDrv.c - END based packet driver for lightweight UDP/IP *//* Copyright 1996-2002 Wind River Systems, Inc. *//*modification history--------------------02c,10apr02,wap Set the M_PKTHDR flag for mBlks which do in fact contain packet headers. (SPR #73331)02b,30oct01,jhw Copied version TOR3_1-RC-1. Fixed ARPOP_REPLY.02a,11sep00,elg Update documentation.01z,20jul00,dbt Fixed some error cases where mBlk were incorrectly freed.01y,14jun00,dbt Fixed problem with Little Endian targets.01x,12jun00,ham removed reference to etherLib.01w,31may00,dbt Modified wdbEndInt() to test if a packet is fragmented (SPR #30194).01v,19apr00,ham merged TOR2_0-NPT-FCS(01s,05mar99,sj-01u,20sep99,sj).01t,13apr00,dbt Adapted to new MUX layer.01u,20sep99,sj htons(ETHERTYPE_IP)01t,29apr99,pul Upgraded NPT phase3 code to tor2.0.001s,05mar99,sj added support for NPT drivers01s,02aug99,dbt added support for standalone agent. Added support for ARP requests (SPR #25685). Added IP address verification (SPR #27815).01r,02mar99,dbt correctly initialize mBlkPktHdr.len field in send routine (SPR #25330).01q,11dec97,vin optimized some code and additional fixes to SPR9563.01p,08dec97,gnn fixed spr#9563 to get MBLK chains.01o,25nov97,gnn fixed spr#9620 polled mode receive01n,19oct97,vin fixed wdbEndInt, wdbEndPoll(), cleanup.01m,17oct97,vin changed wdbEndInt for muxPacketDataGet fixes.01l,09oct97,vin fixed wdbEndInt various error conditions, added htons01k,03oct97,gnn adjusted muxBind call to be in line with new prototype01j,25sep97,gnn SENS beta feedback fixes01i,25aug97,gnn fixed remaining polled mode problems.01h,22aug97,gnn changes due to new buffering scheme.01g,12aug97,gnn changes necessitated by MUX/END update.01f,08apr97,map Free mbuf cluster in wdbEndTx() when output is busy.01e,21jan97,gnn Added code to handle new addressles sending. Changed the way that transmit is done and free'd.01d,22oct96,gnn Name changes to follow the coding standards.01c,22oct96,gnn Removed netVectors and replaced with netBuffers. Replaced the 0 for promiscous protocol with a constant MUX_PROTO_PROMISC.01b,23sep96,gnn Added new buffering scheme information.01a,1jul96,gnn written.*//*DESCRIPTIONThis is an END based driver for the WDB system. It uses the MUX and ENDbased drivers to allow for interaction between the target and targetserver.USAGEThe driver is typically only called only from the configlette wdbEnd.c.The only directly callable routine in this module is wdbEndPktDevInit().To use this driver, just select the component INCLUDE_WDB_COMM_END in thefolder SELECT_WDB_COMM_TYPE. This is the default selection.To modify the MTU, change the value of parameter WDB_END_MTU in componentINCLUDE_WDB_COMM_END.DATA BUFFERINGThe drivers only need to handle one input packet at a time becausethe WDB protocol only supports one outstanding host-request at a time.If multiple input packets arrive, the driver can simply drop them.The driver then loans the input buffer to the WDB agent, and the agentinvokes a driver callback when it is done with the buffer.For output, the agent will pass the driver a chain of mbufs, whichthe driver must send as a packet. When it is done with the mbufs,it calls wdbMbufChainFree() to free them.The header file wdbMbufLib.h provides the calls for allocating, freeing,and initializing mbufs for use with the lightweight UDP/IP interpreter.It ultimately makes calls to the routines wdbMbufAlloc and wdbMbufFree, whichare provided in source code in the configlette usrWdbCore.c.INCLUDE FILES: drv/wdb/wdbEndPktDrv.h*//* includes */#include "string.h"#include "stdio.h"#include "errno.h"#include "sioLib.h"#include "intLib.h"#include "logLib.h"#include "end.h"#include "muxLib.h"#include "muxTkLib.h"#include "endLib.h"#include "private/muxLibP.h"#include "stdlib.h"#include "wdb/wdbMbufLib.h"#include "drv/wdb/wdbEndPktDrv.h"#include "net/if.h"#include "net/if_llc.h"#include "netinet/ip.h"#include "netinet/udp.h"#include "netinet/if_ether.h"#include "inetLib.h"/* defines */#define IP_HDR_SIZE 20#define WDB_NPT_CAPABLE/* globals */WDB_END_PKT_DEV * pEndPktDev;int wdbEndDebug = 0;char *pInPkt;/* pseudo-macros */#define DRIVER_INIT_HARDWARE(pDev) {}#define DRIVER_MODE_SET(pDev, mode)#define DRIVER_PACKET_IS_READY(pDev) FALSE#define DRIVER_RESET_INPUT(pDev) {pDev->inputBusy=FALSE;}#define DRIVER_RESET_OUTPUT(pDev) {pDev->outputBusy=FALSE;}#define DRIVER_GET_INPUT_PACKET(pDev, pBuf) (50)#define DRIVER_DATA_FROM_MBUFS(pDev, pBuf) {}#define DRIVER_POLL_TX(pDev, pBuf) {}#define DRIVER_TX_START(pDev) {}/* forward declarations */LOCAL STATUS wdbEndPoll (void *pDev);LOCAL STATUS wdbEndTx (void *pDev, struct mbuf * pMbuf);LOCAL STATUS wdbEndModeSet (void *pDev, uint_t newMode);LOCAL void wdbEndInputFree (void *pDev);LOCAL void wdbEndOutputFree (void *pDev);LOCAL M_BLK_ID wdbEndMblkClGet (END_OBJ * pEnd, int size);LOCAL int wdbEndInt (void* pCookie, long type, M_BLK_ID pMblk, LL_HDR_INFO *, void * pNull);LOCAL BOOL wdbEndPollArpReply (struct mbuf * pMblk, void * pCookie);#ifdef WDB_NPT_CAPABLEint wdbNptInt ( void *, long type, M_BLK_ID pMblk, void *);void wdbNptShutdown ( void * callbackId );#endif WDB_NPT_CAPABLE/******************************************************************************** wdbEndPktDevInit - initialize an END packet device** This routine initializes an END packet device. It is typically called* from configlette wdbEnd.c when the WDB agent's lightweight END* communication path (INCLUDE_WDB_COMM_END) is selected.** RETURNS: OK or ERROR*/STATUS wdbEndPktDevInit ( WDB_END_PKT_DEV * pPktDev, /* device structure to init */ void (*stackRcv) (), /* receive packet callback (udpRcv) */ char * pDevice, /* Device (ln, ie, etc.) that we */ /* wish to bind to. */ int unit /* unit number (0, 1, etc.) */ ) { END_OBJ * pEnd; char ifname [20]; char inetAdrs [24]; /* initialize the wdbDrvIf field with driver info */ pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_POLL| WDB_COMM_MODE_INT; pPktDev->wdbDrvIf.mtu = WDB_END_PKT_MTU; pPktDev->wdbDrvIf.stackRcv = stackRcv; /* udpRcv */ pPktDev->wdbDrvIf.devId = (WDB_END_PKT_DEV *)pPktDev; pPktDev->wdbDrvIf.pollRtn = wdbEndPoll; pPktDev->wdbDrvIf.pktTxRtn = wdbEndTx; pPktDev->wdbDrvIf.modeSetRtn = wdbEndModeSet; /* initialize the device specific fields in the driver structure */ pPktDev->inputBusy = FALSE; pPktDev->outputBusy = FALSE;#ifndef STANDALONE_AGENT /* * Here is where we bind to the lower layer. * We do not, as yet, provide for a shutdown routine, but perhaps * later. * We are a promiscous protocol. * The Int routine a fakeout. Interrupts are handled by the lower * layer but we use a similar mechanism to check packets for * the proper type and hand them off to the WDB agent from * the "interrupt" routine if it's appropriate to do so. */#ifdef WDB_NPT_CAPABLE if (muxTkDrvCheck (pDevice) == TRUE) { if ((pPktDev->pCookie = muxTkBind (pDevice, unit, wdbNptInt, (FUNCPTR)wdbNptShutdown, NULL, NULL, MUX_PROTO_SNARF, "Wind Debug Agent", NULL, NULL, NULL)) == NULL) { if (wdbEndDebug) logMsg ("Could not bind to NPT Device %s, loading...\n", (int)pDevice, 2, 3, 4, 5, 6); return (ERROR); } } else /* END */ { if (wdbEndDebug) logMsg ("Not a NPT device! %s\n", (int)pDevice,2,3,4,5,6);#endif /* WDB_NPT_CAPABLE */ if ((pPktDev->pCookie = muxBind (pDevice, unit, wdbEndInt, NULL, NULL, NULL, MUX_PROTO_SNARF, "Wind Debug Agent", NULL)) == NULL) { if (wdbEndDebug) logMsg ("Could not bind to %s, loading...\n", (int)pDevice, 2, 3, 4, 5, 6); return (ERROR); }#ifdef WDB_NPT_CAPABLE }#endif /* WDB_NPT_CAPABLE */ pEnd = PCOOKIE_TO_ENDOBJ(pPktDev->pCookie);#else /* STANDALONE_AGENT */ /* * for standalone agent, we simply need to get the address of the * of the device. */ if ((pPktDev->pCookie = endFindByName (pDevice, unit)) == NULL) return (ERROR); #endif /* STANDALONE_AGENT */ /* build interface name */ sprintf (ifname, "%s%d", pDevice, unit); /* get interface inet address */ if (ifAddrGet (ifname, inetAdrs) != OK) { if (wdbEndDebug) logMsg ("Could not get inet address of %s interface...\n", (int) ifname, 2, 3, 4, 5, 6); return (ERROR); } pPktDev->ipAddr.s_addr = inet_addr (inetAdrs); pEnd = PCOOKIE_TO_ENDOBJ(pPktDev->pCookie); if ((pInPkt = memalign (4,pEnd->mib2Tbl.ifMtu)) == NULL) return (ERROR); if ((pPktDev->pInBlk = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu)) == NULL) return (ERROR); pPktDev->pInBlk->mBlkHdr.mFlags |= M_PKTHDR; if ((pPktDev->pOutBlk = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu)) == NULL) return (ERROR); pPktDev->pOutBlk->mBlkHdr.mFlags |= M_PKTHDR; if ((pPktDev->lastHAddr = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu)) == NULL) return (ERROR); if ((pPktDev->srcAddr = wdbEndMblkClGet (pEnd, pEnd->mib2Tbl.ifMtu)) == NULL) return (ERROR); /* Set the length to the size of the buffer just allocated. */ pPktDev->pInBlk->mBlkHdr.mLen = pPktDev->pInBlk->pClBlk->clSize; pPktDev->lastHAddr->mBlkHdr.mLen = pEnd->mib2Tbl.ifPhysAddress.addrLength; memset (pPktDev->lastHAddr->mBlkHdr.mData, 0xff, pPktDev->lastHAddr->mBlkHdr.mLen); /* * Create a source address structure so we can send fully * qualified packets. */ muxIoctl (pPktDev->pCookie, EIOCGADDR, pPktDev->srcAddr->mBlkHdr.mData); pEndPktDev = pPktDev; return (OK); }/******************************************************************************** wdbEndInt - END driver interrupt handler** This is really a MUX receive routine but we let it look like* an interrupt handler to make this interface look as much like the* template as possible.** RETURNS: TRUE if the packet was for us, FALSE otherwise.** NOMANUAL*/int wdbEndInt ( void * pCookie, long type, M_BLK_ID pMblk, LL_HDR_INFO * pLinkHdrInfo, void * pMode ) { struct mbuf * pMbuf; int size; struct udphdr * pUdpHdr; struct ip * pIpHdr; WDB_END_PKT_DEV * pPktDev = pEndPktDev; /* input buffer already in use - drop this packet */ if (wdbEndDebug) logMsg ("Got a packet!\n", 1, 2, 3, 4, 5, 6); if (pPktDev->inputBusy) { if (wdbEndDebug) logMsg ("Input busy!\n", 1, 2, 3, 4, 5, 6); /* * free the packet only if the driver is in polling mode. If not, the * packet will be freed by the MUX layer. */ if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) netMblkClFree (pMblk); return (FALSE); } pPktDev->inputBusy = TRUE; /* Check the type before doing anything expensive. */ if ((type == 0x806) && (pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) { /* * In polling mode we need to answer ARP request so that * communication becomes or remains possible. */ if (wdbEndDebug) logMsg ("Type == 0x806\n", 1, 2, 3, 4, 5, 6); return (wdbEndPollArpReply (pMblk, pCookie)); } if (type != 0x800) { if (wdbEndDebug) logMsg ("Type != 0x800 && Type!= 0x806\n", 1, 2, 3, 4, 5, 6); goto wdbEndIntError; } size = pLinkHdrInfo->dataOffset + IP_HDR_SIZE + sizeof(struct udphdr); if (!(pMblk->mBlkHdr.mFlags & M_PKTHDR) || (pMblk->mBlkPktHdr.len < size)) { goto wdbEndIntError; } if (pMblk->mBlkHdr.mLen < size) { if (netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset, pInPkt, size, NULL) == 0) goto wdbEndIntError; pIpHdr = (struct ip *) pInPkt; pUdpHdr = (struct udphdr *)(pInPkt + IP_HDR_SIZE); } else { pIpHdr = (struct ip *) (pMblk->mBlkHdr.mData + pLinkHdrInfo->dataOffset); pUdpHdr = (struct udphdr *)(pMblk->mBlkHdr.mData + pLinkHdrInfo->dataOffset + IP_HDR_SIZE); } /* If this packet is not for the agent, ignore it */ if ((pIpHdr->ip_p != IPPROTO_UDP) || (pUdpHdr->uh_dport != htons(WDBPORT))) goto wdbEndIntError; if (pPktDev->ipAddr.s_addr != pIpHdr->ip_dst.s_addr) goto wdbEndIntError; /* * Check to see whether the packet is fragmented. WDB does not * handle fragmented packets. */ if (pIpHdr->ip_off & htons(IP_MF|IP_OFFMASK)) { if (wdbEndDebug) logMsg ("Fragmented packet\n", 0, 0, 0, 0, 0, 0); goto wdbEndIntError; } if ((size = netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset, pInPkt, M_COPYALL, NULL)) == 0) goto wdbEndIntError; bcopy ((char *)pMblk->mBlkHdr.mData + pLinkHdrInfo->srcAddrOffset, (char *)pPktDev->lastHAddr->mBlkHdr.mData, pLinkHdrInfo->srcSize); /* We're always going to send an IP packet. */ pPktDev->lastHAddr->mBlkHdr.reserved = htons (0x800); /* * Fill the input buffer with the packet. Use an mbuf cluster * to pass the packet on to the agent. */ pMbuf = wdbMbufAlloc (); if (pMbuf == NULL) goto wdbEndIntError; wdbMbufClusterInit (pMbuf, pInPkt, size, (int (*)())wdbEndInputFree, (int)pPktDev); if (wdbEndDebug) logMsg ("Passing up a packet!\n", 1, 2, 3, 4, 5, 6); (*pPktDev->wdbDrvIf.stackRcv) (pMbuf); /* invoke callback */ netMblkClFree (pMblk); return (TRUE); wdbEndIntError: { /* * drop all non wdb packets received through the poll routine * When call from muxReceive pMode is actually the spare pointer * which is initialized in the NET_PROTOCOL structure, the spare * pointer is passed as the last argument to the stackRcvRtn. * When called from wdbEndPoll it passes a mode in the void pointer * This mode is used to find out whether this routine is called from * wdbEndPoll or muxReceive. You will not be happy camper if the * spare pointer is removed from NET_PROTOCOL or if the stackRcvRtn's * API is changed. */ if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) netMblkClFree (pMblk); DRIVER_RESET_INPUT(pPktDev); return (FALSE); } }/*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -