diff options
author | YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> | 2013-01-21 01:48:49 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-21 13:33:16 -0500 |
commit | 2ce13576144ade3e9340efce9620a6dd338aedc7 (patch) | |
tree | 96e3dca4ed2b8427211439804608ced30c7556f8 /net/ipv6/ndisc.c | |
parent | 5135e633f92ab4deb3600a30cbbec6e0929fc8a4 (diff) |
ndisc: Calculate message body length and option length separately.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r-- | net/ipv6/ndisc.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 62b1415bec25..c2b16ffeb1a8 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -426,6 +426,7 @@ static struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
426 | struct sk_buff *skb; | 426 | struct sk_buff *skb; |
427 | struct icmp6hdr *hdr; | 427 | struct icmp6hdr *hdr; |
428 | int len; | 428 | int len; |
429 | int optlen = 0; | ||
429 | u8 *opt; | 430 | u8 *opt; |
430 | 431 | ||
431 | if (!dev->addr_len) | 432 | if (!dev->addr_len) |
@@ -433,13 +434,13 @@ static struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
433 | 434 | ||
434 | len = sizeof(struct icmp6hdr) + (target ? sizeof(*target) : 0); | 435 | len = sizeof(struct icmp6hdr) + (target ? sizeof(*target) : 0); |
435 | if (llinfo) | 436 | if (llinfo) |
436 | len += ndisc_opt_addr_space(dev); | 437 | optlen += ndisc_opt_addr_space(dev); |
437 | 438 | ||
438 | skb = ndisc_alloc_skb(dev, len); | 439 | skb = ndisc_alloc_skb(dev, len + optlen); |
439 | if (!skb) | 440 | if (!skb) |
440 | return NULL; | 441 | return NULL; |
441 | 442 | ||
442 | skb_put(skb, len); | 443 | skb_put(skb, len + optlen); |
443 | 444 | ||
444 | hdr = (struct icmp6hdr *)skb_transport_header(skb); | 445 | hdr = (struct icmp6hdr *)skb_transport_header(skb); |
445 | memcpy(hdr, icmp6h, sizeof(*hdr)); | 446 | memcpy(hdr, icmp6h, sizeof(*hdr)); |
@@ -1396,7 +1397,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1396 | struct net_device *dev = skb->dev; | 1397 | struct net_device *dev = skb->dev; |
1397 | struct net *net = dev_net(dev); | 1398 | struct net *net = dev_net(dev); |
1398 | struct sock *sk = net->ipv6.ndisc_sk; | 1399 | struct sock *sk = net->ipv6.ndisc_sk; |
1399 | int len = sizeof(struct rd_msg); | 1400 | int optlen = 0; |
1400 | struct inet_peer *peer; | 1401 | struct inet_peer *peer; |
1401 | struct sk_buff *buff; | 1402 | struct sk_buff *buff; |
1402 | struct rd_msg *msg; | 1403 | struct rd_msg *msg; |
@@ -1463,7 +1464,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1463 | memcpy(ha_buf, neigh->ha, dev->addr_len); | 1464 | memcpy(ha_buf, neigh->ha, dev->addr_len); |
1464 | read_unlock_bh(&neigh->lock); | 1465 | read_unlock_bh(&neigh->lock); |
1465 | ha = ha_buf; | 1466 | ha = ha_buf; |
1466 | len += ndisc_opt_addr_space(dev); | 1467 | optlen += ndisc_opt_addr_space(dev); |
1467 | } else | 1468 | } else |
1468 | read_unlock_bh(&neigh->lock); | 1469 | read_unlock_bh(&neigh->lock); |
1469 | 1470 | ||
@@ -1471,15 +1472,16 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1471 | } | 1472 | } |
1472 | 1473 | ||
1473 | rd_len = min_t(unsigned int, | 1474 | rd_len = min_t(unsigned int, |
1474 | IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8); | 1475 | IPV6_MIN_MTU - sizeof(struct ipv6hdr) - sizeof(*msg) - optlen, |
1476 | skb->len + 8); | ||
1475 | rd_len &= ~0x7; | 1477 | rd_len &= ~0x7; |
1476 | len += rd_len; | 1478 | optlen += rd_len; |
1477 | 1479 | ||
1478 | buff = ndisc_alloc_skb(dev, len); | 1480 | buff = ndisc_alloc_skb(dev, sizeof(*msg) + optlen); |
1479 | if (!buff) | 1481 | if (!buff) |
1480 | goto release; | 1482 | goto release; |
1481 | 1483 | ||
1482 | skb_put(buff, len); | 1484 | skb_put(buff, sizeof(*msg) + optlen); |
1483 | msg = (struct rd_msg *)icmp6_hdr(buff); | 1485 | msg = (struct rd_msg *)icmp6_hdr(buff); |
1484 | 1486 | ||
1485 | memset(&msg->icmph, 0, sizeof(struct icmp6hdr)); | 1487 | memset(&msg->icmph, 0, sizeof(struct icmp6hdr)); |