使用libnet, libpcap模拟一个交换机

来源:互联网 发布:linux crontab 服务 编辑:程序博客网 时间:2024/05/17 10:05
动机是我屋里有两台电脑,但到屋里只有一根外出网线,一台机子有双网卡,我就正好运用我前段学习的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, 80001500, 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, sizeofstruct 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, 80001500, 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, sizeofstruct 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 );
    }
}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信qq号登陆改密码忘记了怎么办 本人微信红包赌博输了50万怎么办 4g飞享套餐话费用完了怎么办 手机丢了查话费欠了几百块怎么办 注销电信手机卡里面的余额怎么办 联通手机卡注销后里面的余额怎么办 手机卡网上销户以后剩余话费怎么办 联通新号注册微信发不了短信怎么办 韩博士装机卡在驱动恢复怎么办 xp打印后程序服务没有运行怎么办 刚注册的微信显示异常怎么办 不小心删了照片怎么办不要钱 qq邀请好友辅助验证成功后怎么办 微信申诉怎么让好友发验证码怎么办 微信申诉好友都删除了怎么办 恋与制作人原来的帐号不见了怎么办 手机号被别人注册了手机银行怎么办 想上老婆的陌陌号但要验证码怎么办 中国家医居民端注册信息有误怎么办 别人给我充的q币怎么办 qq忘记密码手机号码也换了怎么办 手机号码不用了微信忘记密码怎么办 手机号码注销了微信忘记密码怎么办 微信忘记密码手机号码也换了怎么办 微信钱包里的钱莫名少了怎么办 被骗给人冲q币了怎么办 支付宝账户异常无法领取红包怎么办 微信q币支付错了怎么办 王者荣耀不小心把点卷用了怎么办 微信绑定的qq号密码忘记了怎么办 微信红包实名认证没银行卡怎么办 手机烂了换新手机微信支付宝怎么办 支付宝转账给别人号码没用了怎么办 微信转账验证码收不到怎么办 陌生网友生日叫我发红包怎么办 微信群的群主不小心推出群该怎么办 支付宝验证码被别人知道了怎么办 微信解除银行卡绑定零钱清零怎么办 qq号被盗了理财通的钱怎么办 工行转错账号的钱被冻结怎么办 微信20w限额满了怎么办