diff options
-rw-r--r-- | net/ipv6/ip6_output.c | 18 | ||||
-rw-r--r-- | net/ipv6/raw.c | 3 |
2 files changed, 13 insertions, 8 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 835c04b5239..1e20b64e646 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1193,6 +1193,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1193 | struct sk_buff *skb; | 1193 | struct sk_buff *skb; |
1194 | unsigned int maxfraglen, fragheaderlen; | 1194 | unsigned int maxfraglen, fragheaderlen; |
1195 | int exthdrlen; | 1195 | int exthdrlen; |
1196 | int dst_exthdrlen; | ||
1196 | int hh_len; | 1197 | int hh_len; |
1197 | int mtu; | 1198 | int mtu; |
1198 | int copy; | 1199 | int copy; |
@@ -1248,7 +1249,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1248 | np->cork.hop_limit = hlimit; | 1249 | np->cork.hop_limit = hlimit; |
1249 | np->cork.tclass = tclass; | 1250 | np->cork.tclass = tclass; |
1250 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | 1251 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
1251 | rt->dst.dev->mtu : dst_mtu(rt->dst.path); | 1252 | rt->dst.dev->mtu : dst_mtu(&rt->dst); |
1252 | if (np->frag_size < mtu) { | 1253 | if (np->frag_size < mtu) { |
1253 | if (np->frag_size) | 1254 | if (np->frag_size) |
1254 | mtu = np->frag_size; | 1255 | mtu = np->frag_size; |
@@ -1259,16 +1260,17 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1259 | cork->length = 0; | 1260 | cork->length = 0; |
1260 | sk->sk_sndmsg_page = NULL; | 1261 | sk->sk_sndmsg_page = NULL; |
1261 | sk->sk_sndmsg_off = 0; | 1262 | sk->sk_sndmsg_off = 0; |
1262 | exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - | 1263 | exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; |
1263 | rt->rt6i_nfheader_len; | ||
1264 | length += exthdrlen; | 1264 | length += exthdrlen; |
1265 | transhdrlen += exthdrlen; | 1265 | transhdrlen += exthdrlen; |
1266 | dst_exthdrlen = rt->dst.header_len; | ||
1266 | } else { | 1267 | } else { |
1267 | rt = (struct rt6_info *)cork->dst; | 1268 | rt = (struct rt6_info *)cork->dst; |
1268 | fl6 = &inet->cork.fl.u.ip6; | 1269 | fl6 = &inet->cork.fl.u.ip6; |
1269 | opt = np->cork.opt; | 1270 | opt = np->cork.opt; |
1270 | transhdrlen = 0; | 1271 | transhdrlen = 0; |
1271 | exthdrlen = 0; | 1272 | exthdrlen = 0; |
1273 | dst_exthdrlen = 0; | ||
1272 | mtu = cork->fragsize; | 1274 | mtu = cork->fragsize; |
1273 | } | 1275 | } |
1274 | 1276 | ||
@@ -1368,6 +1370,8 @@ alloc_new_skb: | |||
1368 | else | 1370 | else |
1369 | alloclen = datalen + fragheaderlen; | 1371 | alloclen = datalen + fragheaderlen; |
1370 | 1372 | ||
1373 | alloclen += dst_exthdrlen; | ||
1374 | |||
1371 | /* | 1375 | /* |
1372 | * The last fragment gets additional space at tail. | 1376 | * The last fragment gets additional space at tail. |
1373 | * Note: we overallocate on fragments with MSG_MODE | 1377 | * Note: we overallocate on fragments with MSG_MODE |
@@ -1419,9 +1423,9 @@ alloc_new_skb: | |||
1419 | /* | 1423 | /* |
1420 | * Find where to start putting bytes | 1424 | * Find where to start putting bytes |
1421 | */ | 1425 | */ |
1422 | data = skb_put(skb, fraglen); | 1426 | data = skb_put(skb, fraglen + dst_exthdrlen); |
1423 | skb_set_network_header(skb, exthdrlen); | 1427 | skb_set_network_header(skb, exthdrlen + dst_exthdrlen); |
1424 | data += fragheaderlen; | 1428 | data += fragheaderlen + dst_exthdrlen; |
1425 | skb->transport_header = (skb->network_header + | 1429 | skb->transport_header = (skb->network_header + |
1426 | fragheaderlen); | 1430 | fragheaderlen); |
1427 | if (fraggap) { | 1431 | if (fraggap) { |
@@ -1434,6 +1438,7 @@ alloc_new_skb: | |||
1434 | pskb_trim_unique(skb_prev, maxfraglen); | 1438 | pskb_trim_unique(skb_prev, maxfraglen); |
1435 | } | 1439 | } |
1436 | copy = datalen - transhdrlen - fraggap; | 1440 | copy = datalen - transhdrlen - fraggap; |
1441 | |||
1437 | if (copy < 0) { | 1442 | if (copy < 0) { |
1438 | err = -EINVAL; | 1443 | err = -EINVAL; |
1439 | kfree_skb(skb); | 1444 | kfree_skb(skb); |
@@ -1448,6 +1453,7 @@ alloc_new_skb: | |||
1448 | length -= datalen - fraggap; | 1453 | length -= datalen - fraggap; |
1449 | transhdrlen = 0; | 1454 | transhdrlen = 0; |
1450 | exthdrlen = 0; | 1455 | exthdrlen = 0; |
1456 | dst_exthdrlen = 0; | ||
1451 | csummode = CHECKSUM_NONE; | 1457 | csummode = CHECKSUM_NONE; |
1452 | 1458 | ||
1453 | /* | 1459 | /* |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 3486f62befa..6f7824e1cea 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -542,8 +542,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | |||
542 | goto out; | 542 | goto out; |
543 | 543 | ||
544 | offset = rp->offset; | 544 | offset = rp->offset; |
545 | total_len = inet_sk(sk)->cork.base.length - (skb_network_header(skb) - | 545 | total_len = inet_sk(sk)->cork.base.length; |
546 | skb->data); | ||
547 | if (offset >= total_len - 1) { | 546 | if (offset >= total_len - 1) { |
548 | err = -EINVAL; | 547 | err = -EINVAL; |
549 | ip6_flush_pending_frames(sk); | 548 | ip6_flush_pending_frames(sk); |