diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 13:43:21 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 13:43:21 -0700 |
commit | 06f4e926d256d902dd9a53dcb400fd74974ce087 (patch) | |
tree | 0b438b67f5f0eff6fd617bc497a9dace6164a488 /net/ipv6/ndisc.c | |
parent | 8e7bfcbab3825d1b404d615cb1b54f44ff81f981 (diff) | |
parent | d93515611bbc70c2fe4db232e5feb448ed8e4cc9 (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: (1446 commits)
macvlan: fix panic if lowerdev in a bond
tg3: Add braces around 5906 workaround.
tg3: Fix NETIF_F_LOOPBACK error
macvlan: remove one synchronize_rcu() call
networking: NET_CLS_ROUTE4 depends on INET
irda: Fix error propagation in ircomm_lmp_connect_response()
irda: Kill set but unused variable 'bytes' in irlan_check_command_param()
irda: Kill set but unused variable 'clen' in ircomm_connect_indication()
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport()
be2net: Kill set but unused variable 'req' in lancer_fw_download()
irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication()
atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined.
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer().
rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler()
rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection()
rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window()
pkt_sched: Kill set but unused variable 'protocol' in tc_classify()
isdn: capi: Use pr_debug() instead of ifdefs.
tg3: Update version to 3.119
tg3: Apply rx_discards fix to 5719/5720
...
Fix up trivial conflicts in arch/x86/Kconfig and net/mac80211/agg-tx.c
as per Davem.
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r-- | net/ipv6/ndisc.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 92f952d093d..7596f071d30 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -324,7 +324,7 @@ static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, return lladdr + prepad; } -int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir) +int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir) { switch (dev->type) { case ARPHRD_ETHER: @@ -611,6 +611,29 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); } +static void ndisc_send_unsol_na(struct net_device *dev) +{ + struct inet6_dev *idev; + struct inet6_ifaddr *ifa; + struct in6_addr mcaddr; + + idev = in6_dev_get(dev); + if (!idev) + return; + + read_lock_bh(&idev->lock); + list_for_each_entry(ifa, &idev->addr_list, if_list) { + addrconf_addr_solict_mult(&ifa->addr, &mcaddr); + ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, + /*router=*/ !!idev->cnf.forwarding, + /*solicited=*/ false, /*override=*/ true, + /*inc_opt=*/ true); + } + read_unlock_bh(&idev->lock); + + in6_dev_put(idev); +} + void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, const struct in6_addr *solicit, const struct in6_addr *daddr, const struct in6_addr *saddr) @@ -725,8 +748,8 @@ static int pndisc_is_router(const void *pkey, static void ndisc_recv_ns(struct sk_buff *skb) { struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); - struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; - struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; + const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; + const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; u8 *lladdr = NULL; u32 ndoptlen = skb->tail - (skb->transport_header + offsetof(struct nd_msg, opt)); @@ -901,8 +924,8 @@ out: static void ndisc_recv_na(struct sk_buff *skb) { struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); - struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; - struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; + const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; + const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; u8 *lladdr = NULL; u32 ndoptlen = skb->tail - (skb->transport_header + offsetof(struct nd_msg, opt)); @@ -945,9 +968,10 @@ static void ndisc_recv_na(struct sk_buff *skb) } ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); if (ifp) { - if (ifp->flags & IFA_F_TENTATIVE) { - addrconf_dad_failure(ifp); - return; + if (skb->pkt_type != PACKET_LOOPBACK + && (ifp->flags & IFA_F_TENTATIVE)) { + addrconf_dad_failure(ifp); + return; } /* What should we make now? The advertisement is invalid, but ndisc specs say nothing @@ -1014,7 +1038,7 @@ static void ndisc_recv_rs(struct sk_buff *skb) unsigned long ndoptlen = skb->len - sizeof(*rs_msg); struct neighbour *neigh; struct inet6_dev *idev; - struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; + const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; struct ndisc_options ndopts; u8 *lladdr = NULL; @@ -1411,8 +1435,8 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) { struct inet6_dev *in6_dev; struct icmp6hdr *icmph; - struct in6_addr *dest; - struct in6_addr *target; /* new first hop to destination */ + const struct in6_addr *dest; + const struct in6_addr *target; /* new first hop to destination */ struct neighbour *neigh; int on_link = 0; struct ndisc_options ndopts; @@ -1445,7 +1469,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) } icmph = icmp6_hdr(skb); - target = (struct in6_addr *) (icmph + 1); + target = (const struct in6_addr *) (icmph + 1); dest = target + 1; if (ipv6_addr_is_multicast(dest)) { @@ -1722,6 +1746,9 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, neigh_ifdown(&nd_tbl, dev); fib6_run_gc(~0UL, net); break; + case NETDEV_NOTIFY_PEERS: + ndisc_send_unsol_na(dev); + break; default: break; } |