netdev
[Top] [All Lists]

Re: what pointers does pskb_may_pull() nuke?

To: Michael Richardson <mcr@xxxxxxxxxxxx>
Subject: Re: what pointers does pskb_may_pull() nuke?
From: Julian Anastasov <ja@xxxxxx>
Date: Sun, 25 Nov 2001 20:29:43 +0000 (GMT)
Cc: <netdev@xxxxxxxxxxx>, <design@xxxxxxxxxxxxxxxxxx>
In-reply-to: <200111250030.fAP0UTH01038@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Sender: owner-netdev@xxxxxxxxxxx
        Hello,

On Sat, 24 Nov 2001, Michael Richardson wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
>
>
>   pskb_may_pull() is documented (well, __pskb_pull_tail) as:
>
>  * 2. It may change skb pointers.
>
>   I don't see that it actually moves or changes any of the pointers.
>   However, since it may move the data around, clearly the may go bad.
>
>   {We think we should be calling pskb_may_pull() on 2.4.4 and later to
> reassemble all the fragments of an ESP packet into a single skbuff so that we
> can decrypt it. Writing a decrypt routing to walk fragments isn't high on our
> list of things to do, although we could probably steal an mbuf-capable one
> from KAME}

        pskb_may_pull does not assemble all fragments, even after
ip_defrag you have to call skb_linearize if the skb is still
non-linear, i.e. something like:

        // not needed in LOCAL_IN:
        if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
                skb = ip_defrag(skb);
                if (!skb)
                        return NF_STOLEN;
                *skb_p = skb;
        }

        if (skb_is_nonlinear(skb)) {
                if (skb_linearize(skb, GFP_ATOMIC) != 0)
                        return NF_DROP;
                ip_send_check(skb->nh.iph); // Not needed for local delivery
        }

        iph = skb->nh.iph;
        ihl = iph->ihl << 2;

        Note that ip_defrag is already called before LOCAL_IN. And
also there are other details.

>   My guess is that this screws the "h" pointers, and the "nh" pointers,
> as well as the "mac" pointers.
>   skb->data should be correct.

        No. You can look in pskb_expand_head which pointers are
changed. All pointers to data can change because it can be
reallocated - when the requested length is not present in first
fragment or when the first skb is used (cloned) from other readers.

>   mac.raw is trivially skb->data, I think.
>   (At least, for ethernet)
>
>   nh.iph may move depending on presence of 802.3 options, etc. Is there a 
> simple
>            call to have it recalculated? I don't that we can rely on
>            dev->hard_header_len for incoming!
>
>   h.raw can be determined by adding nh.iph->ihl<<2.
>
>   Since we actually don't care about mac.raw at all, just nh.iph, if there is
> a way to preserve that we, would be happy. Perhaps advancing skb->data to
> nh.iph before calling pskb_may_pull().

        Then after *_may_pull (or any other functions that move the
data) you have to base everything on skb->nh.iph and to create your
own h.raw and other pointers.

>   Also, we have some code that says:
>
> #ifdef IPH_is_SKB_PULLED
>       /* In Linux 2.4.4, the IP header has been skb_pull()ed before the
>          packet is passed to us. So we'll skb_push() to get back to it. */
>       if (skb->data == skb->h.raw) {
>               skb_push(skb, skb->h.raw - skb->nh.raw);
>       }
> #endif /* IPH_is_SKB_PULLED */

        IIRC, skb->h.raw is changed by ihl after the LOCAL_IN chain,
i.e. in ip_local_deliver_finish. You have to see how is that related
to IPSec. There is __skb_pull call before that. So, skb->h.raw is
changed only when we are sure the sk_buff goes to the protocols.

>   It appears that we never enabled it, not is it clear when we should :-)

        Hm, are you sure it is not enabled? I don't know how you are
using skb->data in the protocol handlers as pointer to iphdr after 2.4.4

        If in doubt, don't use skb->h.raw in your calcs, base
everything on nh.raw (more portable for local delivery)

>   But, is there a document that explains how the skbuff is arranged on
> different versions upon entry to the protocol_rcv() function?

        skb->data and h.raw point after ihl, nh.raw points to iphdr.

        While we played with sk_buffs during the Linux Virtual Server
port we didn't found any docs. If you can't find any docs or don't
have other options feel free to contact me directly.

Regards

--
Julian Anastasov <ja@xxxxxx>


<Prev in Thread] Current Thread [Next in Thread>