1、获取IP头部
iph = ip_hdr(skb);
struct sk_buff {
......
sk_buff_data_t transport_header; /* Transport layer header */
sk_buff_data_t network_header; /* Network layer header */
sk_buff_data_t mac_header; /* Link layer header */
......
}
1)__netif_receive_skb()在进入三层处理前就对network_header进行了设置。
2)ip_rcv()中详细的检查保证了IP头部到netfilter后是完整的。
3)netfilter可以尽情使用ip头部。
2、获取tcp头部
错误1:
tcph = tcp_hdr(skb);
陷阱:
netfilter的钩子点是属于TCP/IP协议栈的三层流程中,而四层的TCP头部此时还没有正确获取,只是初始化为IP头部的值,无法直接使用。
错误2:
tcph = (char *)iph + (iph->ihl << 2);
陷阱:
数据包可能是非线性的
改进:
tcpoff = skb_network_offset(skb) + (iph->ihl << 2);
tcph = skb_header_pointer(skb, tcpoff, sizeof(_tcph), &_tcph);
if (tcph == NULL)
return;
skb_network_offset(struct skb_buff *skb)
计算三层头部相对于skb->data的偏移
void * skb_header_pointer(struct sk_buff *skb, int offset, int len, void *buffer)
从skb的指定偏移取制定长度的数据,如果要取的数据位于线性区,直接返回其开始指 针,否则,则拷贝到buffer中,并将buffer指针返回。