aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ndisc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 15:49:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 15:49:40 -0500
commit0191b625ca5a46206d2fb862bb08f36f2fcb3b31 (patch)
tree454d1842b1833d976da62abcbd5c47521ebe9bd7 /net/ipv6/ndisc.c
parent54a696bd07c14d3b1192d03ce7269bc59b45209a (diff)
parenteb56092fc168bf5af199d47af50c0d84a96db898 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1429 commits) net: Allow dependancies of FDDI & Tokenring to be modular. igb: Fix build warning when DCA is disabled. net: Fix warning fallout from recent NAPI interface changes. gro: Fix potential use after free sfc: If AN is enabled, always read speed/duplex from the AN advertising bits sfc: When disabling the NIC, close the device rather than unregistering it sfc: SFT9001: Add cable diagnostics sfc: Add support for multiple PHY self-tests sfc: Merge top-level functions for self-tests sfc: Clean up PHY mode management in loopback self-test sfc: Fix unreliable link detection in some loopback modes sfc: Generate unique names for per-NIC workqueues 802.3ad: use standard ethhdr instead of ad_header 802.3ad: generalize out mac address initializer 802.3ad: initialize ports LACPDU from const initializer 802.3ad: remove typedef around ad_system 802.3ad: turn ports is_individual into a bool 802.3ad: turn ports is_enabled into a bool 802.3ad: make ntt bool ixgbe: Fix set_ringparam in ixgbe to use the same memory pools. ... Fixed trivial IPv4/6 address printing conflicts in fs/cifs/connect.c due to the conversion to %pI (in this networking merge) and the addition of doing IPv6 addresses (from the earlier merge of CIFS).
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r--net/ipv6/ndisc.c105
1 files changed, 70 insertions, 35 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index d0f54d18e19b..3e2970841bd8 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -437,38 +437,20 @@ static void pndisc_destructor(struct pneigh_entry *n)
437 ipv6_dev_mc_dec(dev, &maddr); 437 ipv6_dev_mc_dec(dev, &maddr);
438} 438}
439 439
440/* 440struct sk_buff *ndisc_build_skb(struct net_device *dev,
441 * Send a Neighbour Advertisement 441 const struct in6_addr *daddr,
442 */ 442 const struct in6_addr *saddr,
443static void __ndisc_send(struct net_device *dev, 443 struct icmp6hdr *icmp6h,
444 struct neighbour *neigh, 444 const struct in6_addr *target,
445 const struct in6_addr *daddr, 445 int llinfo)
446 const struct in6_addr *saddr,
447 struct icmp6hdr *icmp6h, const struct in6_addr *target,
448 int llinfo)
449{ 446{
450 struct flowi fl;
451 struct dst_entry *dst;
452 struct net *net = dev_net(dev); 447 struct net *net = dev_net(dev);
453 struct sock *sk = net->ipv6.ndisc_sk; 448 struct sock *sk = net->ipv6.ndisc_sk;
454 struct sk_buff *skb; 449 struct sk_buff *skb;
455 struct icmp6hdr *hdr; 450 struct icmp6hdr *hdr;
456 struct inet6_dev *idev;
457 int len; 451 int len;
458 int err; 452 int err;
459 u8 *opt, type; 453 u8 *opt;
460
461 type = icmp6h->icmp6_type;
462
463 icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);
464
465 dst = icmp6_dst_alloc(dev, neigh, daddr);
466 if (!dst)
467 return;
468
469 err = xfrm_lookup(&dst, &fl, NULL, 0);
470 if (err < 0)
471 return;
472 454
473 if (!dev->addr_len) 455 if (!dev->addr_len)
474 llinfo = 0; 456 llinfo = 0;
@@ -485,8 +467,7 @@ static void __ndisc_send(struct net_device *dev,
485 ND_PRINTK0(KERN_ERR 467 ND_PRINTK0(KERN_ERR
486 "ICMPv6 ND: %s() failed to allocate an skb.\n", 468 "ICMPv6 ND: %s() failed to allocate an skb.\n",
487 __func__); 469 __func__);
488 dst_release(dst); 470 return NULL;
489 return;
490 } 471 }
491 472
492 skb_reserve(skb, LL_RESERVED_SPACE(dev)); 473 skb_reserve(skb, LL_RESERVED_SPACE(dev));
@@ -510,9 +491,45 @@ static void __ndisc_send(struct net_device *dev,
510 491
511 hdr->icmp6_cksum = csum_ipv6_magic(saddr, daddr, len, 492 hdr->icmp6_cksum = csum_ipv6_magic(saddr, daddr, len,
512 IPPROTO_ICMPV6, 493 IPPROTO_ICMPV6,
513 csum_partial((__u8 *) hdr, 494 csum_partial(hdr,
514 len, 0)); 495 len, 0));
515 496
497 return skb;
498}
499
500EXPORT_SYMBOL(ndisc_build_skb);
501
502void ndisc_send_skb(struct sk_buff *skb,
503 struct net_device *dev,
504 struct neighbour *neigh,
505 const struct in6_addr *daddr,
506 const struct in6_addr *saddr,
507 struct icmp6hdr *icmp6h)
508{
509 struct flowi fl;
510 struct dst_entry *dst;
511 struct net *net = dev_net(dev);
512 struct sock *sk = net->ipv6.ndisc_sk;
513 struct inet6_dev *idev;
514 int err;
515 u8 type;
516
517 type = icmp6h->icmp6_type;
518
519 icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);
520
521 dst = icmp6_dst_alloc(dev, neigh, daddr);
522 if (!dst) {
523 kfree_skb(skb);
524 return;
525 }
526
527 err = xfrm_lookup(net, &dst, &fl, NULL, 0);
528 if (err < 0) {
529 kfree_skb(skb);
530 return;
531 }
532
516 skb->dst = dst; 533 skb->dst = dst;
517 534
518 idev = in6_dev_get(dst->dev); 535 idev = in6_dev_get(dst->dev);
@@ -529,6 +546,27 @@ static void __ndisc_send(struct net_device *dev,
529 in6_dev_put(idev); 546 in6_dev_put(idev);
530} 547}
531 548
549EXPORT_SYMBOL(ndisc_send_skb);
550
551/*
552 * Send a Neighbour Discover packet
553 */
554static void __ndisc_send(struct net_device *dev,
555 struct neighbour *neigh,
556 const struct in6_addr *daddr,
557 const struct in6_addr *saddr,
558 struct icmp6hdr *icmp6h, const struct in6_addr *target,
559 int llinfo)
560{
561 struct sk_buff *skb;
562
563 skb = ndisc_build_skb(dev, daddr, saddr, icmp6h, target, llinfo);
564 if (!skb)
565 return;
566
567 ndisc_send_skb(skb, dev, neigh, daddr, saddr, icmp6h);
568}
569
532static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, 570static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
533 const struct in6_addr *daddr, 571 const struct in6_addr *daddr,
534 const struct in6_addr *solicited_addr, 572 const struct in6_addr *solicited_addr,
@@ -647,11 +685,8 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
647 685
648 if ((probes -= neigh->parms->ucast_probes) < 0) { 686 if ((probes -= neigh->parms->ucast_probes) < 0) {
649 if (!(neigh->nud_state & NUD_VALID)) { 687 if (!(neigh->nud_state & NUD_VALID)) {
650 ND_PRINTK1(KERN_DEBUG 688 ND_PRINTK1(KERN_DEBUG "%s(): trying to ucast probe in NUD_INVALID: %pI6\n",
651 "%s(): trying to ucast probe in NUD_INVALID: " 689 __func__, target);
652 NIP6_FMT "\n",
653 __func__,
654 NIP6(*target));
655 } 690 }
656 ndisc_send_ns(dev, neigh, target, target, saddr); 691 ndisc_send_ns(dev, neigh, target, target, saddr);
657 } else if ((probes -= neigh->parms->app_probes) < 0) { 692 } else if ((probes -= neigh->parms->app_probes) < 0) {
@@ -1494,7 +1529,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1494 if (dst == NULL) 1529 if (dst == NULL)
1495 return; 1530 return;
1496 1531
1497 err = xfrm_lookup(&dst, &fl, NULL, 0); 1532 err = xfrm_lookup(net, &dst, &fl, NULL, 0);
1498 if (err) 1533 if (err)
1499 return; 1534 return;
1500 1535
@@ -1582,7 +1617,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1582 1617
1583 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr, 1618 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr,
1584 len, IPPROTO_ICMPV6, 1619 len, IPPROTO_ICMPV6,
1585 csum_partial((u8 *) icmph, len, 0)); 1620 csum_partial(icmph, len, 0));
1586 1621
1587 buff->dst = dst; 1622 buff->dst = dst;
1588 idev = in6_dev_get(dst->dev); 1623 idev = in6_dev_get(dst->dev);