Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2195412
  • 博文数量: 230
  • 博客积分: 9346
  • 博客等级: 中将
  • 技术积分: 3418
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-26 01:58
文章分类

全部博文(230)

文章存档

2015年(30)

2014年(7)

2013年(12)

2012年(2)

2011年(3)

2010年(42)

2009年(9)

2008年(15)

2007年(74)

2006年(36)

分类: LINUX

2007-09-04 11:28:53

偶然间发现 VMware 对内核协议栈有干扰,看来想研究内核网络协议栈还是要用实体机研究,而不是用虚拟机,免得像下面这样出现意想不到的错误。

#define MODULE
#define __KERNEL__

#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <linux/skbuff.h>

MODULE_AUTHOR("ChinaUnix - platinum");
MODULE_LICENSE("GPL");

struct net_device *d;
int otp_func(struct sk_buff *skb, struct net_device *dev,
             struct packet_type *ptype);


static struct packet_type otp_proto = {
        type: __constant_htons(ETH_P_ALL),
        dev: NULL,
        func: otp_func,
        data: (void *)(1),
        next: NULL
};


int
otp_func (struct sk_buff *skb,
          struct net_device *dev,
          struct packet_type *pt)
{
        struct ethhdr *ethh = (struct ethhdr *)(skb->mac.ethernet);
        struct iphdr *iph;
        struct tcphdr *tcph;

        if (ntohs(ethh->h_proto) != ETH_P_IP)
                goto bye;

        iph = skb->nh.iph;

        if ( (iph->version != 4) || (iph->protocol != IPPROTO_TCP) )
                goto bye;

        tcph = (void *)iph + iph->ihl * 4;

        if (ntohs(tcph->source) != 23 &&
            ntohs(tcph->dest) != 23)
                goto bye;

#ifdef DEBUG
        printk("%d.%d.%d.%d:%u -> %d.%d.%d.%d:%u (%s)\n",
                NIPQUAD(iph->saddr),
                ntohs(tcph->source),
                NIPQUAD(iph->daddr),
                ntohs(tcph->dest),
                tcph->syn ?
                        (tcph->ack ? "SYN/ACK" : "SYN")
                        : (tcph->ack ? "ACK" : ""));
#endif

bye:
        kfree_skb (skb);
        return NET_RX_SUCCESS;
}

int
init_module ()
{
        dev_add_pack(&otp_proto);
        printk("platinum loaded.\n");

        return(0);
}


void cleanup_module()
{
        dev_remove_pack(&otp_proto);
        printk("platinum unloaded.\n");
}


使用上面的程序会发现,如果 telnet VMware 的时候,只能看到从 VMware 发出的数据包,看不到发往 VMware 的,主要原因是
ethh = (struct ethhdr *)skb->data;
作怪,若将其改为
ethh = (struct ethhdr *)skb->mac.ethernet;
则一且正常。

接下来,又做了一个测试,保持 ethh 指向 skb->mac.ethernet,而把后面的 iph 指向 skb->data 的时候,却只能看到发往 VMware 的包而看不到从 VMware 发出的。
上述测试在实体机上是无法重现的。

结论:发往 VMware 时 skb->data 指向 IP 头,从 VMware 发出时指向 ETH 头。
分析:VMware 是虚拟网卡设备,网络接口有可能做在宿主机后面,因此可能协议栈相对靠后。
教训:使用实体机做研究,免得受莫名其妙干扰而误入歧途。

阅读(2631) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~