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>
|