본문 바로가기

프로그래밍/vxWorks

vxWorks에서 모든 패킷 잡는 방법 구현

아래와 같이 함수를 구현한다.


int muxSnarfInit(char *if_name, int if_unit) {
	END_OBJ *pEnd;
	void *pCookie;
	unsigned int flags = 0;
	char ifnameBuf[10];

	pEnd = endFindByName(if_name, if_unit);
	if (NULL == pEnd) {
		printf("Cannot find END device %s%d\n", if_name, if_unit);
		printf("Usage: muxSnarfInit(char *if_name, int if_unit)\n");
		return ERROR;
	}

	pCookie = muxBind(if_name, if_unit, snarfRecvFunc, 0, 0, 0,
	MUX_PROTO_SNARF, "VLAN", (void *) pEnd); //MUX_PROTO_SNARF
	if (NULL == pCookie) {
		printf("Error 0x%x occured in muxBind\n", errnoGet());
		return ERROR;
	}
	sprintf(ifnameBuf, "%s%d", if_name, if_unit);
	flags |= IFF_PROMISC;
	ifFlagSet(ifnameBuf, flags);

	setCookie(pCookie);

	printf("muxSnarfInit started sussessfully!\n");
	return OK;
}


여기서

flags |= IFF_PROMISC;
ifFlagSet(ifnameBuf, flags);

을 빼면 자신의 맥과 다른 맥에 대해서 만 캡쳐되는데, 이것을 넣으면 맥에 관계 없이 모든 데이터를 캡쳐한다.


아래는 이함수를 호출하는 초기화 영역이다.

#ifndef WIN32
	if (muxLibInit() != NO_ERR)
		printf("Failed to initialize mux subsystem\n");
	else {
		if (muxSnarfInit(DUAL_NET_DEV_NAME, unitNum) != OK)
			printf("Failed to muxSnarfInit\n");

	}
#endif

수신되는 함수는 아래와 같으며, 받은 데이터는 메시지 Queue를 통하여 처리한다.

#ifndef WIN32
LOCAL BOOL snarfRecvFunc(void *pCookie, long type, M_BLK_ID pMblk,
		LL_HDR_INFO * pLlHdrInfo, void * pProtoCtrl) {
	/* 
	 please note that for performance issues, one might want to 
	 analyze the incoming packet information by looking at the
	 pMblk->mBlkHdr.mData
	 pointer;
	 
	 To simplify this example, the data is copied into
	 a linear buffer with
	 int netMblkToBufCopy
	 (
	 M_BLK_ID 	pMblk,		/ * pointer to an mBlk * /
	 char *		pBuf,		/ * pointer to the buffer to copy * /
	 FUNCPTR		pCopyRtn	/ * function pointer for copy routine * /
	 )
	 */

	char buffer[2048]; /* should be far more than enouth for ethernet devices */
	char ipAddr[16];
	int len; /* amount of data received */
	END_OBJ *pEnd;
	struct ip *pIp;
	static int k;

	PTNET_ETH_HDREX peth;
	PTNET_TANMP_HDR pthdr;

	int32 status;

	/* 
	 The end device the packet was received on
	 was passed as the last parameter in muxBind below;
	 Therefore, the protocol specific pointer corresponds to pEnd in this case 
	 */

	/* 
	 The following call copies the received packet into a linear buffer
	 */
	len = netMblkToBufCopy(pMblk, buffer, NULL);

	pEnd = (END_OBJ *) pProtoCtrl;

	if (len < sizeof(TNET_HDR)) {
		/*
		 기본적인 데이터 구조가 들어오지 않았으므로 리턴 시킨다.
		 */
		return FALSE;
		/* 
		 returning FALSE means that this function has not consumed 
		 the packet, so it might be adressed for another protocol
		 */
	}

	peth = (PTNET_ETH_HDREX) buffer;
	pthdr = (PTNET_TANMP_HDR) (peth + 1);

	if (ntohs(peth->type) == LSIS_TANMP_PKT_TYPE) {
		if (gTrMsgQueId) {
			if ((status = messageQueueSend(gTrMsgQueId, (char *) &buffer, len,
			NOWAIT,
			MYMSG_PRI_NORMAL)) == NO_ERR) {
			}

		}

		netMblkClChainFree(pMblk);
		return TRUE;
	} else {
		netMblkClChainFree(pMblk);
		return FALSE;
	}

	/* 
	 If the packet NOT to be passed to any other protocol,
	 it is necessary to
	 1) release the mBlk chain by calling
	 netMblkClChainFree(pMblk);
	 and
	 2) inform the MUX that we consumed the packet by returning TRUE
	 
	 otherwise (i.e. if this function didn't consume the packet, return FALSE
	 */

	netMblkClChainFree(pMblk);
	return FALSE;

}

수신된 데이터의 처리는 타스크를 따로 두어 아래와 같이 처리한다.
 

void tNetRecvTask(int32 arg1,int32 arg2,int32 arg3,int32 arg4,int32 arg5,int32 arg6,int32 arg7,int32 arg8,int32 arg9,int32 arg10)
{	
	uint32  status = NO_ERR;
	static u_char recvBuf[1000];
	
	/* 수신 큐 초기화   */
	gTrMsgQueId = msgQCreate(256,sizeof(recvBuf),MSG_Q_FIFO);
	
	if(gTrMsgQueId)
	{
		printf("tNetRecvTask is created\n");
	}
	
	int retLen = 0;
	
	while(1L){
		
		 status = messageQueueRecv( gTrMsgQueId,
				(int8 *)&recvBuf,
				sizeof(recvBuf),
				FOREVERWAIT,
				&retLen
			);		
		 
		 if(status == NO_ERR)
		 {
			 ProcessPacket((u_char*)recvBuf,retLen);
			 //printf("\n");
			 //PrintData(recvBuf,retLen);
		 }
		
		sysTaskDelay(systemClockRateGet()*SYSTEM_TICK / 100);
	}

	return;
}