ndisc.c 44.3 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
/*
 *	Neighbour Discovery for IPv6
3
 *	Linux INET6 implementation
Linus Torvalds's avatar
Linus Torvalds committed
4
5
 *
 *	Authors:
6
 *	Pedro Roque		<roque@di.fc.ul.pt>
Linus Torvalds's avatar
Linus Torvalds committed
7
8
9
10
11
12
13
14
15
16
17
 *	Mike Shaver		<shaver@ingenia.com>
 *
 *	This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */

/*
 *	Changes:
 *
18
 *	Alexey I. Froloff		:	RFC6106 (DNSSL) support
19
20
 *	Pierre Ynard			:	export userland ND options
 *						through netlink (RDNSS support)
Linus Torvalds's avatar
Linus Torvalds committed
21
22
23
24
25
26
27
28
29
 *	Lars Fenneberg			:	fixed MTU setting on receipt
 *						of an RA.
 *	Janos Farkas			:	kmalloc failure checks
 *	Alexey Kuznetsov		:	state machine reworked
 *						and moved to net/core.
 *	Pekka Savola			:	RFC2461 validation
 *	YOSHIFUJI Hideaki @USAGI	:	Verify ND options properly
 */

30
#define pr_fmt(fmt) "ICMPv6: " fmt
Linus Torvalds's avatar
Linus Torvalds committed
31
32
33
34
35
36
37
38
39
40
41
42

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/sched.h>
#include <linux/net.h>
#include <linux/in6.h>
#include <linux/route.h>
#include <linux/init.h>
#include <linux/rcupdate.h>
43
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
44
45
46
47
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif

48
#include <linux/if_addr.h>
Linus Torvalds's avatar
Linus Torvalds committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <linux/if_arp.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/jhash.h>

#include <net/sock.h>
#include <net/snmp.h>

#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/ndisc.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/icmp.h>

64
65
66
#include <net/netlink.h>
#include <linux/rtnetlink.h>

Linus Torvalds's avatar
Linus Torvalds committed
67
68
#include <net/flow.h>
#include <net/ip6_checksum.h>
69
#include <net/inet_common.h>
Linus Torvalds's avatar
Linus Torvalds committed
70
71
72
73
74
#include <linux/proc_fs.h>

#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>

75
76
77
78
79
80
81
82
83
/* Set to 3 to get tracing... */
#define ND_DEBUG 1

#define ND_PRINTK(val, level, fmt, ...)				\
do {								\
	if (val <= ND_DEBUG)					\
		net_##level##_ratelimited(fmt, ##__VA_ARGS__);	\
} while (0)

84
85
static u32 ndisc_hash(const void *pkey,
		      const struct net_device *dev,
86
		      __u32 *hash_rnd);
87
static bool ndisc_key_eq(const struct neighbour *neigh, const void *pkey);
Linus Torvalds's avatar
Linus Torvalds committed
88
89
90
91
92
93
94
static int ndisc_constructor(struct neighbour *neigh);
static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
static int pndisc_constructor(struct pneigh_entry *n);
static void pndisc_destructor(struct pneigh_entry *n);
static void pndisc_redo(struct sk_buff *skb);

95
static const struct neigh_ops ndisc_generic_ops = {
Linus Torvalds's avatar
Linus Torvalds committed
96
97
98
99
100
101
102
	.family =		AF_INET6,
	.solicit =		ndisc_solicit,
	.error_report =		ndisc_error_report,
	.output =		neigh_resolve_output,
	.connected_output =	neigh_connected_output,
};

103
static const struct neigh_ops ndisc_hh_ops = {
Linus Torvalds's avatar
Linus Torvalds committed
104
105
106
107
108
109
110
111
	.family =		AF_INET6,
	.solicit =		ndisc_solicit,
	.error_report =		ndisc_error_report,
	.output =		neigh_resolve_output,
	.connected_output =	neigh_resolve_output,
};


112
static const struct neigh_ops ndisc_direct_ops = {
Linus Torvalds's avatar
Linus Torvalds committed
113
	.family =		AF_INET6,
114
115
	.output =		neigh_direct_output,
	.connected_output =	neigh_direct_output,
Linus Torvalds's avatar
Linus Torvalds committed
116
117
118
119
120
};

struct neigh_table nd_tbl = {
	.family =	AF_INET6,
	.key_len =	sizeof(struct in6_addr),
121
	.protocol =	cpu_to_be16(ETH_P_IPV6),
Linus Torvalds's avatar
Linus Torvalds committed
122
	.hash =		ndisc_hash,
123
	.key_eq =	ndisc_key_eq,
Linus Torvalds's avatar
Linus Torvalds committed
124
125
126
127
128
129
	.constructor =	ndisc_constructor,
	.pconstructor =	pndisc_constructor,
	.pdestructor =	pndisc_destructor,
	.proxy_redo =	pndisc_redo,
	.id =		"ndisc_cache",
	.parms = {
130
131
		.tbl			= &nd_tbl,
		.reachable_time		= ND_REACHABLE_TIME,
Jiri Pirko's avatar
Jiri Pirko committed
132
133
134
135
136
137
138
139
140
141
142
143
		.data = {
			[NEIGH_VAR_MCAST_PROBES] = 3,
			[NEIGH_VAR_UCAST_PROBES] = 3,
			[NEIGH_VAR_RETRANS_TIME] = ND_RETRANS_TIMER,
			[NEIGH_VAR_BASE_REACHABLE_TIME] = ND_REACHABLE_TIME,
			[NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
			[NEIGH_VAR_GC_STALETIME] = 60 * HZ,
			[NEIGH_VAR_QUEUE_LEN_BYTES] = 64 * 1024,
			[NEIGH_VAR_PROXY_QLEN] = 64,
			[NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
			[NEIGH_VAR_PROXY_DELAY] = (8 * HZ) / 10,
		},
Linus Torvalds's avatar
Linus Torvalds committed
144
145
146
147
148
149
150
	},
	.gc_interval =	  30 * HZ,
	.gc_thresh1 =	 128,
	.gc_thresh2 =	 512,
	.gc_thresh3 =	1024,
};

151
static void ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data)
Linus Torvalds's avatar
Linus Torvalds committed
152
{
153
154
155
156
	int pad   = ndisc_addr_option_pad(skb->dev->type);
	int data_len = skb->dev->addr_len;
	int space = ndisc_opt_addr_space(skb->dev);
	u8 *opt = skb_put(skb, space);
Linus Torvalds's avatar
Linus Torvalds committed
157
158
159
160
161
162
163
164
165
166
167

	opt[0] = type;
	opt[1] = space>>3;

	memset(opt + 2, 0, pad);
	opt   += pad;
	space -= pad;

	memcpy(opt+2, data, data_len);
	data_len += 2;
	opt += data_len;
168
169
	space -= data_len;
	if (space > 0)
Linus Torvalds's avatar
Linus Torvalds committed
170
171
172
173
174
175
176
177
178
179
180
181
		memset(opt, 0, space);
}

static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
					    struct nd_opt_hdr *end)
{
	int type;
	if (!cur || !end || cur >= end)
		return NULL;
	type = cur->nd_opt_type;
	do {
		cur = ((void *)cur) + (cur->nd_opt_len << 3);
182
	} while (cur < end && cur->nd_opt_type != type);
Eric Dumazet's avatar
Eric Dumazet committed
183
	return cur <= end && cur->nd_opt_type == type ? cur : NULL;
Linus Torvalds's avatar
Linus Torvalds committed
184
185
}

186
187
static inline int ndisc_is_useropt(struct nd_opt_hdr *opt)
{
188
189
	return opt->nd_opt_type == ND_OPT_RDNSS ||
		opt->nd_opt_type == ND_OPT_DNSSL;
190
191
192
193
194
195
196
197
198
}

static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur,
					     struct nd_opt_hdr *end)
{
	if (!cur || !end || cur >= end)
		return NULL;
	do {
		cur = ((void *)cur) + (cur->nd_opt_len << 3);
199
	} while (cur < end && !ndisc_is_useropt(cur));
Eric Dumazet's avatar
Eric Dumazet committed
200
	return cur <= end && ndisc_is_useropt(cur) ? cur : NULL;
201
202
}

203
204
struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
					  struct ndisc_options *ndopts)
Linus Torvalds's avatar
Linus Torvalds committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
{
	struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;

	if (!nd_opt || opt_len < 0 || !ndopts)
		return NULL;
	memset(ndopts, 0, sizeof(*ndopts));
	while (opt_len) {
		int l;
		if (opt_len < sizeof(struct nd_opt_hdr))
			return NULL;
		l = nd_opt->nd_opt_len << 3;
		if (opt_len < l || l == 0)
			return NULL;
		switch (nd_opt->nd_opt_type) {
		case ND_OPT_SOURCE_LL_ADDR:
		case ND_OPT_TARGET_LL_ADDR:
		case ND_OPT_MTU:
		case ND_OPT_REDIRECT_HDR:
			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
224
225
226
				ND_PRINTK(2, warn,
					  "%s: duplicated ND6 option found: type=%d\n",
					  __func__, nd_opt->nd_opt_type);
Linus Torvalds's avatar
Linus Torvalds committed
227
228
229
230
231
232
			} else {
				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
			}
			break;
		case ND_OPT_PREFIX_INFO:
			ndopts->nd_opts_pi_end = nd_opt;
233
			if (!ndopts->nd_opt_array[nd_opt->nd_opt_type])
Linus Torvalds's avatar
Linus Torvalds committed
234
235
				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
			break;
236
237
238
239
240
241
242
#ifdef CONFIG_IPV6_ROUTE_INFO
		case ND_OPT_ROUTE_INFO:
			ndopts->nd_opts_ri_end = nd_opt;
			if (!ndopts->nd_opts_ri)
				ndopts->nd_opts_ri = nd_opt;
			break;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
243
		default:
244
245
246
247
248
249
250
251
252
253
			if (ndisc_is_useropt(nd_opt)) {
				ndopts->nd_useropts_end = nd_opt;
				if (!ndopts->nd_useropts)
					ndopts->nd_useropts = nd_opt;
			} else {
				/*
				 * Unknown options must be silently ignored,
				 * to accommodate future extension to the
				 * protocol.
				 */
254
255
256
257
258
				ND_PRINTK(2, notice,
					  "%s: ignored unsupported option; type=%d, len=%d\n",
					  __func__,
					  nd_opt->nd_opt_type,
					  nd_opt->nd_opt_len);
259
			}
Linus Torvalds's avatar
Linus Torvalds committed
260
261
262
263
264
265
266
		}
		opt_len -= l;
		nd_opt = ((void *)nd_opt) + l;
	}
	return ndopts;
}

267
int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
Linus Torvalds's avatar
Linus Torvalds committed
268
269
270
271
272
273
274
275
276
277
278
{
	switch (dev->type) {
	case ARPHRD_ETHER:
	case ARPHRD_IEEE802:	/* Not sure. Check it later. --ANK */
	case ARPHRD_FDDI:
		ipv6_eth_mc_map(addr, buf);
		return 0;
	case ARPHRD_ARCNET:
		ipv6_arcnet_mc_map(addr, buf);
		return 0;
	case ARPHRD_INFINIBAND:
279
		ipv6_ib_mc_map(addr, dev->broadcast, buf);
Linus Torvalds's avatar
Linus Torvalds committed
280
		return 0;
281
282
	case ARPHRD_IPGRE:
		return ipv6_ipgre_mc_map(addr, dev->broadcast, buf);
Linus Torvalds's avatar
Linus Torvalds committed
283
284
285
286
287
288
289
290
	default:
		if (dir) {
			memcpy(buf, dev->broadcast, dev->addr_len);
			return 0;
		}
	}
	return -EINVAL;
}
291
292
EXPORT_SYMBOL(ndisc_mc_map);

293
294
static u32 ndisc_hash(const void *pkey,
		      const struct net_device *dev,
295
		      __u32 *hash_rnd)
Linus Torvalds's avatar
Linus Torvalds committed
296
{
297
	return ndisc_hashfn(pkey, dev, hash_rnd);
Linus Torvalds's avatar
Linus Torvalds committed
298
299
}

300
301
302
303
304
static bool ndisc_key_eq(const struct neighbour *n, const void *pkey)
{
	return neigh_key_eq128(n, pkey);
}

Linus Torvalds's avatar
Linus Torvalds committed
305
306
static int ndisc_constructor(struct neighbour *neigh)
{
307
	struct in6_addr *addr = (struct in6_addr *)&neigh->primary_key;
Linus Torvalds's avatar
Linus Torvalds committed
308
309
310
	struct net_device *dev = neigh->dev;
	struct inet6_dev *in6_dev;
	struct neigh_parms *parms;
311
	bool is_multicast = ipv6_addr_is_multicast(addr);
Linus Torvalds's avatar
Linus Torvalds committed
312
313

	in6_dev = in6_dev_get(dev);
314
	if (!in6_dev) {
Linus Torvalds's avatar
Linus Torvalds committed
315
316
317
318
319
320
321
322
		return -EINVAL;
	}

	parms = in6_dev->nd_parms;
	__neigh_parms_put(neigh->parms);
	neigh->parms = neigh_parms_clone(parms);

	neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
323
	if (!dev->header_ops) {
Linus Torvalds's avatar
Linus Torvalds committed
324
325
		neigh->nud_state = NUD_NOARP;
		neigh->ops = &ndisc_direct_ops;
326
		neigh->output = neigh_direct_output;
Linus Torvalds's avatar
Linus Torvalds committed
327
328
329
330
331
332
333
334
335
336
337
338
339
	} else {
		if (is_multicast) {
			neigh->nud_state = NUD_NOARP;
			ndisc_mc_map(addr, neigh->ha, dev, 1);
		} else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
			neigh->nud_state = NUD_NOARP;
			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
			if (dev->flags&IFF_LOOPBACK)
				neigh->type = RTN_LOCAL;
		} else if (dev->flags&IFF_POINTOPOINT) {
			neigh->nud_state = NUD_NOARP;
			memcpy(neigh->ha, dev->broadcast, dev->addr_len);
		}
340
		if (dev->header_ops->cache)
Linus Torvalds's avatar
Linus Torvalds committed
341
342
343
344
345
346
347
348
349
350
351
352
353
354
			neigh->ops = &ndisc_hh_ops;
		else
			neigh->ops = &ndisc_generic_ops;
		if (neigh->nud_state&NUD_VALID)
			neigh->output = neigh->ops->connected_output;
		else
			neigh->output = neigh->ops->output;
	}
	in6_dev_put(in6_dev);
	return 0;
}

static int pndisc_constructor(struct pneigh_entry *n)
{
355
	struct in6_addr *addr = (struct in6_addr *)&n->key;
Linus Torvalds's avatar
Linus Torvalds committed
356
357
358
	struct in6_addr maddr;
	struct net_device *dev = n->dev;

359
	if (!dev || !__in6_dev_get(dev))
Linus Torvalds's avatar
Linus Torvalds committed
360
361
362
363
364
365
366
367
		return -EINVAL;
	addrconf_addr_solict_mult(addr, &maddr);
	ipv6_dev_mc_inc(dev, &maddr);
	return 0;
}

static void pndisc_destructor(struct pneigh_entry *n)
{
368
	struct in6_addr *addr = (struct in6_addr *)&n->key;
Linus Torvalds's avatar
Linus Torvalds committed
369
370
371
	struct in6_addr maddr;
	struct net_device *dev = n->dev;

372
	if (!dev || !__in6_dev_get(dev))
Linus Torvalds's avatar
Linus Torvalds committed
373
374
375
376
377
		return;
	addrconf_addr_solict_mult(addr, &maddr);
	ipv6_dev_mc_dec(dev, &maddr);
}

378
379
380
381
382
383
384
385
static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
				       int len)
{
	int hlen = LL_RESERVED_SPACE(dev);
	int tlen = dev->needed_tailroom;
	struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
	struct sk_buff *skb;

386
	skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
387
	if (!skb) {
388
389
		ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
			  __func__);
390
391
392
		return NULL;
	}

393
394
395
	skb->protocol = htons(ETH_P_IPV6);
	skb->dev = dev;

396
	skb_reserve(skb, hlen + sizeof(struct ipv6hdr));
397
	skb_reset_transport_header(skb);
398

399
400
401
402
403
	/* Manually assign socket ownership as we avoid calling
	 * sock_alloc_send_pskb() to bypass wmem buffer limits
	 */
	skb_set_owner_w(skb, sk);

404
405
406
	return skb;
}

407
static void ip6_nd_hdr(struct sk_buff *skb,
408
409
		       const struct in6_addr *saddr,
		       const struct in6_addr *daddr,
410
		       int hop_limit, int len)
411
412
413
{
	struct ipv6hdr *hdr;

414
	skb_push(skb, sizeof(*hdr));
415
416
417
418
419
420
	skb_reset_network_header(skb);
	hdr = ipv6_hdr(skb);

	ip6_flow_hdr(hdr, 0, 0);

	hdr->payload_len = htons(len);
421
422
	hdr->nexthdr = IPPROTO_ICMPV6;
	hdr->hop_limit = hop_limit;
423
424
425
426
427

	hdr->saddr = *saddr;
	hdr->daddr = *daddr;
}

428
static void ndisc_send_skb(struct sk_buff *skb,
429
			   const struct in6_addr *daddr,
430
			   const struct in6_addr *saddr)
431
{
432
	struct dst_entry *dst = skb_dst(skb);
433
	struct net *net = dev_net(skb->dev);
434
	struct sock *sk = net->ipv6.ndisc_sk;
435
436
	struct inet6_dev *idev;
	int err;
437
	struct icmp6hdr *icmp6h = icmp6_hdr(skb);
438
439
440
441
	u8 type;

	type = icmp6h->icmp6_type;

442
443
	if (!dst) {
		struct flowi6 fl6;
444

445
446
447
448
449
450
451
452
453
		icmpv6_flow_init(sk, &fl6, type, saddr, daddr, skb->dev->ifindex);
		dst = icmp6_dst_alloc(skb->dev, &fl6);
		if (IS_ERR(dst)) {
			kfree_skb(skb);
			return;
		}

		skb_dst_set(skb, dst);
	}
454

455
456
457
458
459
460
461
	icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, skb->len,
					      IPPROTO_ICMPV6,
					      csum_partial(icmp6h,
							   skb->len, 0));

	ip6_nd_hdr(skb, saddr, daddr, inet6_sk(sk)->hop_limit, skb->len);

Eric Dumazet's avatar
Eric Dumazet committed
462
463
	rcu_read_lock();
	idev = __in6_dev_get(dst->dev);
464
	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
465

466
467
468
	err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
		      NULL, dst->dev,
		      dst_output_sk);
Linus Torvalds's avatar
Linus Torvalds committed
469
	if (!err) {
470
		ICMP6MSGOUT_INC_STATS(net, idev, type);
471
		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
Linus Torvalds's avatar
Linus Torvalds committed
472
473
	}

Eric Dumazet's avatar
Eric Dumazet committed
474
	rcu_read_unlock();
475
}
Linus Torvalds's avatar
Linus Torvalds committed
476

Cong Wang's avatar
Cong Wang committed
477
478
479
480
void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
		   const struct in6_addr *daddr,
		   const struct in6_addr *solicited_addr,
		   bool router, bool solicited, bool override, bool inc_opt)
481
{
482
	struct sk_buff *skb;
483
484
	struct in6_addr tmpaddr;
	struct inet6_ifaddr *ifp;
485
	const struct in6_addr *src_addr;
486
487
	struct nd_msg *msg;
	int optlen = 0;
488
489

	/* for anycast or proxy, solicited_addr != src_addr */
490
	ifp = ipv6_get_ifaddr(dev_net(dev), solicited_addr, dev, 1);
491
492
493
	if (ifp) {
		src_addr = solicited_addr;
		if (ifp->flags & IFA_F_OPTIMISTIC)
494
			override = false;
495
		inc_opt |= ifp->idev->cnf.force_tllao;
496
497
		in6_ifa_put(ifp);
	} else {
498
		if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
499
				       inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs,
500
				       &tmpaddr))
501
502
503
504
			return;
		src_addr = &tmpaddr;
	}

505
506
507
508
	if (!dev->addr_len)
		inc_opt = 0;
	if (inc_opt)
		optlen += ndisc_opt_addr_space(dev);
509

510
	skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
511
512
513
	if (!skb)
		return;

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
	msg = (struct nd_msg *)skb_put(skb, sizeof(*msg));
	*msg = (struct nd_msg) {
		.icmph = {
			.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
			.icmp6_router = router,
			.icmp6_solicited = solicited,
			.icmp6_override = override,
		},
		.target = *solicited_addr,
	};

	if (inc_opt)
		ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR,
				       dev->dev_addr);


530
	ndisc_send_skb(skb, daddr, src_addr);
531
532
}

533
534
535
536
537
538
539
540
541
542
543
static void ndisc_send_unsol_na(struct net_device *dev)
{
	struct inet6_dev *idev;
	struct inet6_ifaddr *ifa;

	idev = in6_dev_get(dev);
	if (!idev)
		return;

	read_lock_bh(&idev->lock);
	list_for_each_entry(ifa, &idev->addr_list, if_list) {
544
		ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &ifa->addr,
545
546
547
548
549
550
551
552
553
			      /*router=*/ !!idev->cnf.forwarding,
			      /*solicited=*/ false, /*override=*/ true,
			      /*inc_opt=*/ true);
	}
	read_unlock_bh(&idev->lock);

	in6_dev_put(idev);
}

Linus Torvalds's avatar
Linus Torvalds committed
554
void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
555
		   const struct in6_addr *solicit,
556
557
		   const struct in6_addr *daddr, const struct in6_addr *saddr,
		   struct sk_buff *oskb)
Linus Torvalds's avatar
Linus Torvalds committed
558
{
559
	struct sk_buff *skb;
Linus Torvalds's avatar
Linus Torvalds committed
560
	struct in6_addr addr_buf;
561
562
563
	int inc_opt = dev->addr_len;
	int optlen = 0;
	struct nd_msg *msg;
Linus Torvalds's avatar
Linus Torvalds committed
564

565
	if (!saddr) {
566
567
		if (ipv6_get_lladdr(dev, &addr_buf,
				   (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)))
Linus Torvalds's avatar
Linus Torvalds committed
568
569
570
571
			return;
		saddr = &addr_buf;
	}

572
	if (ipv6_addr_any(saddr))
573
		inc_opt = false;
574
575
576
577
	if (inc_opt)
		optlen += ndisc_opt_addr_space(dev);

	skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
578
579
580
	if (!skb)
		return;

581
582
583
584
585
586
587
588
589
590
591
592
	msg = (struct nd_msg *)skb_put(skb, sizeof(*msg));
	*msg = (struct nd_msg) {
		.icmph = {
			.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION,
		},
		.target = *solicit,
	};

	if (inc_opt)
		ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
				       dev->dev_addr);

593
594
595
	if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE) && oskb)
		skb_dst_copy(skb, oskb);

596
	ndisc_send_skb(skb, daddr, saddr);
Linus Torvalds's avatar
Linus Torvalds committed
597
598
}

599
600
void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
		   const struct in6_addr *daddr)
Linus Torvalds's avatar
Linus Torvalds committed
601
{
602
	struct sk_buff *skb;
603
	struct rs_msg *msg;
604
	int send_sllao = dev->addr_len;
605
	int optlen = 0;
606
607
608
609
610
611
612
613

#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
	/*
	 * According to section 2.2 of RFC 4429, we must not
	 * send router solicitations with a sllao from
	 * optimistic addresses, but we may send the solicitation
	 * if we don't include the sllao.  So here we check
	 * if our address is optimistic, and if so, we
Joe Perches's avatar
Joe Perches committed
614
	 * suppress the inclusion of the sllao.
615
616
	 */
	if (send_sllao) {
617
		struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev_net(dev), saddr,
618
							   dev, 1);
619
620
		if (ifp) {
			if (ifp->flags & IFA_F_OPTIMISTIC)  {
621
				send_sllao = 0;
622
			}
623
			in6_ifa_put(ifp);
624
625
626
627
628
		} else {
			send_sllao = 0;
		}
	}
#endif
629
630
631
632
	if (send_sllao)
		optlen += ndisc_opt_addr_space(dev);

	skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
633
634
635
	if (!skb)
		return;

636
637
638
639
640
641
642
643
644
645
646
	msg = (struct rs_msg *)skb_put(skb, sizeof(*msg));
	*msg = (struct rs_msg) {
		.icmph = {
			.icmp6_type = NDISC_ROUTER_SOLICITATION,
		},
	};

	if (send_sllao)
		ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
				       dev->dev_addr);

647
	ndisc_send_skb(skb, daddr, saddr);
Linus Torvalds's avatar
Linus Torvalds committed
648
}
649

Linus Torvalds's avatar
Linus Torvalds committed
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
{
	/*
	 *	"The sender MUST return an ICMP
	 *	 destination unreachable"
	 */
	dst_link_failure(skb);
	kfree_skb(skb);
}

/* Called with locked neigh: either read or both */

static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
{
	struct in6_addr *saddr = NULL;
	struct in6_addr mcaddr;
	struct net_device *dev = neigh->dev;
	struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
	int probes = atomic_read(&neigh->probes);

671
672
673
	if (skb && ipv6_chk_addr_and_flags(dev_net(dev), &ipv6_hdr(skb)->saddr,
					   dev, 1,
					   IFA_F_TENTATIVE|IFA_F_OPTIMISTIC))
674
		saddr = &ipv6_hdr(skb)->saddr;
675
676
	probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
	if (probes < 0) {
Linus Torvalds's avatar
Linus Torvalds committed
677
		if (!(neigh->nud_state & NUD_VALID)) {
678
679
680
			ND_PRINTK(1, dbg,
				  "%s: trying to ucast probe in NUD_INVALID: %pI6\n",
				  __func__, target);
Linus Torvalds's avatar
Linus Torvalds committed
681
		}
682
		ndisc_send_ns(dev, neigh, target, target, saddr, skb);
Jiri Pirko's avatar
Jiri Pirko committed
683
	} else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
Linus Torvalds's avatar
Linus Torvalds committed
684
685
686
		neigh_app_ns(neigh);
	} else {
		addrconf_addr_solict_mult(target, &mcaddr);
687
		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr, skb);
Linus Torvalds's avatar
Linus Torvalds committed
688
689
690
	}
}

691
692
static int pndisc_is_router(const void *pkey,
			    struct net_device *dev)
693
694
{
	struct pneigh_entry *n;
695
	int ret = -1;
696
697

	read_lock_bh(&nd_tbl.lock);
698
699
700
	n = __pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev);
	if (n)
		ret = !!(n->flags & NTF_ROUTER);
701
702
	read_unlock_bh(&nd_tbl.lock);

703
	return ret;
704
705
}

Linus Torvalds's avatar
Linus Torvalds committed
706
707
static void ndisc_recv_ns(struct sk_buff *skb)
{
708
	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
709
710
	const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
	const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
Linus Torvalds's avatar
Linus Torvalds committed
711
	u8 *lladdr = NULL;
712
	u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
713
				    offsetof(struct nd_msg, opt));
Linus Torvalds's avatar
Linus Torvalds committed
714
715
716
717
718
719
	struct ndisc_options ndopts;
	struct net_device *dev = skb->dev;
	struct inet6_ifaddr *ifp;
	struct inet6_dev *idev = NULL;
	struct neighbour *neigh;
	int dad = ipv6_addr_any(saddr);
720
	bool inc;
721
	int is_router = -1;
Linus Torvalds's avatar
Linus Torvalds committed
722

723
724
725
726
727
	if (skb->len < sizeof(struct nd_msg)) {
		ND_PRINTK(2, warn, "NS: packet too short\n");
		return;
	}

Linus Torvalds's avatar
Linus Torvalds committed
728
	if (ipv6_addr_is_multicast(&msg->target)) {
729
		ND_PRINTK(2, warn, "NS: multicast target address\n");
Linus Torvalds's avatar
Linus Torvalds committed
730
731
732
733
734
735
736
		return;
	}

	/*
	 * RFC2461 7.1.1:
	 * DAD has to be destined for solicited node multicast address.
	 */
737
	if (dad && !ipv6_addr_is_solict_mult(daddr)) {
738
		ND_PRINTK(2, warn, "NS: bad DAD packet (wrong destination)\n");
Linus Torvalds's avatar
Linus Torvalds committed
739
740
741
742
		return;
	}

	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
743
		ND_PRINTK(2, warn, "NS: invalid ND options\n");
Linus Torvalds's avatar
Linus Torvalds committed
744
745
746
747
748
749
		return;
	}

	if (ndopts.nd_opts_src_lladdr) {
		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
		if (!lladdr) {
750
751
			ND_PRINTK(2, warn,
				  "NS: invalid link-layer address length\n");
Linus Torvalds's avatar
Linus Torvalds committed
752
753
754
755
			return;
		}

		/* RFC2461 7.1.1:
756
757
		 *	If the IP source address is the unspecified address,
		 *	there MUST NOT be source link-layer address option
Linus Torvalds's avatar
Linus Torvalds committed
758
759
760
		 *	in the message.
		 */
		if (dad) {
761
762
			ND_PRINTK(2, warn,
				  "NS: bad DAD packet (link-layer address option)\n");
Linus Torvalds's avatar
Linus Torvalds committed
763
764
765
766
767
768
			return;
		}
	}

	inc = ipv6_addr_is_multicast(daddr);

769
	ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
770
	if (ifp) {
771
772
773
774
775
776
777
778
779

		if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
			if (dad) {
				/*
				 * We are colliding with another node
				 * who is doing DAD
				 * so fail our DAD process
				 */
				addrconf_dad_failure(ifp);
780
				return;
781
782
783
784
785
786
787
788
			} else {
				/*
				 * This is not a dad solicitation.
				 * If we are an optimistic node,
				 * we should respond.
				 * Otherwise, we should ignore it.
				 */
				if (!(ifp->flags & IFA_F_OPTIMISTIC))
Linus Torvalds's avatar
Linus Torvalds committed
789
790
791
792
793
794
					goto out;
			}
		}

		idev = ifp->idev;
	} else {
795
796
		struct net *net = dev_net(dev);

Linus Torvalds's avatar
Linus Torvalds committed
797
798
799
800
801
802
		idev = in6_dev_get(dev);
		if (!idev) {
			/* XXX: count this drop? */
			return;
		}

803
		if (ipv6_chk_acast_addr(net, dev, &msg->target) ||
804
		    (idev->cnf.forwarding &&
805
		     (net->ipv6.devconf_all->proxy_ndp || idev->cnf.proxy_ndp) &&
806
		     (is_router = pndisc_is_router(&msg->target, dev)) >= 0)) {
807
			if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
Linus Torvalds's avatar
Linus Torvalds committed
808
			    skb->pkt_type != PACKET_HOST &&
809
			    inc &&
Jiri Pirko's avatar
Jiri Pirko committed
810
			    NEIGH_VAR(idev->nd_parms, PROXY_DELAY) != 0) {
Linus Torvalds's avatar
Linus Torvalds committed
811
812
				/*
				 * for anycast or proxy,
813
814
				 * sender should delay its response
				 * by a random time between 0 and
Linus Torvalds's avatar
Linus Torvalds committed
815
816
817
818
819
820
821
822
823
824
825
826
				 * MAX_ANYCAST_DELAY_TIME seconds.
				 * (RFC2461) -- yoshfuji
				 */
				struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
				if (n)
					pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
				goto out;
			}
		} else
			goto out;
	}

827
	if (is_router < 0)
828
		is_router = idev->cnf.forwarding;
829

Linus Torvalds's avatar
Linus Torvalds committed
830
	if (dad) {
831
		ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target,
832
			      !!is_router, false, (ifp != NULL), true);
Linus Torvalds's avatar
Linus Torvalds committed
833
834
835
836
837
838
839
840
		goto out;
	}

	if (inc)
		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
	else
		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);

841
	/*
Linus Torvalds's avatar
Linus Torvalds committed
842
843
844
845
846
847
	 *	update / create cache entry
	 *	for the source address
	 */
	neigh = __neigh_lookup(&nd_tbl, saddr, dev,
			       !inc || lladdr || !dev->addr_len);
	if (neigh)
848
		neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds's avatar
Linus Torvalds committed
849
850
			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
			     NEIGH_UPDATE_F_OVERRIDE);
851
	if (neigh || !dev->header_ops) {
Linus Torvalds's avatar
Linus Torvalds committed
852
		ndisc_send_na(dev, neigh, saddr, &msg->target,
853
854
			      !!is_router,
			      true, (ifp != NULL && inc), inc);
Linus Torvalds's avatar
Linus Torvalds committed
855
856
857
858
859
860
861
862
863
864
865
866
867
		if (neigh)
			neigh_release(neigh);
	}

out:
	if (ifp)
		in6_ifa_put(ifp);
	else
		in6_dev_put(idev);
}

static void ndisc_recv_na(struct sk_buff *skb)
{
868
	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
869
	struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
870
	const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
Linus Torvalds's avatar
Linus Torvalds committed
871
	u8 *lladdr = NULL;
872
	u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
873
				    offsetof(struct nd_msg, opt));
Linus Torvalds's avatar
Linus Torvalds committed
874
875
876
877
878
879
	struct ndisc_options ndopts;
	struct net_device *dev = skb->dev;
	struct inet6_ifaddr *ifp;
	struct neighbour *neigh;

	if (skb->len < sizeof(struct nd_msg)) {
880
		ND_PRINTK(2, warn, "NA: packet too short\n");
Linus Torvalds's avatar
Linus Torvalds committed
881
882
883
884
		return;
	}

	if (ipv6_addr_is_multicast(&msg->target)) {
885
		ND_PRINTK(2, warn, "NA: target address is multicast\n");
Linus Torvalds's avatar
Linus Torvalds committed
886
887
888
889
890
		return;
	}

	if (ipv6_addr_is_multicast(daddr) &&
	    msg->icmph.icmp6_solicited) {
891
		ND_PRINTK(2, warn, "NA: solicited NA is multicasted\n");
Linus Torvalds's avatar
Linus Torvalds committed
892
893
		return;
	}
894

Linus Torvalds's avatar
Linus Torvalds committed
895
	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
896
		ND_PRINTK(2, warn, "NS: invalid ND option\n");
Linus Torvalds's avatar
Linus Torvalds committed
897
898
899
900
901
		return;
	}
	if (ndopts.nd_opts_tgt_lladdr) {
		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
		if (!lladdr) {
902
903
			ND_PRINTK(2, warn,
				  "NA: invalid link-layer address length\n");
Linus Torvalds's avatar
Linus Torvalds committed
904
905
906
			return;
		}
	}
907
	ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
908
	if (ifp) {
909
910
911
912
		if (skb->pkt_type != PACKET_LOOPBACK
		    && (ifp->flags & IFA_F_TENTATIVE)) {
				addrconf_dad_failure(ifp);
				return;
Linus Torvalds's avatar
Linus Torvalds committed
913
914
915
916
917
		}
		/* What should we make now? The advertisement
		   is invalid, but ndisc specs say nothing
		   about it. It could be misconfiguration, or
		   an smart proxy agent tries to help us :-)
918
919
920
921

		   We should not print the error if NA has been
		   received from loopback - it is just our own
		   unsolicited advertisement.
Linus Torvalds's avatar
Linus Torvalds committed
922
		 */
923
		if (skb->pkt_type != PACKET_LOOPBACK)
924
925
926
			ND_PRINTK(1, warn,
				  "NA: someone advertises our address %pI6 on %s!\n",
				  &ifp->addr, ifp->idev->dev->name);
Linus Torvalds's avatar
Linus Torvalds committed
927
928
929
930
931
932
933
		in6_ifa_put(ifp);
		return;
	}
	neigh = neigh_lookup(&nd_tbl, &msg->target, dev);

	if (neigh) {
		u8 old_flags = neigh->flags;
934
		struct net *net = dev_net(dev);
Linus Torvalds's avatar
Linus Torvalds committed
935
936
937
938

		if (neigh->nud_state & NUD_FAILED)
			goto out;

939
940
941
942
943
944
		/*
		 * Don't update the neighbor cache entry on a proxy NA from
		 * ourselves because either the proxied node is off link or it
		 * has already sent a NA to us.
		 */
		if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
945
946
		    net->ipv6.devconf_all->forwarding && net->ipv6.devconf_all->proxy_ndp &&
		    pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
947
			/* XXX: idev->cnf.proxy_ndp */
948
			goto out;
949
		}
950

Linus Torvalds's avatar
Linus Torvalds committed
951
952
953
954
955
956
957
958
959
960
961
		neigh_update(neigh, lladdr,
			     msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
			     (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
			     (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));

		if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
			/*
			 * Change: router to host
			 */
962
			rt6_clean_tohost(dev_net(dev),  saddr);
Linus Torvalds's avatar
Linus Torvalds committed
963
964
965
966
967
968
969
970
971
		}

out:
		neigh_release(neigh);
	}
}

static void ndisc_recv_rs(struct sk_buff *skb)
{
972
	struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb);
Linus Torvalds's avatar
Linus Torvalds committed
973
974
975
	unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
	struct neighbour *neigh;
	struct inet6_dev *idev;
976
	const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
Linus Torvalds's avatar
Linus Torvalds committed
977
978
979
980
981
982
	struct ndisc_options ndopts;
	u8 *lladdr = NULL;

	if (skb->len < sizeof(*rs_msg))
		return;

Eric Dumazet's avatar
Eric Dumazet committed
983
	idev = __in6_dev_get(skb->dev);
Linus Torvalds's avatar
Linus Torvalds committed
984
	if (!idev) {
985
		ND_PRINTK(1, err, "RS: can't find in6 device\n");
Linus Torvalds's avatar
Linus Torvalds committed
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
		return;
	}

	/* Don't accept RS if we're not in router mode */
	if (!idev->cnf.forwarding)
		goto out;

	/*
	 * Don't update NCE if src = ::;
	 * this implies that the source node has no ip address assigned yet.
	 */
	if (ipv6_addr_any(saddr))
		goto out;

	/* Parse ND options */