本文共 4303 字,大约阅读时间需要 14 分钟。
动机是我屋里有两台电脑,但到屋里只有一根外出网线,一台机子有双网卡,我就正好运用我前段学习的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 ); }} 转载地址:http://ydibb.baihongyu.com/