偶然间发现 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 是虚拟网卡设备,网络接口有可能做在宿主机后面,因此可能协议栈相对靠后。
教训:使用实体机做研究,免得受莫名其妙干扰而误入歧途。
阅读(2682) | 评论(0) | 转发(0) |