关于sk_buff的问题
我写了小程序:但是对于sk_buff中的操作有问题,unsigned char * p_ch_addr = &(p_skb -> nh.iph -> saddr)就是对的,而unsigned char *p_ch_port =&(p_skb->h.th->dest)j就是错的,我看了看raodan翻译的深入Linux网络核心堆栈中使用的是
struct tcphdr * thread;
thread = (struct tcphdr *)(p_skb->data + p_skb->nh.iph->ihl *4);
if((thread->dest) == *((unsigned short *)p_ch_dest_port))但是这样还是会有问题错误是dereferencing pointer to incomplete type,
还有我使用sk_buff中的h.icmph->checksum +=1;没有问题但是如果使用的是tcp的头中的check又会出现上面的错误信息,请那位大侠帮帮忙解释解释为什么错? 你的static unsigned char * p_ch_dest_port = "\x00\x17"中
\x00代表字符结尾,所以p_ch_dest_port指向NULL,另外,
p_ch_access_ip="\xc0\xa8\x00\x07"赋值是不是太威胁了,
不分配就赋值。
我写了另外一种方式,可以使用,你试一试
static unsigned char p_port;
{
unsigned short dest_port=0;
memcpy(p_port,(char*)"\x00\x17",2);
memcpy((char*)&dest_port,p_port,2);
} 你能不能告诉我在那儿可以查到,在内核中可以用的函数?还有对于上面变量的声明我是看了深入Linux网络核心堆栈中介绍来用的. 在内核中可以用的函数,是由gcc决定的,我
也不知道哪儿有专门的定义,但内核也是由
标准c函数和小部分汇编写的,所以除了少数
的内核专用函数外,大部分还是c函数,我
也是在看内核的过程中,看到内核中对一些
函数使用,才使用的,等你看的代码多了,就
会用了,别太急,一口是吃不胖的。 对不起,昨天说的p_ch_access_ip="\xc0\xa8\x00\x07"
等是可以的,现在的编译器都可以了,好像过去的TC是不可以的。 我对于代码中的这段始终没有理解:thread = (struct tcphdr *)(p_skb->data + p_skb->nh.iph->ihl *4);
我知道是偏移,如何偏移的,data这个指针是根据现在所属于的层次来定位的,现在包在ptype_all中被拦截,那么data因该指向的是ip层,那么只有用p_skb->data + p_skb->nh.iph->ihl 就可以的到tcp包而不是tcp的头,你给我解释一下吗? 你看一下struct iphdr里,它的ihl表示ip包的头长,
占4个bit,ip包里存放有tcp包,它就是去掉头长
后的区域,tcp包它包含了它自己的全部数据。每次
sk_buff为不同的数据包时,这个data就指向不同
的数据区。其实sk_buff就是靠移动它来实现对物理
数据包的全包装的。 ip头:
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__u16 tot_len;
__u16 id;
__u16 frag_off;
__u8 ttl;
__u8 protocol;
__u16 check;
__u32 saddr;
__u32 daddr;
/*The options start here. */
};
tcp头:
struct tcphdr {
__u16 source;
__u16 dest;
__u32 seq;
__u32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u16 window;
__u16 check;
__u16 urg_ptr;
};
从这两个结构可以看出,物理数据包中应该是:
以太网头-〉ip头-〉tcp头-〉应用数据 在以太网层:
可以让sk_buff中的data指向ip数据包,它包含ip的头和ip数据区;
在ip层:
可以让sk_buff中的data指向tcp数据包,它包含tcp的头和tcp数据区;
在tcp层:
可以让sk_buff中的data指向应用数据区。
但你的程序中的data还是在以太网中数据区指针。 那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据. netfilter是在ip_recv_finish中调用的,那么它应该是属于ip层?那么为什么它还要用长度*4呢?ip头的长度应该是20个字节,而以太网层的头26个字节,那么他的*4是是什么意思 你知道linux的交叉网址吗?我只知道自由飞鸽可以链出去但是实际的网址却不知道 ip头是20个字节,用4位表示,如果用字节做单位的话,肯定不够,所以在ip头
中,ihl是按4个字节为单位的。好多的书都有错误!!!!!!!!!!!!!!
下面是系统自带的过滤函数,你可以看看(net/ipv4/ip_input.c).
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
struct iphdr *iph = skb->nh.iph;
/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
IP_INC_STATS_BH(IpInReceives);
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
goto out;
/*
* RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
*
* Is the datagram acceptable?
*
* 1. Length at least the size of an ip header
* 2. Version of 4
* 3. Checksums correctly.
* 4. Doesn't have a bogus length
*/
/***********************************************/
if (skb->len < sizeof(struct iphdr) || skb->len < (iph->ihl<<2))
goto inhdr_error;
/***********************************************/
if (iph->ihl < 5 || iph->version != 4 || ip_fast_csum((u8 *)iph, iph->ihl) != 0)
goto inhdr_error;
{
/***********************************/
__u32 len = ntohs(iph->tot_len);
if (skb->len < len || len < (iph->ihl<<2))
goto inhdr_error;
/* Our transport medium may have padded the buffer out. Now we know it
* is IP we can trim to the true length of the frame.
* Note this now means skb->len holds ntohs(iph->tot_len).
*/
__skb_trim(skb, len);
/*由此可以看出,sk_buff的长度整个以太网包的长度*/
}
/*其它钩子函数处理*/
return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
ip_rcv_finish);
inhdr_error:
IP_INC_STATS_BH(IpInHdrErrors);
drop:
kfree_skb(skb);
out:
return NET_RX_DROP;
} “ 那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.“
你说的这个,是由链接层,网络层,和传输层中的联合变量raw实现的,象有些多媒体
的流传输协议,就是利用raw跳过某层实现快速传送的; 我现在是不知道,那儿的错,在以太网层使用h.icmphdr就可以使用,但是如果是tcp的头就不行不知道为什么?
“ 那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.“
我的意思是用data指针加上ip头和tcp头,那么得到的指针应该是指向应用数据的.我做了个试验,我将ip.inl打印出来是5?
页:
[1]
2