ndisc.c revision 3b00944c5c73c49ef52bf17b66557c43c1d945fe
10a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg/*
25484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg *	Neighbour Discovery for IPv6
35484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg *	Linux INET6 implementation
40a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *
50a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *	Authors:
60a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *	Pedro Roque		<roque@di.fc.ul.pt>
70a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *	Mike Shaver		<shaver@ingenia.com>
80a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *
90a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *	This program is free software; you can redistribute it and/or
100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *      modify it under the terms of the GNU General Public License
110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *      as published by the Free Software Foundation; either version
120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *      2 of the License, or (at your option) any later version.
130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */
140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg
150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg/*
16888d04dfbe7e09f930fdaafb257cce2c54c9c3f3Felix Fietkau *	Changes:
17078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg *
18e8db0be1245de16a6cc6365506abc392c3c212d4Jean Pihet *	Pierre Ynard			:	export userland ND options
19df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa *						through netlink (RDNSS support)
205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo *	Lars Fenneberg			:	fixed MTU setting on receipt
21bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker *						of an RA.
220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *	Janos Farkas			:	kmalloc failure checks
230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *	Alexey Kuznetsov		:	state machine reworked
240a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *						and moved to net/core.
252448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg *	Pekka Savola			:	RFC2461 validation
265484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg *	YOSHIFUJI Hideaki @USAGI	:	Verify ND options properly
270a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */
280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg
290a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg/* Set to 3 to get tracing... */
303f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka#define ND_DEBUG 1
310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg
325484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#define ND_PRINTK(fmt, args...) do { if (net_ratelimit()) { printk(fmt, ## args); } } while(0)
33c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg#define ND_NOPRINTK(x...) do { ; } while(0)
345484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#define ND_PRINTK0 ND_PRINTK
350c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#define ND_PRINTK1 ND_NOPRINTK
360c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#define ND_PRINTK2 ND_NOPRINTK
375b112d3d098c97b867cc580f590395cd1e72f18cJohannes Berg#define ND_PRINTK3 ND_NOPRINTK
385b112d3d098c97b867cc580f590395cd1e72f18cJohannes Berg#if ND_DEBUG >= 1
395484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#undef ND_PRINTK1
405484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#define ND_PRINTK1 ND_PRINTK
41ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#endif
42ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#if ND_DEBUG >= 2
43ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#undef ND_PRINTK2
44ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#define ND_PRINTK2 ND_PRINTK
45ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#endif
46ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#if ND_DEBUG >= 3
47ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#undef ND_PRINTK3
48ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#define ND_PRINTK3 ND_PRINTK
49ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#endif
50ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo
51ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/module.h>
52ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/errno.h>
53ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/types.h>
54ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/socket.h>
55ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/sockios.h>
56ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/sched.h>
57ab13315af97919fae0e014748105fdc2e30afb2dKalle Valo#include <linux/net.h>
58c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg#include <linux/in6.h>
595484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#include <linux/route.h>
605484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#include <linux/init.h>
61d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach#include <linux/rcupdate.h>
625484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#ifdef CONFIG_SYSCTL
63d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach#include <linux/sysctl.h>
645484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#endif
65d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach
660c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <linux/if_addr.h>
67c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg#include <linux/if_arp.h>
68f0b058b61711ebf5be94d6865ca7b2c259b71d37Stanislaw Gruszka#include <linux/ipv6.h>
692a5193119269062608582418deba7af82844159aJohannes Berg#include <linux/icmpv6.h>
702a5193119269062608582418deba7af82844159aJohannes Berg#include <linux/jhash.h>
7177965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg
722a5193119269062608582418deba7af82844159aJohannes Berg#include <net/sock.h>
7377965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg#include <net/snmp.h>
742a5193119269062608582418deba7af82844159aJohannes Berg
752a5193119269062608582418deba7af82844159aJohannes Berg#include <net/ipv6.h>
760c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <net/protocol.h>
770c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <net/ndisc.h>
780c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg#include <net/ip6_route.h>
7900d3f14cf9f12c21428121026a5e1d5f65926447Johannes Berg#include <net/addrconf.h>
8000d3f14cf9f12c21428121026a5e1d5f65926447Johannes Berg#include <net/icmp.h>
810c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg
825484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#include <net/netlink.h>
83ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg#include <linux/rtnetlink.h>
84ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg
85ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg#include <net/flow.h>
86ef429dadf33feeb150098dbe84ccaa877e3261f6Johannes Berg#include <net/ip6_checksum.h>
878c358bcd097fa1f63e57fb82525ba52f4a537bfaJohannes Berg#include <linux/proc_fs.h>
88fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
89fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart#include <linux/netfilter.h>
90fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart#include <linux/netfilter_ipv6.h>
91fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
92fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct socket *ndisc_socket;
93fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
94fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic u32 ndisc_hash(const void *pkey, const struct net_device *dev);
95fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic int ndisc_constructor(struct neighbour *neigh);
96fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
97fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
98fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic int pndisc_constructor(struct pneigh_entry *n);
99fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic void pndisc_destructor(struct pneigh_entry *n);
1005484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergstatic void pndisc_redo(struct sk_buff *skb);
101fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
102fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct neigh_ops ndisc_generic_ops = {
103fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.family =		AF_INET6,
1045484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg	.solicit =		ndisc_solicit,
1053db1cd5c05f35fb43eb134df6f321de4e63141f2Rusty Russell	.error_report =		ndisc_error_report,
106fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.output =		neigh_resolve_output,
107fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.connected_output =	neigh_connected_output,
1085484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg	.hh_output =		dev_queue_xmit,
1095484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg	.queue_xmit =		dev_queue_xmit,
110f0b058b61711ebf5be94d6865ca7b2c259b71d37Stanislaw Gruszka};
111fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
112fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct neigh_ops ndisc_hh_ops = {
113fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.family =		AF_INET6,
114fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.solicit =		ndisc_solicit,
115fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.error_report =		ndisc_error_report,
116fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.output =		neigh_resolve_output,
117fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.connected_output =	neigh_resolve_output,
118fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.hh_output =		dev_queue_xmit,
119fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.queue_xmit =		dev_queue_xmit,
120fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart};
121fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
122fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
123fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstatic struct neigh_ops ndisc_direct_ops = {
124fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.family =		AF_INET6,
125fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.output =		dev_queue_xmit,
126fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.connected_output =	dev_queue_xmit,
127fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.hh_output =		dev_queue_xmit,
128fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.queue_xmit =		dev_queue_xmit,
129fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart};
130fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart
131fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewartstruct neigh_table nd_tbl = {
132fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.family =	AF_INET6,
133fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.entry_size =	sizeof(struct neighbour) + sizeof(struct in6_addr),
1345484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg	.key_len =	sizeof(struct in6_addr),
1355484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg	.hash =		ndisc_hash,
136fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.constructor =	ndisc_constructor,
137fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.pconstructor =	pndisc_constructor,
138fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.pdestructor =	pndisc_destructor,
139fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.proxy_redo =	pndisc_redo,
140fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.id =		"ndisc_cache",
141fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart	.parms = {
142fcff4f108dce0692410f390a05565f4b1b84577fPaul Stewart		.tbl =			&nd_tbl,
1435484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg		.base_reachable_time =	30 * HZ,
1445484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg		.retrans_time =	 1 * HZ,
1455484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg		.gc_staletime =	60 * HZ,
1460a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg		.reachable_time =		30 * HZ,
147d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg		.delay_probe_time =	 5 * HZ,
14898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg		.queue_len =		 3,
149f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg		.ucast_probes =	 3,
150d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg		.mcast_probes =	 3,
151d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg		.anycast_delay =	 1 * HZ,
152c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg		.proxy_delay =		(8 * HZ) / 10,
15398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg		.proxy_qlen =		64,
15498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	},
15598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	.gc_interval =	  30 * HZ,
156d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg	.gc_thresh1 =	 128,
15798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	.gc_thresh2 =	 512,
15898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	.gc_thresh3 =	1024,
159d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg};
160d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg
161d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg/* ND options */
162d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Bergstruct ndisc_options {
16398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
164d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#ifdef CONFIG_IPV6_ROUTE_INFO
165d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg	struct nd_opt_hdr *nd_opts_ri;
16698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	struct nd_opt_hdr *nd_opts_ri_end;
167d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#endif
168d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg	struct nd_opt_hdr *nd_useropts;
16998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	struct nd_opt_hdr *nd_useropts_end;
170d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg};
17198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg
172d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#define nd_opts_src_lladdr	nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
173d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#define nd_opts_tgt_lladdr	nd_opt_array[ND_OPT_TARGET_LL_ADDR]
174d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg#define nd_opts_pi		nd_opt_array[ND_OPT_PREFIX_INFO]
17598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define nd_opts_pi_end		nd_opt_array[__ND_OPT_PREFIX_INFO_END]
17698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define nd_opts_rh		nd_opt_array[ND_OPT_REDIRECT_HDR]
17798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define nd_opts_mtu		nd_opt_array[ND_OPT_MTU]
178d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg
17998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
18098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg
18198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg/*
182d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg * Return the padding between the option length and the start of the
18398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg * link addr.  Currently only IP-over-InfiniBand needs this, although
18498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
18598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg * also need a pad of 2.
186d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg */
18798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Bergstatic int ndisc_addr_option_pad(unsigned short type)
18898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg{
18998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	switch (type) {
1900172bb75073e11a5aa9d8a953bdaefb8709f00c8Johannes Berg	case ARPHRD_INFINIBAND: return 2;
19198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	default:                return 0;
19298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg	}
193d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg}
19498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg
195d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Bergstatic inline int ndisc_opt_addr_space(struct net_device *dev)
19698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg{
197d45c41722a3eca639ced2c4c93665ced229b1da9Emmanuel Grumbach	return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
198d048e503a2b01e771ee87921c24d89d7ec3f0c2fJouni Malinen}
199d48b296850f25cb559cb9b907d6d8c09eca3e89dJohannes Berg
20098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Bergstatic u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
20198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg				  unsigned short addr_type)
2024d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{
2034d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	int space = NDISC_OPT_SPACE(data_len);
2044d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	int pad   = ndisc_addr_option_pad(addr_type);
2054d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg
2064d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	opt[0] = type;
2074d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	opt[1] = space>>3;
2084d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg
2094d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	memset(opt + 2, 0, pad);
2104d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	opt   += pad;
2114d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	space -= pad;
2124d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg
2134d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	memcpy(opt+2, data, data_len);
2144d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	data_len += 2;
2154d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	opt += data_len;
2164d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	if ((space -= data_len) > 0)
2174d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg		memset(opt, 0, space);
2184d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	return opt + space;
2194d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg}
2204d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg
2214d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Bergstatic struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
2224d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg					    struct nd_opt_hdr *end)
2234d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{
2244d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	int type;
2254d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	if (!cur || !end || cur >= end)
2264d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg		return NULL;
2274d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	type = cur->nd_opt_type;
2284d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	do {
229c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg		cur = ((void *)cur) + (cur->nd_opt_len << 3);
2308ee3108075c9e9e2701493a245a754b8b0db8e57Johannes Berg	} while(cur < end && cur->nd_opt_type != type);
23185a237fe308405ee38eb9c6733571c49902ec229Johannes Berg	return (cur <= end && cur->nd_opt_type == type ? cur : NULL);
2324d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg}
233dcd83976bea3ae3bc0822ed26cf200d9d6203121Johannes Berg
2344d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Bergstatic inline int ndisc_is_useropt(struct nd_opt_hdr *opt)
2354d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{
2364d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	return (opt->nd_opt_type == ND_OPT_RDNSS);
2374d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg}
238d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg
239e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszkastatic struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur,
2400a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg					     struct nd_opt_hdr *end)
2410a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{
2420a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg	if (!cur || !end || cur >= end)
243e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka		return NULL;
2445bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg	do {
2456d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg		cur = ((void *)cur) + (cur->nd_opt_len << 3);
2466d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg	} while(cur < end && !ndisc_is_useropt(cur));
2476d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg	return (cur <= end && ndisc_is_useropt(cur) ? cur : NULL);
2486d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg}
2496d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg
2506d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Bergstatic struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
2516d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg						 struct ndisc_options *ndopts)
2526d3560d4fc9c5b9fe1a07a63926ea70512c69c32Johannes Berg{
2535bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg	struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
254e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka
255d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg	if (!nd_opt || opt_len < 0 || !ndopts)
256de95a54b1aebe5592cae971ca5e5d9ec6a381a17Johannes Berg		return NULL;
2574d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	memset(ndopts, 0, sizeof(*ndopts));
258e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	while (opt_len) {
259e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg		int l;
260e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg		if (opt_len < sizeof(struct nd_opt_hdr))
261e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg			return NULL;
262e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg		l = nd_opt->nd_opt_len << 3;
263e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg		if (opt_len < l || l == 0)
264e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg			return NULL;
2656eb11a9a311a0f7e5b9b66c18f7498a26c9ec206Stanislaw Gruszka		switch (nd_opt->nd_opt_type) {
266d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg		case ND_OPT_SOURCE_LL_ADDR:
2674d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg		case ND_OPT_TARGET_LL_ADDR:
2684d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg		case ND_OPT_MTU:
2694d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg		case ND_OPT_REDIRECT_HDR:
2704d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
271f3b85252f081581a8f257545ed748062dce7798bJohannes Berg				ND_PRINTK2(KERN_WARNING
2725ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg					   "%s(): duplicated ND6 option found: type=%d\n",
2732a5193119269062608582418deba7af82844159aJohannes Berg					   __FUNCTION__,
2742a5193119269062608582418deba7af82844159aJohannes Berg					   nd_opt->nd_opt_type);
2753aa569c3fedbd0d16041d08bf6e89b8c43aee650Johannes Berg			} else {
2762a5193119269062608582418deba7af82844159aJohannes Berg				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
277fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa			}
27858905ca5b11a0ff3860f55b789cbbf052f7158a7Johannes Berg			break;
279f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		case ND_OPT_PREFIX_INFO:
28007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg			ndopts->nd_opts_pi_end = nd_opt;
28107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg			if (!ndopts->nd_opt_array[nd_opt->nd_opt_type])
282a0daa0e7592ada797d6835f11529097aabc27ad2Luis R. Rodriguez				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
283e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka			break;
284e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka#ifdef CONFIG_IPV6_ROUTE_INFO
285e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka		case ND_OPT_ROUTE_INFO:
286aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka			ndopts->nd_opts_ri_end = nd_opt;
287e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka			if (!ndopts->nd_opts_ri)
2880a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg				ndopts->nd_opts_ri = nd_opt;
2895cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg			break;
290e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka#endif
2910a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg		default:
292469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			if (ndisc_is_useropt(nd_opt)) {
293472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg				ndopts->nd_useropts_end = nd_opt;
2942eb278e083549f4eb29838037004054b3b55df62Johannes Berg				if (!ndopts->nd_useropts)
2950a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg					ndopts->nd_useropts = nd_opt;
2968789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg			} else {
2978789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg				/*
2988789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg				 * Unknown options must be silently ignored,
2998789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg				 * to accommodate future extension to the
3008789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg				 * protocol.
3018789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg				 */
3028789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg				ND_PRINTK2(KERN_NOTICE
3038789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg					   "%s(): ignored unsupported option; type=%d, len=%d\n",
3048789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg					   __FUNCTION__,
3058789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg					   nd_opt->nd_opt_type, nd_opt->nd_opt_len);
3068789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg			}
3078789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg		}
3080a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg		opt_len -= l;
3090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg		nd_opt = ((void *)nd_opt) + l;
310f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	}
311f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	return ndopts;
312fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Berg}
313fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Berg
314fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Bergstatic inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
315fe57d9f5c0a2c1ef97ba8cdc42cfda5743f287b8Johannes Berg				      struct net_device *dev)
316f3b85252f081581a8f257545ed748062dce7798bJohannes Berg{
317f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	u8 *lladdr = (u8 *)(p + 1);
318f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	int lladdrlen = p->nd_opt_len << 3;
319f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	int prepad = ndisc_addr_option_pad(dev->type);
320f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
321f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		return NULL;
322f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	return (lladdr + prepad);
323f3b85252f081581a8f257545ed748062dce7798bJohannes Berg}
324f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
325f3b85252f081581a8f257545ed748062dce7798bJohannes Bergint ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
326f3b85252f081581a8f257545ed748062dce7798bJohannes Berg{
327f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	switch (dev->type) {
328f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	case ARPHRD_ETHER:
3292448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg	case ARPHRD_IEEE802:	/* Not sure. Check it later. --ANK */
330f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	case ARPHRD_FDDI:
331de312db345f9770b64ff39ef5a7f86f6358e93ccRajkumar Manoharan		ipv6_eth_mc_map(addr, buf);
332977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa		return 0;
333f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	case ARPHRD_IEEE802_TR:
334f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		ipv6_tr_mc_map(addr,buf);
335aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka		return 0;
336a80f7c0b088187c8471b441d461e937991870661Johannes Berg	case ARPHRD_ARCNET:
3379c35d7d2368f54313b988a01c408e5cf863ffd9eSeth Forshee		ipv6_arcnet_mc_map(addr, buf);
3389c35d7d2368f54313b988a01c408e5cf863ffd9eSeth Forshee		return 0;
3399c35d7d2368f54313b988a01c408e5cf863ffd9eSeth Forshee	case ARPHRD_INFINIBAND:
3403ac64beecd27400d12cc7afb4108eef26c499f6aJohannes Berg		ipv6_ib_mc_map(addr, dev->broadcast, buf);
341f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		return 0;
34259bdf3b0fe7a183f18ce94696259c4c76abb4568Ben Greear	default:
34359bdf3b0fe7a183f18ce94696259c4c76abb4568Ben Greear		if (dir) {
34459bdf3b0fe7a183f18ce94696259c4c76abb4568Ben Greear			memcpy(buf, dev->broadcast, dev->addr_len);
34542935ecaf4e784d0815afa9a7e5fe7e141157ca3Luis R. Rodriguez			return 0;
34607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		}
347f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	}
348f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	return -EINVAL;
349f3b85252f081581a8f257545ed748062dce7798bJohannes Berg}
350f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
351133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw GruszkaEXPORT_SYMBOL(ndisc_mc_map);
352133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka
353133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszkastatic u32 ndisc_hash(const void *pkey, const struct net_device *dev)
3542eb278e083549f4eb29838037004054b3b55df62Johannes Berg{
355133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	const u32 *p32 = pkey;
356133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	u32 addr_hash, i;
357133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka
358133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	addr_hash = 0;
359133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++)
360133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka		addr_hash ^= *p32++;
361133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka
362133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd);
363133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka}
364133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka
365133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszkastatic int ndisc_constructor(struct neighbour *neigh)
366133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka{
367133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
368133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	struct net_device *dev = neigh->dev;
369133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	struct inet6_dev *in6_dev;
370133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	struct neigh_parms *parms;
371133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	int is_multicast = ipv6_addr_is_multicast(addr);
372e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg
373e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	rcu_read_lock();
374e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	in6_dev = in6_dev_get(dev);
375e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	if (in6_dev == NULL) {
376133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka		rcu_read_unlock();
377133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka		return -EINVAL;
378133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	}
379133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka
380133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	parms = in6_dev->nd_parms;
381f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	__neigh_parms_put(neigh->parms);
3828a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	neigh->parms = neigh_parms_clone(parms);
3838a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	rcu_read_unlock();
3848a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
3858a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
386e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	if (!dev->header_ops) {
3878a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		neigh->nud_state = NUD_NOARP;
3886c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee		neigh->ops = &ndisc_direct_ops;
3896c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee		neigh->output = neigh->ops->queue_xmit;
3906c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee	} else {
3916c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee		if (is_multicast) {
3926c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee			neigh->nud_state = NUD_NOARP;
3938a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			ndisc_mc_map(addr, neigh->ha, dev, 1);
394e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg		} else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
395316b6b5df77db801d62ec381cfae0c38ff84252cPeter Senna Tschudin			neigh->nud_state = NUD_NOARP;
396e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
3978a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			if (dev->flags&IFF_LOOPBACK)
3988a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear				neigh->type = RTN_LOCAL;
3998a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		} else if (dev->flags&IFF_POINTOPOINT) {
4008a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			neigh->nud_state = NUD_NOARP;
4018a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			memcpy(neigh->ha, dev->broadcast, dev->addr_len);
4028a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		}
4038a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		if (dev->header_ops->cache)
4046c17b77b67587b9f9e3070fb89fe98cef3187131Seth Forshee			neigh->ops = &ndisc_hh_ops;
4058a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		else
4068a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			neigh->ops = &ndisc_generic_ops;
4078a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		if (neigh->nud_state&NUD_VALID)
4088a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			neigh->output = neigh->ops->connected_output;
4098a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		else
4108a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			neigh->output = neigh->ops->output;
4118a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	}
4128a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	in6_dev_put(in6_dev);
4138a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	return 0;
414f3b85252f081581a8f257545ed748062dce7798bJohannes Berg}
415f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
416f3b85252f081581a8f257545ed748062dce7798bJohannes Bergstatic int pndisc_constructor(struct pneigh_entry *n)
417f3b85252f081581a8f257545ed748062dce7798bJohannes Berg{
418f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	struct in6_addr *addr = (struct in6_addr*)&n->key;
419f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	struct in6_addr maddr;
420e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka	struct net_device *dev = n->dev;
421e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka
422f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	if (dev == NULL || __in6_dev_get(dev) == NULL)
423f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		return -EINVAL;
424f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	addrconf_addr_solict_mult(addr, &maddr);
425133d40f9a22bdfd2617a446f1e3209537c5415ecStanislaw Gruszka	ipv6_dev_mc_inc(dev, &maddr);
4266e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	return 0;
427c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Berg}
428e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg
429c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Bergstatic void pndisc_destructor(struct pneigh_entry *n)
430c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Berg{
431c0ce77b8323c1a0d4eeef97caf16c0ea971222a9Johannes Berg	struct in6_addr *addr = (struct in6_addr*)&n->key;
432f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	struct in6_addr maddr;
433f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	struct net_device *dev = n->dev;
434f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
435c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg	if (dev == NULL || __in6_dev_get(dev) == NULL)
436c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg		return;
437c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg	addrconf_addr_solict_mult(addr, &maddr);
4384d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	ipv6_dev_mc_dec(dev, &maddr);
4394d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg}
4404d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg
441c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg/*
4424d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg *	Send a Neighbour Advertisement
443f3b85252f081581a8f257545ed748062dce7798bJohannes Berg */
444f3b85252f081581a8f257545ed748062dce7798bJohannes Bergstatic void __ndisc_send(struct net_device *dev,
4454d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg			 struct neighbour *neigh,
4464d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg			 struct in6_addr *daddr, struct in6_addr *saddr,
4474d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg			 struct icmp6hdr *icmp6h, struct in6_addr *target,
4484d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg			 int llinfo)
4494d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg{
4504d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	struct flowi fl;
451cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	struct dst_entry *dst;
4524d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	struct sock *sk = ndisc_socket->sk;
4534d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	struct sk_buff *skb;
4546e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	struct icmp6hdr *hdr;
4556e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	struct inet6_dev *idev;
4566e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	int len;
4576e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	int err;
4586e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	u8 *opt, type;
4596e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville
4606e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	type = icmp6h->icmp6_type;
4616e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville
462f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	icmpv6_flow_init(ndisc_socket->sk, &fl, type,
463f3b85252f081581a8f257545ed748062dce7798bJohannes Berg			 saddr, daddr, dev->ifindex);
464f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
465e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	dst = icmp6_dst_alloc(dev, neigh, daddr);
466f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	if (!dst)
4678a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		return;
468fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa
4698a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	err = xfrm_lookup(&dst, &fl, NULL, 0);
47055de908ab292c03f1eb280f51170ddb9c6b57e31Johannes Berg	if (err < 0)
4719b8648704358e42f9865cd6de7cedb5ac0db67e7Johannes Berg		return;
4729b8648704358e42f9865cd6de7cedb5ac0db67e7Johannes Berg
4739b8648704358e42f9865cd6de7cedb5ac0db67e7Johannes Berg	if (!dev->addr_len)
4748a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		llinfo = 0;
4758a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
4768a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	len = sizeof(struct icmp6hdr) + (target ? sizeof(*target) : 0);
4778a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	if (llinfo)
4788a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		len += ndisc_opt_addr_space(dev);
4798a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
4808a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	skb = sock_alloc_send_skb(sk,
4818a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear				  (MAX_HEADER + sizeof(struct ipv6hdr) +
4828a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear				   len + LL_RESERVED_SPACE(dev)),
4838a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear				  1, &err);
4848a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	if (!skb) {
4858a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		ND_PRINTK0(KERN_ERR
4868a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			   "ICMPv6 ND: %s() failed to allocate an skb.\n",
4878a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			   __FUNCTION__);
4888a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		dst_release(dst);
4898a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		return;
4908a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	}
4918a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
4928a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	skb_reserve(skb, LL_RESERVED_SPACE(dev));
4938a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
4948a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
4958a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	skb->transport_header = skb->tail;
4968a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	skb_put(skb, len);
4978a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
4988a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	hdr = (struct icmp6hdr *)skb_transport_header(skb);
4998a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	memcpy(hdr, icmp6h, sizeof(*hdr));
5008a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
5018a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	opt = skb_transport_header(skb) + sizeof(struct icmp6hdr);
5028a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	if (target) {
5038a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		ipv6_addr_copy((struct in6_addr *)opt, target);
5048a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		opt += sizeof(*target);
505fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa	}
5068a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
5076e7e6213e4956828927c30e3ef5a42812d00c650John W. Linville	if (llinfo)
5085cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg		ndisc_fill_addr_option(opt, llinfo, dev->dev_addr,
509f3b85252f081581a8f257545ed748062dce7798bJohannes Berg				       dev->addr_len, dev->type);
5104d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg
5114d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	hdr->icmp6_cksum = csum_ipv6_magic(saddr, daddr, len,
512a060bbfe4ee95d115e8f9705a66894ac34e2c475Johannes Berg					   IPPROTO_ICMPV6,
5134d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg					   csum_partial((__u8 *) hdr,
514f3b85252f081581a8f257545ed748062dce7798bJohannes Berg							len, 0));
515f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
516f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	skb->dst = dst;
5174d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg
5184d36ec58239eec44d77839ef6c25108efcbbb58cJohannes Berg	idev = in6_dev_get(dst->dev);
519fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
520f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
5215cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
5225cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg		      dst_output);
523f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	if (!err) {
524e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg		ICMP6MSGOUT_INC_STATS(idev, type);
525f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
526f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	}
527f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
528f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	if (likely(idev != NULL))
529f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		in6_dev_put(idev);
530df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa}
531df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa
532df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaastatic void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
533df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		   struct in6_addr *daddr, struct in6_addr *solicited_addr,
534df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		   int router, int solicited, int override, int inc_opt)
535df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa{
536df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	struct in6_addr tmpaddr;
537df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	struct inet6_ifaddr *ifp;
538df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	struct in6_addr *src_addr;
539df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	struct icmp6hdr icmp6h = {
540df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
541df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	};
542e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka
543e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka	/* for anycast or proxy, solicited_addr != src_addr */
5447d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	ifp = ipv6_get_ifaddr(&init_net, solicited_addr, dev, 1);
545142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	if (ifp) {
546df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		src_addr = solicited_addr;
547df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		if (ifp->flags & IFA_F_OPTIMISTIC)
548142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa			override = 0;
549df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		in6_ifa_put(ifp);
550cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	} else {
551142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa		if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
552df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa			return;
553df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		src_addr = &tmpaddr;
554df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	}
555df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa
556df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	icmp6h.icmp6_router = router;
557142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	icmp6h.icmp6_solicited = solicited;
558142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	icmp6h.icmp6_override = override;
5599607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg
560142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	__ndisc_send(dev, neigh, daddr, src_addr,
561142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa		     &icmp6h, solicited_addr,
562142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa		     inc_opt ? ND_OPT_TARGET_LL_ADDR : 0);
563142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa}
564142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa
565df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaavoid ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
566df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		   struct in6_addr *solicit,
567df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa		   struct in6_addr *daddr, struct in6_addr *saddr)
568df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa{
569df13cce53a7b28a81460e6bfc4857e9df4956141Helmut Schaa	struct in6_addr addr_buf;
570142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	struct icmp6hdr icmp6h = {
571142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa		.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION,
572142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	};
573142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa
574142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	if (saddr == NULL) {
575b23b025fe246f3acc2988eb6d400df34c27cb8aeBen Greear		if (ipv6_get_lladdr(dev, &addr_buf,
576b23b025fe246f3acc2988eb6d400df34c27cb8aeBen Greear				   (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)))
577a80f7c0b088187c8471b441d461e937991870661Johannes Berg			return;
57807ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		saddr = &addr_buf;
57907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	}
58007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg
58107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	__ndisc_send(dev, neigh, daddr, saddr,
5823f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka		     &icmp6h, solicit,
583a80f7c0b088187c8471b441d461e937991870661Johannes Berg		     !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0);
584a80f7c0b088187c8471b441d461e937991870661Johannes Berg}
58507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg
5863f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszkavoid ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
5873f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka		   struct in6_addr *daddr)
588142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa{
589cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	struct icmp6hdr icmp6h = {
590cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler		.icmp6_type = NDISC_ROUTER_SOLICITATION,
591cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	};
592cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	int send_sllao = dev->addr_len;
593cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler
5943f892b61a8cf6a85bc389c8d13209d686a4f6403Stanislaw Gruszka#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
595cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	/*
596cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	 * According to section 2.2 of RFC 4429, we must not
597cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	 * send router solicitations with a sllao from
598cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	 * optimistic addresses, but we may send the solicitation
599cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	 * if we don't include the sllao.  So here we check
600cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	 * if our address is optimistic, and if so, we
601142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	 * suppress the inclusion of the sllao.
60207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	 */
603142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa	if (send_sllao) {
604142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa		struct inet6_ifaddr *ifp = ipv6_get_ifaddr(&init_net, saddr,
6052fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa							   dev, 1);
6062fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa		if (ifp) {
6072fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa			if (ifp->flags & IFA_F_OPTIMISTIC)  {
6082fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa				send_sllao = 0;
6092fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa			}
6102fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa			in6_ifa_put(ifp);
6117d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa		} else {
6127d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa			send_sllao = 0;
6137d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa		}
614584991dccfd347cd2e1675ab262998f6c335d3c0Johannes Berg	}
615b23b025fe246f3acc2988eb6d400df34c27cb8aeBen Greear#endif
61607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	__ndisc_send(dev, NULL, daddr, saddr,
61707ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		     &icmp6h, NULL,
6187d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa		     send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0);
6197d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa}
6207d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa
6217d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa
6220ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaastatic void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
6230ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaa{
6240ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaa	/*
6252fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa	 *	"The sender MUST return an ICMP
6260ee9c13c7c92581ab005d80795cf65897213b249Helmut Schaa	 *	 destination unreachable"
6277d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	 */
6287d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	dst_link_failure(skb);
6297d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	kfree_skb(skb);
6307d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa}
6317d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa
6327d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa/* Called with locked neigh: either read or both */
6337d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa
6347d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaastatic void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
6357d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa{
6367d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	struct in6_addr *saddr = NULL;
6377d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	struct in6_addr mcaddr;
6387d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	struct net_device *dev = neigh->dev;
6397d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
6407d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa	int probes = atomic_read(&neigh->probes);
641977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa
6422fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa	if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1))
6437d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa		saddr = &ipv6_hdr(skb)->saddr;
6447d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa
6452fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa	if ((probes -= neigh->parms->ucast_probes) < 0) {
6467d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa		if (!(neigh->nud_state & NUD_VALID)) {
647977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa			ND_PRINTK1(KERN_DEBUG
6487d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa				   "%s(): trying to ucast probe in NUD_INVALID: "
6497d3be3cc489176bc7bd23e673b0b4aef597af2b3Helmut Schaa				   NIP6_FMT "\n",
65007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg				   __FUNCTION__,
65107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg				   NIP6(*target));
65207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		}
65307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		ndisc_send_ns(dev, neigh, target, target, saddr);
65407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	} else if ((probes -= neigh->parms->app_probes) < 0) {
65507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg#ifdef CONFIG_ARPD
65607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		neigh_app_ns(neigh);
657aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka#endif
658aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka	} else {
65907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		addrconf_addr_solict_mult(target, &mcaddr);
66007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
66107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	}
66207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg}
66307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg
66407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Bergstatic void ndisc_recv_ns(struct sk_buff *skb)
66507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg{
66607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
66707ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
668aacde9ee45225f7e0b90960f479aef83c66bfdc0Stanislaw Gruszka	struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
66907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	u8 *lladdr = NULL;
67007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	u32 ndoptlen = skb->tail - (skb->transport_header +
67107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg				    offsetof(struct nd_msg, opt));
67207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct ndisc_options ndopts;
67307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct net_device *dev = skb->dev;
67407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct inet6_ifaddr *ifp;
67507ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct inet6_dev *idev = NULL;
67607ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct neighbour *neigh;
67707ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	struct pneigh_entry *pneigh = NULL;
67807ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	int dad = ipv6_addr_any(saddr);
67907ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	int inc;
680de2ee84db6a0201278e35590821cd014cb71830aMohammed Shafi Shajakhan	int is_router;
68107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg
68207ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg	if (ipv6_addr_is_multicast(&msg->target)) {
683c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg		ND_PRINTK2(KERN_WARNING
6840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg			   "ICMPv6 NS: multicast target address");
6850a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg		return;
6860a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg	}
687d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg
6880a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg	/*
689d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg	 * RFC2461 7.1.1:
6900a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg	 * DAD has to be destined for solicited node multicast address.
691259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka	 */
6928789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg	if (dad &&
693e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	    !(daddr->s6_addr32[0] == htonl(0xff020000) &&
694e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg	      daddr->s6_addr32[1] == htonl(0x00000000) &&
695d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg	      daddr->s6_addr32[2] == htonl(0x00000001) &&
6968a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	      daddr->s6_addr [12] == 0xff )) {
6978a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		ND_PRINTK2(KERN_WARNING
6988a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear			   "ICMPv6 NS: bad DAD packet (wrong destination)\n");
6998a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear		return;
7008a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear	}
7018a690674e0601efbe9a7b16a5826fc522645cca3Ben Greear
702259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
7038789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg		ND_PRINTK2(KERN_WARNING
704259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka			   "ICMPv6 NS: invalid ND options\n");
7058789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg		return;
7068789d459bc5e837bf37d261453df96ef54018d7bJohannes Berg	}
707259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka
708259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka	if (ndopts.nd_opts_src_lladdr) {
709f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
710fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa		if (!lladdr) {
711f3b85252f081581a8f257545ed748062dce7798bJohannes Berg			ND_PRINTK2(KERN_WARNING
712f3b85252f081581a8f257545ed748062dce7798bJohannes Berg				   "ICMPv6 NS: invalid link-layer address length\n");
713f3b85252f081581a8f257545ed748062dce7798bJohannes Berg			return;
714f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		}
715e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg
716f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		/* RFC2461 7.1.1:
717f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		 *	If the IP source address is the unspecified address,
718259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka		 *	there MUST NOT be source link-layer address option
7193aed49ef17c7bc8397420529ac976fe058818e3dStanislaw Gruszka		 *	in the message.
7203aed49ef17c7bc8397420529ac976fe058818e3dStanislaw Gruszka		 */
721259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka		if (dad) {
722259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka			ND_PRINTK2(KERN_WARNING
723259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka				   "ICMPv6 NS: bad DAD packet (link-layer address option)\n");
724259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka			return;
725f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		}
726f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	}
7275bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg
7285bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg	inc = ipv6_addr_is_multicast(daddr);
7295bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg
7309607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg	if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1)) != NULL) {
731259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka
732259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka		if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
733f3b85252f081581a8f257545ed748062dce7798bJohannes Berg			if (dad) {
7340a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg				if (dev->type == ARPHRD_IEEE802_TR) {
735f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa					const unsigned char *sadr;
736f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa					sadr = skb_mac_header(skb);
737f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa					if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 &&
738f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa					    sadr[9] == dev->dev_addr[1] &&
739f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa					    sadr[10] == dev->dev_addr[2] &&
740c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan					    sadr[11] == dev->dev_addr[3] &&
741c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan					    sadr[12] == dev->dev_addr[4] &&
742c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan					    sadr[13] == dev->dev_addr[5]) {
743c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan						/* looped-back to us */
744c29acf201007a6d73223f864f52406eb5ba19933Rajkumar Manoharan						goto out;
745977923b00c79185c11b4b47664f5ffa4c3820438Helmut Schaa					}
7462fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa				}
747e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka
748e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka				/*
749e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka				 * We are colliding with another node
750e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka				 * who is doing DAD
751e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka				 * so fail our DAD process
752e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka				 */
753f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa				addrconf_dad_failure(ifp);
7542fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa				return;
7552fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa			} else {
7562fb3f028a9a46bd344329766257699b4acb36525Helmut Schaa				/*
757f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa				 * This is not a dad solicitation.
758f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa				 * If we are an optimistic node,
759f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa				 * we should respond.
76007ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg				 * Otherwise, we should ignore it.
76107ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg				 */
762142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa				if (!(ifp->flags & IFA_F_OPTIMISTIC))
76307ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg					goto out;
76407ef03ee8b280a536b38ccfe512b9556996f0492Johannes Berg			}
765142b9f5074dc0d09dc0025739ad437723d7bf527Helmut Schaa		}
766cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler
767cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler		idev = ifp->idev;
768cd2bb512cda58f1efb922ad6dc29013ea5d5d9d0Sam Leffler	} else {
769f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa		idev = in6_dev_get(dev);
770f502d09b750437a4ec9c63333acf1070fe7958afHelmut Schaa		if (!idev) {
7710a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg			/* XXX: count this drop? */
77242935ecaf4e784d0815afa9a7e5fe7e141157ca3Luis R. Rodriguez			return;
773d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg		}
774259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka
775259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka		if (ipv6_chk_acast_addr(dev, &msg->target) ||
776e229f844d7223b7063bea1e649203ac521a58fe1Stanislaw Gruszka		    (idev->cnf.forwarding &&
777d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg		     (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
778259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka		     (pneigh = pneigh_lookup(&nd_tbl, &init_net,
779259b62e35bf44a97983f275de569929a7d2bd5ddStanislaw Gruszka					     &msg->target, dev, 0)) != NULL)) {
7800a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg			if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
7810a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg			    skb->pkt_type != PACKET_HOST &&
782f3b85252f081581a8f257545ed748062dce7798bJohannes Berg			    inc != 0 &&
783f3b85252f081581a8f257545ed748062dce7798bJohannes Berg			    idev->nd_parms->proxy_delay != 0) {
7840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg				/*
785f3b85252f081581a8f257545ed748062dce7798bJohannes Berg				 * for anycast or proxy,
786de95a54b1aebe5592cae971ca5e5d9ec6a381a17Johannes Berg				 * sender should delay its response
787a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg				 * by a random time between 0 and
788f3b85252f081581a8f257545ed748062dce7798bJohannes Berg				 * MAX_ANYCAST_DELAY_TIME seconds.
789a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg				 * (RFC2461) -- yoshfuji
7900a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg				 */
791f3b85252f081581a8f257545ed748062dce7798bJohannes Berg				struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
7920a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg				if (n)
7930a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg					pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
79434bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka				goto out;
79534bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka			}
79634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka		} else
7970a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg			goto out;
7980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg	}
799f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
800fb63bc41772259701a827e9a6117219a7393554fGertjan van Wingerde	is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding);
8012a5193119269062608582418deba7af82844159aJohannes Berg
802a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg	if (dad) {
8030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg		struct in6_addr maddr;
804f3b85252f081581a8f257545ed748062dce7798bJohannes Berg
805f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		ipv6_addr_all_nodes(&maddr);
806f3b85252f081581a8f257545ed748062dce7798bJohannes Berg		ndisc_send_na(dev, NULL, &maddr, &msg->target,
8079116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg			      is_router, 0, (ifp != NULL), 1);
808be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg		goto out;
809be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	}
81034bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka
81134bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	if (inc)
812be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
813be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	else
814be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
815be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg
81634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	/*
81734bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	 *	update / create cache entry
81834bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	 *	for the source address
81934bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	 */
820be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	neigh = __neigh_lookup(&nd_tbl, saddr, dev,
82134bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka			       !inc || lladdr || !dev->addr_len);
82234bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	if (neigh)
82334bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka		neigh_update(neigh, lladdr, NUD_STALE,
82434bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
82534bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka			     NEIGH_UPDATE_F_OVERRIDE);
82634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	if (neigh || !dev->header_ops) {
82734bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka		ndisc_send_na(dev, neigh, saddr, &msg->target,
828be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg			      is_router,
829be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg			      1, (ifp != NULL && inc), inc);
830be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg		if (neigh)
83134bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka			neigh_release(neigh);
83234bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	}
83334bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka
83434bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszkaout:
835be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	if (ifp)
83634bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka		in6_ifa_put(ifp);
83734bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka	else
83834bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka		in6_dev_put(idev);
83934bcf71502413f8903ade93746f2d0f04b937a78Stanislaw Gruszka
840be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	return;
841be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg}
842be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg
843be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Bergstatic void ndisc_recv_na(struct sk_buff *skb)
844be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg{
845be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
8465ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg	struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
8475ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg	struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
8489116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg	u8 *lladdr = NULL;
8495ba63533bbf653631faab60f6988506160ec6ba4Johannes Berg	u32 ndoptlen = skb->tail - (skb->transport_header +
850f3b85252f081581a8f257545ed748062dce7798bJohannes Berg				    offsetof(struct nd_msg, opt));
851a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg	struct ndisc_options ndopts;
852f3b85252f081581a8f257545ed748062dce7798bJohannes Berg	struct net_device *dev = skb->dev;
8530a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg	struct inet6_ifaddr *ifp;
8545bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	struct neighbour *neigh;
8554136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka
8564136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka	if (skb->len < sizeof(struct nd_msg)) {
8574136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka		ND_PRINTK2(KERN_WARNING
8585bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg			   "ICMPv6 NA: packet too short\n");
8595bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		return;
8605bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	}
861b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller
8624136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka	if (ipv6_addr_is_multicast(&msg->target)) {
8634136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka		ND_PRINTK2(KERN_WARNING
8644136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka			   "ICMPv6 NA: target address is multicast.\n");
8654136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka		return;
8664136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka	}
8674136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka
8684136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka	if (ipv6_addr_is_multicast(daddr) &&
8694136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka	    msg->icmph.icmp6_solicited) {
8704136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka		ND_PRINTK2(KERN_WARNING
8714136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka			   "ICMPv6 NA: solicited NA is multicasted.\n");
8724136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka		return;
873b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller	}
874b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller
875b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
8765bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		ND_PRINTK2(KERN_WARNING
8774136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka			   "ICMPv6 NS: invalid ND option\n");
878a1699b75a1db31a1da2f0fc610ee696d02a19280Johannes Berg		return;
879b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller	}
880b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller	if (ndopts.nd_opts_tgt_lladdr) {
881b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
882b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		if (!lladdr) {
883b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller			ND_PRINTK2(KERN_WARNING
884e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg				   "ICMPv6 NA: invalid link-layer address length\n");
885e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg			return;
886e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68aJohannes Berg		}
887b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller	}
8884136c4224ccf1907d309e1cdfaefef9da97dbc5eStanislaw Gruszka	if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1))) {
889b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		if (ifp->flags & IFA_F_TENTATIVE) {
890b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller			addrconf_dad_failure(ifp);
891b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller			return;
892b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		}
893b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		/* What should we make now? The advertisement
894b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		   is invalid, but ndisc specs say nothing
895b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		   about it. It could be misconfiguration, or
896b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		   an smart proxy agent tries to help us :-)
897b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		 */
898b856439b1b54358e580aaee5dbe683af5ada9403Eliad Peller		ND_PRINTK1(KERN_WARNING
899d07bfd8b6f20a81d7ec65c50f35b053d9e3aa740Johannes Berg			   "ICMPv6 NA: someone advertises our address on %s!\n",
9005bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg			   ifp->idev->dev->name);
90179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		in6_ifa_put(ifp);
90279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		return;
90379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	}
90479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
90579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
906bca1e29fb54c51856dda6772d488d41b10ed91daDavid Spinadel	if (neigh) {
907c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg		u8 old_flags = neigh->flags;
908c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg
909c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg		if (neigh->nud_state & NUD_FAILED)
910c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg			goto out;
91179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
9125260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg		/*
91379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		 * Don't update the neighbor cache entry on a proxy NA from
9145260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg		 * ourselves because either the proxied node is off link or it
91579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		 * has already sent a NA to us.
91679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		 */
91779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
91879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		    ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
91979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		    pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) {
92079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho			/* XXX: idev->cnf.prixy_ndp */
92179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho			goto out;
92279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		}
92379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
92479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		neigh_update(neigh, lladdr,
925d811b3d5566f1441b321a1219c260124b209e0bdArik Nemtsov			     msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
926d811b3d5566f1441b321a1219c260124b209e0bdArik Nemtsov			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
927d811b3d5566f1441b321a1219c260124b209e0bdArik Nemtsov			     (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
928c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
92930dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg			     (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
93079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
93179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
93279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho			/*
93379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho			 * Change: router to host
93430dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg			 */
93530dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg			struct rt6_info *rt;
936c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg			rt = rt6_get_dflt_router(saddr, dev);
937c604b9f219422e969fe371cc7259de34c3c5601dJohannes Berg			if (rt)
93879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho				ip6_del_rt(rt);
93979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		}
94030dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg
94130dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Bergout:
9425260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg		neigh_release(neigh);
94379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	}
94479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho}
94579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
94630dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Bergstatic void ndisc_recv_rs(struct sk_buff *skb)
94779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho{
9485260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg	struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb);
94979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
95079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	struct neighbour *neigh;
95179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	struct inet6_dev *idev;
95285a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho	struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
95379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	struct ndisc_options ndopts;
95479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	u8 *lladdr = NULL;
95530dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg
95679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	if (skb->len < sizeof(*rs_msg))
9575260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg		return;
95879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
95979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	idev = in6_dev_get(skb->dev);
96079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	if (!idev) {
96179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		if (net_ratelimit())
96279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho			ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
96379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		return;
96430dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg	}
96585a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho
96630dd3edf97abda301150c8cf26fed21e53e3a9ceJohannes Berg	/* Don't accept RS if we're not in router mode */
96779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	if (!idev->cnf.forwarding)
9685260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg		goto out;
96979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
97079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	/*
97179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	 * Don't update NCE if src = ::;
97279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	 * this implies that the source node has no ip address assigned yet.
97379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	 */
97479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	if (ipv6_addr_any(saddr))
97579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		goto out;
97679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho
97779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	/* Parse ND options */
97879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
97979f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		if (net_ratelimit())
98079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho			ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n");
98179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho		goto out;
98279f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	}
98385a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho
98485a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho	if (ndopts.nd_opts_src_lladdr) {
98585a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
98685a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho					     skb->dev);
98785a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho		if (!lladdr)
98885a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho			goto out;
98985a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho	}
99085a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho
9915260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg	neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
99285a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho	if (neigh) {
99385a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho		neigh_update(neigh, lladdr, NUD_STALE,
99485a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
99585a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho			     NEIGH_UPDATE_F_OVERRIDE|
9965260a5b2c3524f198ea062fe0a6a4faa724e6a9dJohannes Berg			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
99785a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho		neigh_release(neigh);
99885a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho	}
99985a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelhoout:
100085a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho	in6_dev_put(idev);
100185a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho}
100285a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho
100379f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelhostatic void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
100479f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho{
100579f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	struct icmp6hdr *icmp6h = (struct icmp6hdr *)skb_transport_header(ra);
100679f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	struct sk_buff *skb;
100779f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	struct nlmsghdr *nlh;
100879f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	struct nduseroptmsg *ndmsg;
100985a9994a0a6cba1a6cc6af4bd3ebd85f778be0feLuciano Coelho	int err;
101079f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho	int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg)
101179f460ca49d8d5700756ab7071c951311c7f29ccLuciano Coelho				    + (opt->nd_opt_len << 3));
1012	size_t msg_size = base_size + nla_total_size(sizeof(struct in6_addr));
1013
1014	skb = nlmsg_new(msg_size, GFP_ATOMIC);
1015	if (skb == NULL) {
1016		err = -ENOBUFS;
1017		goto errout;
1018	}
1019
1020	nlh = nlmsg_put(skb, 0, 0, RTM_NEWNDUSEROPT, base_size, 0);
1021	if (nlh == NULL) {
1022		goto nla_put_failure;
1023	}
1024
1025	ndmsg = nlmsg_data(nlh);
1026	ndmsg->nduseropt_family = AF_INET6;
1027	ndmsg->nduseropt_ifindex = ra->dev->ifindex;
1028	ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type;
1029	ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code;
1030	ndmsg->nduseropt_opts_len = opt->nd_opt_len << 3;
1031
1032	memcpy(ndmsg + 1, opt, opt->nd_opt_len << 3);
1033
1034	NLA_PUT(skb, NDUSEROPT_SRCADDR, sizeof(struct in6_addr),
1035		&ipv6_hdr(ra)->saddr);
1036	nlmsg_end(skb, nlh);
1037
1038	err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL,
1039			  GFP_ATOMIC);
1040	if (err < 0)
1041		goto errout;
1042
1043	return;
1044
1045nla_put_failure:
1046	nlmsg_free(skb);
1047	err = -EMSGSIZE;
1048errout:
1049	rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err);
1050}
1051
1052static void ndisc_router_discovery(struct sk_buff *skb)
1053{
1054	struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
1055	struct neighbour *neigh = NULL;
1056	struct inet6_dev *in6_dev;
1057	struct rt6_info *rt = NULL;
1058	int lifetime;
1059	struct ndisc_options ndopts;
1060	int optlen;
1061	unsigned int pref = 0;
1062
1063	__u8 * opt = (__u8 *)(ra_msg + 1);
1064
1065	optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg);
1066
1067	if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
1068		ND_PRINTK2(KERN_WARNING
1069			   "ICMPv6 RA: source address is not link-local.\n");
1070		return;
1071	}
1072	if (optlen < 0) {
1073		ND_PRINTK2(KERN_WARNING
1074			   "ICMPv6 RA: packet too short\n");
1075		return;
1076	}
1077
1078	/*
1079	 *	set the RA_RECV flag in the interface
1080	 */
1081
1082	in6_dev = in6_dev_get(skb->dev);
1083	if (in6_dev == NULL) {
1084		ND_PRINTK0(KERN_ERR
1085			   "ICMPv6 RA: can't find inet6 device for %s.\n",
1086			   skb->dev->name);
1087		return;
1088	}
1089	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
1090		in6_dev_put(in6_dev);
1091		return;
1092	}
1093
1094	if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1095		in6_dev_put(in6_dev);
1096		ND_PRINTK2(KERN_WARNING
1097			   "ICMP6 RA: invalid ND options\n");
1098		return;
1099	}
1100
1101	if (in6_dev->if_flags & IF_RS_SENT) {
1102		/*
1103		 *	flag that an RA was received after an RS was sent
1104		 *	out on this interface.
1105		 */
1106		in6_dev->if_flags |= IF_RA_RCVD;
1107	}
1108
1109	/*
1110	 * Remember the managed/otherconf flags from most recently
1111	 * received RA message (RFC 2462) -- yoshfuji
1112	 */
1113	in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
1114				IF_RA_OTHERCONF)) |
1115				(ra_msg->icmph.icmp6_addrconf_managed ?
1116					IF_RA_MANAGED : 0) |
1117				(ra_msg->icmph.icmp6_addrconf_other ?
1118					IF_RA_OTHERCONF : 0);
1119
1120	if (!in6_dev->cnf.accept_ra_defrtr)
1121		goto skip_defrtr;
1122
1123	lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
1124
1125#ifdef CONFIG_IPV6_ROUTER_PREF
1126	pref = ra_msg->icmph.icmp6_router_pref;
1127	/* 10b is handled as if it were 00b (medium) */
1128	if (pref == ICMPV6_ROUTER_PREF_INVALID ||
1129	    !in6_dev->cnf.accept_ra_rtr_pref)
1130		pref = ICMPV6_ROUTER_PREF_MEDIUM;
1131#endif
1132
1133	rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
1134
1135	if (rt)
1136		neigh = rt->rt6i_nexthop;
1137
1138	if (rt && lifetime == 0) {
1139		neigh_clone(neigh);
1140		ip6_del_rt(rt);
1141		rt = NULL;
1142	}
1143
1144	if (rt == NULL && lifetime) {
1145		ND_PRINTK3(KERN_DEBUG
1146			   "ICMPv6 RA: adding default router.\n");
1147
1148		rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref);
1149		if (rt == NULL) {
1150			ND_PRINTK0(KERN_ERR
1151				   "ICMPv6 RA: %s() failed to add default route.\n",
1152				   __FUNCTION__);
1153			in6_dev_put(in6_dev);
1154			return;
1155		}
1156
1157		neigh = rt->rt6i_nexthop;
1158		if (neigh == NULL) {
1159			ND_PRINTK0(KERN_ERR
1160				   "ICMPv6 RA: %s() got default router without neighbour.\n",
1161				   __FUNCTION__);
1162			dst_release(&rt->u.dst);
1163			in6_dev_put(in6_dev);
1164			return;
1165		}
1166		neigh->flags |= NTF_ROUTER;
1167	} else if (rt) {
1168		rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
1169	}
1170
1171	if (rt)
1172		rt->rt6i_expires = jiffies + (HZ * lifetime);
1173
1174	if (ra_msg->icmph.icmp6_hop_limit) {
1175		in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1176		if (rt)
1177			rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
1178	}
1179
1180skip_defrtr:
1181
1182	/*
1183	 *	Update Reachable Time and Retrans Timer
1184	 */
1185
1186	if (in6_dev->nd_parms) {
1187		unsigned long rtime = ntohl(ra_msg->retrans_timer);
1188
1189		if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
1190			rtime = (rtime*HZ)/1000;
1191			if (rtime < HZ/10)
1192				rtime = HZ/10;
1193			in6_dev->nd_parms->retrans_time = rtime;
1194			in6_dev->tstamp = jiffies;
1195			inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1196		}
1197
1198		rtime = ntohl(ra_msg->reachable_time);
1199		if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
1200			rtime = (rtime*HZ)/1000;
1201
1202			if (rtime < HZ/10)
1203				rtime = HZ/10;
1204
1205			if (rtime != in6_dev->nd_parms->base_reachable_time) {
1206				in6_dev->nd_parms->base_reachable_time = rtime;
1207				in6_dev->nd_parms->gc_staletime = 3 * rtime;
1208				in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
1209				in6_dev->tstamp = jiffies;
1210				inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1211			}
1212		}
1213	}
1214
1215	/*
1216	 *	Process options.
1217	 */
1218
1219	if (!neigh)
1220		neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr,
1221				       skb->dev, 1);
1222	if (neigh) {
1223		u8 *lladdr = NULL;
1224		if (ndopts.nd_opts_src_lladdr) {
1225			lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1226						     skb->dev);
1227			if (!lladdr) {
1228				ND_PRINTK2(KERN_WARNING
1229					   "ICMPv6 RA: invalid link-layer address length\n");
1230				goto out;
1231			}
1232		}
1233		neigh_update(neigh, lladdr, NUD_STALE,
1234			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
1235			     NEIGH_UPDATE_F_OVERRIDE|
1236			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
1237			     NEIGH_UPDATE_F_ISROUTER);
1238	}
1239
1240#ifdef CONFIG_IPV6_ROUTE_INFO
1241	if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
1242		struct nd_opt_hdr *p;
1243		for (p = ndopts.nd_opts_ri;
1244		     p;
1245		     p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
1246			if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
1247				continue;
1248			rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
1249				      &ipv6_hdr(skb)->saddr);
1250		}
1251	}
1252#endif
1253
1254	if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
1255		struct nd_opt_hdr *p;
1256		for (p = ndopts.nd_opts_pi;
1257		     p;
1258		     p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
1259			addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3);
1260		}
1261	}
1262
1263	if (ndopts.nd_opts_mtu) {
1264		__be32 n;
1265		u32 mtu;
1266
1267		memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
1268		mtu = ntohl(n);
1269
1270		if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
1271			ND_PRINTK2(KERN_WARNING
1272				   "ICMPv6 RA: invalid mtu: %d\n",
1273				   mtu);
1274		} else if (in6_dev->cnf.mtu6 != mtu) {
1275			in6_dev->cnf.mtu6 = mtu;
1276
1277			if (rt)
1278				rt->u.dst.metrics[RTAX_MTU-1] = mtu;
1279
1280			rt6_mtu_change(skb->dev, mtu);
1281		}
1282	}
1283
1284	if (ndopts.nd_useropts) {
1285		struct nd_opt_hdr *p;
1286		for (p = ndopts.nd_useropts;
1287		     p;
1288		     p = ndisc_next_useropt(p, ndopts.nd_useropts_end)) {
1289			ndisc_ra_useropt(skb, p);
1290		}
1291	}
1292
1293	if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
1294		ND_PRINTK2(KERN_WARNING
1295			   "ICMPv6 RA: invalid RA options");
1296	}
1297out:
1298	if (rt)
1299		dst_release(&rt->u.dst);
1300	else if (neigh)
1301		neigh_release(neigh);
1302	in6_dev_put(in6_dev);
1303}
1304
1305static void ndisc_redirect_rcv(struct sk_buff *skb)
1306{
1307	struct inet6_dev *in6_dev;
1308	struct icmp6hdr *icmph;
1309	struct in6_addr *dest;
1310	struct in6_addr *target;	/* new first hop to destination */
1311	struct neighbour *neigh;
1312	int on_link = 0;
1313	struct ndisc_options ndopts;
1314	int optlen;
1315	u8 *lladdr = NULL;
1316
1317	if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
1318		ND_PRINTK2(KERN_WARNING
1319			   "ICMPv6 Redirect: source address is not link-local.\n");
1320		return;
1321	}
1322
1323	optlen = skb->tail - skb->transport_header;
1324	optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1325
1326	if (optlen < 0) {
1327		ND_PRINTK2(KERN_WARNING
1328			   "ICMPv6 Redirect: packet too short\n");
1329		return;
1330	}
1331
1332	icmph = icmp6_hdr(skb);
1333	target = (struct in6_addr *) (icmph + 1);
1334	dest = target + 1;
1335
1336	if (ipv6_addr_is_multicast(dest)) {
1337		ND_PRINTK2(KERN_WARNING
1338			   "ICMPv6 Redirect: destination address is multicast.\n");
1339		return;
1340	}
1341
1342	if (ipv6_addr_equal(dest, target)) {
1343		on_link = 1;
1344	} else if (ipv6_addr_type(target) !=
1345		   (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
1346		ND_PRINTK2(KERN_WARNING
1347			   "ICMPv6 Redirect: target address is not link-local unicast.\n");
1348		return;
1349	}
1350
1351	in6_dev = in6_dev_get(skb->dev);
1352	if (!in6_dev)
1353		return;
1354	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
1355		in6_dev_put(in6_dev);
1356		return;
1357	}
1358
1359	/* RFC2461 8.1:
1360	 *	The IP source address of the Redirect MUST be the same as the current
1361	 *	first-hop router for the specified ICMP Destination Address.
1362	 */
1363
1364	if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
1365		ND_PRINTK2(KERN_WARNING
1366			   "ICMPv6 Redirect: invalid ND options\n");
1367		in6_dev_put(in6_dev);
1368		return;
1369	}
1370	if (ndopts.nd_opts_tgt_lladdr) {
1371		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
1372					     skb->dev);
1373		if (!lladdr) {
1374			ND_PRINTK2(KERN_WARNING
1375				   "ICMPv6 Redirect: invalid link-layer address length\n");
1376			in6_dev_put(in6_dev);
1377			return;
1378		}
1379	}
1380
1381	neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
1382	if (neigh) {
1383		rt6_redirect(dest, &ipv6_hdr(skb)->daddr,
1384			     &ipv6_hdr(skb)->saddr, neigh, lladdr,
1385			     on_link);
1386		neigh_release(neigh);
1387	}
1388	in6_dev_put(in6_dev);
1389}
1390
1391void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1392			 struct in6_addr *target)
1393{
1394	struct sock *sk = ndisc_socket->sk;
1395	int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1396	struct sk_buff *buff;
1397	struct icmp6hdr *icmph;
1398	struct in6_addr saddr_buf;
1399	struct in6_addr *addrp;
1400	struct net_device *dev;
1401	struct rt6_info *rt;
1402	struct dst_entry *dst;
1403	struct inet6_dev *idev;
1404	struct flowi fl;
1405	u8 *opt;
1406	int rd_len;
1407	int err;
1408	int hlen;
1409	u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
1410
1411	dev = skb->dev;
1412
1413	if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) {
1414		ND_PRINTK2(KERN_WARNING
1415			   "ICMPv6 Redirect: no link-local address on %s\n",
1416			   dev->name);
1417		return;
1418	}
1419
1420	if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
1421	    ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
1422		ND_PRINTK2(KERN_WARNING
1423			"ICMPv6 Redirect: target address is not link-local unicast.\n");
1424		return;
1425	}
1426
1427	icmpv6_flow_init(ndisc_socket->sk, &fl, NDISC_REDIRECT,
1428			 &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex);
1429
1430	dst = ip6_route_output(NULL, &fl);
1431	if (dst == NULL)
1432		return;
1433
1434	err = xfrm_lookup(&dst, &fl, NULL, 0);
1435	if (err)
1436		return;
1437
1438	rt = (struct rt6_info *) dst;
1439
1440	if (rt->rt6i_flags & RTF_GATEWAY) {
1441		ND_PRINTK2(KERN_WARNING
1442			   "ICMPv6 Redirect: destination is not a neighbour.\n");
1443		dst_release(dst);
1444		return;
1445	}
1446	if (!xrlim_allow(dst, 1*HZ)) {
1447		dst_release(dst);
1448		return;
1449	}
1450
1451	if (dev->addr_len) {
1452		read_lock_bh(&neigh->lock);
1453		if (neigh->nud_state & NUD_VALID) {
1454			memcpy(ha_buf, neigh->ha, dev->addr_len);
1455			read_unlock_bh(&neigh->lock);
1456			ha = ha_buf;
1457			len += ndisc_opt_addr_space(dev);
1458		} else
1459			read_unlock_bh(&neigh->lock);
1460	}
1461
1462	rd_len = min_t(unsigned int,
1463		     IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, skb->len + 8);
1464	rd_len &= ~0x7;
1465	len += rd_len;
1466
1467	buff = sock_alloc_send_skb(sk,
1468				   (MAX_HEADER + sizeof(struct ipv6hdr) +
1469				    len + LL_RESERVED_SPACE(dev)),
1470				   1, &err);
1471	if (buff == NULL) {
1472		ND_PRINTK0(KERN_ERR
1473			   "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
1474			   __FUNCTION__);
1475		dst_release(dst);
1476		return;
1477	}
1478
1479	hlen = 0;
1480
1481	skb_reserve(buff, LL_RESERVED_SPACE(dev));
1482	ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr,
1483		   IPPROTO_ICMPV6, len);
1484
1485	skb_set_transport_header(buff, skb_tail_pointer(buff) - buff->data);
1486	skb_put(buff, len);
1487	icmph = icmp6_hdr(buff);
1488
1489	memset(icmph, 0, sizeof(struct icmp6hdr));
1490	icmph->icmp6_type = NDISC_REDIRECT;
1491
1492	/*
1493	 *	copy target and destination addresses
1494	 */
1495
1496	addrp = (struct in6_addr *)(icmph + 1);
1497	ipv6_addr_copy(addrp, target);
1498	addrp++;
1499	ipv6_addr_copy(addrp, &ipv6_hdr(skb)->daddr);
1500
1501	opt = (u8*) (addrp + 1);
1502
1503	/*
1504	 *	include target_address option
1505	 */
1506
1507	if (ha)
1508		opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha,
1509					     dev->addr_len, dev->type);
1510
1511	/*
1512	 *	build redirect option and copy skb over to the new packet.
1513	 */
1514
1515	memset(opt, 0, 8);
1516	*(opt++) = ND_OPT_REDIRECT_HDR;
1517	*(opt++) = (rd_len >> 3);
1518	opt += 6;
1519
1520	memcpy(opt, ipv6_hdr(skb), rd_len - 8);
1521
1522	icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr,
1523					     len, IPPROTO_ICMPV6,
1524					     csum_partial((u8 *) icmph, len, 0));
1525
1526	buff->dst = dst;
1527	idev = in6_dev_get(dst->dev);
1528	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
1529	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
1530		      dst_output);
1531	if (!err) {
1532		ICMP6MSGOUT_INC_STATS(idev, NDISC_REDIRECT);
1533		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
1534	}
1535
1536	if (likely(idev != NULL))
1537		in6_dev_put(idev);
1538}
1539
1540static void pndisc_redo(struct sk_buff *skb)
1541{
1542	ndisc_recv_ns(skb);
1543	kfree_skb(skb);
1544}
1545
1546int ndisc_rcv(struct sk_buff *skb)
1547{
1548	struct nd_msg *msg;
1549
1550	if (!pskb_may_pull(skb, skb->len))
1551		return 0;
1552
1553	msg = (struct nd_msg *)skb_transport_header(skb);
1554
1555	__skb_push(skb, skb->data - skb_transport_header(skb));
1556
1557	if (ipv6_hdr(skb)->hop_limit != 255) {
1558		ND_PRINTK2(KERN_WARNING
1559			   "ICMPv6 NDISC: invalid hop-limit: %d\n",
1560			   ipv6_hdr(skb)->hop_limit);
1561		return 0;
1562	}
1563
1564	if (msg->icmph.icmp6_code != 0) {
1565		ND_PRINTK2(KERN_WARNING
1566			   "ICMPv6 NDISC: invalid ICMPv6 code: %d\n",
1567			   msg->icmph.icmp6_code);
1568		return 0;
1569	}
1570
1571	memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
1572
1573	switch (msg->icmph.icmp6_type) {
1574	case NDISC_NEIGHBOUR_SOLICITATION:
1575		ndisc_recv_ns(skb);
1576		break;
1577
1578	case NDISC_NEIGHBOUR_ADVERTISEMENT:
1579		ndisc_recv_na(skb);
1580		break;
1581
1582	case NDISC_ROUTER_SOLICITATION:
1583		ndisc_recv_rs(skb);
1584		break;
1585
1586	case NDISC_ROUTER_ADVERTISEMENT:
1587		ndisc_router_discovery(skb);
1588		break;
1589
1590	case NDISC_REDIRECT:
1591		ndisc_redirect_rcv(skb);
1592		break;
1593	}
1594
1595	return 0;
1596}
1597
1598static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1599{
1600	struct net_device *dev = ptr;
1601
1602	if (dev->nd_net != &init_net)
1603		return NOTIFY_DONE;
1604
1605	switch (event) {
1606	case NETDEV_CHANGEADDR:
1607		neigh_changeaddr(&nd_tbl, dev);
1608		fib6_run_gc(~0UL);
1609		break;
1610	case NETDEV_DOWN:
1611		neigh_ifdown(&nd_tbl, dev);
1612		fib6_run_gc(~0UL);
1613		break;
1614	default:
1615		break;
1616	}
1617
1618	return NOTIFY_DONE;
1619}
1620
1621static struct notifier_block ndisc_netdev_notifier = {
1622	.notifier_call = ndisc_netdev_event,
1623};
1624
1625#ifdef CONFIG_SYSCTL
1626static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
1627					 const char *func, const char *dev_name)
1628{
1629	static char warncomm[TASK_COMM_LEN];
1630	static int warned;
1631	if (strcmp(warncomm, current->comm) && warned < 5) {
1632		strcpy(warncomm, current->comm);
1633		printk(KERN_WARNING
1634			"process `%s' is using deprecated sysctl (%s) "
1635			"net.ipv6.neigh.%s.%s; "
1636			"Use net.ipv6.neigh.%s.%s_ms "
1637			"instead.\n",
1638			warncomm, func,
1639			dev_name, ctl->procname,
1640			dev_name, ctl->procname);
1641		warned++;
1642	}
1643}
1644
1645int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos)
1646{
1647	struct net_device *dev = ctl->extra1;
1648	struct inet6_dev *idev;
1649	int ret;
1650
1651	if ((strcmp(ctl->procname, "retrans_time") == 0) ||
1652	    (strcmp(ctl->procname, "base_reachable_time") == 0))
1653		ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
1654
1655	if (strcmp(ctl->procname, "retrans_time") == 0)
1656		ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
1657
1658	else if (strcmp(ctl->procname, "base_reachable_time") == 0)
1659		ret = proc_dointvec_jiffies(ctl, write,
1660					    filp, buffer, lenp, ppos);
1661
1662	else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) ||
1663		 (strcmp(ctl->procname, "base_reachable_time_ms") == 0))
1664		ret = proc_dointvec_ms_jiffies(ctl, write,
1665					       filp, buffer, lenp, ppos);
1666	else
1667		ret = -1;
1668
1669	if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
1670		if (ctl->data == &idev->nd_parms->base_reachable_time)
1671			idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1672		idev->tstamp = jiffies;
1673		inet6_ifinfo_notify(RTM_NEWLINK, idev);
1674		in6_dev_put(idev);
1675	}
1676	return ret;
1677}
1678
1679static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
1680					int nlen, void __user *oldval,
1681					size_t __user *oldlenp,
1682					void __user *newval, size_t newlen)
1683{
1684	struct net_device *dev = ctl->extra1;
1685	struct inet6_dev *idev;
1686	int ret;
1687
1688	if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
1689	    ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
1690		ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default");
1691
1692	switch (ctl->ctl_name) {
1693	case NET_NEIGH_REACHABLE_TIME:
1694		ret = sysctl_jiffies(ctl, name, nlen,
1695				     oldval, oldlenp, newval, newlen);
1696		break;
1697	case NET_NEIGH_RETRANS_TIME_MS:
1698	case NET_NEIGH_REACHABLE_TIME_MS:
1699		 ret = sysctl_ms_jiffies(ctl, name, nlen,
1700					 oldval, oldlenp, newval, newlen);
1701		 break;
1702	default:
1703		ret = 0;
1704	}
1705
1706	if (newval && newlen && ret > 0 &&
1707	    dev && (idev = in6_dev_get(dev)) != NULL) {
1708		if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
1709		    ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
1710			idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
1711		idev->tstamp = jiffies;
1712		inet6_ifinfo_notify(RTM_NEWLINK, idev);
1713		in6_dev_put(idev);
1714	}
1715
1716	return ret;
1717}
1718
1719#endif
1720
1721int __init ndisc_init(void)
1722{
1723	struct ipv6_pinfo *np;
1724	struct sock *sk;
1725	int err;
1726
1727	err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
1728	if (err < 0) {
1729		ND_PRINTK0(KERN_ERR
1730			   "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
1731			   err);
1732		ndisc_socket = NULL; /* For safety. */
1733		return err;
1734	}
1735
1736	sk = ndisc_socket->sk;
1737	np = inet6_sk(sk);
1738	sk->sk_allocation = GFP_ATOMIC;
1739	np->hop_limit = 255;
1740	/* Do not loopback ndisc messages */
1741	np->mc_loop = 0;
1742	sk->sk_prot->unhash(sk);
1743
1744	/*
1745	 * Initialize the neighbour table
1746	 */
1747
1748	neigh_table_init(&nd_tbl);
1749
1750#ifdef CONFIG_SYSCTL
1751	neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
1752			      "ipv6",
1753			      &ndisc_ifinfo_sysctl_change,
1754			      &ndisc_ifinfo_sysctl_strategy);
1755#endif
1756
1757	register_netdevice_notifier(&ndisc_netdev_notifier);
1758	return 0;
1759}
1760
1761void ndisc_cleanup(void)
1762{
1763	unregister_netdevice_notifier(&ndisc_netdev_notifier);
1764#ifdef CONFIG_SYSCTL
1765	neigh_sysctl_unregister(&nd_tbl.parms);
1766#endif
1767	neigh_table_clear(&nd_tbl);
1768	sock_release(ndisc_socket);
1769	ndisc_socket = NULL; /* For safety. */
1770}
1771