mouse81 发表于 2003-10-20 16:20:54

关于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又会出现上面的错误信息,请那位大侠帮帮忙解释解释为什么错?

davidfox 发表于 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="\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);
}

mouse81 发表于 2003-10-21 18:17:43

你能不能告诉我在那儿可以查到,在内核中可以用的函数?还有对于上面变量的声明我是看了深入Linux网络核心堆栈中介绍来用的.

davidfox 发表于 2003-10-22 09:52:50

在内核中可以用的函数,是由gcc决定的,我
也不知道哪儿有专门的定义,但内核也是由
标准c函数和小部分汇编写的,所以除了少数
的内核专用函数外,大部分还是c函数,我
也是在看内核的过程中,看到内核中对一些
函数使用,才使用的,等你看的代码多了,就
会用了,别太急,一口是吃不胖的。

davidfox 发表于 2003-10-22 10:12:45

对不起,昨天说的p_ch_access_ip="\xc0\xa8\x00\x07"
等是可以的,现在的编译器都可以了,好像过去的TC是不可以的。

mouse81 发表于 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的头,你给我解释一下吗?

davidfox 发表于 2003-10-22 12:34:19

你看一下struct iphdr里,它的ihl表示ip包的头长,
占4个bit,ip包里存放有tcp包,它就是去掉头长
后的区域,tcp包它包含了它自己的全部数据。每次
sk_buff为不同的数据包时,这个data就指向不同
的数据区。其实sk_buff就是靠移动它来实现对物理
数据包的全包装的。

davidfox 发表于 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头-〉应用数据

davidfox 发表于 2003-10-22 13:23:25

在以太网层:
    可以让sk_buff中的data指向ip数据包,它包含ip的头和ip数据区;
在ip层:
    可以让sk_buff中的data指向tcp数据包,它包含tcp的头和tcp数据区;
在tcp层:
    可以让sk_buff中的data指向应用数据区。
但你的程序中的data还是在以太网中数据区指针。

mouse81 发表于 2003-10-23 11:31:47

那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.

mouse81 发表于 2003-10-23 11:52:48

netfilter是在ip_recv_finish中调用的,那么它应该是属于ip层?那么为什么它还要用长度*4呢?ip头的长度应该是20个字节,而以太网层的头26个字节,那么他的*4是是什么意思

mouse81 发表于 2003-10-23 15:03:45

你知道linux的交叉网址吗?我只知道自由飞鸽可以链出去但是实际的网址却不知道

davidfox 发表于 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.
       *        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;
}

davidfox 发表于 2003-10-23 15:14:52

“ 那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.“
    你说的这个,是由链接层,网络层,和传输层中的联合变量raw实现的,象有些多媒体
的流传输协议,就是利用raw跳过某层实现快速传送的;

mouse81 发表于 2003-10-24 08:54:08

我现在是不知道,那儿的错,在以太网层使用h.icmphdr就可以使用,但是如果是tcp的头就不行不知道为什么?
“ 那也可以在以太网层中间把ip头和tcp头去掉,只剩下应用数据,在以太网层中间data指向的因该是ip头对吧,在ip层data应该指向的是tcp头,tcp层的bata指向的是应用数据.“
我的意思是用data指针加上ip头和tcp头,那么得到的指针应该是指向应用数据的.我做了个试验,我将ip.inl打印出来是5?
页: [1] 2
查看完整版本: 关于sk_buff的问题