www.pudn.com > ipman.zip > IPMAN.C, change:1998-04-08,size:43444b


/*	IPMan.C 
	Console application to send and receive IP packet 
        Written by HiHint 
        Using vpacket.vxd */ 
 
#include <stdio.h> 
#include <windows.h> 
#include <string.h> 
 
#include "ntddpack.h" 
#include "conpack.h" 
 
#include "ip.h" 
 
#define ERROR_OUT(str) { fprintf(stderr,str); CloseHandle(hEvent); return(0); } 
 
#define RECV_MAX 32 
#define SEND_MAX 32 
#define MAX_CONNECTION 64 
#define MAX_COMMAND 64 
#define MAX_DATA 64 
#define MAX_QUERY 64 
#define SYSERR -1 
#define OK 0 
 
#define OPT_DO_NOTHING 0x0	/* Do nothing, print local ethernet address */ 
#define OPT_LISTEN_ALL 0x1	/* Listen all packet */ 
#define OPT_LISTEN_SPEC 0x41e	/* Listen specially */ 
#define OPT_LISTEN	0x41f	/* Listen */ 
#define OPT_LISTEN_IP 0xa	/* Listen IP packet carry special address */ 
#define OPT_LISTEN_IP_1	0x2	/* Listen IP packet carry one special address */ 
#define OPT_LISTEN_PORT 0x14	/* Listen IP packet carry special port */ 
#define OPT_LISTEN_PORT_1 0x4	/* Listen IP packet carry one special port */ 
#define OPT_LISTEN_IP_2 0x8 /* Listern IP packet between two address */ 
#define OPT_LISTEN_PORT_2 0x10	/* Listen IP packet between two port */ 
 
#define OPT_QUE_IP 0x20	/* Query ethernet address from IP address */ 
#define OPT_QUE_ETHER 0x40	/* Query IP address from ethernet address */ 
 
#define OPT_COMMAND_FILE 0x80	/* Work with command file */ 
 
#define OPT_OUTPUT_FILE 0x100	/* Output to file */ 
 
#define OPT_HELP 0x200	/* Print help message */ 
 
#define COMMAND_SEND_ARP 0x1	/* Send ARP packet */ 
#define COMMAND_SEND_TCP 0x2	/* Send TCP packet */ 
#define COMMAND_RECV_TCP 0x4	/* Receive TCP packet */ 
#define COMMAND_CONNECT_TCP 0x8	/* Connect TCP */ 
#define COMMAND_CLOSE_TCP 0x10	/* Close TCP */ 
 
#define COMMENT 0x8000	/* Comment line */ 
 
#define COMMAND_UNKNOWN 0x0	/* Unknown command */ 
 
#define OPT_LISTEN_INIT 0x400	/* Listen IP packet match INI file speciallity */ 
#define INITIAL_FILE "ipman.ini"	/* Initial file name */ 
#define INITIAL_MAX_DATA 0x01	/* Initial file max data legth */ 
#define INITIAL_IP_ADDR 0x02	/* Initial file my IP address */ 
#define INITIAL_NDIS 0x04	/* Initial file NDIS */ 
#define INITIAL_QUERY_IP 0x08	/* Initial file query ip array */ 
#define INITIAL_QUERY_PORT 0x10	/* Initial file query port array */ 
#define INITIAL_TIMEOUT	0x20	/* Initial file timeout */ 
#define INITIAL_INFINITE "INFINITE"	/* Initial file timeout infinite */ 
#define INITIAL_END_SEGMENT 0x40	/* Initial file blank line as end of segment */ 
 
struct CommandLine { 
	DWORD option; 
	char outfile[50]; 
	char cmdfile[50]; 
	struct IPAddr queip[2]; 
	struct EtherAddr queeth[2]; 
	WORD queport[2]; 
}; 
 
struct InitialFile { 
	int maxdatalen; 
	struct IPAddr mipaddr; 
	char ndis[16]; 
	struct IPAddr qip[MAX_QUERY]; 
	int ipno; 
	WORD qport[MAX_QUERY]; 
	int portno; 
	DWORD timeout; 
}; 
 
struct TCPConnection { 
	struct EtherAddr sendeth,recveth; 
	struct IPAddr sourip,destip; 
	WORD sourport,destport; 
	WORD id; 
	DWORD ackno,seqno; 
	BOOL inuse; 
};	 
 
BYTE InBuff[ sizeof(PACKET_OID_DATA) + 128 ]; 
 
DWORD Bind(HANDLE hVxD, BYTE* inBuffer); 
WORD  GetHardEtherAddr(HANDLE hVxD,struct EtherAddr *petheraddr); 
BYTE* SetOid(HANDLE hVxD, ULONG ulOid, ULONG ulLength, ULONG data); 
DWORD QueryPacket(HANDLE hVxD,ULONG ioctl,BYTE* inBuffer,DWORD cbIn, 
				  BYTE* outBuffer,DWORD cbOut); 
BYTE* QueryOid(HANDLE hVxD, ULONG ulOid, ULONG ulLength); 
WORD RecvStart(HANDLE hVxD,struct PacketTable *packtab); 
WORD SendStart(HANDLE hVxD,struct PacketTable *packtab); 
WORD RecvPacket(HANDLE hVxD,BYTE *pbuf); 
WORD SendPacket(HANDLE hVxD,BYTE *pbuf,WORD len); 
WORD CheckSum(WORD *pbuf,WORD len); 
WORD ListenStart(HANDLE hVxD); 
 
WORD SendARPPacket(HANDLE hVxD, 
				   struct EtherAddr *psourether, 
				   struct EtherAddr *pdestether, 
				   struct EtherAddr *psendether, 
				   struct EtherAddr *precvether, 
				   struct IPAddr *psendip, 
				   struct IPAddr *precvip, 
				   WORD oper); 
WORD SendTCPPacket(HANDLE hVxD, 
				   struct EtherAddr *psourether, 
				   struct EtherAddr *pdestether, 
				   struct IPAddr *psourip, 
				   struct IPAddr *pdestip, 
				   WORD sourport, 
				   WORD destport, 
				   WORD flag, 
				   DWORD seqno, 
				   DWORD ackno, 
				   char *pbuf, 
				   WORD len); 
WORD RecvTCPPacket(HANDLE hVxD, 
				   struct IPAddr *psourip, 
				   struct IPAddr *pdestip, 
				   WORD sourport, 
				   WORD destport, 
				   WORD *flag, 
				   DWORD *seqno, 
				   DWORD *ackno, 
				   char *pbuf, 
				   WORD *size); 
WORD swaps(WORD net); 
DWORD swapl(DWORD net); 
WORD GetOption(int argc,char *argv[],struct CommandLine *cmdline); 
WORD GetInitial(FILE *pfini,struct InitialFile *inifile); 
void ReadCommand(FILE *pf,char *pbuf); 
WORD GetCommand(char *pbuf); 
void GetSendARPArg(char *pbuf, 
   				   struct EtherAddr *psendeth, 
				   struct EtherAddr *precveth, 
				   struct EtherAddr *soureth, 
				   struct EtherAddr *desteth, 
				   struct IPAddr *sourip, 
				   struct IPAddr *destip, 
				   WORD *oper); 
void GetSendTCPArg(char *pbuf,WORD *id,char *pdata,WORD *size); 
void GetRecvTCPArg(char *pbuf,WORD *id); 
void GetConnectArg(char *pbuf, 
				   struct EtherAddr *sendeth, 
				   struct EtherAddr *recveth, 
				   struct IPAddr *sourip, 
				   struct IPAddr *destip, 
				   WORD *sourport, 
				   WORD *destport, 
				   WORD *id); 
void GetCloseArg(char *pbuf,WORD *id); 
void GetDataArg(char *pbuf,char *pdata,WORD *size); 
void GetIPAddr(char *pbuf,struct IPAddr *pipaddr); 
void GetEtherAddr(char *pbuf,struct EtherAddr *pethaddr); 
void PrintEtherAddr(FILE *pf,struct EtherAddr *pethaddr); 
void PrintIPAddr(FILE *pf,struct IPAddr *pIPaddr); 
void PrintData(FILE *pf,BYTE *pdata,int size); 
void ToUpper(char *pbuf); 
 
static Max_Data_Len; 
 
int main(int argc,char *argv[]) 
{ 
	HANDLE hVxD; 
	DWORD dwErrorCode; 
	struct EtherAddr m_EtherAddr; 
	struct IPAddr m_IPAddr; 
	HANDLE hEvent; 
	BOOL Continue; 
	int i,j,k; 
	BYTE Buffer[BUFFER_SIZE]; 
	WORD DataLen; 
	struct EtherPacketHead *pEtherHead; 
	struct IPPacketHead *pIPHead; 
	struct TCPPacketHead *pTCPHead; 
	struct ARPPacket *pARPHead; 
	struct ICMPPacketHead *pICMPHead; 
	struct UDPPacketHead *pUDPHead; 
	int headlen,totallen; 
	struct IPAddr *psourip,*pdestip; 
	struct EtherAddr *psoureth,*pdesteth; 
	WORD sourport,destport; 
	DWORD seqno,ackno; 
	BYTE *pdata; 
	WORD filter; 
	BOOL flag; 
	FILE *pfout=NULL,*pfcmd=NULL,*pfini=NULL; 
	struct EtherAddr ethernull,etherbroad; 
	struct IPAddr ipnull; 
	struct CommandLine cmdline; 
	struct InitialFile inifile; 
	char Command[BUFFER_SIZE]; 
	char *pbufh,*pbuft; 
	struct EtherAddr sendethaddr,recvethaddr,sourethaddr,destethaddr; 
	struct IPAddr sipaddr,dipaddr; 
	WORD arpoper,tcpid; 
	struct TCPConnection TCP[MAX_CONNECTION]; 
	WORD maxconn=0; 
	WORD TCPFlag; 
 
	/* Set null ethernet address and broadcast ethernet address */ 
	memset((void*)ðernull,0,6); 
	memset((void*)ðerbroad,0xff,6); 
	memset((void*)&ipnull,0,6); 
 
	/* Get initial file property */ 
	if((pfini=fopen(INITIAL_FILE,"r"))==NULL) { 
		fprintf(stderr,"Can not open %s\n",INITIAL_FILE); 
		return 0; 
	} 
	if(GetInitial(pfini,&inifile)!=OK) { 
		fprintf(stderr,"Not valid initial file.\n"); 
		return 0; 
	} 
	Max_Data_Len=inifile.maxdatalen; 
	memcpy((void *)&m_IPAddr,(void *)&inifile.mipaddr,4); 
 
	/* Get command line option */ 
	if(GetOption(argc,argv,&cmdline)!=OK||cmdline.option&OPT_HELP) { 
                fprintf(stderr,"IPMan Version 0.5b\n"); 
                fprintf(stderr,"Author: HiHint\nEmail:HiHint@hotmail.com\n\n"); 
                fprintf(stderr,"Usage ipman [-?] [-l[ini] [-ip:sour_ip[:dest_ip]] [-port:sour_port[:dest_port]]] [-qeth:ip_addr] [-qip:eth_addr] [-fout:output_file] [-fcmd:command_file]\n"); 
		return 0; 
	} 
 
	if((cmdline.option&OPT_LISTEN)!=0) filter=NDIS_PACKET_TYPE_PROMISCUOUS; 
	else filter=NDIS_PACKET_TYPE_DIRECTED; 
 
	/* Open device */ 
    hVxD = CreateFile("\\\\.\\VPACKET.VXD",  
                      GENERIC_READ | GENERIC_WRITE, 
                      0, 
                      NULL, 
                      OPEN_EXISTING, 
                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | 
                      FILE_FLAG_DELETE_ON_CLOSE, 
                      NULL); 
 
    if (hVxD == INVALID_HANDLE_VALUE) { 
        dwErrorCode = GetLastError(); 
        if (dwErrorCode == ERROR_NOT_SUPPORTED) { 
            fprintf(stderr,"Unable to open VxD,\ndevice does not support DeviceIOCTL\n"); 
        } 
        else 
            fprintf(stderr,"Unable to open VxD, Error code: %lx\n", dwErrorCode); 
		return(0); 
    } 
 
	/* Device opened successfully */ 
	/* Bind driver to NDIS3 adapter	*/ 
 
	Bind(hVxD,inifile.ndis); 
 
	/* Get ethernet address and IP */ 
	if(GetHardEtherAddr(hVxD,&m_EtherAddr)!=OK) return 0; 
 
	/* Set Filter */ 
	SetOid(hVxD, OID_GEN_CURRENT_PACKET_FILTER, 4, filter); 
	 
	if((cmdline.option&OPT_OUTPUT_FILE)!=0) {	/* Open output file */ 
		if((pfout=fopen(cmdline.outfile,"w"))==NULL) { 
			fprintf(stderr,"Can not open output file.\n"); 
			goto ENDOFTASK; 
		} 
	} 
	else pfout=stdout;		 
 
	if(cmdline.option==0) { 
		fprintf(pfout,"Ether address:"); 
		PrintEtherAddr(pfout,&m_EtherAddr); 
		goto ENDOFTASK; 
	} 
	 
	if((cmdline.option&OPT_COMMAND_FILE)!=0) {	/* Open command file */ 
		if((pfcmd=fopen(cmdline.cmdfile,"r"))==NULL) { 
			fprintf(stderr,"Can not open command file.\n"); 
			goto ENDOFTASK; 
		} 
		for(i=0;i<MAX_CONNECTION;i++) TCP[i].inuse=FALSE; 
	} 
 
	if((cmdline.option&OPT_LISTEN)!=0) {	 
		/* Do listen */ 
		Continue=TRUE; 
		while(Continue) { 
			DataLen=RecvPacket(hVxD,Buffer); 
			if(DataLen==SYSERR) goto ENDOFTASK; 
			/* Begin to process data */ 
			pEtherHead=(struct EtherPacketHead *)Buffer; 
			switch (swaps(pEtherHead->ServType)) { 
			case ETHER_PROTO_IP:	/* IP packet */ 
				pIPHead=(struct IPPacketHead *)(Buffer+ETHER_HEAD_LEN); 
				headlen=(pIPHead->VerHLen)&0xf; 
				headlen*=4; 
				totallen=swaps(pIPHead->TtlLen); 
				psourip=&(pIPHead->SourIP); 
				pdestip=&(pIPHead->DestIP); 
				flag=TRUE; 
				if(cmdline.option&OPT_LISTEN_IP) { 
					flag=FALSE; 
					if((cmdline.option&OPT_LISTEN_IP_1)&& 
					   (memcmp((void *)&cmdline.queip[0],(void *)psourip,4)==0|| 
						memcmp((void *)&cmdline.queip[0],(void *)pdestip,4)==0))   
						flag=TRUE; 
					else if((cmdline.option&OPT_LISTEN_IP_2)&& 
							((memcmp((void *)&cmdline.queip[0],(void *)psourip,4)==0&& 
							  memcmp((void *)&cmdline.queip[1],(void *)pdestip,4))|| 
							 (memcmp((void *)&cmdline.queip[0],(void *)pdestip,4)==0&& 
							  memcmp((void *)&cmdline.queip[1],(void *)psourip,4)))) 
						flag=TRUE; 
				} 
				else if(cmdline.option&OPT_LISTEN_INIT) { 
					flag=FALSE; 
					for(i=0;i<inifile.ipno;i++)  
						if(memcmp((void *)&inifile.qip[i],(void *)psourip,4)==0|| 
						   memcmp((void *)&inifile.qip[i],(void *)pdestip,4)==0) break; 
					if(i<inifile.ipno) flag=TRUE; 
				} 
				if(flag) { 
					switch (pIPHead->Proto) { 
					case IP_PROTO_TCP:	/* TCP packet */ 
						pTCPHead=(struct TCPPacketHead *)(Buffer+ETHER_HEAD_LEN+headlen); 
						totallen-=headlen; 
						sourport=swaps(pTCPHead->SourPort); 
						destport=swaps(pTCPHead->DestPort); 
						seqno=swapl(pTCPHead->SeqNo); 
						ackno=swapl(pTCPHead->AckNo); 
						headlen=(pTCPHead->HLen)>>4; 
						headlen*=4; 
						totallen-=headlen; 
						pdata=((BYTE *)pTCPHead)+headlen; 
						/* TODO */ 
						flag=TRUE; 
						if(cmdline.option&OPT_LISTEN_PORT) { 
							flag=FALSE; 
							if((cmdline.option&OPT_LISTEN_PORT_1)&& 
							   (cmdline.queport[0]==sourport|| 
							    cmdline.queport[0]==destport)) 
								flag=TRUE; 
							else if((cmdline.option&OPT_LISTEN_PORT_2)&& 
								     ((cmdline.queport[0]==sourport&&cmdline.queport[1]==destport)|| 
									  (cmdline.queport[0]==destport&&cmdline.queport[1]==sourport))) 
								flag=TRUE;										 
						} 
						else if(cmdline.option&OPT_LISTEN_INIT) { 
							flag=FALSE; 
							for(i=0;i<inifile.portno;i++)  
								if(sourport==inifile.qport[i]|| 
								   destport==inifile.qport[i]) break; 
							if(i<inifile.portno) flag=TRUE; 
						} 
						if(flag) { 
							PrintIPAddr(pfout,psourip); 
							fprintf(pfout,":%d -> ",sourport); 
							PrintIPAddr(pfout,pdestip); 
							fprintf(pfout,":%d\n",destport); 
							fprintf(pfout,"%d Byte(s) TCP Message:",totallen); 
							PrintData(pfout,pdata,totallen); 
							fprintf(pfout,"\n"); 
						} 
						break; 
					case IP_PROTO_UDP:	/* UDP packet */ 
						pUDPHead=(struct UDPPacketHead *)(Buffer+ETHER_HEAD_LEN+headlen); 
						totallen-=headlen; 
						sourport=swaps(pUDPHead->SourPort); 
						destport=swaps(pUDPHead->DestPort); 
						pdata=((BYTE *)pUDPHead)+UDP_HEAD_LEN; 
						/* TODO */ 
						totallen-=UDP_HEAD_LEN; 
						flag=TRUE; 
						if(cmdline.option&OPT_LISTEN_PORT) { 
							flag=FALSE; 
							if((cmdline.option&OPT_LISTEN_PORT_1)&& 
							   (cmdline.queport[0]==sourport|| 
							    cmdline.queport[0]==destport)) 
								flag=TRUE; 
							else if((cmdline.option&OPT_LISTEN_PORT_2)&& 
								     ((cmdline.queport[0]==sourport&&cmdline.queport[1]==destport)|| 
									  (cmdline.queport[0]==destport&&cmdline.queport[1]==sourport))) 
								flag=TRUE;										 
						} 
						else if(cmdline.option&OPT_LISTEN_INIT) { 
							flag=FALSE; 
							for(i=0;i<inifile.portno;i++)  
								if(sourport==inifile.qport[i]|| 
								   destport==inifile.qport[i]) break; 
							if(i<inifile.portno) flag=TRUE; 
						} 
						if(flag) { 
							PrintIPAddr(pfout,psourip); 
							fprintf(pfout,":%d -> ",sourport); 
							PrintIPAddr(pfout,pdestip); 
							fprintf(pfout,":%d\n",destport); 
							fprintf(pfout,"%d Byte(s) UDP Message:",totallen); 
							PrintData(pfout,pdata,totallen); 
							fprintf(pfout,"\n"); 
						} 
						break; 
					case IP_PROTO_ICMP:	/* ICMP packet */ 
						flag=TRUE; 
						if(cmdline.option&OPT_LISTEN_PORT)  
						   flag=FALSE; 
						if(flag) { 
							pICMPHead=(struct ICMPPacketHead *)(Buffer+ETHER_HEAD_LEN+headlen); 
							totallen-=headlen; 
							pdata=((BYTE *)pICMPHead)+ICMP_HEAD_LEN; 
							totallen-=ICMP_HEAD_LEN; 
							/* TODO */ 
							PrintIPAddr(pfout,psourip); 
							fprintf(pfout," -> "); 
							PrintIPAddr(pfout,pdestip); 
							fprintf(pfout,"\n"); 
							fprintf(pfout,"%d Byte(s) ICMP Message:Type:%d Code:%d\n",totallen,pICMPHead->Type,pICMPHead->Code); 
						} 
						break; 
					default:	/* Unknown packet */ 
						/*fprintf(stderr,"Unknown ip packet type.\n");*/ 
						break; 
					} 
				} 
				break; 
			case ETHER_PROTO_ARP:	/* ARP packet */ 
				if((cmdline.option&OPT_LISTEN_SPEC)==0) { 
					pARPHead=(struct ARPPacket*)(Buffer+ETHER_HEAD_LEN); 
					psourip=&(pARPHead->SourIP); 
					pdestip=&(pARPHead->DestIP); 
					psoureth=&(pARPHead->SourEther); 
					pdesteth=&(pARPHead->DestEther); 
					/* TODO */ 
					fprintf(pfout,"ARP Message:From:"); 
					PrintEtherAddr(pfout,psoureth); 
					fprintf(pfout,":"); 
					PrintIPAddr(pfout,psourip); 
					fprintf(pfout," To:"); 
					PrintEtherAddr(pfout,pdesteth); 
					fprintf(pfout,":"); 
					PrintIPAddr(pfout,pdestip); 
					fprintf(pfout," Operation:%d\n",swaps(pARPHead->Oper)); 
				} 
				break; 
			default:	/* Unknown packet */ 
				/*fprintf(stderr,"Unknown ethernet packet type.\n");*/ 
				break; 
			} 
		} 
	} 
	else if((cmdline.option&OPT_QUE_ETHER)!=0) { 
		/* Do query ethernet address form IP */ 
		ListenStart(hVxD); 
		SendARPPacket(hVxD, 
					  &m_EtherAddr, 
					  ðerbroad, 
					  &m_EtherAddr, 
					  ðernull, 
					  &m_IPAddr, 
					  &cmdline.queip[0], 
					  ARP_OPER_ARP_REQ); 
		Continue=TRUE; 
		while(Continue) { 
			if((DataLen=RecvPacket(hVxD,Buffer))==SYSERR) { 
				fprintf(stderr,"Can not recv ARP packet.\n"); 
				goto ENDOFTASK; 
			} 
			pEtherHead=(struct EtherPacketHead *)Buffer; 
			if(swaps(pEtherHead->ServType)!=ETHER_PROTO_ARP) continue; 
			pARPHead=(struct ARPPacket *)(Buffer+ETHER_HEAD_LEN); 
			if(swaps(pARPHead->Oper)!=ARP_OPER_ARP_ANS) continue; 
			if(memcmp((void *)&pARPHead->SourIP,(void *)&cmdline.queip[0],4)!=0) continue; 
			/* Get ethernet address */ 
			fprintf(pfout,"Ethernet Address:"); 
			PrintEtherAddr(pfout,&pARPHead->SourEther); 
			fprintf(pfout," of IP Address:"); 
			PrintIPAddr(pfout,&cmdline.queip[0]); 
			fprintf(pfout,"\n");  
			Continue=FALSE; 
		} 
	} 
	else if((cmdline.option&OPT_QUE_IP)!=0) { 
		/* Do query IP from ethernet address */ 
		ListenStart(hVxD); 
		SendARPPacket(hVxD, 
					  &m_EtherAddr, 
					  ðerbroad, 
					  &m_EtherAddr, 
					  &cmdline.queeth[0], 
					  &m_IPAddr, 
					  &ipnull, 
					  ARP_OPER_RARP_REQ); 
		Continue=TRUE; 
		while(Continue) { 
			if((DataLen=RecvPacket(hVxD,Buffer))==SYSERR) { 
				fprintf(stderr,"Can not recv ARP packet.\n"); 
				goto ENDOFTASK; 
			} 
			pEtherHead=(struct EtherPacketHead *)Buffer; 
			if(swaps(pEtherHead->ServType)!=ETHER_PROTO_ARP) continue; 
			pARPHead=(struct ARPPacket *)(Buffer+ETHER_HEAD_LEN); 
			if(swaps(pARPHead->Oper)!=ARP_OPER_RARP_ANS) continue; 
			if(memcmp((void *)&pARPHead->SourEther,(void *)&cmdline.queeth[0],6)!=0) continue; 
			/* Get IP address */ 
			fprintf(pfout,"IP Address:"); 
			PrintIPAddr(pfout,&pARPHead->SourIP); 
			fprintf(pfout," of Ethernet Address:"); 
			PrintEtherAddr(pfout,&cmdline.queeth[0]); 
			fprintf(pfout,"\n"); 
			Continue=FALSE; 
		} 
	} 
	else if((cmdline.option&OPT_COMMAND_FILE)!=0) { 
		/* Do command file */ 
		while(feof(pfcmd)==0) { 
			ReadCommand(pfcmd,Command); 
			switch (GetCommand(Command)) { 
			case COMMAND_SEND_ARP: 
				GetSendARPArg(Command, 
					          &sendethaddr, 
							  &recvethaddr, 
							  &sourethaddr, 
							  &destethaddr, 
							  &sipaddr, 
							  &dipaddr, 
							  &arpoper); 
				SendARPPacket(hVxD, 
					          &sendethaddr, 
							  &recvethaddr, 
							  &sourethaddr, 
							  &destethaddr, 
							  &sipaddr, 
							  &dipaddr, 
							  arpoper); 
				fprintf(pfout,"Send ARP.\n"); 
				break; 
			case COMMAND_SEND_TCP: 
				GetSendTCPArg(Command,&tcpid,Buffer,&DataLen); 
				if(TCP[tcpid].inuse==FALSE)  
					fprintf(stdout,"Connection %d invalid or already closed.\n",tcpid); 
				else { 
					SendTCPPacket(hVxD, 
								  &TCP[tcpid].sendeth, 
								  &TCP[tcpid].recveth, 
								  &TCP[tcpid].sourip, 
								  &TCP[tcpid].destip, 
								  TCP[tcpid].sourport, 
								  TCP[tcpid].destport, 
								  TCP_ACK|TCP_PSH, 
								  TCP[tcpid].seqno, 
								  TCP[tcpid].ackno, 
								  Buffer, 
								  DataLen); 
					fprintf(pfout,"Send %d TCP:",tcpid); 
					PrintData(pfout,Buffer,DataLen); 
					fprintf(pfout,"\n"); 
				} 
				break; 
			case COMMAND_RECV_TCP: 
				GetRecvTCPArg(Command,&tcpid); 
				RecvTCPPacket(hVxD, 
							  &TCP[tcpid].destip, 
							  &TCP[tcpid].sourip, 
							  TCP[tcpid].destport, 
							  TCP[tcpid].sourport, 
							  &TCPFlag, 
							  &TCP[tcpid].ackno, 
							  &TCP[tcpid].seqno, 
							  Buffer, 
							  &DataLen); 
				if(DataLen==0) TCP[tcpid].ackno++; 
				else TCP[tcpid].ackno+=DataLen; 
				fprintf(pfout,"Receive %d TCP %d byte(s):",tcpid,DataLen); 
				PrintData(pfout,Buffer,DataLen); 
				fprintf(pfout,"\n"); 
				/*fprintf(pfout,"Flag:%x\n",TCPFlag);*/ 
				if(TCPFlag&TCP_FIN||TCPFlag&TCP_RST) { 
					TCP[tcpid].inuse=FALSE; 
					fprintf(pfout,"Peer close connection %d.\n",tcpid); 
				} 
				break; 
			case COMMAND_CONNECT_TCP: 
				ListenStart(hVxD); 
				GetConnectArg(Command, 
							  &sendethaddr, 
							  &recvethaddr, 
							  &sipaddr, 
							  &dipaddr, 
							  &sourport, 
							  &destport, 
							  &tcpid); 
				memcpy((void *)&TCP[tcpid].sendeth,(void *)&sendethaddr,6); 
				memcpy((void *)&TCP[tcpid].recveth,(void *)&recvethaddr,6); 
				memcpy((void *)&TCP[tcpid].sourip,(void *)&sipaddr,4); 
				memcpy((void *)&TCP[tcpid].destip,(void *)&dipaddr,4); 
				TCP[tcpid].sourport=sourport; 
				TCP[tcpid].destport=destport; 
				TCP[tcpid].seqno=swapl(0x1234); 
				TCP[tcpid].ackno=0; 
				TCPFlag=TCP_SYN; 
				SendTCPPacket(hVxD, 
							  &TCP[tcpid].sendeth, 
							  &TCP[tcpid].recveth, 
							  &TCP[tcpid].sourip, 
							  &TCP[tcpid].destip, 
							  TCP[tcpid].sourport, 
							  TCP[tcpid].destport, 
							  TCPFlag, 
							  TCP[tcpid].seqno, 
							  TCP[tcpid].ackno, 
							  Buffer, 
							  0); 
				/*fprintf(pfout,"First:Flag:%x Seq:%lu Ack:%lu\n", 
					    TCPFlag,swapl(0x1234),ackno);*/ 
				RecvTCPPacket(hVxD, 
							  &TCP[tcpid].destip, 
							  &TCP[tcpid].sourip, 
							  TCP[tcpid].destport, 
							  TCP[tcpid].sourport, 
							  &TCPFlag, 
							  &TCP[tcpid].ackno, 
							  &TCP[tcpid].seqno, 
							  Buffer, 
							  &DataLen); 
				/*fprintf(pfout,"Second:Flag:%x Seq:%lu Ack:%lu\n", 
					    TCPFlag,TCP[tcpid].ackno,TCP[tcpid].seqno);*/ 
				TCP[tcpid].ackno++; 
				TCPFlag=TCP_ACK; 
				SendTCPPacket(hVxD, 
							  &TCP[tcpid].sendeth, 
							  &TCP[tcpid].recveth, 
							  &TCP[tcpid].sourip, 
							  &TCP[tcpid].destip, 
							  TCP[tcpid].sourport, 
							  TCP[tcpid].destport, 
							  TCPFlag, 
							  TCP[tcpid].seqno, 
							  TCP[tcpid].ackno, 
							  Buffer, 
							  0); 
				/*fprintf(pfout,"Third:Flag:%x Seq:%lu Ack:%lu\n", 
					    TCPFlag,TCP[tcpid].seqno,TCP[tcpid].ackno);*/ 
				fprintf(pfout,"TCP %d Connected\n",tcpid); 
				TCP[tcpid].inuse=TRUE; 
				break; 
			case COMMAND_CLOSE_TCP: 
				GetCloseArg(Command,&tcpid); 
				TCPFlag=TCP_FIN|TCP_ACK; 
				SendTCPPacket(hVxD, 
							  &TCP[tcpid].sendeth, 
							  &TCP[tcpid].recveth, 
							  &TCP[tcpid].sourip, 
							  &TCP[tcpid].destip, 
							  TCP[tcpid].sourport, 
							  TCP[tcpid].destport, 
							  TCPFlag, 
							  TCP[tcpid].seqno, 
							  TCP[tcpid].ackno, 
							  Buffer, 
							  0); 
				fprintf(pfout,"Close\n"); 
				TCP[tcpid].inuse=FALSE; 
				break; 
			case COMMENT: 
				break; 
			case COMMAND_UNKNOWN: 
				if(feof(pfcmd)==0) fprintf(stderr,"Command unknown.\n"); 
				/*goto ENDOFTASK;*/ 
			}			 
		} 
	} 
 
ENDOFTASK: 
	CloseHandle(hVxD); 
	if(pfout!=NULL) fclose(pfout); 
	if(pfcmd!=NULL) fclose(pfcmd); 
	return 0; 
} 
 
DWORD Bind(HANDLE hVxD, BYTE* inBuffer) 
{ 
    HANDLE          hEvent  = 0; 
    DWORD           cbRet   = 0; 
    OVERLAPPED      ovlp    = {0,0,0,0,0}; 
    int result; 
    int cbIn = 5; 
     
    hEvent = CreateEvent(0, TRUE, 0, NULL); 
	if(!hEvent) { 
		fprintf(stderr,"Can not create event\n"); 
		return SYSERR; 
	} 
 
	ovlp.hEvent=hEvent; 
 
    result = DeviceIoControl(hVxD, 
							 IOCTL_PROTOCOL_BIND,  
							 inBuffer,  
							 cbIn,  
							 inBuffer,  
							 cbIn,  
							 &cbRet,  
							 &ovlp); 
 
    if (!result) 
        GetOverlappedResult(hVxD, &ovlp, &cbRet, TRUE); 
	 
	CloseHandle(hEvent); 
    return OK; 
} 
 
WORD GetHardEtherAddr(HANDLE hVxD,struct EtherAddr *petheraddr) 
{ 
    BYTE*   buffer = QueryOid(hVxD, OID_802_3_CURRENT_ADDRESS, 6); 
 
    if (buffer!=NULL) { 
		memcpy((void *)petheraddr->AddrByte,(void*)buffer,6); 
		return OK; 
	} 
	return SYSERR; 
} 
 
DWORD QueryPacket(HANDLE hVxD,ULONG ioctl,BYTE* inBuffer,DWORD cbIn, 
				  BYTE* outBuffer,DWORD cbOut) 
{ 
    HANDLE      hEvent = 0; 
    DWORD       cbRet; 
    OVERLAPPED  ovlp = {0,0,0,0,0}; 
    
    if (!(hEvent = CreateEvent(0, TRUE, 0, NULL))) 
        ERROR_OUT("CreateEvent failed!\n") 
 
    ovlp.hEvent = hEvent; 
     
    if (!DeviceIoControl(hVxD, ioctl, inBuffer, cbIn, outBuffer, cbOut, &cbRet, &ovlp)) { 
        if (GetLastError() == ERROR_IO_PENDING)                          
            fprintf(stderr,"VxD correctly returned operation incomplete.\n" ); 
        else 
            ERROR_OUT( "VxD does not support the requested API!!!\n" ); 
        if (!GetOverlappedResult(hVxD, &ovlp, &cbRet, FALSE)) { 
            if (GetLastError() == ERROR_IO_INCOMPLETE) 
                fprintf(stderr,"GetOverlappedResult returned expected value.\n"); 
            else 
                ERROR_OUT("GetOverlappedResult returned unexpected error.\n"); 
        } 
        GetOverlappedResult( hVxD, &ovlp, &cbRet, TRUE); 
	} 
    return cbRet; 
} 
 
BYTE* QueryOid(HANDLE hVxD, ULONG ulOid, ULONG ulLength) 
{ 
    DWORD               cbIn = sizeof(PACKET_OID_DATA) + ulLength; 
    DWORD               cbRet; 
	PPACKET_OID_DATA	pOidData = (PPACKET_OID_DATA)InBuff; 
    ULONG               ioctl; 
	 
    ioctl = (ulOid >= OID_802_3_PERMANENT_ADDRESS)  
		  	 
		  			? IOCTL_PROTOCOL_QUERY_OID : IOCTL_PROTOCOL_STATISTICS; 
 
    memset(InBuff, 0, cbIn+1); 
 
	pOidData->Oid    = ulOid; 
	pOidData->Length = ulLength; 
 
	cbRet = QueryPacket( hVxD, ioctl, InBuff, cbIn, InBuff, cbIn ); 
    
	if ( cbRet > 0 )  
        return (InBuff+sizeof(PACKET_OID_DATA)-1); 
 
	return 0; 
} 
 
BYTE* SetOid(HANDLE hVxD, ULONG ulOid, ULONG ulLength, ULONG data) 
{ 
    DWORD               cbIn = sizeof(PACKET_OID_DATA) + ulLength; 
    DWORD               cbRet; 
	PPACKET_OID_DATA	pOidData = (PPACKET_OID_DATA)InBuff; 
    ULONG               ioctl; 
	 
    if (ulOid == OID_GEN_CURRENT_PACKET_FILTER) 
        ioctl = (ULONG) IOCTL_PROTOCOL_SET_OID; 
 
    memset(InBuff, 0, cbIn+1); 
 
    pOidData->Oid     = ulOid; 
    pOidData->Length  = ulLength; 
    pOidData->Data[0] = (UCHAR) data; 
 
    cbRet = QueryPacket(hVxD, ioctl, InBuff, cbIn, InBuff, cbIn); 
    
	return 0; 
} 
 
WORD RecvStart(HANDLE hVxD,struct PacketTable *packtab) 
{ 
	int result; 
 
	packtab->Overlap.Internal=0; 
	packtab->Overlap.InternalHigh=0; 
	packtab->Overlap.Offset=0; 
	packtab->Overlap.OffsetHigh=0; 
	packtab->Overlap.hEvent=packtab->hEvent; 
 
	result=DeviceIoControl(hVxD, 
						   IOCTL_PROTOCOL_READ, 
						   &packtab->Buffer, 
						   packtab->Size, 
						   &packtab->Buffer, 
						   packtab->Size, 
						   &packtab->Length, 
						   &packtab->Overlap); 
 
	if(result) return SYSERR; 
 
	return OK; 
} 
 
WORD SendStart(HANDLE hVxD,struct PacketTable *packtab) 
{ 
	int result; 
 
	packtab->Overlap.Internal=0; 
	packtab->Overlap.InternalHigh=0; 
	packtab->Overlap.Offset=0; 
	packtab->Overlap.OffsetHigh=0; 
	packtab->Overlap.hEvent=packtab->hEvent; 
 
	result=DeviceIoControl(hVxD, 
						   IOCTL_PROTOCOL_WRITE, 
						   &packtab->Buffer, 
						   packtab->Size, 
						   &packtab->Buffer, 
						   packtab->Length, 
						   &packtab->Length, 
						   &packtab->Overlap); 
 
	if(result) return SYSERR; 
 
	return OK; 
} 
 
WORD ListenStart(HANDLE hVxD) 
{ 
	return RecvPacket(hVxD,NULL); 
} 
 
WORD RecvPacket(HANDLE hVxD,BYTE *pbuf) 
{ 
	static BOOL first=TRUE; 
	static struct PacketTable RecvTab[RECV_MAX]; 
	static HANDLE EventTab[RECV_MAX]; 
	HANDLE hEvent; 
	int i,j,k; 
	WORD len; 
 
	if(first) { 
		for(i=0;i<RECV_MAX;i++) { 
			hEvent=CreateEvent(0, TRUE, 0, NULL); 
			if(!hEvent) { 
				fprintf(stderr,"Can not create event\n"); 
				return SYSERR; 
			} 
			RecvTab[i].hEvent=hEvent; 
			memset(RecvTab[i].Buffer,0,BUFFER_SIZE); 
			RecvTab[i].Size=BUFFER_SIZE; 
			RecvTab[i].Active=TRUE; 
			RecvTab[i].Type=READ; 
			EventTab[i]=hEvent; 
			RecvStart(hVxD,&RecvTab[i]); 
		} 
		first=FALSE; 
	} 
	if(pbuf==NULL) return OK; 
	i=WaitForMultipleObjectsEx(RECV_MAX,EventTab,FALSE,INFINITE,FALSE); 
	if(i==WAIT_FAILED) return SYSERR; 
	for(j=0;j<RECV_MAX;j++)  
		if(EventTab[i]==RecvTab[j].hEvent) break; 
	k=j; 
	if(RecvTab[k].Type==READ&&RecvTab[k].Active==TRUE) {	/* read complete */ 
		GetOverlappedResult(hVxD,&RecvTab[k].Overlap,&RecvTab[k].Length,FALSE); 
		if(RecvTab[k].Length>BUFFER_SIZE) RecvTab[k].Length=BUFFER_SIZE; 
		memcpy((void *)pbuf,(void *)RecvTab[k].Buffer,RecvTab[k].Length); 
		len=RecvTab[k].Length; 
		CloseHandle(RecvTab[k].hEvent); 
		for(j=i;j<RECV_MAX-1;i++)  
			EventTab[i]=EventTab[++j];			 
		hEvent=CreateEvent(0, TRUE, 0, NULL); 
		if(!hEvent) { 
			fprintf(stderr,"Can not create event\n"); 
			return SYSERR; 
		} 
		RecvTab[k].hEvent=hEvent; 
		memset(RecvTab[k].Buffer,0,BUFFER_SIZE); 
		RecvTab[k].Size=BUFFER_SIZE; 
		RecvTab[k].Active=TRUE; 
		RecvTab[k].Type=READ; 
		EventTab[RECV_MAX-1]=hEvent; 
		RecvStart(hVxD,&RecvTab[k]); 
		return len; 
	} 
	else return SYSERR;	 
} 
 
WORD SendPacket(HANDLE hVxD,BYTE *pbuf,WORD len) 
{ 
	static struct PacketTable SendTab; 
	HANDLE hEvent; 
 
	hEvent=CreateEvent(0, TRUE, 0, NULL); 
	if(!hEvent) { 
		fprintf(stderr,"Can not create event\n"); 
		return SYSERR; 
	} 
	SendTab.hEvent=hEvent; 
	memcpy(SendTab.Buffer,(void *)pbuf,len); 
	SendTab.Size=len; 
	SendTab.Length=BUFFER_SIZE; 
	SendTab.Active=TRUE; 
	SendTab.Type=WRITE; 
	SendStart(hVxD,&SendTab); 
 
	GetOverlappedResult(hVxD,&SendTab.Overlap,&SendTab.Length,TRUE); 
	return OK;	 
} 
 
WORD CheckSum(WORD *addr,WORD len) 
{ 
	DWORD lSum; 
	WORD wOddByte; 
	WORD wAnswer;  
 
	lSum=0l; 
 
	while(len>1) { 
		lSum+= *addr++; 
		len-=2; 
	} 
 
	if(len==1) { 
		wOddByte=0; 
		*((unsigned char*)&wOddByte)=*(unsigned char*)addr; 
		lSum+=wOddByte; 
	} 
 
	lSum=(lSum>>16)+(lSum&0xffff); 
	lSum+=(lSum>>16); 
	wAnswer=(unsigned int)~lSum; 
 
	return wAnswer; 
} 
 
WORD swaps(WORD net) 
{ 
	WORD lo,hi; 
	WORD host; 
 
	lo=net&0xff; 
	hi=net&0xff00; 
	lo=lo<<8; 
	hi=hi>>8; 
	host=hi|lo; 
 
	return host; 
} 
 
DWORD swapl(DWORD net) 
{ 
	DWORD b1,b2,b3,b4; 
	DWORD host; 
 
	b1=net&0xff; 
	b2=net&0xff00; 
	b3=net&0xff0000; 
	b4=net&0xff000000; 
 
	b1=b1<<24; 
	b2=b2<<8; 
	b3=b3>>8; 
	b4=b4>>24; 
 
	host=b1|b2|b3|b4; 
 
	return host; 
} 
 
WORD GetOption(int argc,char *argv[],struct CommandLine *cmdline) 
{ 
	int i; 
	char *pbufh,*pbuft; 
	char c; 
 
	cmdline->option=OPT_DO_NOTHING; 
	for(i=1;i<argc;i++) { 
		if((pbufh=strstr(argv[i],"-l"))!=NULL) {	/* Listen */ 
			if(strstr(argv[i],"-lini")!=NULL) cmdline->option|=OPT_LISTEN_INIT; 
			else cmdline->option|=OPT_LISTEN_ALL; 
			/*printf("listen\n");*/ 
		} 
		else if(strstr(argv[i],"-?")!=NULL) { 
			cmdline->option|=OPT_HELP; 
		} 
		else if((pbufh=strstr(argv[i],"-ip:"))!=NULL&& 
			(cmdline->option&OPT_LISTEN_ALL)!=0) {	/* IP address */ 
			pbufh+=4; 
			if((pbuft=strstr(pbufh,":"))!=NULL) {	/* Two IP */ 
				pbuft++; 
				GetIPAddr(pbufh,&cmdline->queip[0]); 
				GetIPAddr(pbuft,&cmdline->queip[1]); 
				cmdline->option|=OPT_LISTEN_IP_2; 
			} 
			else {	/* One IP */ 
				GetIPAddr(pbufh,&cmdline->queip[0]); 
				cmdline->option|=OPT_LISTEN_IP_1; 
			} 
		} 
		else if((pbufh=strstr(argv[i],"-port:"))!=NULL&& 
			(cmdline->option&OPT_LISTEN_ALL)!=0) {	/* Port */ 
			pbufh+=6; 
			if((pbuft=strstr(pbufh,":"))!=NULL) {	/* Two port */ 
				pbuft++; 
				sscanf(pbufh,"%d",&cmdline->queport[0]); 
				sscanf(pbuft,"%d",&cmdline->queport[1]); 
				cmdline->option|=OPT_LISTEN_PORT_2; 
			} 
			else {	/* One port */ 
				sscanf(pbufh,"%d",&cmdline->queport[0]); 
				cmdline->option|=OPT_LISTEN_PORT_1; 
			} 
		} 
		else if((pbufh=strstr(argv[i],"-qeth:"))!=NULL) {	/* Query ethernet address */ 
			cmdline->option|=OPT_QUE_ETHER; 
			pbufh+=6; 
			GetIPAddr(pbufh,&cmdline->queip[0]); 
		} 
		else if((pbufh=strstr(argv[i],"-qip:"))!=NULL) {	/* Query IP */ 
			cmdline->option|=OPT_QUE_IP; 
			pbufh+=5; 
			GetEtherAddr(pbufh,&cmdline->queeth[0]); 
		} 
		else if((pbufh=strstr(argv[i],"-fout:"))!=NULL) {	/* Output file */ 
			cmdline->option|=OPT_OUTPUT_FILE; 
			pbufh+=6; 
			sscanf(pbufh,"%s",cmdline->outfile); 
		} 
		else if((pbufh=strstr(argv[i],"-fcmd:"))!=NULL) {	/* Command file */ 
			cmdline->option|=OPT_COMMAND_FILE; 
			pbufh+=6; 
			sscanf(pbufh,"%s",cmdline->cmdfile); 
		} 
	} 
	if(cmdline->option&OPT_LISTEN_SPEC) cmdline->option&=~OPT_LISTEN_ALL; 
	return OK; 
} 
 
WORD GetInitial(FILE *pfini,struct InitialFile *inifile) 
{ 
	char Command[BUFFER_SIZE]; 
	int i; 
	int out; 
 
	out=2; 
	inifile->ipno=0; 
	inifile->portno=0; 
	inifile->timeout=INFINITE; 
	inifile->maxdatalen=MAX_DATA; 
	while(feof(pfini)==0) { 
		ReadCommand(pfini,Command); 
		switch (GetCommand(Command)) { 
		case INITIAL_MAX_DATA: 
			ReadCommand(pfini,Command); 
			sscanf(Command,"%d",&inifile->maxdatalen); 
			break; 
		case INITIAL_IP_ADDR: 
			ReadCommand(pfini,Command); 
			out--; 
			GetIPAddr(Command,&inifile->mipaddr); 
			break; 
		case INITIAL_NDIS: 
			out--; 
			ReadCommand(pfini,inifile->ndis); 
			break; 
		case INITIAL_QUERY_IP: 
			ReadCommand(pfini,Command); 
			i=0; 
			while(GetCommand(Command)!=INITIAL_END_SEGMENT) { 
				GetIPAddr(Command,&inifile->qip[i]); 
				i++; 
				if(i==MAX_QUERY) return SYSERR; 
				ReadCommand(pfini,Command); 
			} 
			inifile->ipno=i; 
			break; 
		case INITIAL_QUERY_PORT: 
			ReadCommand(pfini,Command); 
			i=0; 
			while(GetCommand(Command)!=INITIAL_END_SEGMENT) { 
				sscanf(Command,"%d",&inifile->qport[i]); 
				i++; 
				if(i==MAX_QUERY) return SYSERR; 
				ReadCommand(pfini,Command); 
			} 
			inifile->portno=i; 
			break; 
		case INITIAL_TIMEOUT: 
			ReadCommand(pfini,Command); 
			if(strstr(Command,INITIAL_INFINITE)==NULL)  
				sscanf(Command,"%d",&inifile->timeout); 
			else inifile->timeout=INFINITE; 
			break; 
		case COMMENT: 
			break; 
		case INITIAL_END_SEGMENT: 
			break; 
		default: 
			if(feof(pfini)==0) return SYSERR; 
		} 
	} 
	if(out>0) return SYSERR; 
	else return OK; 
	return OK; 
} 
 
void PrintEtherAddr(FILE *pf,struct EtherAddr *pethaddr) 
{ 
	fprintf(pf,"%02x.%02x.%02x.%02x.%02x.%02x",pethaddr->AddrByte[0], 
		    pethaddr->AddrByte[1], 
		    pethaddr->AddrByte[2], 
		    pethaddr->AddrByte[3], 
		    pethaddr->AddrByte[4], 
		    pethaddr->AddrByte[5]); 
} 
 
void PrintIPAddr(FILE *pf,struct IPAddr *pIPaddr) 
{ 
	fprintf(pf,"%d.%d.%d.%d",pIPaddr->AddrByte[0], 
		    pIPaddr->AddrByte[1], 
		    pIPaddr->AddrByte[2], 
		    pIPaddr->AddrByte[3]); 
} 
 
WORD SendARPPacket(HANDLE hVxD, 
				   struct EtherAddr *psourether, 
				   struct EtherAddr *pdestether, 
				   struct EtherAddr *psendether, 
				   struct EtherAddr *precvether, 
				   struct IPAddr *psendip, 
				   struct IPAddr *precvip, 
				   WORD oper) 
{ 
	char Buffer[BUFFER_SIZE]; 
	struct EtherPacketHead *pEtherHead; 
	struct ARPPacket *pARPHead; 
 
	memset(Buffer,0,BUFFER_SIZE); 
	pEtherHead=(struct EtherPacketHead *)Buffer; 
	pARPHead=(struct ARPPacket *)(Buffer+ETHER_HEAD_LEN); 
	memcpy((void *)&pEtherHead->SourEther,(void *)psourether,6); 
	memcpy((void *)&pEtherHead->DestEther,(void *)pdestether,6); 
	pEtherHead->ServType=swaps(ETHER_PROTO_ARP); 
	memset((void *)pARPHead,0,ARP_PACKET_LEN); 
	pARPHead->Type=swaps(ARP_HARD_TYPE); 
	pARPHead->Proto=swaps(ARP_PROTO_TYPE); 
	pARPHead->HardAddrLen=ARP_HARD_ADDR_LEN; 
	pARPHead->AddrLen=ARP_ADDR_LEN; 
	pARPHead->Oper=swaps(oper); 
	memcpy((void *)&pARPHead->SourEther,(void *)psendether,6); 
	memcpy((void *)&pARPHead->DestEther,(void *)precvether,6); 
	memcpy((void *)&pARPHead->SourIP,(void *)psendip,4); 
	memcpy((void *)&pARPHead->DestIP,(void *)precvip,4); 
	if(SendPacket(hVxD,Buffer,ETHER_HEAD_LEN+ARP_PACKET_LEN)==SYSERR) { 
		fprintf(stderr,"Can not send ARP packet.\n"); 
		return SYSERR; 
	} 
	return OK; 
} 
 
WORD SendTCPPacket(HANDLE hVxD, 
				   struct EtherAddr *psourether, 
				   struct EtherAddr *pdestether, 
				   struct IPAddr *psourip, 
				   struct IPAddr *pdestip, 
				   WORD sourport, 
				   WORD destport, 
				   WORD flag, 
				   DWORD seqno, 
				   DWORD ackno, 
				   char *pbuf, 
				   WORD len) 
{ 
	char Buffer[BUFFER_SIZE]; 
	char HelpBuffer[BUFFER_SIZE]; 
	char *pdata; 
	struct EtherPacketHead *pEtherHead; 
	struct IPPacketHead *pIPHead; 
	struct TCPPacketHead *pTCPHead,*pHelpTCPHead; 
	struct PseudoHead *pPseudoHead; 
	static WORD id=0; 
	WORD wlen; 
 
	id++; 
	memset(Buffer,0,BUFFER_SIZE); 
	pEtherHead=(struct EtherPacketHead *)Buffer; 
	pIPHead=(struct IPPacketHead *)(Buffer+ETHER_HEAD_LEN); 
	pTCPHead=(struct TCPPacketHead *)(Buffer+ETHER_HEAD_LEN+IP_HEAD_BYTE_LEN); 
	pPseudoHead=(struct PseudoHead *)HelpBuffer; 
	pHelpTCPHead=(struct TCPPacketHead *)(HelpBuffer+PSEUDO_HEAD_LEN); 
	pdata=(char *)(Buffer+ETHER_HEAD_LEN+IP_HEAD_BYTE_LEN+TCP_HEAD_BYTE_LEN); 
	/* Set ether head */ 
	memcpy((void *)&pEtherHead->SourEther,(void *)psourether,6); 
	memcpy((void *)&pEtherHead->DestEther,(void *)pdestether,6); 
	pEtherHead->ServType=swaps(ETHER_PROTO_IP); 
	/* Set IP head */ 
	memcpy((void *)&pIPHead->SourIP,(void *)psourip,4); 
	memcpy((void *)&pIPHead->DestIP,(void *)pdestip,4); 
	pIPHead->VerHLen=(IP_VER<<4)|IP_HEAD_LEN; 
	pIPHead->Type=IP_SERV_TYPE; 
	wlen=len+TCP_HEAD_BYTE_LEN+IP_HEAD_BYTE_LEN; 
	pIPHead->TtlLen=swaps(wlen); 
	pIPHead->Id=swaps(id); 
	pIPHead->FlgOff=0; 
	pIPHead->TTL=69; 
	pIPHead->Proto=IP_PROTO_TCP; 
	pIPHead->ChkSum=0; 
	pIPHead->ChkSum=CheckSum((WORD *)pIPHead,IP_HEAD_BYTE_LEN); 
	/* Set TCP head */ 
	pTCPHead->SourPort=swaps(sourport); 
	pTCPHead->DestPort=swaps(destport); 
	pTCPHead->SeqNo=swapl(seqno); 
	pTCPHead->AckNo=swapl(ackno); 
	pTCPHead->HLen=TCP_HEAD_LEN<<4; 
	pTCPHead->Flag=flag; 
	pTCPHead->WndSize=swaps(8192); 
	pTCPHead->ChkSum=0; 
	pTCPHead->UrgPtr=0; 
	/* Set TCP data */ 
	memcpy((void *)pdata,(void *)pbuf,len); 
	/* Calculate TCP checksum */ 
	memcpy((void *)&pPseudoHead->SourIP,(void *)psourip,4); 
	memcpy((void *)&pPseudoHead->DestIP,(void *)pdestip,4); 
	pPseudoHead->Pad=0; 
	pPseudoHead->Proto=IP_PROTO_TCP; 
	wlen=len+TCP_HEAD_BYTE_LEN; 
	pPseudoHead->Len=swaps(wlen); 
	memcpy((void *)pHelpTCPHead,(void *)pTCPHead,wlen); 
	wlen=len+TCP_HEAD_BYTE_LEN+PSEUDO_HEAD_LEN; 
	pTCPHead->ChkSum=CheckSum((WORD *)HelpBuffer,wlen); 
	wlen=len+TCP_HEAD_BYTE_LEN+IP_HEAD_BYTE_LEN+ETHER_HEAD_LEN; 
	if(SendPacket(hVxD,Buffer,wlen)==SYSERR) { 
		fprintf(stderr,"Can not send TCP packet.\n"); 
		return SYSERR; 
	} 
	return OK; 
} 
 
WORD RecvTCPPacket(HANDLE hVxD, 
				   struct IPAddr *psourip, 
				   struct IPAddr *pdestip, 
				   WORD sourport, 
				   WORD destport, 
				   WORD *flag, 
				   DWORD *seqno, 
				   DWORD *ackno, 
				   char *pbuf, 
				   WORD *size) 
{ 
	BOOL Continue; 
	WORD DataLen; 
	char Buffer[BUFFER_SIZE]; 
	struct EtherPacketHead *pEtherHead; 
	struct IPPacketHead *pIPHead; 
	struct TCPPacketHead *pTCPHead; 
	int headlen; 
	int totallen; 
	char *pdata; 
 
	 
	struct IPAddr *mpsourip,*mpdestip; 
	WORD msourport,mdestport,i; 
	DWORD mackno,mseqno; 
 
	Continue=TRUE; 
	while(Continue) { 
		if((DataLen=RecvPacket(hVxD,Buffer))==SYSERR) { 
			fprintf(stderr,"Can not recv TCP packet.\n"); 
			return SYSERR; 
		} 
		pEtherHead=(struct EtherPacketHead *)Buffer; 
		if(swaps(pEtherHead->ServType)!=ETHER_PROTO_IP) continue; 
		pIPHead=(struct IPPacketHead *)(Buffer+ETHER_HEAD_LEN); 
		if(memcmp((void *)&pIPHead->SourIP,(void *)psourip,4)!=0) continue; 
		if(memcmp((void *)&pIPHead->DestIP,(void *)pdestip,4)!=0) continue; 
		headlen=(pIPHead->VerHLen)&0xf; 
		headlen*=4; 
		totallen=swaps(pIPHead->TtlLen); 
		pTCPHead=(struct TCPPacketHead *)(Buffer+ETHER_HEAD_LEN+headlen); 
		if(swaps(pTCPHead->SourPort)!=sourport) continue; 
		if(swaps(pTCPHead->DestPort)!=destport) continue; 
		/* Get TCP data */ 
		totallen-=headlen; 
		headlen=pTCPHead->HLen>>4; 
		headlen*=4; 
		totallen-=headlen; 
		*flag=pTCPHead->Flag; 
		*seqno=swapl(pTCPHead->SeqNo); 
		*ackno=swapl(pTCPHead->AckNo); 
		*size=totallen; 
		pdata=((char *)pTCPHead)+headlen; 
		memcpy((void *)pbuf,(void *)pdata,totallen); 
		Continue=FALSE; 
	} 
	return OK; 
} 
 
void ReadCommand(FILE *pf,char *pbuf) 
{ 
	while(feof(pf)==0) { 
		*pbuf=fgetc(pf); 
		if(*pbuf=='\n') break; 
		pbuf++; 
	} 
	*pbuf=0; 
} 
 
WORD GetCommand(char *pbuf) 
{ 
	char buf[MAX_COMMAND]; 
 
	if(*pbuf==0) return INITIAL_END_SEGMENT; 
	sscanf(pbuf,"%s",buf); 
	ToUpper(buf); 
	if(strstr(buf,"SENDARP")!=NULL) return COMMAND_SEND_ARP; 
	else if(strstr(buf,"SENDTCP")!=NULL) return COMMAND_SEND_TCP; 
	else if(strstr(buf,"RECVTCP")!=NULL) return COMMAND_RECV_TCP; 
	else if(strstr(buf,"CONNECT")!=NULL) return COMMAND_CONNECT_TCP; 
	else if(strstr(buf,"CLOSE")!=NULL) return COMMAND_CLOSE_TCP; 
	else if(buf[0]=='#') return COMMENT; 
	else if(strstr(buf,"[IPADDR]")!=NULL) return INITIAL_IP_ADDR; 
	else if(strstr(buf,"[NDIS]")!=NULL) return INITIAL_NDIS; 
	else if(strstr(buf,"[MAXDATALEN]")!=NULL) return INITIAL_MAX_DATA; 
	else if(strstr(buf,"[QUERYIP]")!=NULL) return INITIAL_QUERY_IP; 
	else if(strstr(buf,"[QUERYPORT]")!=NULL) return INITIAL_QUERY_PORT; 
	else if(strstr(buf,"[TIMEOUT]")!=NULL) return INITIAL_TIMEOUT; 
	else return COMMAND_UNKNOWN; 
} 
 
void ToUpper(char *pbuf) 
{ 
	char c; 
 
	while(*pbuf) { 
		c=*pbuf; 
		if(c>='a'&&c<='z') *pbuf=c+'A'-'a'; 
		pbuf++; 
	} 
} 
 
void GetSendARPArg(char *pbuf, 
				   struct EtherAddr *psendeth, 
				   struct EtherAddr *precveth, 
				   struct EtherAddr *soureth, 
				   struct EtherAddr *desteth, 
				   struct IPAddr *sourip, 
				   struct IPAddr *destip, 
				   WORD *oper) 
{ 
	char pcmd[20],pseth[20],preth[20],psoureth[20],pdesteth[20],psip[20],pdip[20],poper[20]; 
 
	/* A line as "SENDARP sendeth recveth soureth sourip desteth destip oper" */ 
	sscanf(pbuf,"%s %s %s %s %s %s %s %s", 
		   pcmd,pseth,preth,psoureth,psip,pdesteth,pdip,poper); 
	GetEtherAddr(pseth,psendeth); 
	GetEtherAddr(preth,precveth); 
	GetEtherAddr(psoureth,soureth); 
	GetEtherAddr(pdesteth,desteth); 
	GetIPAddr(psip,sourip); 
	GetIPAddr(pdip,destip); 
	sscanf(poper,"%d",oper); 
} 
 
void GetSendTCPArg(char *pbuf,WORD *id,char *pdata,WORD *size) 
{ 
	/* A line as "SENDTCP id data" */ 
	char pcmd[20],pid[20],Buffer[BUFFER_SIZE]; 
 
	sscanf(pbuf,"%s %s %s",pcmd,pid,Buffer); 
	sscanf(pid,"%d",id); 
	GetDataArg(Buffer,pdata,size); 
} 
 
void GetRecvTCPArg(char *pbuf,WORD *id) 
{ 
	/* A line as "RECVTCP id" */ 
	char pcmd[20],pid[20]; 
 
	sscanf(pbuf,"%s %s",pcmd,pid); 
	sscanf(pid,"%d",id); 
} 
 
void GetConnectArg(char *pbuf, 
				   struct EtherAddr *sendeth, 
				   struct EtherAddr *recveth, 
				   struct IPAddr *sourip, 
				   struct IPAddr *destip, 
				   WORD *sourport, 
				   WORD *destport, 
				   WORD *id) 
{ 
	/* A line as "CONNECT sendeth recveth sourip destip sourport destport id" */ 
	char pcmd[20],psip[20],pdip[20],psport[20],pdport[20],pid[20],pseth[20],preth[20]; 
	 
	sscanf(pbuf,"%s %s %s %s %s %s %s %s", 
		   pcmd,pseth,preth,psip,pdip,psport,pdport,pid); 
	GetEtherAddr(pseth,sendeth); 
	GetEtherAddr(preth,recveth); 
	GetIPAddr(psip,sourip); 
	GetIPAddr(pdip,destip); 
	sscanf(psport,"%d",sourport); 
	sscanf(pdport,"%d",destport); 
	sscanf(pid,"%d",id); 
} 
 
void GetCloseArg(char *pbuf,WORD *id) 
{ 
	/* A line as "CLOSE id */ 
	char pcmd[20],pid[20]; 
 
	sscanf(pbuf,"%s %s",pcmd,pid); 
	sscanf(pid,"%d",id); 
} 
 
void GetIPAddr(char *pbuf,struct IPAddr *pipaddr) 
{ 
	char c; 
 
	sscanf(pbuf,"%d%c%d%c%d%c%d",&pipaddr->AddrByte[0],&c, 
	   &pipaddr->AddrByte[1],&c, 
	   &pipaddr->AddrByte[2],&c, 
	   &pipaddr->AddrByte[3]); 
} 
 
void GetEtherAddr(char *pbuf,struct EtherAddr *pethaddr) 
{ 
	char c; 
 
	sscanf(pbuf,"%x%c%x%c%x%c%x%c%x%c%x",&pethaddr->AddrByte[0],&c, 
	   &pethaddr->AddrByte[1],&c, 
	   &pethaddr->AddrByte[2],&c, 
	   &pethaddr->AddrByte[3],&c, 
	   &pethaddr->AddrByte[4],&c, 
	   &pethaddr->AddrByte[5]); 
} 
 
void GetDataArg(char *pbuf,char *pdata,WORD *size) 
{ 
	char buf[4]; 
 
	(*size)=0; 
	while(*pbuf) { 
		if(*pbuf=='\\') { 
			pbuf++; 
			memcpy(buf,pbuf,3); 
			buf[3]=0; 
			sscanf(buf,"%d",pdata); 
			pbuf+=2; 
		} 
		else *pdata=*pbuf; 
		pdata++; 
		pbuf++; 
		(*size)++; 
	} 
} 
 
void PrintData(FILE *pf,BYTE *pdata,int size) 
{ 
	int i; 
 
	if(size>Max_Data_Len) size=Max_Data_Len; 
	for(i=0;i<size;i++) { 
		if(pdata[i]<' ') fprintf(pf,"\\%03d",pdata[i]); 
		else fprintf(pf,"%c",pdata[i]); 
	} 
}