使用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 );
    }
}

你可能感兴趣的:(职场,休闲,libpcap,交换机,libnet)