diff options
author | YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> | 2013-01-21 01:49:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-21 13:33:17 -0500 |
commit | f4de84c64e3d801965ee4c6dadd19b76b9424bbf (patch) | |
tree | 0f502d604d5b53901c5a95842e12a018fefec914 /net/ipv6 | |
parent | aa4bdd4b3f43274252c1280f6464850b0f004fc8 (diff) |
ndisc: Use ndisc_send_skb() for redirect.
Reuse dst if one is attached with skb.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ndisc.c | 37 |
1 files changed, 14 insertions, 23 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index f0c436b49255..437781c2af41 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -467,10 +467,8 @@ static void ndisc_send_skb(struct sk_buff *skb, | |||
467 | const struct in6_addr *daddr, | 467 | const struct in6_addr *daddr, |
468 | const struct in6_addr *saddr) | 468 | const struct in6_addr *saddr) |
469 | { | 469 | { |
470 | struct flowi6 fl6; | 470 | struct dst_entry *dst = skb_dst(skb); |
471 | struct dst_entry *dst; | ||
472 | struct net *net = dev_net(skb->dev); | 471 | struct net *net = dev_net(skb->dev); |
473 | struct sock *sk = net->ipv6.ndisc_sk; | ||
474 | struct inet6_dev *idev; | 472 | struct inet6_dev *idev; |
475 | int err; | 473 | int err; |
476 | struct icmp6hdr *icmp6h = icmp6_hdr(skb); | 474 | struct icmp6hdr *icmp6h = icmp6_hdr(skb); |
@@ -478,14 +476,19 @@ static void ndisc_send_skb(struct sk_buff *skb, | |||
478 | 476 | ||
479 | type = icmp6h->icmp6_type; | 477 | type = icmp6h->icmp6_type; |
480 | 478 | ||
481 | icmpv6_flow_init(sk, &fl6, type, saddr, daddr, skb->dev->ifindex); | 479 | if (!dst) { |
482 | dst = icmp6_dst_alloc(skb->dev, &fl6); | 480 | struct sock *sk = net->ipv6.ndisc_sk; |
483 | if (IS_ERR(dst)) { | 481 | struct flowi6 fl6; |
484 | kfree_skb(skb); | ||
485 | return; | ||
486 | } | ||
487 | 482 | ||
488 | skb_dst_set(skb, dst); | 483 | icmpv6_flow_init(sk, &fl6, type, saddr, daddr, skb->dev->ifindex); |
484 | dst = icmp6_dst_alloc(skb->dev, &fl6); | ||
485 | if (IS_ERR(dst)) { | ||
486 | kfree_skb(skb); | ||
487 | return; | ||
488 | } | ||
489 | |||
490 | skb_dst_set(skb, dst); | ||
491 | } | ||
489 | 492 | ||
490 | rcu_read_lock(); | 493 | rcu_read_lock(); |
491 | idev = __in6_dev_get(dst->dev); | 494 | idev = __in6_dev_get(dst->dev); |
@@ -1404,10 +1407,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1404 | struct in6_addr saddr_buf; | 1407 | struct in6_addr saddr_buf; |
1405 | struct rt6_info *rt; | 1408 | struct rt6_info *rt; |
1406 | struct dst_entry *dst; | 1409 | struct dst_entry *dst; |
1407 | struct inet6_dev *idev; | ||
1408 | struct flowi6 fl6; | 1410 | struct flowi6 fl6; |
1409 | int rd_len; | 1411 | int rd_len; |
1410 | int err; | ||
1411 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; | 1412 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; |
1412 | bool ret; | 1413 | bool ret; |
1413 | 1414 | ||
@@ -1515,17 +1516,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1515 | inet6_sk(sk)->hop_limit, buff->len); | 1516 | inet6_sk(sk)->hop_limit, buff->len); |
1516 | 1517 | ||
1517 | skb_dst_set(buff, dst); | 1518 | skb_dst_set(buff, dst); |
1518 | rcu_read_lock(); | 1519 | ndisc_send_skb(buff, &ipv6_hdr(skb)->saddr, &saddr_buf); |
1519 | idev = __in6_dev_get(dst->dev); | ||
1520 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | ||
1521 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, | ||
1522 | dst_output); | ||
1523 | if (!err) { | ||
1524 | ICMP6MSGOUT_INC_STATS(net, idev, NDISC_REDIRECT); | ||
1525 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); | ||
1526 | } | ||
1527 | |||
1528 | rcu_read_unlock(); | ||
1529 | return; | 1520 | return; |
1530 | 1521 | ||
1531 | release: | 1522 | release: |