]> err.no Git - linux-2.6/blobdiff - net/ipv6/ip6_output.c
[IPV6]: Remove unused code in ndisc_send_redirect().
[linux-2.6] / net / ipv6 / ip6_output.c
index 3bef30e4a23d870e6c8d55c253412ce1356f01ca..98762fde2b65bb7714d46117d312a6d5b1ae91cd 100644 (file)
@@ -29,7 +29,7 @@
  */
 
 #include <linux/errno.h>
-#include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/net.h>
@@ -70,6 +70,31 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f
        spin_unlock_bh(&ip6_id_lock);
 }
 
+int __ip6_local_out(struct sk_buff *skb)
+{
+       int len;
+
+       len = skb->len - sizeof(struct ipv6hdr);
+       if (len > IPV6_MAXPLEN)
+               len = 0;
+       ipv6_hdr(skb)->payload_len = htons(len);
+
+       return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev,
+                      dst_output);
+}
+
+int ip6_local_out(struct sk_buff *skb)
+{
+       int err;
+
+       err = __ip6_local_out(skb);
+       if (likely(err == 1))
+               err = dst_output(skb);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(ip6_local_out);
+
 static int ip6_output_finish(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb->dst;
@@ -120,8 +145,8 @@ static int ip6_output2(struct sk_buff *skb)
                           is not supported in any case.
                         */
                        if (newskb)
-                               NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, newskb, NULL,
-                                       newskb->dev,
+                               NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, newskb,
+                                       NULL, newskb->dev,
                                        ip6_dev_loopback_xmit);
 
                        if (ipv6_hdr(skb)->hop_limit == 0) {
@@ -134,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb)
                IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
        }
 
-       return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish);
+       return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
+                      ip6_output_finish);
 }
 
 static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
@@ -231,12 +257,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
        ipv6_addr_copy(&hdr->daddr, first_hop);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        mtu = dst_mtu(dst);
        if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) {
                IP6_INC_STATS(ip6_dst_idev(skb->dst),
                              IPSTATS_MIB_OUTREQUESTS);
-               return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev,
+               return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
                                dst_output);
        }
 
@@ -377,6 +404,7 @@ int ip6_forward(struct sk_buff *skb)
        struct dst_entry *dst = skb->dst;
        struct ipv6hdr *hdr = ipv6_hdr(skb);
        struct inet6_skb_parm *opt = IP6CB(skb);
+       struct net *net = dst->dev->nd_net;
 
        if (ipv6_devconf.forwarding == 0)
                goto error;
@@ -423,7 +451,7 @@ int ip6_forward(struct sk_buff *skb)
 
        /* XXX: idev->cnf.proxy_ndp? */
        if (ipv6_devconf.proxy_ndp &&
-           pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
+           pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
                int proxied = ip6_forward_proxy_check(skb);
                if (proxied > 0)
                        return ip6_input(skb);
@@ -500,7 +528,8 @@ int ip6_forward(struct sk_buff *skb)
        hdr->hop_limit--;
 
        IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
-       return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish);
+       return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev,
+                      ip6_forward_finish);
 
 error:
        IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS);
@@ -568,7 +597,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 *))
 {
@@ -593,7 +621,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
         * or if the skb it not generated by a local socket.  (This last
         * check should be redundant, but it's free.)
         */
-       if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) {
+       if (!skb->local_df) {
                skb->dev = skb->dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
                IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
@@ -609,6 +637,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
        if (skb_shinfo(skb)->frag_list) {
                int first_len = skb_pagelen(skb);
+               int truesizes = 0;
 
                if (first_len - hlen > mtu ||
                    ((first_len - hlen) & 7) ||
@@ -631,7 +660,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                                sock_hold(skb->sk);
                                frag->sk = skb->sk;
                                frag->destructor = sock_wfree;
-                               skb->truesize -= frag->truesize;
+                               truesizes += frag->truesize;
                        }
                }
 
@@ -662,6 +691,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
                first_len = skb_pagelen(skb);
                skb->data_len = first_len - skb_headlen(skb);
+               skb->truesize -= truesizes;
                skb->len = first_len;
                ipv6_hdr(skb)->payload_len = htons(first_len -
                                                   sizeof(struct ipv6hdr));
@@ -882,15 +912,17 @@ static int ip6_dst_lookup_tail(struct sock *sk,
                               struct dst_entry **dst, struct flowi *fl)
 {
        int err;
+       struct net *net = sk->sk_net;
 
        if (*dst == NULL)
-               *dst = ip6_route_output(sk, fl);
+               *dst = ip6_route_output(net, sk, fl);
 
        if ((err = (*dst)->error))
                goto out_err_release;
 
        if (ipv6_addr_any(&fl->fl6_src)) {
-               err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
+               err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev,
+                                        &fl->fl6_dst, &fl->fl6_src);
                if (err)
                        goto out_err_release;
        }
@@ -909,7 +941,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
                        struct flowi fl_gw;
                        int redirect;
 
-                       ifp = ipv6_get_ifaddr(&fl->fl6_src, (*dst)->dev, 1);
+                       ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
+                                             (*dst)->dev, 1);
 
                        redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
                        if (ifp)
@@ -923,7 +956,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
                                dst_release(*dst);
                                memcpy(&fl_gw, fl, sizeof(struct flowi));
                                memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
-                               *dst = ip6_route_output(sk, &fl_gw);
+                               *dst = ip6_route_output(net, sk, &fl_gw);
                                if ((err = (*dst)->error))
                                        goto out_err_release;
                        }
@@ -1098,7 +1131,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                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 = rt->u.dst.header_len + (opt ? opt->opt_flen : 0) -
+                           rt->rt6i_nfheader_len;
                length += exthdrlen;
                transhdrlen += exthdrlen;
        } else {
@@ -1113,7 +1147,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
        hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
 
-       fragheaderlen = sizeof(struct ipv6hdr) + rt->u.dst.nfheader_len + (opt ? opt->opt_nflen : 0);
+       fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
+                       (opt ? opt->opt_nflen : 0);
        maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
 
        if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
@@ -1387,6 +1422,10 @@ int ip6_push_pending_frames(struct sock *sk)
                tmp_skb->sk = NULL;
        }
 
+       /* Allow local fragmentation. */
+       if (np->pmtudisc < IPV6_PMTUDISC_DO)
+               skb->local_df = 1;
+
        ipv6_addr_copy(final_dst, &fl->fl6_dst);
        __skb_pull(skb, skb_network_header_len(skb));
        if (opt && opt->opt_flen)
@@ -1401,16 +1440,13 @@ int ip6_push_pending_frames(struct sock *sk)
        *(__be32*)hdr = fl->fl6_flowlabel |
                     htonl(0x60000000 | ((int)np->cork.tclass << 20));
 
-       if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
-               hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
-       else
-               hdr->payload_len = 0;
        hdr->hop_limit = np->cork.hop_limit;
        hdr->nexthdr = proto;
        ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
        ipv6_addr_copy(&hdr->daddr, final_dst);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        skb->dst = dst_clone(&rt->u.dst);
        IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
@@ -1421,7 +1457,7 @@ int ip6_push_pending_frames(struct sock *sk)
                ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
        }
 
-       err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
+       err = ip6_local_out(skb);
        if (err) {
                if (err > 0)
                        err = np->recverr ? net_xmit_errno(err) : 0;