]> git.neil.brown.name Git - history.git/commitdiff
[IPV4/IPV6]: Fix IPsec calculation in ip_append_data/ip6_append_data
authorHerbert Xu <herbert@gondor.apana.org.au>
Tue, 15 Mar 2005 02:18:07 +0000 (18:18 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Tue, 15 Mar 2005 02:18:07 +0000 (18:18 -0800)
This patch fixes the IPsec overhead handling in ip_append_data and
ip6_append_data.  As it is they assume that the IPsec overhead is
constant.  This is not true as with ESP the IPsec overhead will vary
as the MTU varies.

The result is that they may produce packets that will exceed the MTU
when ESP is used.  Had it taken the trailer_len into account, it would
have produced packets less than the real MTU.

By switching to dst_mtu we get the optimal result.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/ip_output.c
net/ipv6/ip6_output.c

index 47054f8a3a33f449e93f6f8bd96603641d07ade0..d99cbce25237f56c30c6abe5dd61023d938391d6 100644 (file)
@@ -719,7 +719,6 @@ int ip_append_data(struct sock *sk,
 
        struct ip_options *opt = NULL;
        int hh_len;
-       int exthdrlen;
        int mtu;
        int copy;
        int err;
@@ -746,22 +745,17 @@ int ip_append_data(struct sock *sk,
                        inet->cork.addr = ipc->addr;
                }
                dst_hold(&rt->u.dst);
-               inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+               inet->cork.fragsize = mtu = dst_mtu(&rt->u.dst);
                inet->cork.rt = rt;
                inet->cork.length = 0;
                sk->sk_sndmsg_page = NULL;
                sk->sk_sndmsg_off = 0;
-               if ((exthdrlen = rt->u.dst.header_len) != 0) {
-                       length += exthdrlen;
-                       transhdrlen += exthdrlen;
-               }
        } else {
                rt = inet->cork.rt;
                if (inet->cork.flags & IPCORK_OPT)
                        opt = inet->cork.opt;
 
                transhdrlen = 0;
-               exthdrlen = 0;
                mtu = inet->cork.fragsize;
        }
        hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
@@ -770,7 +764,7 @@ int ip_append_data(struct sock *sk,
        maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen;
 
        if (inet->cork.length + length > 0xFFFF - fragheaderlen) {
-               ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu-exthdrlen);
+               ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu);
                return -EMSGSIZE;
        }
 
@@ -781,7 +775,7 @@ int ip_append_data(struct sock *sk,
        if (transhdrlen &&
            length + fragheaderlen <= mtu &&
            rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
-           !exthdrlen)
+           !rt->u.dst.header_len)
                csummode = CHECKSUM_HW;
 
        inet->cork.length += length;
@@ -866,9 +860,9 @@ alloc_new_skb:
                         *      Find where to start putting bytes.
                         */
                        data = skb_put(skb, fraglen);
-                       skb->nh.raw = data + exthdrlen;
+                       skb->nh.raw = data;
                        data += fragheaderlen;
-                       skb->h.raw = data + exthdrlen;
+                       skb->h.raw = data;
 
                        if (fraggap) {
                                skb->csum = skb_copy_and_csum_bits(
@@ -890,7 +884,6 @@ alloc_new_skb:
                        offset += copy;
                        length -= datalen - fraggap;
                        transhdrlen = 0;
-                       exthdrlen = 0;
                        csummode = CHECKSUM_NONE;
 
                        /*
index 918a08d7295869e75573d0035d0ae5098901b53e..5bce272a8171268f0ce42bea87ea99826502e8b2 100644 (file)
@@ -850,13 +850,13 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
                np->cork.rt = rt;
                inet->cork.fl = *fl;
                np->cork.hop_limit = hlimit;
-               inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+               inet->cork.fragsize = mtu = dst_mtu(&rt->u.dst);
                if (dst_allfrag(&rt->u.dst))
                        inet->cork.flags |= IPCORK_ALLFRAG;
                inet->cork.length = 0;
                sk->sk_sndmsg_page = NULL;
                sk->sk_sndmsg_off = 0;
-               exthdrlen = rt->u.dst.header_len + (opt ? opt->opt_flen : 0);
+               exthdrlen = opt ? opt->opt_flen : 0;
                length += exthdrlen;
                transhdrlen += exthdrlen;
        } else {