aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 8b67ca07467d..0af2e055f883 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -55,6 +55,7 @@
55#include <net/icmp.h> 55#include <net/icmp.h>
56#include <net/xfrm.h> 56#include <net/xfrm.h>
57#include <net/checksum.h> 57#include <net/checksum.h>
58#include <linux/mroute6.h>
58 59
59static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); 60static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
60 61
@@ -137,8 +138,9 @@ static int ip6_output2(struct sk_buff *skb)
137 struct inet6_dev *idev = ip6_dst_idev(skb->dst); 138 struct inet6_dev *idev = ip6_dst_idev(skb->dst);
138 139
139 if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && 140 if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
140 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, 141 ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
141 &ipv6_hdr(skb)->saddr)) { 142 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
143 &ipv6_hdr(skb)->saddr))) {
142 struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); 144 struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
143 145
144 /* Do not check for IFF_ALLMULTI; multicast routing 146 /* Do not check for IFF_ALLMULTI; multicast routing
@@ -237,9 +239,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
237 if (np) 239 if (np)
238 hlimit = np->hop_limit; 240 hlimit = np->hop_limit;
239 if (hlimit < 0) 241 if (hlimit < 0)
240 hlimit = dst_metric(dst, RTAX_HOPLIMIT); 242 hlimit = ip6_dst_hoplimit(dst);
241 if (hlimit < 0)
242 hlimit = ipv6_get_hoplimit(dst->dev);
243 243
244 tclass = -1; 244 tclass = -1;
245 if (np) 245 if (np)
@@ -286,7 +286,7 @@ EXPORT_SYMBOL(ip6_xmit);
286 */ 286 */
287 287
288int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, 288int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
289 struct in6_addr *saddr, struct in6_addr *daddr, 289 const struct in6_addr *saddr, const struct in6_addr *daddr,
290 int proto, int len) 290 int proto, int len)
291{ 291{
292 struct ipv6_pinfo *np = inet6_sk(sk); 292 struct ipv6_pinfo *np = inet6_sk(sk);
@@ -404,6 +404,7 @@ int ip6_forward(struct sk_buff *skb)
404 struct dst_entry *dst = skb->dst; 404 struct dst_entry *dst = skb->dst;
405 struct ipv6hdr *hdr = ipv6_hdr(skb); 405 struct ipv6hdr *hdr = ipv6_hdr(skb);
406 struct inet6_skb_parm *opt = IP6CB(skb); 406 struct inet6_skb_parm *opt = IP6CB(skb);
407 struct net *net = dev_net(dst->dev);
407 408
408 if (ipv6_devconf.forwarding == 0) 409 if (ipv6_devconf.forwarding == 0)
409 goto error; 410 goto error;
@@ -450,7 +451,7 @@ int ip6_forward(struct sk_buff *skb)
450 451
451 /* XXX: idev->cnf.proxy_ndp? */ 452 /* XXX: idev->cnf.proxy_ndp? */
452 if (ipv6_devconf.proxy_ndp && 453 if (ipv6_devconf.proxy_ndp &&
453 pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) { 454 pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
454 int proxied = ip6_forward_proxy_check(skb); 455 int proxied = ip6_forward_proxy_check(skb);
455 if (proxied > 0) 456 if (proxied > 0)
456 return ip6_input(skb); 457 return ip6_input(skb);
@@ -596,7 +597,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
596 597
597 return offset; 598 return offset;
598} 599}
599EXPORT_SYMBOL_GPL(ip6_find_1stfragopt);
600 600
601static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) 601static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
602{ 602{
@@ -912,15 +912,19 @@ static int ip6_dst_lookup_tail(struct sock *sk,
912 struct dst_entry **dst, struct flowi *fl) 912 struct dst_entry **dst, struct flowi *fl)
913{ 913{
914 int err; 914 int err;
915 struct net *net = sock_net(sk);
915 916
916 if (*dst == NULL) 917 if (*dst == NULL)
917 *dst = ip6_route_output(sk, fl); 918 *dst = ip6_route_output(net, sk, fl);
918 919
919 if ((err = (*dst)->error)) 920 if ((err = (*dst)->error))
920 goto out_err_release; 921 goto out_err_release;
921 922
922 if (ipv6_addr_any(&fl->fl6_src)) { 923 if (ipv6_addr_any(&fl->fl6_src)) {
923 err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); 924 err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev,
925 &fl->fl6_dst,
926 sk ? inet6_sk(sk)->srcprefs : 0,
927 &fl->fl6_src);
924 if (err) 928 if (err)
925 goto out_err_release; 929 goto out_err_release;
926 } 930 }
@@ -939,7 +943,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
939 struct flowi fl_gw; 943 struct flowi fl_gw;
940 int redirect; 944 int redirect;
941 945
942 ifp = ipv6_get_ifaddr(&init_net, &fl->fl6_src, 946 ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
943 (*dst)->dev, 1); 947 (*dst)->dev, 1);
944 948
945 redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); 949 redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
@@ -954,7 +958,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
954 dst_release(*dst); 958 dst_release(*dst);
955 memcpy(&fl_gw, fl, sizeof(struct flowi)); 959 memcpy(&fl_gw, fl, sizeof(struct flowi));
956 memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); 960 memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
957 *dst = ip6_route_output(sk, &fl_gw); 961 *dst = ip6_route_output(net, sk, &fl_gw);
958 if ((err = (*dst)->error)) 962 if ((err = (*dst)->error))
959 goto out_err_release; 963 goto out_err_release;
960 } 964 }
@@ -1113,7 +1117,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1113 /* need source address above miyazawa*/ 1117 /* need source address above miyazawa*/
1114 } 1118 }
1115 dst_hold(&rt->u.dst); 1119 dst_hold(&rt->u.dst);
1116 np->cork.rt = rt; 1120 inet->cork.dst = &rt->u.dst;
1117 inet->cork.fl = *fl; 1121 inet->cork.fl = *fl;
1118 np->cork.hop_limit = hlimit; 1122 np->cork.hop_limit = hlimit;
1119 np->cork.tclass = tclass; 1123 np->cork.tclass = tclass;
@@ -1134,7 +1138,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1134 length += exthdrlen; 1138 length += exthdrlen;
1135 transhdrlen += exthdrlen; 1139 transhdrlen += exthdrlen;
1136 } else { 1140 } else {
1137 rt = np->cork.rt; 1141 rt = (struct rt6_info *)inet->cork.dst;
1138 fl = &inet->cork.fl; 1142 fl = &inet->cork.fl;
1139 if (inet->cork.flags & IPCORK_OPT) 1143 if (inet->cork.flags & IPCORK_OPT)
1140 opt = np->cork.opt; 1144 opt = np->cork.opt;
@@ -1379,9 +1383,9 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
1379 inet->cork.flags &= ~IPCORK_OPT; 1383 inet->cork.flags &= ~IPCORK_OPT;
1380 kfree(np->cork.opt); 1384 kfree(np->cork.opt);
1381 np->cork.opt = NULL; 1385 np->cork.opt = NULL;
1382 if (np->cork.rt) { 1386 if (inet->cork.dst) {
1383 dst_release(&np->cork.rt->u.dst); 1387 dst_release(inet->cork.dst);
1384 np->cork.rt = NULL; 1388 inet->cork.dst = NULL;
1385 inet->cork.flags &= ~IPCORK_ALLFRAG; 1389 inet->cork.flags &= ~IPCORK_ALLFRAG;
1386 } 1390 }
1387 memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); 1391 memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
@@ -1396,7 +1400,7 @@ int ip6_push_pending_frames(struct sock *sk)
1396 struct ipv6_pinfo *np = inet6_sk(sk); 1400 struct ipv6_pinfo *np = inet6_sk(sk);
1397 struct ipv6hdr *hdr; 1401 struct ipv6hdr *hdr;
1398 struct ipv6_txoptions *opt = np->cork.opt; 1402 struct ipv6_txoptions *opt = np->cork.opt;
1399 struct rt6_info *rt = np->cork.rt; 1403 struct rt6_info *rt = (struct rt6_info *)inet->cork.dst;
1400 struct flowi *fl = &inet->cork.fl; 1404 struct flowi *fl = &inet->cork.fl;
1401 unsigned char proto = fl->proto; 1405 unsigned char proto = fl->proto;
1402 int err = 0; 1406 int err = 0;