QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2909|回复: 16

关于sk_buff的问题

[复制链接]
发表于 2003-10-20 16:20:54 | 显示全部楼层 |阅读模式
我写了小程序:但是对于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又会出现上面的错误信息,请那位大侠帮帮忙解释解释为什么错?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2003-10-21 17:53:50 | 显示全部楼层
你的static unsigned char * p_ch_dest_port = "\x00\x17"中
\x00代表字符结尾,所以p_ch_dest_port指向NULL,另外,
p_ch_access_ip[0]="\xc0\xa8\x00\x07"赋值是不是太威胁了,
不分配就赋值。

我写了另外一种方式,可以使用,你试一试
static unsigned char p_port[4];
{
        unsigned short dest_port=0;

        memcpy(p_port,(char*)"\x00\x17",2);
        memcpy((char*)&dest_port,p_port,2);
}
回复

使用道具 举报

 楼主| 发表于 2003-10-21 18:17:43 | 显示全部楼层
你能不能告诉我在那儿可以查到,在内核中可以用的函数?还有对于上面变量的声明我是看了深入Linux网络核心堆栈中介绍来用的.
回复

使用道具 举报

发表于 2003-10-22 09:52:50 | 显示全部楼层
在内核中可以用的函数,是由gcc决定的,我
也不知道哪儿有专门的定义,但内核也是由
标准c函数和小部分汇编写的,所以除了少数
的内核专用函数外,大部分还是c函数,我
也是在看内核的过程中,看到内核中对一些
函数使用,才使用的,等你看的代码多了,就
会用了,别太急,一口是吃不胖的。
回复

使用道具 举报

发表于 2003-10-22 10:12:45 | 显示全部楼层
对不起,昨天说的p_ch_access_ip[0]="\xc0\xa8\x00\x07"
等是可以的,现在的编译器都可以了,好像过去的TC是不可以的。
回复

使用道具 举报

 楼主| 发表于 2003-10-22 11:39:24 | 显示全部楼层
我对于代码中的这段始终没有理解: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的头,你给我解释一下吗?
回复

使用道具 举报

发表于 2003-10-22 12:34:19 | 显示全部楼层
你看一下struct iphdr里,它的ihl表示ip包的头长,
占4个bit,ip包里存放有tcp包,它就是去掉头长
后的区域,tcp包它包含了它自己的全部数据。每次
sk_buff为不同的数据包时,这个data就指向不同
的数据区。其实sk_buff就是靠移动它来实现对物理
数据包的全包装的。
回复

使用道具 举报

发表于 2003-10-22 13:13:03 | 显示全部楼层
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头-〉应用数据
回复

使用道具 举报

发表于 2003-10-22 13:23:25 | 显示全部楼层
在以太网层:
    可以让sk_buff中的data指向ip数据包,它包含ip的头和ip数据区;
在ip层:
    可以让sk_buff中的data指向tcp数据包,它包含tcp的头和tcp数据区;
在tcp层:
    可以让sk_buff中的data指向应用数据区。
但你的程序中的data还是在以太网中数据区指针。
回复

使用道具 举报

 楼主| 发表于 2003-10-23 11:31:47 | 显示全部楼层
那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.
回复

使用道具 举报

 楼主| 发表于 2003-10-23 11:52:48 | 显示全部楼层
netfilter是在ip_recv_finish中调用的,那么它应该是属于ip层?那么为什么它还要用长度*4呢?ip头的长度应该是20个字节,而以太网层的头26个字节,那么他的*4是是什么意思
回复

使用道具 举报

 楼主| 发表于 2003-10-23 15:03:45 | 显示全部楼层
你知道linux的交叉网址吗?我只知道自由飞鸽可以链出去但是实际的网址却不知道
回复

使用道具 举报

发表于 2003-10-23 15:06:16 | 显示全部楼层
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. [Speed optimisation for later, skip loopback checksums]
         *        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;
}
回复

使用道具 举报

发表于 2003-10-23 15:14:52 | 显示全部楼层
“ 那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.“
    你说的这个,是由链接层,网络层,和传输层中的联合变量raw实现的,象有些多媒体
的流传输协议,就是利用raw跳过某层实现快速传送的;
回复

使用道具 举报

 楼主| 发表于 2003-10-24 08:54:08 | 显示全部楼层
我现在是不知道,那儿的错,在以太网层使用h.icmphdr就可以使用,但是如果是tcp的头就不行不知道为什么?
“ 那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.“
我的意思是用data指针加上ip头和tcp头,那么得到的指针应该是指向应用数据的.我做了个试验,我将ip.inl打印出来是5?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-16 10:17 , Processed in 0.077439 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表