aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-05-10 12:39:28 -0400
committerPatrick McHardy <kaber@trash.net>2010-05-10 12:39:28 -0400
commit1e4b1057121bc756b91758a434b504d2010f6088 (patch)
treeb016cf2c728289c7e36d9e4e488f30ab0bd0ae6e /net/ipv6/ip6_output.c
parent3b254c54ec46eb022cb26ee6ab37fae23f5f7d6a (diff)
parent3ee943728fff536edaf8f59faa58aaa1aa7366e3 (diff)
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts: net/bridge/br_device.c net/bridge/br_forward.c Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7f12e30cfa73..5173acaeb501 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -92,7 +92,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
92 newskb->ip_summed = CHECKSUM_UNNECESSARY; 92 newskb->ip_summed = CHECKSUM_UNNECESSARY;
93 WARN_ON(!skb_dst(newskb)); 93 WARN_ON(!skb_dst(newskb));
94 94
95 netif_rx(newskb); 95 netif_rx_ni(newskb);
96 return 0; 96 return 0;
97} 97}
98 98
@@ -216,8 +216,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
216 } 216 }
217 kfree_skb(skb); 217 kfree_skb(skb);
218 skb = skb2; 218 skb = skb2;
219 if (sk) 219 skb_set_owner_w(skb, sk);
220 skb_set_owner_w(skb, sk);
221 } 220 }
222 if (opt->opt_flen) 221 if (opt->opt_flen)
223 ipv6_push_frag_opts(skb, opt, &proto); 222 ipv6_push_frag_opts(skb, opt, &proto);
@@ -623,7 +622,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
623 /* We must not fragment if the socket is set to force MTU discovery 622 /* We must not fragment if the socket is set to force MTU discovery
624 * or if the skb it not generated by a local socket. 623 * or if the skb it not generated by a local socket.
625 */ 624 */
626 if (!skb->local_df) { 625 if (!skb->local_df && skb->len > mtu) {
627 skb->dev = skb_dst(skb)->dev; 626 skb->dev = skb_dst(skb)->dev;
628 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 627 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
629 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 628 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
@@ -1103,7 +1102,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1103 int offset, int len, int odd, struct sk_buff *skb), 1102 int offset, int len, int odd, struct sk_buff *skb),
1104 void *from, int length, int transhdrlen, 1103 void *from, int length, int transhdrlen,
1105 int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, 1104 int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
1106 struct rt6_info *rt, unsigned int flags) 1105 struct rt6_info *rt, unsigned int flags, int dontfrag)
1107{ 1106{
1108 struct inet_sock *inet = inet_sk(sk); 1107 struct inet_sock *inet = inet_sk(sk);
1109 struct ipv6_pinfo *np = inet6_sk(sk); 1108 struct ipv6_pinfo *np = inet6_sk(sk);
@@ -1217,15 +1216,23 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1217 */ 1216 */
1218 1217
1219 inet->cork.length += length; 1218 inet->cork.length += length;
1220 if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && 1219 if (length > mtu) {
1221 (rt->u.dst.dev->features & NETIF_F_UFO)) { 1220 int proto = sk->sk_protocol;
1221 if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
1222 ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen);
1223 return -EMSGSIZE;
1224 }
1222 1225
1223 err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, 1226 if (proto == IPPROTO_UDP &&
1224 fragheaderlen, transhdrlen, mtu, 1227 (rt->u.dst.dev->features & NETIF_F_UFO)) {
1225 flags); 1228
1226 if (err) 1229 err = ip6_ufo_append_data(sk, getfrag, from, length,
1227 goto error; 1230 hh_len, fragheaderlen,
1228 return 0; 1231 transhdrlen, mtu, flags);
1232 if (err)
1233 goto error;
1234 return 0;
1235 }
1229 } 1236 }
1230 1237
1231 if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) 1238 if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)