135 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { |
135 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { |
136 struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; |
136 struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; |
137 struct inet6_dev *idev = ip6_dst_idev(skb->dst); |
137 struct inet6_dev *idev = ip6_dst_idev(skb->dst); |
138 |
138 |
139 if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && |
139 if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && |
140 ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || |
140 ((mroute6_socket(dev_net(dev)) && |
|
141 !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || |
141 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
142 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
142 &ipv6_hdr(skb)->saddr))) { |
143 &ipv6_hdr(skb)->saddr))) { |
143 struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
144 struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
144 |
145 |
145 /* Do not check for IFF_ALLMULTI; multicast routing |
146 /* Do not check for IFF_ALLMULTI; multicast routing |
488 /* IPv6 specs say nothing about it, but it is clear that we cannot |
489 /* IPv6 specs say nothing about it, but it is clear that we cannot |
489 send redirects to source routed frames. |
490 send redirects to source routed frames. |
490 We don't send redirects to frames decapsulated from IPsec. |
491 We don't send redirects to frames decapsulated from IPsec. |
491 */ |
492 */ |
492 if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 && |
493 if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 && |
493 !skb->sp) { |
494 !skb_sec_path(skb)) { |
494 struct in6_addr *target = NULL; |
495 struct in6_addr *target = NULL; |
495 struct rt6_info *rt; |
496 struct rt6_info *rt; |
496 struct neighbour *n = dst->neighbour; |
497 struct neighbour *n = dst->neighbour; |
497 |
498 |
498 /* |
499 /* |
1102 kfree_skb(skb); |
1103 kfree_skb(skb); |
1103 |
1104 |
1104 return err; |
1105 return err; |
1105 } |
1106 } |
1106 |
1107 |
|
1108 static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, |
|
1109 gfp_t gfp) |
|
1110 { |
|
1111 return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; |
|
1112 } |
|
1113 |
|
1114 static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, |
|
1115 gfp_t gfp) |
|
1116 { |
|
1117 return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; |
|
1118 } |
|
1119 |
1107 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
1120 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
1108 int offset, int len, int odd, struct sk_buff *skb), |
1121 int offset, int len, int odd, struct sk_buff *skb), |
1109 void *from, int length, int transhdrlen, |
1122 void *from, int length, int transhdrlen, |
1110 int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, |
1123 int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, |
1111 struct rt6_info *rt, unsigned int flags) |
1124 struct rt6_info *rt, unsigned int flags) |
1127 if (skb_queue_empty(&sk->sk_write_queue)) { |
1140 if (skb_queue_empty(&sk->sk_write_queue)) { |
1128 /* |
1141 /* |
1129 * setup for corking |
1142 * setup for corking |
1130 */ |
1143 */ |
1131 if (opt) { |
1144 if (opt) { |
1132 if (np->cork.opt == NULL) { |
1145 if (WARN_ON(np->cork.opt)) |
1133 np->cork.opt = kmalloc(opt->tot_len, |
|
1134 sk->sk_allocation); |
|
1135 if (unlikely(np->cork.opt == NULL)) |
|
1136 return -ENOBUFS; |
|
1137 } else if (np->cork.opt->tot_len < opt->tot_len) { |
|
1138 printk(KERN_DEBUG "ip6_append_data: invalid option length\n"); |
|
1139 return -EINVAL; |
1146 return -EINVAL; |
1140 } |
1147 |
1141 memcpy(np->cork.opt, opt, opt->tot_len); |
1148 np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); |
1142 inet->cork.flags |= IPCORK_OPT; |
1149 if (unlikely(np->cork.opt == NULL)) |
|
1150 return -ENOBUFS; |
|
1151 |
|
1152 np->cork.opt->tot_len = opt->tot_len; |
|
1153 np->cork.opt->opt_flen = opt->opt_flen; |
|
1154 np->cork.opt->opt_nflen = opt->opt_nflen; |
|
1155 |
|
1156 np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt, |
|
1157 sk->sk_allocation); |
|
1158 if (opt->dst0opt && !np->cork.opt->dst0opt) |
|
1159 return -ENOBUFS; |
|
1160 |
|
1161 np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt, |
|
1162 sk->sk_allocation); |
|
1163 if (opt->dst1opt && !np->cork.opt->dst1opt) |
|
1164 return -ENOBUFS; |
|
1165 |
|
1166 np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt, |
|
1167 sk->sk_allocation); |
|
1168 if (opt->hopopt && !np->cork.opt->hopopt) |
|
1169 return -ENOBUFS; |
|
1170 |
|
1171 np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt, |
|
1172 sk->sk_allocation); |
|
1173 if (opt->srcrt && !np->cork.opt->srcrt) |
|
1174 return -ENOBUFS; |
|
1175 |
1143 /* need source address above miyazawa*/ |
1176 /* need source address above miyazawa*/ |
1144 } |
1177 } |
1145 dst_hold(&rt->u.dst); |
1178 dst_hold(&rt->u.dst); |
1146 inet->cork.dst = &rt->u.dst; |
1179 inet->cork.dst = &rt->u.dst; |
1147 inet->cork.fl = *fl; |
1180 inet->cork.fl = *fl; |
1164 length += exthdrlen; |
1197 length += exthdrlen; |
1165 transhdrlen += exthdrlen; |
1198 transhdrlen += exthdrlen; |
1166 } else { |
1199 } else { |
1167 rt = (struct rt6_info *)inet->cork.dst; |
1200 rt = (struct rt6_info *)inet->cork.dst; |
1168 fl = &inet->cork.fl; |
1201 fl = &inet->cork.fl; |
1169 if (inet->cork.flags & IPCORK_OPT) |
1202 opt = np->cork.opt; |
1170 opt = np->cork.opt; |
|
1171 transhdrlen = 0; |
1203 transhdrlen = 0; |
1172 exthdrlen = 0; |
1204 exthdrlen = 0; |
1173 mtu = inet->cork.fragsize; |
1205 mtu = inet->cork.fragsize; |
1174 } |
1206 } |
1175 |
1207 |
1404 return err; |
1436 return err; |
1405 } |
1437 } |
1406 |
1438 |
1407 static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) |
1439 static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) |
1408 { |
1440 { |
1409 inet->cork.flags &= ~IPCORK_OPT; |
1441 if (np->cork.opt) { |
1410 kfree(np->cork.opt); |
1442 kfree(np->cork.opt->dst0opt); |
1411 np->cork.opt = NULL; |
1443 kfree(np->cork.opt->dst1opt); |
|
1444 kfree(np->cork.opt->hopopt); |
|
1445 kfree(np->cork.opt->srcrt); |
|
1446 kfree(np->cork.opt); |
|
1447 np->cork.opt = NULL; |
|
1448 } |
|
1449 |
1412 if (inet->cork.dst) { |
1450 if (inet->cork.dst) { |
1413 dst_release(inet->cork.dst); |
1451 dst_release(inet->cork.dst); |
1414 inet->cork.dst = NULL; |
1452 inet->cork.dst = NULL; |
1415 inet->cork.flags &= ~IPCORK_ALLFRAG; |
1453 inet->cork.flags &= ~IPCORK_ALLFRAG; |
1416 } |
1454 } |