diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 40 |
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 | ||
59 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); | 60 | static 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 | ||
288 | int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | 288 | int 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 | } |
599 | EXPORT_SYMBOL_GPL(ip6_find_1stfragopt); | ||
600 | 600 | ||
601 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 601 | static 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; |