使用libnet, libpcap模拟一个交换机
这位仁兄比较有意思,将电脑做成交换机,但是太浪费了,做成路由器多好,还不影响那台双网卡的机器。 动机是我屋里有两台电脑,但到屋里只有一根外出网线,一台机子有双网卡,我就正好运用我前段学习的libpcap和libnet写了一个数据包转发的小工具,把双网卡的机子模拟成一个交换机,使另一台机子能通过它访问外网,虽然用其它方法以能实现,但这正好是一个练习上面说的两个工具的好地方,还有以可免除当双网卡机子不开机时,另一台机子只要直接接上外网的网线就行了,不用频繁的更改IP。 /* net data packet transmit tools * liujx * 2007-4-1 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <netinet/ip.h> #include <sys/time.h> #include <net/ethernet.h> #include <pthread.h> #include <pcap.h> #include <libnet.h> #define IN_ETH "eth1" char *dev_a, *dev_b; pcap_t *pt_a, *pt_b; pthread_t pid_a, pid_b; libnet_t *net_a, *net_b; static char errbuf[256]; void sigproc( int sig ); void* dev_a_capture( void *); void dev_a_handle( u_char *devId, const struct pcap_pkthdr *h, const u_char *p ); void* dev_b_capture( void *); void dev_b_handle( u_char *devId, const struct pcap_pkthdr *h, const u_char *p ); int main( int argc, char* argv[] ) { /* regise signal ctrl+c stop capture */ signal( SIGINT, sigproc ) ; /* init libnet */ net_a = libnet_init( LIBNET_LINK, "eth2", errbuf ); if( net_a == NULL ) { fprintf(stderr, "libnet_init fail:%s ", errbuf ); return; } net_b = libnet_init( LIBNET_LINK, "eth1", errbuf ); if( net_a == NULL ) { fprintf(stderr, "libnet_init fail:%s ", errbuf ); return; } /* create thread */ int status; printf("create a "); status = pthread_create( &pid_a, NULL, dev_a_capture, NULL ); if ( status != 0 ) { printf( "pthread_create( A ) faile. "); goto end; } printf("create b "); status = pthread_create( &pid_b, NULL, dev_b_capture, NULL ); if ( status != 0 ) { printf( "pthread_create( B ) faile. "); goto end; } pthread_join( pid_a, NULL ); pthread_join( pid_b, NULL ); end: pcap_close( pt_a ); pcap_close( pt_b ); return 0; } /* single processing function */ void sigproc( int sig ) { pthread_cancel( pid_a ); pthread_cancel( pid_b ); pcap_close( pt_a ); pcap_close( pt_b ); libnet_destroy( net_a ); libnet_destroy( net_b ); printf("exit transmit. "); exit(0); } /*receive eth1's packet and transmit to eth2 */ void* dev_a_capture(void *arg) { dev_a = pcap_lookupdev( errbuf ); if ( dev_a == NULL) { printf("pcap_lookupdev: %s ", errbuf ); exit( 0 ); } printf("get dev: '%s' ", dev_a ); pt_a = pcap_open_live( dev_a, 8000, 1, 500, errbuf ); if( pt_a == NULL ) { printf("pcap_open_live:%s ", errbuf ); exit(0); } for(;;) { int ret; ret = pcap_dispatch( pt_a, 0, dev_a_handle, NULL); if ( ret == -1 ) { pcap_perror( pt_a, "pcap_dispatch err:"); } } } void dev_a_handle( u_char *devId, const struct pcap_pkthdr *hdr, const u_char *packet ) { //printf("%s,capture size :%d ",devId, hdr->caplen ); struct ether_header ehdr; memcpy( &ehdr, packet, sizeof( struct ether_header )); /* labpcap can capture all packet ,include self send packet. * only transmit distination address is 221(eth2 MAC last bytes) or broadcast address, * 221 is eth2 link host's MAC. */ if( ehdr.ether_shost[ETH_ALEN-1] == 221 ) { return; } if( ehdr.ether_dhost[ETH_ALEN-1] == 221 || ehdr.ether_dhost[ETH_ALEN-1] == 255 ) { printf("A src:%d, dst:%d ", ehdr.ether_shost[ETH_ALEN-1], ehdr.ether_dhost[ETH_ALEN-1] ); int c; c = libnet_write_link( net_a, (u_char*)packet, hdr->caplen ); //printf("A write: %d ", c ); } } /* receive eth2's packet and transmit to eth1. */ void* dev_b_capture(void *arg) { //dev_b = pcap_lookupdev( errbuf ); dev_b = "eth2"; pt_b = pcap_open_live( dev_b, 8000, 1, 500, errbuf ); if( pt_b == NULL ) { printf("pcap_open_live:%s ", errbuf ); exit(0); } for(;;) { int ret; ret = pcap_dispatch( pt_b, 0, dev_b_handle, NULL); if ( ret == -1 ) { pcap_perror( pt_b, "pcap_dispatch err:"); } } } void dev_b_handle( u_char *devId, const struct pcap_pkthdr *hdr, const u_char *packet ) { //printf("%s,capture size :%d ",devId, hdr->caplen ); u_int8_t eth_a[ETH_ALEN]; u_int8_t eth_b[ETH_ALEN]; struct ether_header ehdr; memcpy( &ehdr, packet, sizeof( struct ether_header )); /* Only transmit source address is 221(eth2 MAC last bytes) */ if( ehdr.ether_shost[ETH_ALEN-1] == 221 ) { printf("B src:%d, dst:%d ", ehdr.ether_shost[ETH_ALEN-1], ehdr.ether_dhost[ETH_ALEN-1] ); int c; c = libnet_write_link( net_b, (u_char*)packet, hdr->caplen ); //printf("B write: %d ", c ); } } |


xiong2127
博客统计信息
热门文章
最新评论
友情链接