linux下软件实现端口镜像

星空ID 2015-12-06 10:34:56

大家帮忙看一哈,麻烦了,我想把经过eth0的数据镜像一份到eth2上。上面这个是我设备的连接图示。该网络设备有三个网口,分别是eth0、eth1、eth2。现在我把三个网口桥接到了br0上。 br0设置了一个有效网址。我在用电脑PC A ping 设备br0,这个时候我能用电脑PC C在eth2这个地方抓到请求和相应包。但是当我用电脑PC A ping 电脑PC B时,我在eth2这个地方就抓不到包了,怎么回事呢。下面是我的代码(嘿嘿,网上找的,没怎么看懂)


#define MAX_PORTS 32 /* Max number of the ports that we can capture. */

#define DEBUG 0
#if DEBUG
#define debugK printk
#else
#define debugK(format, args...)
#endif

struct net_device *mirror;
struct net_device *ports_dev[MAX_PORTS] = { NULL };
static char config[256];
module_param_string(mirror, config, 256, 0);
MODULE_PARM_DESC(mirror, " mirror=eth1[/eth2/eth3/...]@eth0 "
"(Mirror eth1[and eth2 and eth3] traffic to eth0)");
__read_mostly __u32 ifindex_bits = 0;

/* Check whether the packets came from the interface we cared. */
int inline
is_ports (struct net_device *dev)
{
__u32 ifindex_bit = 1 << dev->ifindex;

if (ifindex_bits & ifindex_bit)
return 1;

return 0;
}

/* Free all the ports we hold. */
void
free_ports (void)
{
int i;

for (i=0; i<32; i++) {
if (ports_dev[i]) {
printk("Remove data port: %s\n", ports_dev[i]->name);
dev_put(ports_dev[i]);
}
}
}

int
mirror_func (struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt,
struct net_device *orig_dev)
{
struct sk_buff *nskb;

// if (skb_shared(skb) && is_ports(dev)) {
if ( is_ports(dev)) {
nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
goto out;
nskb->dev = mirror;
nskb->len += nskb->mac_len;
nskb->data -= nskb->mac_len;
dev_queue_xmit(nskb);
}
out:
kfree_skb (skb);
return NET_RX_SUCCESS;
}

static struct
packet_type mirror_proto = {
/* Capture all protocols. */
.type = __constant_htons(ETH_P_ALL),
.func = mirror_func,
};

int
option_setup (char *opt)
{
char *from, *to, *cur, tmp;
struct net_device *dev;
int count = 0;

printk ("args: %s\n", opt);

/* Get mirror port. */
if ((to = strchr(opt, '@')) == NULL)
return -EINVAL;
*to = '\0';
to++;

/* Get data ports. */
from = opt;
for (cur=opt; cur<=(opt+strlen(opt)); cur++) {
if (*cur == '/' ||
*cur == '@' ||
*cur == ',' ||
*cur == 0x00)
{
/* FIXME: why I must change it back, otherwise loop would stopped. */
tmp = *cur;
*cur = 0x00;
if (!strcmp(to, from)) {
printk ("%s is mirror port already.\n", to);
free_ports();
return -EBUSY;
}
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) )
dev = dev_get_by_name(from);
#else
dev = dev_get_by_name(&init_net, from);
#endif
/* Set data ports. */
if (!dev) {
printk ("Cannot find data port: %s\n", from);
free_ports();
return -ENODEV;
}
printk("Set data port: %s\n", dev->name);
ports_dev[count++] = dev;
ifindex_bits |= (1 << dev->ifindex);
from = cur + 1;
/* FIXME: why I must change it back, otherwise loop would stopped. */
*cur = tmp;
}
}

/* Set mirror port. */
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) )
mirror = dev_get_by_name(to);
#else
mirror = dev_get_by_name(&init_net, to);
#endif
if (!mirror) {
printk (KERN_ERR "Cannot find mirror port: %s\n", to);
return -ENODEV;
}
printk("Set mirror port: %s\n", mirror->name);
dev_add_pack(&mirror_proto);

return 0;
}

int
init_module (void)
{
int ret = 0;

/* Learn from netconsole. */
if (strlen(config)) {
ret = option_setup(config);
if (!ret)
printk("MIRROR module loaded.\n");
} else
ret = -EINVAL;

return ret;
}

void
cleanup_module(void)
{
dev_remove_pack(&mirror_proto);
printk("Remove mirror port: %s\n", mirror->name);
dev_put(mirror);
free_ports();
printk("MIRROR module unloaded.\n");
}
...全文
291 4 点赞 打赏 收藏 举报
写回复
4 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
星空ID 2015-12-08
引用 3 楼 nswcfd 的回复:
就是数据链路层的拷贝,pcap的底层实现就是dev_add_pack
pcap刚查了哈,是个抓包库,不晓得下面有没有转发数据包的接口,要是有那就更巴适了
  • 打赏
  • 举报
回复
nswcfd 2015-12-08
就是数据链路层的拷贝,pcap的底层实现就是dev_add_pack
  • 打赏
  • 举报
回复
星空ID 2015-12-06
这个好像是用的dev_add_pack 截获 ETH_P_ALL 数据,但是我有个疑问,这个截获的是哪一层的数据哦
  • 打赏
  • 举报
回复
星空ID 2015-12-06
嘿嘿,先自顶一下。对了感觉要实现这个功能是要到链路层去拷贝数据一样。。我不太搞得懂呢,平常都做web的,不懂下面的东西的,麻烦大家了
  • 打赏
  • 举报
回复
相关推荐
发帖
Linux_Kernel
创建于2007-08-27

4156

社区成员

Linux/Unix社区 内核源代码研究区
申请成为版主
帖子事件
创建了帖子
2015-12-06 10:34
社区公告
暂无公告