博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用libnet, libpcap模拟一个交换机
阅读量:2234 次
发布时间:2019-05-09

本文共 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/

你可能感兴趣的文章
【MyBatis学习12】MyBatis中的一级缓存
查看>>
【MyBatis学习13】MyBatis中的二级缓存
查看>>
【MyBatis学习14】MyBatis和Spring整合
查看>>
【MyBatis学习15】MyBatis的逆向工程生成代码
查看>>
Java 中 final、finally 和 finalize 使用总结
查看>>
volatile关键字解析
查看>>
单例模式的八种写法比较
查看>>
比较常见的数据库SQL面试题以及答案
查看>>
MySQL与Oracle的区别
查看>>
关于Oracle数据库优化的几点总结
查看>>
69道Spring面试题和答案
查看>>
40个Java多线程问题总结
查看>>
Oracle数据库面试题
查看>>
java面试中的智力题
查看>>
本地如何连接hbase数据库
查看>>
Maven出错-Missing artifact org.apache.openejb:openejb-core:jar:4.1.0-SNAPSHOT:test
查看>>
dubbo配置文件xml校验报错
查看>>
eclipse生成export生成jar详解
查看>>
oracle 模糊查询忽略大小写
查看>>
Java项目导出可运行的jar文件
查看>>