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