Wireshark-dev: [Wireshark-dev] Developing an application suing pacap in windows which simulates
From: "shakthi.pradeep" <[email protected]>
Date: Tue, 26 Jun 2007 18:24:09 +0530

Hello All,

 

I am trying to write an application using pcap in windows which acts like a Network Layer 2 switch. This is what I am doing.

 

 

 

1.       PC A has 1 LAN card

2.       PC B has 2 LAN cards

3.       PC C has 1 LAN card

 

I Connect PC A to PC B over LAN 1 and connect PC C and PC B over LAN 2. LAN cards in PC B are NOT bridged. So when I send data from PC A to PC C, it will not reach the destination.

 

Application that I wrote does the following:

 

Let’s assume PC A is connected to LAN card 1 in PC B and PC C is connected to LAN card 2 in PC B.

 

When PC A sends data intended for PC C, application running on PC B, using PCAP api’s receives the Data link layer data at the application layer through LAN card 1 and forwards the same without modifying to PC C through LAN card 2 using pcap api’s and vice versa. I could verify that data sent by PC A is received by LAN card 1 by observing the contents of the packet received in the application. Api used to transmit the same packet over LAN card 2 return success but when I ran ethereal on PC C to capture all packets received I don’t see the packet that was forwarded by PC B. I used pcap library in PC B and ethereal in PC C in promiscuous mode.

 

Am I missing something???????

 

I have also attached the source code. Please take a look and let me know if I missed something.

Thanks & Regards

Shakthi


E-Mail : shakthi[email protected]

 

 

#include "include/pcap.h"


void PacketReceiver_A(unsigned char *, const struct pcap_pkthdr *, const unsigned char *);
void PacketReceiver_B(unsigned char *, const struct pcap_pkthdr *, const unsigned char *);
int OpenAndRegisterCallBackWithInterfaceA(struct PcapInfo *);
int OpenAndRegisterCallBackWithInterfaceB(struct PcapInfo *);
pcap_if_t *SelectInterface(pcap_if_t *,int );
void DexExit(pcap_if_t *);

struct PcapInfo
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
}pcapinfoA,pcapinfoB;

pcap_t *adhandleA,*adhandleB;

void DexExit(pcap_if_t *alldevs)
{
	getch();
	/* At this point, we don't need any more the device list. Free it */
	pcap_freealldevs(alldevs);
	exit(0);
}

main()
{
	pcap_if_t *alldevs;
	pcap_if_t *d, *dA, *dB;
	int inum;
	int i=0;
	pcap_t *adhandleA,*adhandleB;
	char errbuf[PCAP_ERRBUF_SIZE];
	HANDLE InterfaceA,InterfaceB;
	int InterfaceAStatus,InterfaceBStatus;
	
	/* Retrieve the device list */
	if(pcap_findalldevs(&alldevs, errbuf) == -1)
	{
		fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
		DexExit(alldevs);
	}
	
	/* Print the list */
	for(d=alldevs; d; d=d->next)
	{
		printf("%d. %s", ++i, d->name);
		if (d->description)
			printf(" (%s)\n\n", d->description);
		else
			printf(" (No description available)\n");
	}
	
	if(i==0)
	{
		printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
		DexExit(alldevs);
	}

	/* Select Interface A */
	dA = SelectInterface(alldevs,i);

	if(dA == -1)
	{
		printf("Selected Wrong Interface\n");
		DexExit(alldevs);
	}
	
	/* Select Interface B */
	dB = SelectInterface(alldevs,i);
	if(dB == -1)
	{
		printf("Selected Wrong Interface\n");
		DexExit(alldevs);
	}

	/* check if both selected interfaces are same */
	if(dA == dB)
	{
		printf("Selected Same Interface\nPlease select different Interfaces\n");
		DexExit(alldevs);
	}

	/* Create threadto Hadle Interface A */
    
	pcapinfoA.alldevs = alldevs;
	pcapinfoA.d = dA;

	InterfaceAStatus = CreateThread( 
	NULL,              // default security attributes
	0,                 // use default stack size  
	(void *)OpenAndRegisterCallBackWithInterfaceA,        // thread function 
	&pcapinfoA,             // argument to thread function 
	0,                 // use default creation flags 
	&InterfaceA);   // returns the thread identifier 

	if(InterfaceAStatus)
	{
		printf("Interface A Handler started.\n");
	}
	else
	{
		printf("Interface A Handler start failed\n");
		DexExit(alldevs);
	}

	/* Create threadto Hadle Interface A */
    
	pcapinfoB.alldevs = alldevs;
	pcapinfoB.d = dB;

	InterfaceBStatus = CreateThread( 
	NULL,              // default security attributes
	0,                 // use default stack size  
	(void *)OpenAndRegisterCallBackWithInterfaceB,        // thread function 
	&pcapinfoB,             // argument to thread function 
	0,                 // use default creation flags 
	&InterfaceB);   // returns the thread identifier 

	if(InterfaceAStatus)
	{
		printf("Interface B Handler started.\n");
	}
	else
	{
		printf("Interface B Handler start failed\n");
		DexExit(alldevs);
	}


	//WaitForSingleObject(InterfaceA,INFINITE);
	//WaitForSingleObject(InterfaceB,INFINITE);

	while(1) Sleep(1);
	
	return 0;
}

pcap_if_t *SelectInterface(pcap_if_t *alldevs,int numinterfaces)
{
	int inum=-1;
	pcap_if_t *d;
	/* Request to select interface */
	printf("Enter the interface number A (1-%d):",numinterfaces);
	scanf("%d", &inum);
	
	if(inum < 1 || inum > numinterfaces)
	{
		printf("\nInterface number out of range.\n");
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}

	/* Jump to the selected adapter */
	for(d=alldevs, numinterfaces=0; numinterfaces< inum-1 ;d=d->next, numinterfaces++);

	return d;
}

int OpenAndRegisterCallBackWithInterfaceA(struct PcapInfo *InterfaceInfoA)
{
	int inum;
	int i=0;
	char errbuf[PCAP_ERRBUF_SIZE];


	
	/* Open the device A*/
	/* Open the adapter A*/
	if ((adhandleA= pcap_open_live(InterfaceInfoA->d->name,	// name of the device
							 65536,			// portion of the packet to capture. 
											// 65536 grants that the whole packet will be captured on all the MACs.
							 1,				// promiscuous mode (nonzero means promiscuous)
							 1000,			// read timeout
							 errbuf			// error buffer
							 )) == NULL)
	{
		fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", InterfaceInfoA->d->name);
		/* Free the device list */
		pcap_freealldevs(InterfaceInfoA->alldevs);
		return -1;
	}
	
	printf("\nlistening on %s...\n\n", InterfaceInfoA->d->description);
	

	/* start the capture */
	pcap_loop(adhandleA, 0, PacketReceiver_A, NULL);
	
	pcap_close(adhandleA);
	return 0;

}


int OpenAndRegisterCallBackWithInterfaceB(struct PcapInfo *InterfaceInfoB)
{
	int inum;
	int i=0;
	char errbuf[PCAP_ERRBUF_SIZE];


	
	/* Open the device B*/
	/* Open the adapter B*/
	if ((adhandleB= pcap_open_live(InterfaceInfoB->d->name,	// name of the device
							 65536,			// portion of the packet to capture. 
											// 65536 grants that the whole packet will be captured on all the MACs.
							 1,				// promiscuous mode (nonzero means promiscuous)
							 1000,			// read timeout
							 errbuf			// error buffer
							 )) == NULL)
	{
		fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", InterfaceInfoB->d->name);
		/* Free the device list */
		pcap_freealldevs(InterfaceInfoB->alldevs);
		return -1;
	}
	
	printf("\nlistening on %s...\n\n", InterfaceInfoB->d->description);
	
	/* start the capture */
	pcap_loop(adhandleB, 0, PacketReceiver_B, NULL);
	
	pcap_close(adhandleB);
	return 0;

}


/* Callback function invoked by libpcap for every incoming packet on Interface A*/
void PacketReceiver_A(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data)
{
	printf("Interface A : len:%d\n",header->len);

	/* Forward the packet on Interface B */
	if (pcap_sendpacket(adhandleB,	// Adapter
		pkt_data,				// buffer with the packet
		header->len				// size
		) != 0)
	{
		fprintf(stderr,"\nError sending the packet to Interface B: \n", pcap_geterr(adhandleA));
		return 3;
	}
}

/* Callback function invoked by libpcap for every incoming packet on Interface A*/
void PacketReceiver_B(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data)
{
	printf("Interface B : len:%d\n",header->len);

	/* Forward the packet on Interface B */
	if (pcap_sendpacket(adhandleA,	// Adapter
		pkt_data,				// buffer with the packet
		header->len				// size
		) != 0)
	{
		fprintf(stderr,"\nError sending the packet to Interface A: \n", pcap_geterr(adhandleB));
		return 3;
	}
}