Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Neighbour Discovery for IPv6
4 : : * Linux INET6 implementation
5 : : *
6 : : * Authors:
7 : : * Pedro Roque <roque@di.fc.ul.pt>
8 : : * Mike Shaver <shaver@ingenia.com>
9 : : */
10 : :
11 : : /*
12 : : * Changes:
13 : : *
14 : : * Alexey I. Froloff : RFC6106 (DNSSL) support
15 : : * Pierre Ynard : export userland ND options
16 : : * through netlink (RDNSS support)
17 : : * Lars Fenneberg : fixed MTU setting on receipt
18 : : * of an RA.
19 : : * Janos Farkas : kmalloc failure checks
20 : : * Alexey Kuznetsov : state machine reworked
21 : : * and moved to net/core.
22 : : * Pekka Savola : RFC2461 validation
23 : : * YOSHIFUJI Hideaki @USAGI : Verify ND options properly
24 : : */
25 : :
26 : : #define pr_fmt(fmt) "ICMPv6: " fmt
27 : :
28 : : #include <linux/module.h>
29 : : #include <linux/errno.h>
30 : : #include <linux/types.h>
31 : : #include <linux/socket.h>
32 : : #include <linux/sockios.h>
33 : : #include <linux/sched.h>
34 : : #include <linux/net.h>
35 : : #include <linux/in6.h>
36 : : #include <linux/route.h>
37 : : #include <linux/init.h>
38 : : #include <linux/rcupdate.h>
39 : : #include <linux/slab.h>
40 : : #ifdef CONFIG_SYSCTL
41 : : #include <linux/sysctl.h>
42 : : #endif
43 : :
44 : : #include <linux/if_addr.h>
45 : : #include <linux/if_ether.h>
46 : : #include <linux/if_arp.h>
47 : : #include <linux/ipv6.h>
48 : : #include <linux/icmpv6.h>
49 : : #include <linux/jhash.h>
50 : :
51 : : #include <net/sock.h>
52 : : #include <net/snmp.h>
53 : :
54 : : #include <net/ipv6.h>
55 : : #include <net/protocol.h>
56 : : #include <net/ndisc.h>
57 : : #include <net/ip6_route.h>
58 : : #include <net/addrconf.h>
59 : : #include <net/icmp.h>
60 : :
61 : : #include <net/netlink.h>
62 : : #include <linux/rtnetlink.h>
63 : :
64 : : #include <net/flow.h>
65 : : #include <net/ip6_checksum.h>
66 : : #include <net/inet_common.h>
67 : : #include <linux/proc_fs.h>
68 : :
69 : : #include <linux/netfilter.h>
70 : : #include <linux/netfilter_ipv6.h>
71 : :
72 : : static u32 ndisc_hash(const void *pkey,
73 : : const struct net_device *dev,
74 : : __u32 *hash_rnd);
75 : : static bool ndisc_key_eq(const struct neighbour *neigh, const void *pkey);
76 : : static bool ndisc_allow_add(const struct net_device *dev,
77 : : struct netlink_ext_ack *extack);
78 : : static int ndisc_constructor(struct neighbour *neigh);
79 : : static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
80 : : static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
81 : : static int pndisc_constructor(struct pneigh_entry *n);
82 : : static void pndisc_destructor(struct pneigh_entry *n);
83 : : static void pndisc_redo(struct sk_buff *skb);
84 : :
85 : : static const struct neigh_ops ndisc_generic_ops = {
86 : : .family = AF_INET6,
87 : : .solicit = ndisc_solicit,
88 : : .error_report = ndisc_error_report,
89 : : .output = neigh_resolve_output,
90 : : .connected_output = neigh_connected_output,
91 : : };
92 : :
93 : : static const struct neigh_ops ndisc_hh_ops = {
94 : : .family = AF_INET6,
95 : : .solicit = ndisc_solicit,
96 : : .error_report = ndisc_error_report,
97 : : .output = neigh_resolve_output,
98 : : .connected_output = neigh_resolve_output,
99 : : };
100 : :
101 : :
102 : : static const struct neigh_ops ndisc_direct_ops = {
103 : : .family = AF_INET6,
104 : : .output = neigh_direct_output,
105 : : .connected_output = neigh_direct_output,
106 : : };
107 : :
108 : : struct neigh_table nd_tbl = {
109 : : .family = AF_INET6,
110 : : .key_len = sizeof(struct in6_addr),
111 : : .protocol = cpu_to_be16(ETH_P_IPV6),
112 : : .hash = ndisc_hash,
113 : : .key_eq = ndisc_key_eq,
114 : : .constructor = ndisc_constructor,
115 : : .pconstructor = pndisc_constructor,
116 : : .pdestructor = pndisc_destructor,
117 : : .proxy_redo = pndisc_redo,
118 : : .allow_add = ndisc_allow_add,
119 : : .id = "ndisc_cache",
120 : : .parms = {
121 : : .tbl = &nd_tbl,
122 : : .reachable_time = ND_REACHABLE_TIME,
123 : : .data = {
124 : : [NEIGH_VAR_MCAST_PROBES] = 3,
125 : : [NEIGH_VAR_UCAST_PROBES] = 3,
126 : : [NEIGH_VAR_RETRANS_TIME] = ND_RETRANS_TIMER,
127 : : [NEIGH_VAR_BASE_REACHABLE_TIME] = ND_REACHABLE_TIME,
128 : : [NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
129 : : [NEIGH_VAR_GC_STALETIME] = 60 * HZ,
130 : : [NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
131 : : [NEIGH_VAR_PROXY_QLEN] = 64,
132 : : [NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
133 : : [NEIGH_VAR_PROXY_DELAY] = (8 * HZ) / 10,
134 : : },
135 : : },
136 : : .gc_interval = 30 * HZ,
137 : : .gc_thresh1 = 128,
138 : : .gc_thresh2 = 512,
139 : : .gc_thresh3 = 1024,
140 : : };
141 : : EXPORT_SYMBOL_GPL(nd_tbl);
142 : :
143 : 0 : void __ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data,
144 : : int data_len, int pad)
145 : : {
146 : : int space = __ndisc_opt_addr_space(data_len, pad);
147 : 0 : u8 *opt = skb_put(skb, space);
148 : :
149 : 0 : opt[0] = type;
150 : 0 : opt[1] = space>>3;
151 : :
152 : 0 : memset(opt + 2, 0, pad);
153 : 0 : opt += pad;
154 : 0 : space -= pad;
155 : :
156 : 0 : memcpy(opt+2, data, data_len);
157 : 0 : data_len += 2;
158 : 0 : opt += data_len;
159 : 0 : space -= data_len;
160 [ # # ]: 0 : if (space > 0)
161 : 0 : memset(opt, 0, space);
162 : 0 : }
163 : : EXPORT_SYMBOL_GPL(__ndisc_fill_addr_option);
164 : :
165 : 0 : static inline void ndisc_fill_addr_option(struct sk_buff *skb, int type,
166 : : void *data, u8 icmp6_type)
167 : : {
168 : 0 : __ndisc_fill_addr_option(skb, type, data, skb->dev->addr_len,
169 : : ndisc_addr_option_pad(skb->dev->type));
170 : 0 : ndisc_ops_fill_addr_option(skb->dev, skb, icmp6_type);
171 : 0 : }
172 : :
173 : 0 : static inline void ndisc_fill_redirect_addr_option(struct sk_buff *skb,
174 : : void *ha,
175 : : const u8 *ops_data)
176 : : {
177 : 0 : ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR, ha, NDISC_REDIRECT);
178 : 0 : ndisc_ops_fill_redirect_addr_option(skb->dev, skb, ops_data);
179 : 0 : }
180 : :
181 : 0 : static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
182 : : struct nd_opt_hdr *end)
183 : : {
184 : : int type;
185 [ # # # # ]: 0 : if (!cur || !end || cur >= end)
186 : : return NULL;
187 : 0 : type = cur->nd_opt_type;
188 : : do {
189 : 0 : cur = ((void *)cur) + (cur->nd_opt_len << 3);
190 [ # # # # ]: 0 : } while (cur < end && cur->nd_opt_type != type);
191 [ # # # # ]: 0 : return cur <= end && cur->nd_opt_type == type ? cur : NULL;
192 : : }
193 : :
194 : 0 : static inline int ndisc_is_useropt(const struct net_device *dev,
195 : : struct nd_opt_hdr *opt)
196 : : {
197 : 0 : return opt->nd_opt_type == ND_OPT_RDNSS ||
198 [ # # ]: 0 : opt->nd_opt_type == ND_OPT_DNSSL ||
199 [ # # # # ]: 0 : opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL ||
200 : : ndisc_ops_is_useropt(dev, opt->nd_opt_type);
201 : : }
202 : :
203 : 0 : static struct nd_opt_hdr *ndisc_next_useropt(const struct net_device *dev,
204 : : struct nd_opt_hdr *cur,
205 : : struct nd_opt_hdr *end)
206 : : {
207 [ # # # # ]: 0 : if (!cur || !end || cur >= end)
208 : : return NULL;
209 : : do {
210 : 0 : cur = ((void *)cur) + (cur->nd_opt_len << 3);
211 [ # # # # ]: 0 : } while (cur < end && !ndisc_is_useropt(dev, cur));
212 [ # # # # ]: 0 : return cur <= end && ndisc_is_useropt(dev, cur) ? cur : NULL;
213 : : }
214 : :
215 : 0 : struct ndisc_options *ndisc_parse_options(const struct net_device *dev,
216 : : u8 *opt, int opt_len,
217 : : struct ndisc_options *ndopts)
218 : : {
219 : : struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
220 : :
221 [ # # # # ]: 0 : if (!nd_opt || opt_len < 0 || !ndopts)
222 : : return NULL;
223 : 0 : memset(ndopts, 0, sizeof(*ndopts));
224 [ # # ]: 0 : while (opt_len) {
225 : : int l;
226 [ # # ]: 0 : if (opt_len < sizeof(struct nd_opt_hdr))
227 : : return NULL;
228 : 0 : l = nd_opt->nd_opt_len << 3;
229 [ # # ]: 0 : if (opt_len < l || l == 0)
230 : : return NULL;
231 [ # # ]: 0 : if (ndisc_ops_parse_options(dev, nd_opt, ndopts))
232 : : goto next_opt;
233 [ # # # # ]: 0 : switch (nd_opt->nd_opt_type) {
234 : : case ND_OPT_SOURCE_LL_ADDR:
235 : : case ND_OPT_TARGET_LL_ADDR:
236 : : case ND_OPT_MTU:
237 : : case ND_OPT_NONCE:
238 : : case ND_OPT_REDIRECT_HDR:
239 [ # # ]: 0 : if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
240 : : ND_PRINTK(2, warn,
241 : : "%s: duplicated ND6 option found: type=%d\n",
242 : : __func__, nd_opt->nd_opt_type);
243 : : } else {
244 : 0 : ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
245 : : }
246 : : break;
247 : : case ND_OPT_PREFIX_INFO:
248 : 0 : ndopts->nd_opts_pi_end = nd_opt;
249 [ # # ]: 0 : if (!ndopts->nd_opt_array[nd_opt->nd_opt_type])
250 : 0 : ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
251 : : break;
252 : : #ifdef CONFIG_IPV6_ROUTE_INFO
253 : : case ND_OPT_ROUTE_INFO:
254 : 0 : ndopts->nd_opts_ri_end = nd_opt;
255 [ # # ]: 0 : if (!ndopts->nd_opts_ri)
256 : 0 : ndopts->nd_opts_ri = nd_opt;
257 : : break;
258 : : #endif
259 : : default:
260 [ # # ]: 0 : if (ndisc_is_useropt(dev, nd_opt)) {
261 : 0 : ndopts->nd_useropts_end = nd_opt;
262 [ # # ]: 0 : if (!ndopts->nd_useropts)
263 : 0 : ndopts->nd_useropts = nd_opt;
264 : : } else {
265 : : /*
266 : : * Unknown options must be silently ignored,
267 : : * to accommodate future extension to the
268 : : * protocol.
269 : : */
270 : : ND_PRINTK(2, notice,
271 : : "%s: ignored unsupported option; type=%d, len=%d\n",
272 : : __func__,
273 : : nd_opt->nd_opt_type,
274 : : nd_opt->nd_opt_len);
275 : : }
276 : : }
277 : : next_opt:
278 : 0 : opt_len -= l;
279 : 0 : nd_opt = ((void *)nd_opt) + l;
280 : : }
281 : : return ndopts;
282 : : }
283 : :
284 : 2866 : int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
285 : : {
286 [ + - - - : 2866 : switch (dev->type) {
+ ]
287 : : case ARPHRD_ETHER:
288 : : case ARPHRD_IEEE802: /* Not sure. Check it later. --ANK */
289 : : case ARPHRD_FDDI:
290 : : ipv6_eth_mc_map(addr, buf);
291 : 2659 : return 0;
292 : : case ARPHRD_ARCNET:
293 : : ipv6_arcnet_mc_map(addr, buf);
294 : 0 : return 0;
295 : : case ARPHRD_INFINIBAND:
296 : 0 : ipv6_ib_mc_map(addr, dev->broadcast, buf);
297 : 0 : return 0;
298 : : case ARPHRD_IPGRE:
299 : 0 : return ipv6_ipgre_mc_map(addr, dev->broadcast, buf);
300 : : default:
301 [ - + ]: 207 : if (dir) {
302 : 0 : memcpy(buf, dev->broadcast, dev->addr_len);
303 : 0 : return 0;
304 : : }
305 : : }
306 : : return -EINVAL;
307 : : }
308 : : EXPORT_SYMBOL(ndisc_mc_map);
309 : :
310 : 1210 : static u32 ndisc_hash(const void *pkey,
311 : : const struct net_device *dev,
312 : : __u32 *hash_rnd)
313 : : {
314 : 1210 : return ndisc_hashfn(pkey, dev, hash_rnd);
315 : : }
316 : :
317 : 0 : static bool ndisc_key_eq(const struct neighbour *n, const void *pkey)
318 : : {
319 : 0 : return neigh_key_eq128(n, pkey);
320 : : }
321 : :
322 : 1210 : static int ndisc_constructor(struct neighbour *neigh)
323 : : {
324 : 1210 : struct in6_addr *addr = (struct in6_addr *)&neigh->primary_key;
325 : 1210 : struct net_device *dev = neigh->dev;
326 : : struct inet6_dev *in6_dev;
327 : : struct neigh_parms *parms;
328 : : bool is_multicast = ipv6_addr_is_multicast(addr);
329 : :
330 : : in6_dev = in6_dev_get(dev);
331 [ + - ]: 1210 : if (!in6_dev) {
332 : : return -EINVAL;
333 : : }
334 : :
335 : 1210 : parms = in6_dev->nd_parms;
336 : 1210 : __neigh_parms_put(neigh->parms);
337 : 1210 : neigh->parms = neigh_parms_clone(parms);
338 : :
339 [ - + ]: 1210 : neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
340 [ - + ]: 1210 : if (!dev->header_ops) {
341 : 0 : neigh->nud_state = NUD_NOARP;
342 : 0 : neigh->ops = &ndisc_direct_ops;
343 : 0 : neigh->output = neigh_direct_output;
344 : : } else {
345 [ + - ]: 1210 : if (is_multicast) {
346 : 1210 : neigh->nud_state = NUD_NOARP;
347 : 1210 : ndisc_mc_map(addr, neigh->ha, dev, 1);
348 [ # # ]: 0 : } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
349 : 0 : neigh->nud_state = NUD_NOARP;
350 : 0 : memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
351 [ # # ]: 0 : if (dev->flags&IFF_LOOPBACK)
352 : 0 : neigh->type = RTN_LOCAL;
353 [ # # ]: 0 : } else if (dev->flags&IFF_POINTOPOINT) {
354 : 0 : neigh->nud_state = NUD_NOARP;
355 : 0 : memcpy(neigh->ha, dev->broadcast, dev->addr_len);
356 : : }
357 [ + - ]: 1210 : if (dev->header_ops->cache)
358 : 1210 : neigh->ops = &ndisc_hh_ops;
359 : : else
360 : 0 : neigh->ops = &ndisc_generic_ops;
361 [ + - ]: 1210 : if (neigh->nud_state&NUD_VALID)
362 : 1210 : neigh->output = neigh->ops->connected_output;
363 : : else
364 : 0 : neigh->output = neigh->ops->output;
365 : : }
366 : 1210 : in6_dev_put(in6_dev);
367 : 1210 : return 0;
368 : : }
369 : :
370 : 0 : static int pndisc_constructor(struct pneigh_entry *n)
371 : : {
372 : : struct in6_addr *addr = (struct in6_addr *)&n->key;
373 : : struct in6_addr maddr;
374 : 0 : struct net_device *dev = n->dev;
375 : :
376 [ # # # # ]: 0 : if (!dev || !__in6_dev_get(dev))
377 : : return -EINVAL;
378 : : addrconf_addr_solict_mult(addr, &maddr);
379 : 0 : ipv6_dev_mc_inc(dev, &maddr);
380 : 0 : return 0;
381 : : }
382 : :
383 : 0 : static void pndisc_destructor(struct pneigh_entry *n)
384 : : {
385 : : struct in6_addr *addr = (struct in6_addr *)&n->key;
386 : : struct in6_addr maddr;
387 : 0 : struct net_device *dev = n->dev;
388 : :
389 [ # # # # ]: 0 : if (!dev || !__in6_dev_get(dev))
390 : 0 : return;
391 : : addrconf_addr_solict_mult(addr, &maddr);
392 : 0 : ipv6_dev_mc_dec(dev, &maddr);
393 : : }
394 : :
395 : : /* called with rtnl held */
396 : 0 : static bool ndisc_allow_add(const struct net_device *dev,
397 : : struct netlink_ext_ack *extack)
398 : : {
399 : : struct inet6_dev *idev = __in6_dev_get(dev);
400 : :
401 [ # # # # ]: 0 : if (!idev || idev->cnf.disable_ipv6) {
402 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "IPv6 is disabled on this device");
403 : : return false;
404 : : }
405 : :
406 : : return true;
407 : : }
408 : :
409 : 392 : static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
410 : : int len)
411 : : {
412 : 392 : int hlen = LL_RESERVED_SPACE(dev);
413 : 392 : int tlen = dev->needed_tailroom;
414 : 392 : struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
415 : : struct sk_buff *skb;
416 : :
417 : 392 : skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
418 [ - + ]: 392 : if (!skb) {
419 [ # # ]: 0 : ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
420 : : __func__);
421 : : return NULL;
422 : : }
423 : :
424 : 392 : skb->protocol = htons(ETH_P_IPV6);
425 : 392 : skb->dev = dev;
426 : :
427 : 392 : skb_reserve(skb, hlen + sizeof(struct ipv6hdr));
428 : : skb_reset_transport_header(skb);
429 : :
430 : : /* Manually assign socket ownership as we avoid calling
431 : : * sock_alloc_send_pskb() to bypass wmem buffer limits
432 : : */
433 : 392 : skb_set_owner_w(skb, sk);
434 : :
435 : 392 : return skb;
436 : : }
437 : :
438 : 392 : static void ip6_nd_hdr(struct sk_buff *skb,
439 : : const struct in6_addr *saddr,
440 : : const struct in6_addr *daddr,
441 : : int hop_limit, int len)
442 : : {
443 : : struct ipv6hdr *hdr;
444 : : struct inet6_dev *idev;
445 : : unsigned tclass;
446 : :
447 : : rcu_read_lock();
448 : 392 : idev = __in6_dev_get(skb->dev);
449 [ + - ]: 392 : tclass = idev ? idev->cnf.ndisc_tclass : 0;
450 : : rcu_read_unlock();
451 : :
452 : 392 : skb_push(skb, sizeof(*hdr));
453 : : skb_reset_network_header(skb);
454 : : hdr = ipv6_hdr(skb);
455 : :
456 : : ip6_flow_hdr(hdr, tclass, 0);
457 : :
458 : 392 : hdr->payload_len = htons(len);
459 : 392 : hdr->nexthdr = IPPROTO_ICMPV6;
460 : 392 : hdr->hop_limit = hop_limit;
461 : :
462 : 392 : hdr->saddr = *saddr;
463 : 392 : hdr->daddr = *daddr;
464 : 392 : }
465 : :
466 : 392 : static void ndisc_send_skb(struct sk_buff *skb,
467 : : const struct in6_addr *daddr,
468 : : const struct in6_addr *saddr)
469 : : {
470 : : struct dst_entry *dst = skb_dst(skb);
471 : 392 : struct net *net = dev_net(skb->dev);
472 : 392 : struct sock *sk = net->ipv6.ndisc_sk;
473 : : struct inet6_dev *idev;
474 : : int err;
475 : : struct icmp6hdr *icmp6h = icmp6_hdr(skb);
476 : : u8 type;
477 : :
478 : 392 : type = icmp6h->icmp6_type;
479 : :
480 [ + - ]: 392 : if (!dst) {
481 : : struct flowi6 fl6;
482 : 392 : int oif = skb->dev->ifindex;
483 : :
484 : 392 : icmpv6_flow_init(sk, &fl6, type, saddr, daddr, oif);
485 : 392 : dst = icmp6_dst_alloc(skb->dev, &fl6);
486 [ - + ]: 392 : if (IS_ERR(dst)) {
487 : 0 : kfree_skb(skb);
488 : 392 : return;
489 : : }
490 : :
491 : : skb_dst_set(skb, dst);
492 : : }
493 : :
494 : 784 : icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, skb->len,
495 : : IPPROTO_ICMPV6,
496 : : csum_partial(icmp6h,
497 : 392 : skb->len, 0));
498 : :
499 : 392 : ip6_nd_hdr(skb, saddr, daddr, inet6_sk(sk)->hop_limit, skb->len);
500 : :
501 : : rcu_read_lock();
502 : 392 : idev = __in6_dev_get(dst->dev);
503 [ + - ]: 3920 : IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
504 : :
505 : 392 : err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
506 : : net, sk, skb, NULL, dst->dev,
507 : : dst_output);
508 [ + + ]: 392 : if (!err) {
509 [ + - ]: 758 : ICMP6MSGOUT_INC_STATS(net, idev, type);
510 [ + - ]: 1137 : ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
511 : : }
512 : :
513 : : rcu_read_unlock();
514 : : }
515 : :
516 : 0 : void ndisc_send_na(struct net_device *dev, const struct in6_addr *daddr,
517 : : const struct in6_addr *solicited_addr,
518 : : bool router, bool solicited, bool override, bool inc_opt)
519 : : {
520 : : struct sk_buff *skb;
521 : : struct in6_addr tmpaddr;
522 : : struct inet6_ifaddr *ifp;
523 : : const struct in6_addr *src_addr;
524 : : struct nd_msg *msg;
525 : : int optlen = 0;
526 : :
527 : : /* for anycast or proxy, solicited_addr != src_addr */
528 : 0 : ifp = ipv6_get_ifaddr(dev_net(dev), solicited_addr, dev, 1);
529 [ # # ]: 0 : if (ifp) {
530 : : src_addr = solicited_addr;
531 [ # # ]: 0 : if (ifp->flags & IFA_F_OPTIMISTIC)
532 : : override = false;
533 : 0 : inc_opt |= ifp->idev->cnf.force_tllao;
534 : 0 : in6_ifa_put(ifp);
535 : : } else {
536 [ # # ]: 0 : if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
537 : 0 : inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs,
538 : : &tmpaddr))
539 : 0 : return;
540 : : src_addr = &tmpaddr;
541 : : }
542 : :
543 [ # # ]: 0 : if (!dev->addr_len)
544 : : inc_opt = false;
545 [ # # ]: 0 : if (inc_opt)
546 : 0 : optlen += ndisc_opt_addr_space(dev,
547 : : NDISC_NEIGHBOUR_ADVERTISEMENT);
548 : :
549 : 0 : skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
550 [ # # ]: 0 : if (!skb)
551 : : return;
552 : :
553 : 0 : msg = skb_put(skb, sizeof(*msg));
554 : 0 : *msg = (struct nd_msg) {
555 : : .icmph = {
556 : : .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
557 : : .icmp6_router = router,
558 : : .icmp6_solicited = solicited,
559 : : .icmp6_override = override,
560 : : },
561 : 0 : .target = *solicited_addr,
562 : : };
563 : :
564 [ # # ]: 0 : if (inc_opt)
565 : 0 : ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR,
566 : 0 : dev->dev_addr,
567 : : NDISC_NEIGHBOUR_ADVERTISEMENT);
568 : :
569 : 0 : ndisc_send_skb(skb, daddr, src_addr);
570 : : }
571 : :
572 : 0 : static void ndisc_send_unsol_na(struct net_device *dev)
573 : : {
574 : : struct inet6_dev *idev;
575 : : struct inet6_ifaddr *ifa;
576 : :
577 : : idev = in6_dev_get(dev);
578 [ # # ]: 0 : if (!idev)
579 : 0 : return;
580 : :
581 : 0 : read_lock_bh(&idev->lock);
582 [ # # ]: 0 : list_for_each_entry(ifa, &idev->addr_list, if_list) {
583 : : /* skip tentative addresses until dad completes */
584 [ # # ]: 0 : if (ifa->flags & IFA_F_TENTATIVE &&
585 : : !(ifa->flags & IFA_F_OPTIMISTIC))
586 : 0 : continue;
587 : :
588 : 0 : ndisc_send_na(dev, &in6addr_linklocal_allnodes, &ifa->addr,
589 : 0 : /*router=*/ !!idev->cnf.forwarding,
590 : : /*solicited=*/ false, /*override=*/ true,
591 : : /*inc_opt=*/ true);
592 : : }
593 : 0 : read_unlock_bh(&idev->lock);
594 : :
595 : 0 : in6_dev_put(idev);
596 : : }
597 : :
598 : 392 : void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
599 : : const struct in6_addr *daddr, const struct in6_addr *saddr,
600 : : u64 nonce)
601 : : {
602 : : struct sk_buff *skb;
603 : : struct in6_addr addr_buf;
604 : 392 : int inc_opt = dev->addr_len;
605 : : int optlen = 0;
606 : : struct nd_msg *msg;
607 : :
608 [ - + ]: 392 : if (!saddr) {
609 [ # # ]: 0 : if (ipv6_get_lladdr(dev, &addr_buf,
610 : : (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)))
611 : 0 : return;
612 : : saddr = &addr_buf;
613 : : }
614 : :
615 [ + - ]: 392 : if (ipv6_addr_any(saddr))
616 : : inc_opt = false;
617 [ - + ]: 392 : if (inc_opt)
618 : 0 : optlen += ndisc_opt_addr_space(dev,
619 : : NDISC_NEIGHBOUR_SOLICITATION);
620 [ + - ]: 392 : if (nonce != 0)
621 : 392 : optlen += 8;
622 : :
623 : 392 : skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
624 [ + - ]: 392 : if (!skb)
625 : : return;
626 : :
627 : 392 : msg = skb_put(skb, sizeof(*msg));
628 : 392 : *msg = (struct nd_msg) {
629 : : .icmph = {
630 : : .icmp6_type = NDISC_NEIGHBOUR_SOLICITATION,
631 : : },
632 : 392 : .target = *solicit,
633 : : };
634 : :
635 [ - + ]: 392 : if (inc_opt)
636 : 0 : ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
637 : 0 : dev->dev_addr,
638 : : NDISC_NEIGHBOUR_SOLICITATION);
639 [ + - ]: 392 : if (nonce != 0) {
640 : 392 : u8 *opt = skb_put(skb, 8);
641 : :
642 : 392 : opt[0] = ND_OPT_NONCE;
643 : 392 : opt[1] = 8 >> 3;
644 : 392 : memcpy(opt + 2, &nonce, 6);
645 : : }
646 : :
647 : 392 : ndisc_send_skb(skb, daddr, saddr);
648 : : }
649 : :
650 : 0 : void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
651 : : const struct in6_addr *daddr)
652 : : {
653 : : struct sk_buff *skb;
654 : : struct rs_msg *msg;
655 : 0 : int send_sllao = dev->addr_len;
656 : : int optlen = 0;
657 : :
658 : : #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
659 : : /*
660 : : * According to section 2.2 of RFC 4429, we must not
661 : : * send router solicitations with a sllao from
662 : : * optimistic addresses, but we may send the solicitation
663 : : * if we don't include the sllao. So here we check
664 : : * if our address is optimistic, and if so, we
665 : : * suppress the inclusion of the sllao.
666 : : */
667 : : if (send_sllao) {
668 : : struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev_net(dev), saddr,
669 : : dev, 1);
670 : : if (ifp) {
671 : : if (ifp->flags & IFA_F_OPTIMISTIC) {
672 : : send_sllao = 0;
673 : : }
674 : : in6_ifa_put(ifp);
675 : : } else {
676 : : send_sllao = 0;
677 : : }
678 : : }
679 : : #endif
680 [ # # ]: 0 : if (send_sllao)
681 : 0 : optlen += ndisc_opt_addr_space(dev, NDISC_ROUTER_SOLICITATION);
682 : :
683 : 0 : skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
684 [ # # ]: 0 : if (!skb)
685 : 0 : return;
686 : :
687 : 0 : msg = skb_put(skb, sizeof(*msg));
688 : 0 : *msg = (struct rs_msg) {
689 : : .icmph = {
690 : : .icmp6_type = NDISC_ROUTER_SOLICITATION,
691 : : },
692 : : };
693 : :
694 [ # # ]: 0 : if (send_sllao)
695 : 0 : ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
696 : 0 : dev->dev_addr,
697 : : NDISC_ROUTER_SOLICITATION);
698 : :
699 : 0 : ndisc_send_skb(skb, daddr, saddr);
700 : : }
701 : :
702 : :
703 : 0 : static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
704 : : {
705 : : /*
706 : : * "The sender MUST return an ICMP
707 : : * destination unreachable"
708 : : */
709 : 0 : dst_link_failure(skb);
710 : 0 : kfree_skb(skb);
711 : 0 : }
712 : :
713 : : /* Called with locked neigh: either read or both */
714 : :
715 : 0 : static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
716 : : {
717 : : struct in6_addr *saddr = NULL;
718 : : struct in6_addr mcaddr;
719 : 0 : struct net_device *dev = neigh->dev;
720 : 0 : struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
721 : 0 : int probes = atomic_read(&neigh->probes);
722 : :
723 [ # # # # ]: 0 : if (skb && ipv6_chk_addr_and_flags(dev_net(dev), &ipv6_hdr(skb)->saddr,
724 : : dev, false, 1,
725 : : IFA_F_TENTATIVE|IFA_F_OPTIMISTIC))
726 : 0 : saddr = &ipv6_hdr(skb)->saddr;
727 : 0 : probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
728 [ # # ]: 0 : if (probes < 0) {
729 : : if (!(neigh->nud_state & NUD_VALID)) {
730 : : ND_PRINTK(1, dbg,
731 : : "%s: trying to ucast probe in NUD_INVALID: %pI6\n",
732 : : __func__, target);
733 : : }
734 : 0 : ndisc_send_ns(dev, target, target, saddr, 0);
735 [ # # ]: 0 : } else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
736 : 0 : neigh_app_ns(neigh);
737 : : } else {
738 : : addrconf_addr_solict_mult(target, &mcaddr);
739 : 0 : ndisc_send_ns(dev, target, &mcaddr, saddr, 0);
740 : : }
741 : 0 : }
742 : :
743 : 0 : static int pndisc_is_router(const void *pkey,
744 : : struct net_device *dev)
745 : : {
746 : : struct pneigh_entry *n;
747 : : int ret = -1;
748 : :
749 : 0 : read_lock_bh(&nd_tbl.lock);
750 : 0 : n = __pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev);
751 [ # # ]: 0 : if (n)
752 : 0 : ret = !!(n->flags & NTF_ROUTER);
753 : 0 : read_unlock_bh(&nd_tbl.lock);
754 : :
755 : 0 : return ret;
756 : : }
757 : :
758 : 0 : void ndisc_update(const struct net_device *dev, struct neighbour *neigh,
759 : : const u8 *lladdr, u8 new, u32 flags, u8 icmp6_type,
760 : : struct ndisc_options *ndopts)
761 : : {
762 : 0 : neigh_update(neigh, lladdr, new, flags, 0);
763 : : /* report ndisc ops about neighbour update */
764 : : ndisc_ops_update(dev, neigh, flags, icmp6_type, ndopts);
765 : 0 : }
766 : :
767 : 0 : static void ndisc_recv_ns(struct sk_buff *skb)
768 : : {
769 : : struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
770 : 0 : const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
771 : : const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
772 : : u8 *lladdr = NULL;
773 : 0 : u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
774 : : offsetof(struct nd_msg, opt));
775 : : struct ndisc_options ndopts;
776 : 0 : struct net_device *dev = skb->dev;
777 : : struct inet6_ifaddr *ifp;
778 : : struct inet6_dev *idev = NULL;
779 : : struct neighbour *neigh;
780 : 0 : int dad = ipv6_addr_any(saddr);
781 : : bool inc;
782 : : int is_router = -1;
783 : 0 : u64 nonce = 0;
784 : :
785 [ # # ]: 0 : if (skb->len < sizeof(struct nd_msg)) {
786 : : ND_PRINTK(2, warn, "NS: packet too short\n");
787 : 0 : return;
788 : : }
789 : :
790 [ # # ]: 0 : if (ipv6_addr_is_multicast(&msg->target)) {
791 : : ND_PRINTK(2, warn, "NS: multicast target address\n");
792 : : return;
793 : : }
794 : :
795 : : /*
796 : : * RFC2461 7.1.1:
797 : : * DAD has to be destined for solicited node multicast address.
798 : : */
799 [ # # # # ]: 0 : if (dad && !ipv6_addr_is_solict_mult(daddr)) {
800 : : ND_PRINTK(2, warn, "NS: bad DAD packet (wrong destination)\n");
801 : : return;
802 : : }
803 : :
804 [ # # ]: 0 : if (!ndisc_parse_options(dev, msg->opt, ndoptlen, &ndopts)) {
805 : : ND_PRINTK(2, warn, "NS: invalid ND options\n");
806 : : return;
807 : : }
808 : :
809 [ # # ]: 0 : if (ndopts.nd_opts_src_lladdr) {
810 : : lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
811 [ # # ]: 0 : if (!lladdr) {
812 : : ND_PRINTK(2, warn,
813 : : "NS: invalid link-layer address length\n");
814 : : return;
815 : : }
816 : :
817 : : /* RFC2461 7.1.1:
818 : : * If the IP source address is the unspecified address,
819 : : * there MUST NOT be source link-layer address option
820 : : * in the message.
821 : : */
822 [ # # ]: 0 : if (dad) {
823 : : ND_PRINTK(2, warn,
824 : : "NS: bad DAD packet (link-layer address option)\n");
825 : : return;
826 : : }
827 : : }
828 [ # # # # ]: 0 : if (ndopts.nd_opts_nonce && ndopts.nd_opts_nonce->nd_opt_len == 1)
829 : 0 : memcpy(&nonce, (u8 *)(ndopts.nd_opts_nonce + 1), 6);
830 : :
831 : : inc = ipv6_addr_is_multicast(daddr);
832 : :
833 : 0 : ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
834 [ # # ]: 0 : if (ifp) {
835 : : have_ifp:
836 [ # # ]: 0 : if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
837 [ # # ]: 0 : if (dad) {
838 [ # # # # ]: 0 : if (nonce != 0 && ifp->dad_nonce == nonce) {
839 : : u8 *np = (u8 *)&nonce;
840 : : /* Matching nonce if looped back */
841 : : ND_PRINTK(2, notice,
842 : : "%s: IPv6 DAD loopback for address %pI6c nonce %pM ignored\n",
843 : : ifp->idev->dev->name,
844 : : &ifp->addr, np);
845 : : goto out;
846 : : }
847 : : /*
848 : : * We are colliding with another node
849 : : * who is doing DAD
850 : : * so fail our DAD process
851 : : */
852 : 0 : addrconf_dad_failure(skb, ifp);
853 : 0 : return;
854 : : } else {
855 : : /*
856 : : * This is not a dad solicitation.
857 : : * If we are an optimistic node,
858 : : * we should respond.
859 : : * Otherwise, we should ignore it.
860 : : */
861 [ # # ]: 0 : if (!(ifp->flags & IFA_F_OPTIMISTIC))
862 : : goto out;
863 : : }
864 : : }
865 : :
866 : 0 : idev = ifp->idev;
867 : : } else {
868 : : struct net *net = dev_net(dev);
869 : :
870 : : /* perhaps an address on the master device */
871 [ # # ]: 0 : if (netif_is_l3_slave(dev)) {
872 : : struct net_device *mdev;
873 : :
874 : 0 : mdev = netdev_master_upper_dev_get_rcu(dev);
875 [ # # ]: 0 : if (mdev) {
876 : 0 : ifp = ipv6_get_ifaddr(net, &msg->target, mdev, 1);
877 [ # # ]: 0 : if (ifp)
878 : : goto have_ifp;
879 : : }
880 : : }
881 : :
882 : : idev = in6_dev_get(dev);
883 [ # # ]: 0 : if (!idev) {
884 : : /* XXX: count this drop? */
885 : : return;
886 : : }
887 : :
888 [ # # # # ]: 0 : if (ipv6_chk_acast_addr(net, dev, &msg->target) ||
889 [ # # ]: 0 : (idev->cnf.forwarding &&
890 [ # # # # ]: 0 : (net->ipv6.devconf_all->proxy_ndp || idev->cnf.proxy_ndp) &&
891 : : (is_router = pndisc_is_router(&msg->target, dev)) >= 0)) {
892 [ # # # # ]: 0 : if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
893 [ # # ]: 0 : skb->pkt_type != PACKET_HOST &&
894 [ # # ]: 0 : inc &&
895 : 0 : NEIGH_VAR(idev->nd_parms, PROXY_DELAY) != 0) {
896 : : /*
897 : : * for anycast or proxy,
898 : : * sender should delay its response
899 : : * by a random time between 0 and
900 : : * MAX_ANYCAST_DELAY_TIME seconds.
901 : : * (RFC2461) -- yoshfuji
902 : : */
903 : 0 : struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
904 [ # # ]: 0 : if (n)
905 : 0 : pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
906 : : goto out;
907 : : }
908 : : } else
909 : : goto out;
910 : : }
911 : :
912 [ # # ]: 0 : if (is_router < 0)
913 : 0 : is_router = idev->cnf.forwarding;
914 : :
915 [ # # ]: 0 : if (dad) {
916 : 0 : ndisc_send_na(dev, &in6addr_linklocal_allnodes, &msg->target,
917 : : !!is_router, false, (ifp != NULL), true);
918 : 0 : goto out;
919 : : }
920 : :
921 [ # # ]: 0 : if (inc)
922 : 0 : NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
923 : : else
924 : 0 : NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
925 : :
926 : : /*
927 : : * update / create cache entry
928 : : * for the source address
929 : : */
930 [ # # # # ]: 0 : neigh = __neigh_lookup(&nd_tbl, saddr, dev,
931 : 0 : !inc || lladdr || !dev->addr_len);
932 [ # # ]: 0 : if (neigh)
933 : 0 : ndisc_update(dev, neigh, lladdr, NUD_STALE,
934 : : NEIGH_UPDATE_F_WEAK_OVERRIDE|
935 : : NEIGH_UPDATE_F_OVERRIDE,
936 : : NDISC_NEIGHBOUR_SOLICITATION, &ndopts);
937 [ # # # # ]: 0 : if (neigh || !dev->header_ops) {
938 : 0 : ndisc_send_na(dev, saddr, &msg->target, !!is_router,
939 : 0 : true, (ifp != NULL && inc), inc);
940 [ # # ]: 0 : if (neigh)
941 : 0 : neigh_release(neigh);
942 : : }
943 : :
944 : : out:
945 [ # # ]: 0 : if (ifp)
946 : 0 : in6_ifa_put(ifp);
947 : : else
948 : 0 : in6_dev_put(idev);
949 : : }
950 : :
951 : 0 : static void ndisc_recv_na(struct sk_buff *skb)
952 : : {
953 : : struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
954 : 0 : struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
955 : : const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
956 : : u8 *lladdr = NULL;
957 : 0 : u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
958 : : offsetof(struct nd_msg, opt));
959 : : struct ndisc_options ndopts;
960 : 0 : struct net_device *dev = skb->dev;
961 : : struct inet6_dev *idev = __in6_dev_get(dev);
962 : : struct inet6_ifaddr *ifp;
963 : : struct neighbour *neigh;
964 : :
965 [ # # ]: 0 : if (skb->len < sizeof(struct nd_msg)) {
966 : : ND_PRINTK(2, warn, "NA: packet too short\n");
967 : 0 : return;
968 : : }
969 : :
970 [ # # ]: 0 : if (ipv6_addr_is_multicast(&msg->target)) {
971 : : ND_PRINTK(2, warn, "NA: target address is multicast\n");
972 : : return;
973 : : }
974 : :
975 [ # # # # ]: 0 : if (ipv6_addr_is_multicast(daddr) &&
976 : : msg->icmph.icmp6_solicited) {
977 : : ND_PRINTK(2, warn, "NA: solicited NA is multicasted\n");
978 : : return;
979 : : }
980 : :
981 : : /* For some 802.11 wireless deployments (and possibly other networks),
982 : : * there will be a NA proxy and unsolicitd packets are attacks
983 : : * and thus should not be accepted.
984 : : */
985 [ # # # # : 0 : if (!msg->icmph.icmp6_solicited && idev &&
# # ]
986 : 0 : idev->cnf.drop_unsolicited_na)
987 : : return;
988 : :
989 [ # # ]: 0 : if (!ndisc_parse_options(dev, msg->opt, ndoptlen, &ndopts)) {
990 : : ND_PRINTK(2, warn, "NS: invalid ND option\n");
991 : : return;
992 : : }
993 [ # # ]: 0 : if (ndopts.nd_opts_tgt_lladdr) {
994 : : lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
995 [ # # ]: 0 : if (!lladdr) {
996 : : ND_PRINTK(2, warn,
997 : : "NA: invalid link-layer address length\n");
998 : : return;
999 : : }
1000 : : }
1001 : 0 : ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
1002 [ # # ]: 0 : if (ifp) {
1003 [ # # ]: 0 : if (skb->pkt_type != PACKET_LOOPBACK
1004 [ # # ]: 0 : && (ifp->flags & IFA_F_TENTATIVE)) {
1005 : 0 : addrconf_dad_failure(skb, ifp);
1006 : 0 : return;
1007 : : }
1008 : : /* What should we make now? The advertisement
1009 : : is invalid, but ndisc specs say nothing
1010 : : about it. It could be misconfiguration, or
1011 : : an smart proxy agent tries to help us :-)
1012 : :
1013 : : We should not print the error if NA has been
1014 : : received from loopback - it is just our own
1015 : : unsolicited advertisement.
1016 : : */
1017 [ # # ]: 0 : if (skb->pkt_type != PACKET_LOOPBACK)
1018 [ # # ]: 0 : ND_PRINTK(1, warn,
1019 : : "NA: %pM advertised our address %pI6c on %s!\n",
1020 : : eth_hdr(skb)->h_source, &ifp->addr, ifp->idev->dev->name);
1021 : 0 : in6_ifa_put(ifp);
1022 : 0 : return;
1023 : : }
1024 : 0 : neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
1025 : :
1026 [ # # ]: 0 : if (neigh) {
1027 : 0 : u8 old_flags = neigh->flags;
1028 : : struct net *net = dev_net(dev);
1029 : :
1030 [ # # ]: 0 : if (neigh->nud_state & NUD_FAILED)
1031 : : goto out;
1032 : :
1033 : : /*
1034 : : * Don't update the neighbor cache entry on a proxy NA from
1035 : : * ourselves because either the proxied node is off link or it
1036 : : * has already sent a NA to us.
1037 : : */
1038 [ # # # # : 0 : if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
# # ]
1039 [ # # # # ]: 0 : net->ipv6.devconf_all->forwarding && net->ipv6.devconf_all->proxy_ndp &&
1040 : 0 : pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
1041 : : /* XXX: idev->cnf.proxy_ndp */
1042 : : goto out;
1043 : : }
1044 : :
1045 [ # # ]: 0 : ndisc_update(dev, neigh, lladdr,
1046 : 0 : msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
1047 : : NEIGH_UPDATE_F_WEAK_OVERRIDE|
1048 [ # # ]: 0 : (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
1049 : 0 : NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
1050 [ # # ]: 0 : (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0),
1051 : : NDISC_NEIGHBOUR_ADVERTISEMENT, &ndopts);
1052 : :
1053 [ # # ]: 0 : if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
1054 : : /*
1055 : : * Change: router to host
1056 : : */
1057 : 0 : rt6_clean_tohost(dev_net(dev), saddr);
1058 : : }
1059 : :
1060 : : out:
1061 : 0 : neigh_release(neigh);
1062 : : }
1063 : : }
1064 : :
1065 : 0 : static void ndisc_recv_rs(struct sk_buff *skb)
1066 : : {
1067 : : struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb);
1068 : 0 : unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
1069 : : struct neighbour *neigh;
1070 : : struct inet6_dev *idev;
1071 : 0 : const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
1072 : : struct ndisc_options ndopts;
1073 : : u8 *lladdr = NULL;
1074 : :
1075 [ # # ]: 0 : if (skb->len < sizeof(*rs_msg))
1076 : : return;
1077 : :
1078 : 0 : idev = __in6_dev_get(skb->dev);
1079 [ # # ]: 0 : if (!idev) {
1080 [ # # ]: 0 : ND_PRINTK(1, err, "RS: can't find in6 device\n");
1081 : : return;
1082 : : }
1083 : :
1084 : : /* Don't accept RS if we're not in router mode */
1085 [ # # ]: 0 : if (!idev->cnf.forwarding)
1086 : : goto out;
1087 : :
1088 : : /*
1089 : : * Don't update NCE if src = ::;
1090 : : * this implies that the source node has no ip address assigned yet.
1091 : : */
1092 [ # # ]: 0 : if (ipv6_addr_any(saddr))
1093 : : goto out;
1094 : :
1095 : : /* Parse ND options */
1096 [ # # ]: 0 : if (!ndisc_parse_options(skb->dev, rs_msg->opt, ndoptlen, &ndopts)) {
1097 : : ND_PRINTK(2, notice, "NS: invalid ND option, ignored\n");
1098 : : goto out;
1099 : : }
1100 : :
1101 [ # # ]: 0 : if (ndopts.nd_opts_src_lladdr) {
1102 : 0 : lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1103 : : skb->dev);
1104 [ # # ]: 0 : if (!lladdr)
1105 : : goto out;
1106 : : }
1107 : :
1108 : 0 : neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
1109 [ # # ]: 0 : if (neigh) {
1110 : 0 : ndisc_update(skb->dev, neigh, lladdr, NUD_STALE,
1111 : : NEIGH_UPDATE_F_WEAK_OVERRIDE|
1112 : : NEIGH_UPDATE_F_OVERRIDE|
1113 : : NEIGH_UPDATE_F_OVERRIDE_ISROUTER,
1114 : : NDISC_ROUTER_SOLICITATION, &ndopts);
1115 : 0 : neigh_release(neigh);
1116 : : }
1117 : : out:
1118 : : return;
1119 : : }
1120 : :
1121 : 0 : static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
1122 : : {
1123 : : struct icmp6hdr *icmp6h = (struct icmp6hdr *)skb_transport_header(ra);
1124 : : struct sk_buff *skb;
1125 : : struct nlmsghdr *nlh;
1126 : : struct nduseroptmsg *ndmsg;
1127 : 0 : struct net *net = dev_net(ra->dev);
1128 : : int err;
1129 : 0 : int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg)
1130 : : + (opt->nd_opt_len << 3));
1131 : 0 : size_t msg_size = base_size + nla_total_size(sizeof(struct in6_addr));
1132 : :
1133 : : skb = nlmsg_new(msg_size, GFP_ATOMIC);
1134 [ # # ]: 0 : if (!skb) {
1135 : : err = -ENOBUFS;
1136 : : goto errout;
1137 : : }
1138 : :
1139 : 0 : nlh = nlmsg_put(skb, 0, 0, RTM_NEWNDUSEROPT, base_size, 0);
1140 [ # # ]: 0 : if (!nlh) {
1141 : : goto nla_put_failure;
1142 : : }
1143 : :
1144 : : ndmsg = nlmsg_data(nlh);
1145 : 0 : ndmsg->nduseropt_family = AF_INET6;
1146 : 0 : ndmsg->nduseropt_ifindex = ra->dev->ifindex;
1147 : 0 : ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type;
1148 : 0 : ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code;
1149 : 0 : ndmsg->nduseropt_opts_len = opt->nd_opt_len << 3;
1150 : :
1151 : 0 : memcpy(ndmsg + 1, opt, opt->nd_opt_len << 3);
1152 : :
1153 [ # # ]: 0 : if (nla_put_in6_addr(skb, NDUSEROPT_SRCADDR, &ipv6_hdr(ra)->saddr))
1154 : : goto nla_put_failure;
1155 : : nlmsg_end(skb, nlh);
1156 : :
1157 : 0 : rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, GFP_ATOMIC);
1158 : 0 : return;
1159 : :
1160 : : nla_put_failure:
1161 : : nlmsg_free(skb);
1162 : : err = -EMSGSIZE;
1163 : : errout:
1164 : 0 : rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
1165 : : }
1166 : :
1167 : 0 : static void ndisc_router_discovery(struct sk_buff *skb)
1168 : : {
1169 : : struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
1170 : : struct neighbour *neigh = NULL;
1171 : : struct inet6_dev *in6_dev;
1172 : : struct fib6_info *rt = NULL;
1173 : : struct net *net;
1174 : : int lifetime;
1175 : : struct ndisc_options ndopts;
1176 : : int optlen;
1177 : : unsigned int pref = 0;
1178 : : __u32 old_if_flags;
1179 : : bool send_ifinfo_notify = false;
1180 : :
1181 : 0 : __u8 *opt = (__u8 *)(ra_msg + 1);
1182 : :
1183 : 0 : optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) -
1184 : : sizeof(struct ra_msg);
1185 : :
1186 : : ND_PRINTK(2, info,
1187 : : "RA: %s, dev: %s\n",
1188 : : __func__, skb->dev->name);
1189 [ # # ]: 0 : if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
1190 : : ND_PRINTK(2, warn, "RA: source address is not link-local\n");
1191 : 0 : return;
1192 : : }
1193 [ # # ]: 0 : if (optlen < 0) {
1194 : : ND_PRINTK(2, warn, "RA: packet too short\n");
1195 : : return;
1196 : : }
1197 : :
1198 : : #ifdef CONFIG_IPV6_NDISC_NODETYPE
1199 [ # # ]: 0 : if (skb->ndisc_nodetype == NDISC_NODETYPE_HOST) {
1200 : : ND_PRINTK(2, warn, "RA: from host or unauthorized router\n");
1201 : : return;
1202 : : }
1203 : : #endif
1204 : :
1205 : : /*
1206 : : * set the RA_RECV flag in the interface
1207 : : */
1208 : :
1209 : 0 : in6_dev = __in6_dev_get(skb->dev);
1210 [ # # ]: 0 : if (!in6_dev) {
1211 [ # # ]: 0 : ND_PRINTK(0, err, "RA: can't find inet6 device for %s\n",
1212 : : skb->dev->name);
1213 : : return;
1214 : : }
1215 : :
1216 [ # # ]: 0 : if (!ndisc_parse_options(skb->dev, opt, optlen, &ndopts)) {
1217 : : ND_PRINTK(2, warn, "RA: invalid ND options\n");
1218 : : return;
1219 : : }
1220 : :
1221 [ # # ]: 0 : if (!ipv6_accept_ra(in6_dev)) {
1222 : : ND_PRINTK(2, info,
1223 : : "RA: %s, did not accept ra for dev: %s\n",
1224 : : __func__, skb->dev->name);
1225 : : goto skip_linkparms;
1226 : : }
1227 : :
1228 : : #ifdef CONFIG_IPV6_NDISC_NODETYPE
1229 : : /* skip link-specific parameters from interior routers */
1230 [ # # ]: 0 : if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) {
1231 : : ND_PRINTK(2, info,
1232 : : "RA: %s, nodetype is NODEFAULT, dev: %s\n",
1233 : : __func__, skb->dev->name);
1234 : : goto skip_linkparms;
1235 : : }
1236 : : #endif
1237 : :
1238 [ # # ]: 0 : if (in6_dev->if_flags & IF_RS_SENT) {
1239 : : /*
1240 : : * flag that an RA was received after an RS was sent
1241 : : * out on this interface.
1242 : : */
1243 : 0 : in6_dev->if_flags |= IF_RA_RCVD;
1244 : : }
1245 : :
1246 : : /*
1247 : : * Remember the managed/otherconf flags from most recently
1248 : : * received RA message (RFC 2462) -- yoshfuji
1249 : : */
1250 : 0 : old_if_flags = in6_dev->if_flags;
1251 : 0 : in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
1252 [ # # ]: 0 : IF_RA_OTHERCONF)) |
1253 : 0 : (ra_msg->icmph.icmp6_addrconf_managed ?
1254 [ # # ]: 0 : IF_RA_MANAGED : 0) |
1255 : 0 : (ra_msg->icmph.icmp6_addrconf_other ?
1256 : : IF_RA_OTHERCONF : 0);
1257 : :
1258 [ # # ]: 0 : if (old_if_flags != in6_dev->if_flags)
1259 : : send_ifinfo_notify = true;
1260 : :
1261 [ # # ]: 0 : if (!in6_dev->cnf.accept_ra_defrtr) {
1262 : : ND_PRINTK(2, info,
1263 : : "RA: %s, defrtr is false for dev: %s\n",
1264 : : __func__, skb->dev->name);
1265 : : goto skip_defrtr;
1266 : : }
1267 : :
1268 : : /* Do not accept RA with source-addr found on local machine unless
1269 : : * accept_ra_from_local is set to true.
1270 : : */
1271 : 0 : net = dev_net(in6_dev->dev);
1272 [ # # # # ]: 0 : if (!in6_dev->cnf.accept_ra_from_local &&
1273 : 0 : ipv6_chk_addr(net, &ipv6_hdr(skb)->saddr, in6_dev->dev, 0)) {
1274 : : ND_PRINTK(2, info,
1275 : : "RA from local address detected on dev: %s: default router ignored\n",
1276 : : skb->dev->name);
1277 : : goto skip_defrtr;
1278 : : }
1279 : :
1280 : 0 : lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
1281 : :
1282 : : #ifdef CONFIG_IPV6_ROUTER_PREF
1283 : 0 : pref = ra_msg->icmph.icmp6_router_pref;
1284 : : /* 10b is handled as if it were 00b (medium) */
1285 [ # # # # ]: 0 : if (pref == ICMPV6_ROUTER_PREF_INVALID ||
1286 : 0 : !in6_dev->cnf.accept_ra_rtr_pref)
1287 : : pref = ICMPV6_ROUTER_PREF_MEDIUM;
1288 : : #endif
1289 : : /* routes added from RAs do not use nexthop objects */
1290 : 0 : rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev);
1291 [ # # ]: 0 : if (rt) {
1292 : 0 : neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
1293 : : rt->fib6_nh->fib_nh_dev, NULL,
1294 : 0 : &ipv6_hdr(skb)->saddr);
1295 [ # # ]: 0 : if (!neigh) {
1296 [ # # ]: 0 : ND_PRINTK(0, err,
1297 : : "RA: %s got default router without neighbour\n",
1298 : : __func__);
1299 : 0 : fib6_info_release(rt);
1300 : 0 : return;
1301 : : }
1302 : : }
1303 [ # # ]: 0 : if (rt && lifetime == 0) {
1304 : 0 : ip6_del_rt(net, rt);
1305 : : rt = NULL;
1306 : : }
1307 : :
1308 : : ND_PRINTK(3, info, "RA: rt: %p lifetime: %d, for dev: %s\n",
1309 : : rt, lifetime, skb->dev->name);
1310 [ # # ]: 0 : if (!rt && lifetime) {
1311 : : ND_PRINTK(3, info, "RA: adding default router\n");
1312 : :
1313 : 0 : rt = rt6_add_dflt_router(net, &ipv6_hdr(skb)->saddr,
1314 : : skb->dev, pref);
1315 [ # # ]: 0 : if (!rt) {
1316 [ # # ]: 0 : ND_PRINTK(0, err,
1317 : : "RA: %s failed to add default route\n",
1318 : : __func__);
1319 : : return;
1320 : : }
1321 : :
1322 : 0 : neigh = ip6_neigh_lookup(&rt->fib6_nh->fib_nh_gw6,
1323 : : rt->fib6_nh->fib_nh_dev, NULL,
1324 : 0 : &ipv6_hdr(skb)->saddr);
1325 [ # # ]: 0 : if (!neigh) {
1326 [ # # ]: 0 : ND_PRINTK(0, err,
1327 : : "RA: %s got default router without neighbour\n",
1328 : : __func__);
1329 : 0 : fib6_info_release(rt);
1330 : 0 : return;
1331 : : }
1332 : 0 : neigh->flags |= NTF_ROUTER;
1333 [ # # ]: 0 : } else if (rt) {
1334 : 0 : rt->fib6_flags = (rt->fib6_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
1335 : : }
1336 : :
1337 [ # # ]: 0 : if (rt)
1338 : 0 : fib6_set_expires(rt, jiffies + (HZ * lifetime));
1339 [ # # # # ]: 0 : if (in6_dev->cnf.accept_ra_min_hop_limit < 256 &&
1340 : 0 : ra_msg->icmph.icmp6_hop_limit) {
1341 [ # # ]: 0 : if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) {
1342 : 0 : in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1343 : 0 : fib6_metric_set(rt, RTAX_HOPLIMIT,
1344 : 0 : ra_msg->icmph.icmp6_hop_limit);
1345 : : } else {
1346 : : ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than minimum\n");
1347 : : }
1348 : : }
1349 : :
1350 : : skip_defrtr:
1351 : :
1352 : : /*
1353 : : * Update Reachable Time and Retrans Timer
1354 : : */
1355 : :
1356 [ # # ]: 0 : if (in6_dev->nd_parms) {
1357 : 0 : unsigned long rtime = ntohl(ra_msg->retrans_timer);
1358 : :
1359 [ # # ]: 0 : if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
1360 : 0 : rtime = (rtime*HZ)/1000;
1361 [ # # ]: 0 : if (rtime < HZ/10)
1362 : : rtime = HZ/10;
1363 : 0 : NEIGH_VAR_SET(in6_dev->nd_parms, RETRANS_TIME, rtime);
1364 : 0 : in6_dev->tstamp = jiffies;
1365 : : send_ifinfo_notify = true;
1366 : : }
1367 : :
1368 : 0 : rtime = ntohl(ra_msg->reachable_time);
1369 [ # # ]: 0 : if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
1370 : 0 : rtime = (rtime*HZ)/1000;
1371 : :
1372 [ # # ]: 0 : if (rtime < HZ/10)
1373 : : rtime = HZ/10;
1374 : :
1375 [ # # ]: 0 : if (rtime != NEIGH_VAR(in6_dev->nd_parms, BASE_REACHABLE_TIME)) {
1376 : 0 : NEIGH_VAR_SET(in6_dev->nd_parms,
1377 : : BASE_REACHABLE_TIME, rtime);
1378 : 0 : NEIGH_VAR_SET(in6_dev->nd_parms,
1379 : : GC_STALETIME, 3 * rtime);
1380 : 0 : in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
1381 : 0 : in6_dev->tstamp = jiffies;
1382 : : send_ifinfo_notify = true;
1383 : : }
1384 : : }
1385 : : }
1386 : :
1387 : : /*
1388 : : * Send a notify if RA changed managed/otherconf flags or timer settings
1389 : : */
1390 [ # # ]: 0 : if (send_ifinfo_notify)
1391 : 0 : inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
1392 : :
1393 : : skip_linkparms:
1394 : :
1395 : : /*
1396 : : * Process options.
1397 : : */
1398 : :
1399 [ # # ]: 0 : if (!neigh)
1400 : 0 : neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr,
1401 : : skb->dev, 1);
1402 [ # # ]: 0 : if (neigh) {
1403 : : u8 *lladdr = NULL;
1404 [ # # ]: 0 : if (ndopts.nd_opts_src_lladdr) {
1405 : 0 : lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
1406 : : skb->dev);
1407 [ # # ]: 0 : if (!lladdr) {
1408 : : ND_PRINTK(2, warn,
1409 : : "RA: invalid link-layer address length\n");
1410 : : goto out;
1411 : : }
1412 : : }
1413 : 0 : ndisc_update(skb->dev, neigh, lladdr, NUD_STALE,
1414 : : NEIGH_UPDATE_F_WEAK_OVERRIDE|
1415 : : NEIGH_UPDATE_F_OVERRIDE|
1416 : : NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
1417 : : NEIGH_UPDATE_F_ISROUTER,
1418 : : NDISC_ROUTER_ADVERTISEMENT, &ndopts);
1419 : : }
1420 : :
1421 [ # # ]: 0 : if (!ipv6_accept_ra(in6_dev)) {
1422 : : ND_PRINTK(2, info,
1423 : : "RA: %s, accept_ra is false for dev: %s\n",
1424 : : __func__, skb->dev->name);
1425 : : goto out;
1426 : : }
1427 : :
1428 : : #ifdef CONFIG_IPV6_ROUTE_INFO
1429 [ # # # # ]: 0 : if (!in6_dev->cnf.accept_ra_from_local &&
1430 : 0 : ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
1431 : : in6_dev->dev, 0)) {
1432 : : ND_PRINTK(2, info,
1433 : : "RA from local address detected on dev: %s: router info ignored.\n",
1434 : : skb->dev->name);
1435 : : goto skip_routeinfo;
1436 : : }
1437 : :
1438 [ # # # # ]: 0 : if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
1439 : : struct nd_opt_hdr *p;
1440 [ # # ]: 0 : for (p = ndopts.nd_opts_ri;
1441 : : p;
1442 : 0 : p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
1443 : : struct route_info *ri = (struct route_info *)p;
1444 : : #ifdef CONFIG_IPV6_NDISC_NODETYPE
1445 [ # # # # ]: 0 : if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT &&
1446 : 0 : ri->prefix_len == 0)
1447 : 0 : continue;
1448 : : #endif
1449 [ # # # # ]: 0 : if (ri->prefix_len == 0 &&
1450 : 0 : !in6_dev->cnf.accept_ra_defrtr)
1451 : 0 : continue;
1452 [ # # ]: 0 : if (ri->prefix_len < in6_dev->cnf.accept_ra_rt_info_min_plen)
1453 : 0 : continue;
1454 [ # # ]: 0 : if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
1455 : 0 : continue;
1456 : 0 : rt6_route_rcv(skb->dev, (u8 *)p, (p->nd_opt_len) << 3,
1457 : 0 : &ipv6_hdr(skb)->saddr);
1458 : : }
1459 : : }
1460 : :
1461 : : skip_routeinfo:
1462 : : #endif
1463 : :
1464 : : #ifdef CONFIG_IPV6_NDISC_NODETYPE
1465 : : /* skip link-specific ndopts from interior routers */
1466 [ # # ]: 0 : if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) {
1467 : : ND_PRINTK(2, info,
1468 : : "RA: %s, nodetype is NODEFAULT (interior routes), dev: %s\n",
1469 : : __func__, skb->dev->name);
1470 : : goto out;
1471 : : }
1472 : : #endif
1473 : :
1474 [ # # # # ]: 0 : if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
1475 : : struct nd_opt_hdr *p;
1476 [ # # ]: 0 : for (p = ndopts.nd_opts_pi;
1477 : : p;
1478 : 0 : p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
1479 : 0 : addrconf_prefix_rcv(skb->dev, (u8 *)p,
1480 : 0 : (p->nd_opt_len) << 3,
1481 : 0 : ndopts.nd_opts_src_lladdr != NULL);
1482 : : }
1483 : : }
1484 : :
1485 [ # # # # ]: 0 : if (ndopts.nd_opts_mtu && in6_dev->cnf.accept_ra_mtu) {
1486 : : __be32 n;
1487 : : u32 mtu;
1488 : :
1489 : 0 : memcpy(&n, ((u8 *)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
1490 : 0 : mtu = ntohl(n);
1491 : :
1492 [ # # # # ]: 0 : if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
1493 : : ND_PRINTK(2, warn, "RA: invalid mtu: %d\n", mtu);
1494 [ # # ]: 0 : } else if (in6_dev->cnf.mtu6 != mtu) {
1495 : 0 : in6_dev->cnf.mtu6 = mtu;
1496 : 0 : fib6_metric_set(rt, RTAX_MTU, mtu);
1497 : 0 : rt6_mtu_change(skb->dev, mtu);
1498 : : }
1499 : : }
1500 : :
1501 [ # # ]: 0 : if (ndopts.nd_useropts) {
1502 : : struct nd_opt_hdr *p;
1503 [ # # ]: 0 : for (p = ndopts.nd_useropts;
1504 : : p;
1505 : 0 : p = ndisc_next_useropt(skb->dev, p,
1506 : : ndopts.nd_useropts_end)) {
1507 : 0 : ndisc_ra_useropt(skb, p);
1508 : : }
1509 : : }
1510 : :
1511 : : if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
1512 : : ND_PRINTK(2, warn, "RA: invalid RA options\n");
1513 : : }
1514 : : out:
1515 : 0 : fib6_info_release(rt);
1516 [ # # ]: 0 : if (neigh)
1517 : 0 : neigh_release(neigh);
1518 : : }
1519 : :
1520 : 0 : static void ndisc_redirect_rcv(struct sk_buff *skb)
1521 : : {
1522 : : u8 *hdr;
1523 : : struct ndisc_options ndopts;
1524 : : struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
1525 : 0 : u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
1526 : : offsetof(struct rd_msg, opt));
1527 : :
1528 : : #ifdef CONFIG_IPV6_NDISC_NODETYPE
1529 [ # # ]: 0 : switch (skb->ndisc_nodetype) {
1530 : : case NDISC_NODETYPE_HOST:
1531 : : case NDISC_NODETYPE_NODEFAULT:
1532 : : ND_PRINTK(2, warn,
1533 : : "Redirect: from host or unauthorized router\n");
1534 : 0 : return;
1535 : : }
1536 : : #endif
1537 : :
1538 [ # # ]: 0 : if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
1539 : : ND_PRINTK(2, warn,
1540 : : "Redirect: source address is not link-local\n");
1541 : : return;
1542 : : }
1543 : :
1544 [ # # ]: 0 : if (!ndisc_parse_options(skb->dev, msg->opt, ndoptlen, &ndopts))
1545 : : return;
1546 : :
1547 [ # # ]: 0 : if (!ndopts.nd_opts_rh) {
1548 : 0 : ip6_redirect_no_header(skb, dev_net(skb->dev),
1549 : : skb->dev->ifindex);
1550 : 0 : return;
1551 : : }
1552 : :
1553 : : hdr = (u8 *)ndopts.nd_opts_rh;
1554 : 0 : hdr += 8;
1555 [ # # ]: 0 : if (!pskb_pull(skb, hdr - skb_transport_header(skb)))
1556 : : return;
1557 : :
1558 : 0 : icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
1559 : : }
1560 : :
1561 : 0 : static void ndisc_fill_redirect_hdr_option(struct sk_buff *skb,
1562 : : struct sk_buff *orig_skb,
1563 : : int rd_len)
1564 : : {
1565 : 0 : u8 *opt = skb_put(skb, rd_len);
1566 : :
1567 : 0 : memset(opt, 0, 8);
1568 : 0 : *(opt++) = ND_OPT_REDIRECT_HDR;
1569 : 0 : *(opt++) = (rd_len >> 3);
1570 : 0 : opt += 6;
1571 : :
1572 : 0 : skb_copy_bits(orig_skb, skb_network_offset(orig_skb), opt,
1573 : : rd_len - 8);
1574 : 0 : }
1575 : :
1576 : 0 : void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
1577 : : {
1578 : 0 : struct net_device *dev = skb->dev;
1579 : : struct net *net = dev_net(dev);
1580 : 0 : struct sock *sk = net->ipv6.ndisc_sk;
1581 : : int optlen = 0;
1582 : : struct inet_peer *peer;
1583 : : struct sk_buff *buff;
1584 : : struct rd_msg *msg;
1585 : : struct in6_addr saddr_buf;
1586 : : struct rt6_info *rt;
1587 : : struct dst_entry *dst;
1588 : : struct flowi6 fl6;
1589 : : int rd_len;
1590 : : u8 ha_buf[MAX_ADDR_LEN], *ha = NULL,
1591 : 0 : ops_data_buf[NDISC_OPS_REDIRECT_DATA_SPACE], *ops_data = NULL;
1592 : : bool ret;
1593 : :
1594 [ # # ]: 0 : if (netif_is_l3_master(skb->dev)) {
1595 : 0 : dev = __dev_get_by_index(dev_net(skb->dev), IPCB(skb)->iif);
1596 [ # # ]: 0 : if (!dev)
1597 : 0 : return;
1598 : : }
1599 : :
1600 [ # # ]: 0 : if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) {
1601 : : ND_PRINTK(2, warn, "Redirect: no link-local address on %s\n",
1602 : : dev->name);
1603 : : return;
1604 : : }
1605 : :
1606 [ # # # # ]: 0 : if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
1607 : : ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
1608 : : ND_PRINTK(2, warn,
1609 : : "Redirect: target address is not link-local unicast\n");
1610 : : return;
1611 : : }
1612 : :
1613 : 0 : icmpv6_flow_init(sk, &fl6, NDISC_REDIRECT,
1614 : 0 : &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex);
1615 : :
1616 : : dst = ip6_route_output(net, NULL, &fl6);
1617 [ # # ]: 0 : if (dst->error) {
1618 : 0 : dst_release(dst);
1619 : 0 : return;
1620 : : }
1621 : 0 : dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
1622 [ # # ]: 0 : if (IS_ERR(dst))
1623 : : return;
1624 : :
1625 : : rt = (struct rt6_info *) dst;
1626 : :
1627 [ # # ]: 0 : if (rt->rt6i_flags & RTF_GATEWAY) {
1628 : : ND_PRINTK(2, warn,
1629 : : "Redirect: destination is not a neighbour\n");
1630 : : goto release;
1631 : : }
1632 : 0 : peer = inet_getpeer_v6(net->ipv6.peers, &ipv6_hdr(skb)->saddr, 1);
1633 : 0 : ret = inet_peer_xrlim_allow(peer, 1*HZ);
1634 [ # # ]: 0 : if (peer)
1635 : 0 : inet_putpeer(peer);
1636 [ # # ]: 0 : if (!ret)
1637 : : goto release;
1638 : :
1639 [ # # ]: 0 : if (dev->addr_len) {
1640 : : struct neighbour *neigh = dst_neigh_lookup(skb_dst(skb), target);
1641 [ # # ]: 0 : if (!neigh) {
1642 : : ND_PRINTK(2, warn,
1643 : : "Redirect: no neigh for target address\n");
1644 : : goto release;
1645 : : }
1646 : :
1647 : 0 : read_lock_bh(&neigh->lock);
1648 [ # # ]: 0 : if (neigh->nud_state & NUD_VALID) {
1649 : 0 : memcpy(ha_buf, neigh->ha, dev->addr_len);
1650 : 0 : read_unlock_bh(&neigh->lock);
1651 : : ha = ha_buf;
1652 : 0 : optlen += ndisc_redirect_opt_addr_space(dev, neigh,
1653 : : ops_data_buf,
1654 : : &ops_data);
1655 : : } else
1656 : 0 : read_unlock_bh(&neigh->lock);
1657 : :
1658 : 0 : neigh_release(neigh);
1659 : : }
1660 : :
1661 : 0 : rd_len = min_t(unsigned int,
1662 : : IPV6_MIN_MTU - sizeof(struct ipv6hdr) - sizeof(*msg) - optlen,
1663 : : skb->len + 8);
1664 : 0 : rd_len &= ~0x7;
1665 : 0 : optlen += rd_len;
1666 : :
1667 : 0 : buff = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
1668 [ # # ]: 0 : if (!buff)
1669 : : goto release;
1670 : :
1671 : 0 : msg = skb_put(buff, sizeof(*msg));
1672 : 0 : *msg = (struct rd_msg) {
1673 : : .icmph = {
1674 : : .icmp6_type = NDISC_REDIRECT,
1675 : : },
1676 : 0 : .target = *target,
1677 : 0 : .dest = ipv6_hdr(skb)->daddr,
1678 : : };
1679 : :
1680 : : /*
1681 : : * include target_address option
1682 : : */
1683 : :
1684 [ # # ]: 0 : if (ha)
1685 : 0 : ndisc_fill_redirect_addr_option(buff, ha, ops_data);
1686 : :
1687 : : /*
1688 : : * build redirect option and copy skb over to the new packet.
1689 : : */
1690 : :
1691 [ # # ]: 0 : if (rd_len)
1692 : 0 : ndisc_fill_redirect_hdr_option(buff, skb, rd_len);
1693 : :
1694 : : skb_dst_set(buff, dst);
1695 : 0 : ndisc_send_skb(buff, &ipv6_hdr(skb)->saddr, &saddr_buf);
1696 : 0 : return;
1697 : :
1698 : : release:
1699 : 0 : dst_release(dst);
1700 : : }
1701 : :
1702 : 0 : static void pndisc_redo(struct sk_buff *skb)
1703 : : {
1704 : 0 : ndisc_recv_ns(skb);
1705 : 0 : kfree_skb(skb);
1706 : 0 : }
1707 : :
1708 : 0 : static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
1709 : : {
1710 : 0 : struct inet6_dev *idev = __in6_dev_get(skb->dev);
1711 : :
1712 [ # # ]: 0 : if (!idev)
1713 : : return true;
1714 [ # # # # ]: 0 : if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED &&
1715 : 0 : idev->cnf.suppress_frag_ndisc) {
1716 [ # # ]: 0 : net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n");
1717 : : return true;
1718 : : }
1719 : : return false;
1720 : : }
1721 : :
1722 : 0 : int ndisc_rcv(struct sk_buff *skb)
1723 : : {
1724 : : struct nd_msg *msg;
1725 : :
1726 [ # # ]: 0 : if (ndisc_suppress_frag_ndisc(skb))
1727 : : return 0;
1728 : :
1729 [ # # ]: 0 : if (skb_linearize(skb))
1730 : : return 0;
1731 : :
1732 : : msg = (struct nd_msg *)skb_transport_header(skb);
1733 : :
1734 : 0 : __skb_push(skb, skb->data - skb_transport_header(skb));
1735 : :
1736 [ # # ]: 0 : if (ipv6_hdr(skb)->hop_limit != 255) {
1737 : : ND_PRINTK(2, warn, "NDISC: invalid hop-limit: %d\n",
1738 : : ipv6_hdr(skb)->hop_limit);
1739 : : return 0;
1740 : : }
1741 : :
1742 [ # # ]: 0 : if (msg->icmph.icmp6_code != 0) {
1743 : : ND_PRINTK(2, warn, "NDISC: invalid ICMPv6 code: %d\n",
1744 : : msg->icmph.icmp6_code);
1745 : : return 0;
1746 : : }
1747 : :
1748 [ # # # # : 0 : switch (msg->icmph.icmp6_type) {
# # ]
1749 : : case NDISC_NEIGHBOUR_SOLICITATION:
1750 : 0 : memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
1751 : 0 : ndisc_recv_ns(skb);
1752 : 0 : break;
1753 : :
1754 : : case NDISC_NEIGHBOUR_ADVERTISEMENT:
1755 : 0 : ndisc_recv_na(skb);
1756 : 0 : break;
1757 : :
1758 : : case NDISC_ROUTER_SOLICITATION:
1759 : 0 : ndisc_recv_rs(skb);
1760 : 0 : break;
1761 : :
1762 : : case NDISC_ROUTER_ADVERTISEMENT:
1763 : 0 : ndisc_router_discovery(skb);
1764 : 0 : break;
1765 : :
1766 : : case NDISC_REDIRECT:
1767 : 0 : ndisc_redirect_rcv(skb);
1768 : 0 : break;
1769 : : }
1770 : :
1771 : : return 0;
1772 : : }
1773 : :
1774 : 2070 : static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1775 : : {
1776 : : struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1777 : : struct netdev_notifier_change_info *change_info;
1778 : : struct net *net = dev_net(dev);
1779 : : struct inet6_dev *idev;
1780 : :
1781 [ - + + - : 2070 : switch (event) {
- + ]
1782 : : case NETDEV_CHANGEADDR:
1783 : 0 : neigh_changeaddr(&nd_tbl, dev);
1784 : 0 : fib6_run_gc(0, net, false);
1785 : : /* fallthrough */
1786 : : case NETDEV_UP:
1787 : : idev = in6_dev_get(dev);
1788 [ + - ]: 414 : if (!idev)
1789 : : break;
1790 [ + - - + ]: 828 : if (idev->cnf.ndisc_notify ||
1791 : 414 : net->ipv6.devconf_all->ndisc_notify)
1792 : 0 : ndisc_send_unsol_na(dev);
1793 : 414 : in6_dev_put(idev);
1794 : 414 : break;
1795 : : case NETDEV_CHANGE:
1796 : : change_info = ptr;
1797 [ - + ]: 828 : if (change_info->flags_changed & IFF_NOARP)
1798 : 0 : neigh_changeaddr(&nd_tbl, dev);
1799 [ + + ]: 828 : if (!netif_carrier_ok(dev))
1800 : 207 : neigh_carrier_down(&nd_tbl, dev);
1801 : : break;
1802 : : case NETDEV_DOWN:
1803 : 0 : neigh_ifdown(&nd_tbl, dev);
1804 : 0 : fib6_run_gc(0, net, false);
1805 : 0 : break;
1806 : : case NETDEV_NOTIFY_PEERS:
1807 : 0 : ndisc_send_unsol_na(dev);
1808 : 0 : break;
1809 : : default:
1810 : : break;
1811 : : }
1812 : :
1813 : 2070 : return NOTIFY_DONE;
1814 : : }
1815 : :
1816 : : static struct notifier_block ndisc_netdev_notifier = {
1817 : : .notifier_call = ndisc_netdev_event,
1818 : : .priority = ADDRCONF_NOTIFY_PRIORITY - 5,
1819 : : };
1820 : :
1821 : : #ifdef CONFIG_SYSCTL
1822 : 0 : static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
1823 : : const char *func, const char *dev_name)
1824 : : {
1825 : : static char warncomm[TASK_COMM_LEN];
1826 : : static int warned;
1827 [ # # # # ]: 0 : if (strcmp(warncomm, current->comm) && warned < 5) {
1828 : 0 : strcpy(warncomm, current->comm);
1829 : 0 : pr_warn("process `%s' is using deprecated sysctl (%s) net.ipv6.neigh.%s.%s - use net.ipv6.neigh.%s.%s_ms instead\n",
1830 : : warncomm, func,
1831 : : dev_name, ctl->procname,
1832 : : dev_name, ctl->procname);
1833 : 0 : warned++;
1834 : : }
1835 : 0 : }
1836 : :
1837 : 0 : int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1838 : : {
1839 : 0 : struct net_device *dev = ctl->extra1;
1840 : : struct inet6_dev *idev;
1841 : : int ret;
1842 : :
1843 [ # # # # ]: 0 : if ((strcmp(ctl->procname, "retrans_time") == 0) ||
1844 : 0 : (strcmp(ctl->procname, "base_reachable_time") == 0))
1845 [ # # ]: 0 : ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
1846 : :
1847 [ # # ]: 0 : if (strcmp(ctl->procname, "retrans_time") == 0)
1848 : 0 : ret = neigh_proc_dointvec(ctl, write, buffer, lenp, ppos);
1849 : :
1850 [ # # ]: 0 : else if (strcmp(ctl->procname, "base_reachable_time") == 0)
1851 : 0 : ret = neigh_proc_dointvec_jiffies(ctl, write,
1852 : : buffer, lenp, ppos);
1853 : :
1854 [ # # # # ]: 0 : else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) ||
1855 : 0 : (strcmp(ctl->procname, "base_reachable_time_ms") == 0))
1856 : 0 : ret = neigh_proc_dointvec_ms_jiffies(ctl, write,
1857 : : buffer, lenp, ppos);
1858 : : else
1859 : : ret = -1;
1860 : :
1861 [ # # # # : 0 : if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
# # ]
1862 [ # # ]: 0 : if (ctl->data == &NEIGH_VAR(idev->nd_parms, BASE_REACHABLE_TIME))
1863 : 0 : idev->nd_parms->reachable_time =
1864 : 0 : neigh_rand_reach_time(NEIGH_VAR(idev->nd_parms, BASE_REACHABLE_TIME));
1865 : 0 : idev->tstamp = jiffies;
1866 : 0 : inet6_ifinfo_notify(RTM_NEWLINK, idev);
1867 : 0 : in6_dev_put(idev);
1868 : : }
1869 : 0 : return ret;
1870 : : }
1871 : :
1872 : :
1873 : : #endif
1874 : :
1875 : 207 : static int __net_init ndisc_net_init(struct net *net)
1876 : : {
1877 : : struct ipv6_pinfo *np;
1878 : : struct sock *sk;
1879 : : int err;
1880 : :
1881 : 207 : err = inet_ctl_sock_create(&sk, PF_INET6,
1882 : : SOCK_RAW, IPPROTO_ICMPV6, net);
1883 [ - + ]: 207 : if (err < 0) {
1884 [ # # ]: 0 : ND_PRINTK(0, err,
1885 : : "NDISC: Failed to initialize the control socket (err %d)\n",
1886 : : err);
1887 : 0 : return err;
1888 : : }
1889 : :
1890 : 207 : net->ipv6.ndisc_sk = sk;
1891 : :
1892 : : np = inet6_sk(sk);
1893 : 207 : np->hop_limit = 255;
1894 : : /* Do not loopback ndisc messages */
1895 : 207 : np->mc_loop = 0;
1896 : :
1897 : 207 : return 0;
1898 : : }
1899 : :
1900 : 0 : static void __net_exit ndisc_net_exit(struct net *net)
1901 : : {
1902 : 0 : inet_ctl_sock_destroy(net->ipv6.ndisc_sk);
1903 : 0 : }
1904 : :
1905 : : static struct pernet_operations ndisc_net_ops = {
1906 : : .init = ndisc_net_init,
1907 : : .exit = ndisc_net_exit,
1908 : : };
1909 : :
1910 : 207 : int __init ndisc_init(void)
1911 : : {
1912 : : int err;
1913 : :
1914 : 207 : err = register_pernet_subsys(&ndisc_net_ops);
1915 [ + - ]: 207 : if (err)
1916 : : return err;
1917 : : /*
1918 : : * Initialize the neighbour table
1919 : : */
1920 : 207 : neigh_table_init(NEIGH_ND_TABLE, &nd_tbl);
1921 : :
1922 : : #ifdef CONFIG_SYSCTL
1923 : 207 : err = neigh_sysctl_register(NULL, &nd_tbl.parms,
1924 : : ndisc_ifinfo_sysctl_change);
1925 [ + - ]: 207 : if (err)
1926 : : goto out_unregister_pernet;
1927 : : out:
1928 : : #endif
1929 : 207 : return err;
1930 : :
1931 : : #ifdef CONFIG_SYSCTL
1932 : : out_unregister_pernet:
1933 : 0 : unregister_pernet_subsys(&ndisc_net_ops);
1934 : 0 : goto out;
1935 : : #endif
1936 : : }
1937 : :
1938 : 207 : int __init ndisc_late_init(void)
1939 : : {
1940 : 207 : return register_netdevice_notifier(&ndisc_netdev_notifier);
1941 : : }
1942 : :
1943 : 0 : void ndisc_late_cleanup(void)
1944 : : {
1945 : 0 : unregister_netdevice_notifier(&ndisc_netdev_notifier);
1946 : 0 : }
1947 : :
1948 : 0 : void ndisc_cleanup(void)
1949 : : {
1950 : : #ifdef CONFIG_SYSCTL
1951 : 0 : neigh_sysctl_unregister(&nd_tbl.parms);
1952 : : #endif
1953 : 0 : neigh_table_clear(NEIGH_ND_TABLE, &nd_tbl);
1954 : 0 : unregister_pernet_subsys(&ndisc_net_ops);
1955 : 0 : }
|