aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/ip6_output.c18
-rw-r--r--net/ipv6/raw.c3
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);