diff options
-rw-r--r-- | net/ipv6/ndisc.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 539b2ec37d3a..53a545f32625 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1341,6 +1341,19 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1341 | icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); | 1341 | icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); |
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | static u8 *ndisc_fill_redirect_hdr_option(u8 *opt, struct sk_buff *orig_skb, | ||
1345 | int rd_len) | ||
1346 | { | ||
1347 | memset(opt, 0, 8); | ||
1348 | *(opt++) = ND_OPT_REDIRECT_HDR; | ||
1349 | *(opt++) = (rd_len >> 3); | ||
1350 | opt += 6; | ||
1351 | |||
1352 | memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8); | ||
1353 | |||
1354 | return opt + rd_len - 8; | ||
1355 | } | ||
1356 | |||
1344 | void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | 1357 | void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) |
1345 | { | 1358 | { |
1346 | struct net_device *dev = skb->dev; | 1359 | struct net_device *dev = skb->dev; |
@@ -1470,12 +1483,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1470 | * build redirect option and copy skb over to the new packet. | 1483 | * build redirect option and copy skb over to the new packet. |
1471 | */ | 1484 | */ |
1472 | 1485 | ||
1473 | memset(opt, 0, 8); | 1486 | if (rd_len) |
1474 | *(opt++) = ND_OPT_REDIRECT_HDR; | 1487 | opt = ndisc_fill_redirect_hdr_option(opt, skb, rd_len); |
1475 | *(opt++) = (rd_len >> 3); | ||
1476 | opt += 6; | ||
1477 | |||
1478 | memcpy(opt, ipv6_hdr(skb), rd_len - 8); | ||
1479 | 1488 | ||
1480 | msg->icmph.icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr, | 1489 | msg->icmph.icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr, |
1481 | len, IPPROTO_ICMPV6, | 1490 | len, IPPROTO_ICMPV6, |