linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / net / ipv6 / ip6_output.c
index 4fb47a2..5bf70b1 100644 (file)
@@ -28,6 +28,7 @@
  *                             for datagram xmit
  */
 
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -38,7 +39,6 @@
 #include <linux/in6.h>
 #include <linux/tcp.h>
 #include <linux/route.h>
-#include <linux/module.h>
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *skb)
 
 int ip6_output(struct sk_buff *skb)
 {
-       if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
+       if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
                                dst_allfrag(skb->dst))
                return ip6_fragment(skb, ip6_output2);
        else
@@ -161,7 +161,7 @@ int ip6_output(struct sk_buff *skb)
 int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
             struct ipv6_txoptions *opt, int ipfragok)
 {
-       struct ipv6_pinfo *np = inet6_sk(sk);
+       struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL;
        struct in6_addr *first_hop = &fl->fl6_dst;
        struct dst_entry *dst = skb->dst;
        struct ipv6hdr *hdr;
@@ -229,7 +229,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
        skb->priority = sk->sk_priority;
 
        mtu = dst_mtu(dst);
-       if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) {
+       if ((skb->len <= mtu) || ipfragok) {
                IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
                return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev,
                                dst_output);
@@ -356,7 +356,6 @@ int ip6_forward(struct sk_buff *skb)
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
                            0, skb->dev);
-               IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
 
                kfree_skb(skb);
                return -ETIMEDOUT;
@@ -459,7 +458,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
        nf_bridge_get(to->nf_bridge);
 #endif
 #endif
-       skb_copy_secmark(to, from);
 }
 
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
@@ -490,7 +488,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 
        return offset;
 }
-EXPORT_SYMBOL_GPL(ip6_find_1stfragopt);
 
 static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
@@ -596,9 +593,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                        }
                        
                        err = output(skb);
-                       if(!err)
-                               IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
-
                        if (err || !frag)
                                break;
 
@@ -710,11 +704,12 @@ slow_path:
                /*
                 *      Put this fragment into the sending queue.
                 */
+
+               IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
+
                err = output(frag);
                if (err)
                        goto fail;
-
-               IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
        }
        kfree_skb(skb);
        IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
@@ -726,51 +721,47 @@ fail:
        return err;
 }
 
-static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
-                                         struct dst_entry *dst,
-                                         struct flowi *fl)
+int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
 {
-       struct ipv6_pinfo *np = inet6_sk(sk);
-       struct rt6_info *rt = (struct rt6_info *)dst;
-
-       if (!dst)
-               goto out;
+       int err = 0;
 
-       /* Yes, checking route validity in not connected
-        * case is not very simple. Take into account,
-        * that we do not support routing by source, TOS,
-        * and MSG_DONTROUTE            --ANK (980726)
-        *
-        * 1. If route was host route, check that
-        *    cached destination is current.
-        *    If it is network route, we still may
-        *    check its validity using saved pointer
-        *    to the last used address: daddr_cache.
-        *    We do not want to save whole address now,
-        *    (because main consumer of this service
-        *    is tcp, which has not this problem),
-        *    so that the last trick works only on connected
-        *    sockets.
-        * 2. oif also should be the same.
-        */
-       if (((rt->rt6i_dst.plen != 128 ||
-             !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr))
-            && (np->daddr_cache == NULL ||
-                !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache)))
-           || (fl->oif && fl->oif != dst->dev->ifindex)) {
-               dst_release(dst);
-               dst = NULL;
+       *dst = NULL;
+       if (sk) {
+               struct ipv6_pinfo *np = inet6_sk(sk);
+       
+               *dst = sk_dst_check(sk, np->dst_cookie);
+               if (*dst) {
+                       struct rt6_info *rt = (struct rt6_info*)*dst;
+       
+                               /* Yes, checking route validity in not connected
+                                  case is not very simple. Take into account,
+                                  that we do not support routing by source, TOS,
+                                  and MSG_DONTROUTE            --ANK (980726)
+       
+                                  1. If route was host route, check that
+                                     cached destination is current.
+                                     If it is network route, we still may
+                                     check its validity using saved pointer
+                                     to the last used address: daddr_cache.
+                                     We do not want to save whole address now,
+                                     (because main consumer of this service
+                                      is tcp, which has not this problem),
+                                     so that the last trick works only on connected
+                                     sockets.
+                                  2. oif also should be the same.
+                                */
+       
+                       if (((rt->rt6i_dst.plen != 128 ||
+                             !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr))
+                            && (np->daddr_cache == NULL ||
+                                !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache)))
+                           || (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
+                               dst_release(*dst);
+                               *dst = NULL;
+                       }
+               }
        }
 
-out:
-       return dst;
-}
-
-static int ip6_dst_lookup_tail(struct sock *sk,
-                              struct dst_entry **dst, struct flowi *fl)
-{
-       int err;
-
        if (*dst == NULL)
                *dst = ip6_route_output(sk, fl);
 
@@ -779,6 +770,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 
        if (ipv6_addr_any(&fl->fl6_src)) {
                err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
+
                if (err)
                        goto out_err_release;
        }
@@ -791,48 +783,8 @@ out_err_release:
        return err;
 }
 
-/**
- *     ip6_dst_lookup - perform route lookup on flow
- *     @sk: socket which provides route info
- *     @dst: pointer to dst_entry * for result
- *     @fl: flow to lookup
- *
- *     This function performs a route lookup on the given flow.
- *
- *     It returns zero on success, or a standard errno code on error.
- */
-int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
-{
-       *dst = NULL;
-       return ip6_dst_lookup_tail(sk, dst, fl);
-}
 EXPORT_SYMBOL_GPL(ip6_dst_lookup);
 
-/**
- *     ip6_sk_dst_lookup - perform socket cached route lookup on flow
- *     @sk: socket which provides the dst cache and route info
- *     @dst: pointer to dst_entry * for result
- *     @fl: flow to lookup
- *
- *     This function performs a route lookup on the given flow with the
- *     possibility of using the cached route in the socket if it is valid.
- *     It will take the socket dst lock when operating on the dst cache.
- *     As a result, this function can only be used in process context.
- *
- *     It returns zero on success, or a standard errno code on error.
- */
-int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
-{
-       *dst = NULL;
-       if (sk) {
-               *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
-               *dst = ip6_sk_dst_check(sk, *dst, fl);
-       }
-
-       return ip6_dst_lookup_tail(sk, dst, fl);
-}
-EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup);
-
 static inline int ip6_ufo_append_data(struct sock *sk,
                        int getfrag(void *from, char *to, int offset, int len,
                        int odd, struct sk_buff *skb),
@@ -877,9 +829,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
                struct frag_hdr fhdr;
 
                /* specify the length of each IP datagram fragment*/
-               skb_shinfo(skb)->gso_size = mtu - fragheaderlen - 
-                                           sizeof(struct frag_hdr);
-               skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+               skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - 
+                                               sizeof(struct frag_hdr);
                ipv6_select_ident(skb, &fhdr);
                skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
                __skb_queue_tail(&sk->sk_write_queue, skb);
@@ -938,7 +889,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                np->cork.hop_limit = hlimit;
                np->cork.tclass = tclass;
                mtu = dst_mtu(rt->u.dst.path);
-               if (np->frag_size < mtu) {
+               if (np && np->frag_size < mtu) {
                        if (np->frag_size)
                                mtu = np->frag_size;
                }
@@ -1095,7 +1046,7 @@ alloc_new_skb:
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
                                data += fraggap;
-                               pskb_trim_unique(skb_prev, maxfraglen);
+                               skb_trim(skb_prev, maxfraglen);
                        }
                        copy = datalen - transhdrlen - fraggap;
                        if (copy < 0) {