aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>2013-01-21 01:49:03 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-21 13:33:17 -0500
commitf4de84c64e3d801965ee4c6dadd19b76b9424bbf (patch)
tree0f502d604d5b53901c5a95842e12a018fefec914 /net/ipv6
parentaa4bdd4b3f43274252c1280f6464850b0f004fc8 (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.c37
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
1531release: 1522release: