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