1
2#ifndef _NDISC_H
3#define _NDISC_H
4
5#include <net/ipv6_stubs.h>
6
7
8
9
10
11#define NDISC_ROUTER_SOLICITATION 133
12#define NDISC_ROUTER_ADVERTISEMENT 134
13#define NDISC_NEIGHBOUR_SOLICITATION 135
14#define NDISC_NEIGHBOUR_ADVERTISEMENT 136
15#define NDISC_REDIRECT 137
16
17
18
19
20
21#define NDISC_NODETYPE_UNSPEC 0
22#define NDISC_NODETYPE_HOST 1
23#define NDISC_NODETYPE_NODEFAULT 2
24#define NDISC_NODETYPE_DEFAULT 3
25
26
27
28
29
30enum {
31 __ND_OPT_PREFIX_INFO_END = 0,
32 ND_OPT_SOURCE_LL_ADDR = 1,
33 ND_OPT_TARGET_LL_ADDR = 2,
34 ND_OPT_PREFIX_INFO = 3,
35 ND_OPT_REDIRECT_HDR = 4,
36 ND_OPT_MTU = 5,
37 ND_OPT_NONCE = 14,
38 __ND_OPT_ARRAY_MAX,
39 ND_OPT_ROUTE_INFO = 24,
40 ND_OPT_RDNSS = 25,
41 ND_OPT_DNSSL = 31,
42 ND_OPT_6CO = 34,
43 ND_OPT_CAPTIVE_PORTAL = 37,
44 ND_OPT_PREF64 = 38,
45 __ND_OPT_MAX
46};
47
48#define MAX_RTR_SOLICITATION_DELAY HZ
49
50#define ND_REACHABLE_TIME (30*HZ)
51#define ND_RETRANS_TIMER HZ
52
53#include <linux/compiler.h>
54#include <linux/icmpv6.h>
55#include <linux/in6.h>
56#include <linux/types.h>
57#include <linux/if_arp.h>
58#include <linux/netdevice.h>
59#include <linux/hash.h>
60
61#include <net/neighbour.h>
62
63
64#define ND_DEBUG 1
65
66#define ND_PRINTK(val, level, fmt, ...) \
67do { \
68 if (val <= ND_DEBUG) \
69 net_##level##_ratelimited(fmt, ##__VA_ARGS__); \
70} while (0)
71
72struct ctl_table;
73struct inet6_dev;
74struct net_device;
75struct net_proto_family;
76struct sk_buff;
77struct prefix_info;
78
79extern struct neigh_table nd_tbl;
80
81struct nd_msg {
82 struct icmp6hdr icmph;
83 struct in6_addr target;
84 __u8 opt[];
85};
86
87struct rs_msg {
88 struct icmp6hdr icmph;
89 __u8 opt[];
90};
91
92struct ra_msg {
93 struct icmp6hdr icmph;
94 __be32 reachable_time;
95 __be32 retrans_timer;
96};
97
98struct rd_msg {
99 struct icmp6hdr icmph;
100 struct in6_addr target;
101 struct in6_addr dest;
102 __u8 opt[];
103};
104
105struct nd_opt_hdr {
106 __u8 nd_opt_type;
107 __u8 nd_opt_len;
108} __packed;
109
110
111struct ndisc_options {
112 struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
113#ifdef CONFIG_IPV6_ROUTE_INFO
114 struct nd_opt_hdr *nd_opts_ri;
115 struct nd_opt_hdr *nd_opts_ri_end;
116#endif
117 struct nd_opt_hdr *nd_useropts;
118 struct nd_opt_hdr *nd_useropts_end;
119#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
120 struct nd_opt_hdr *nd_802154_opt_array[ND_OPT_TARGET_LL_ADDR + 1];
121#endif
122};
123
124#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
125#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
126#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
127#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
128#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
129#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
130#define nd_opts_nonce nd_opt_array[ND_OPT_NONCE]
131#define nd_802154_opts_src_lladdr nd_802154_opt_array[ND_OPT_SOURCE_LL_ADDR]
132#define nd_802154_opts_tgt_lladdr nd_802154_opt_array[ND_OPT_TARGET_LL_ADDR]
133
134#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
135
136struct ndisc_options *ndisc_parse_options(const struct net_device *dev,
137 u8 *opt, int opt_len,
138 struct ndisc_options *ndopts);
139
140void __ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data,
141 int data_len, int pad);
142
143#define NDISC_OPS_REDIRECT_DATA_SPACE 2
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202struct ndisc_ops {
203 int (*is_useropt)(u8 nd_opt_type);
204 int (*parse_options)(const struct net_device *dev,
205 struct nd_opt_hdr *nd_opt,
206 struct ndisc_options *ndopts);
207 void (*update)(const struct net_device *dev, struct neighbour *n,
208 u32 flags, u8 icmp6_type,
209 const struct ndisc_options *ndopts);
210 int (*opt_addr_space)(const struct net_device *dev, u8 icmp6_type,
211 struct neighbour *neigh, u8 *ha_buf,
212 u8 **ha);
213 void (*fill_addr_option)(const struct net_device *dev,
214 struct sk_buff *skb, u8 icmp6_type,
215 const u8 *ha);
216 void (*prefix_rcv_add_addr)(struct net *net, struct net_device *dev,
217 const struct prefix_info *pinfo,
218 struct inet6_dev *in6_dev,
219 struct in6_addr *addr,
220 int addr_type, u32 addr_flags,
221 bool sllao, bool tokenized,
222 __u32 valid_lft, u32 prefered_lft,
223 bool dev_addr_generated);
224};
225
226#if IS_ENABLED(CONFIG_IPV6)
227static inline int ndisc_ops_is_useropt(const struct net_device *dev,
228 u8 nd_opt_type)
229{
230 if (dev->ndisc_ops && dev->ndisc_ops->is_useropt)
231 return dev->ndisc_ops->is_useropt(nd_opt_type);
232 else
233 return 0;
234}
235
236static inline int ndisc_ops_parse_options(const struct net_device *dev,
237 struct nd_opt_hdr *nd_opt,
238 struct ndisc_options *ndopts)
239{
240 if (dev->ndisc_ops && dev->ndisc_ops->parse_options)
241 return dev->ndisc_ops->parse_options(dev, nd_opt, ndopts);
242 else
243 return 0;
244}
245
246static inline void ndisc_ops_update(const struct net_device *dev,
247 struct neighbour *n, u32 flags,
248 u8 icmp6_type,
249 const struct ndisc_options *ndopts)
250{
251 if (dev->ndisc_ops && dev->ndisc_ops->update)
252 dev->ndisc_ops->update(dev, n, flags, icmp6_type, ndopts);
253}
254
255static inline int ndisc_ops_opt_addr_space(const struct net_device *dev,
256 u8 icmp6_type)
257{
258 if (dev->ndisc_ops && dev->ndisc_ops->opt_addr_space &&
259 icmp6_type != NDISC_REDIRECT)
260 return dev->ndisc_ops->opt_addr_space(dev, icmp6_type, NULL,
261 NULL, NULL);
262 else
263 return 0;
264}
265
266static inline int ndisc_ops_redirect_opt_addr_space(const struct net_device *dev,
267 struct neighbour *neigh,
268 u8 *ha_buf, u8 **ha)
269{
270 if (dev->ndisc_ops && dev->ndisc_ops->opt_addr_space)
271 return dev->ndisc_ops->opt_addr_space(dev, NDISC_REDIRECT,
272 neigh, ha_buf, ha);
273 else
274 return 0;
275}
276
277static inline void ndisc_ops_fill_addr_option(const struct net_device *dev,
278 struct sk_buff *skb,
279 u8 icmp6_type)
280{
281 if (dev->ndisc_ops && dev->ndisc_ops->fill_addr_option &&
282 icmp6_type != NDISC_REDIRECT)
283 dev->ndisc_ops->fill_addr_option(dev, skb, icmp6_type, NULL);
284}
285
286static inline void ndisc_ops_fill_redirect_addr_option(const struct net_device *dev,
287 struct sk_buff *skb,
288 const u8 *ha)
289{
290 if (dev->ndisc_ops && dev->ndisc_ops->fill_addr_option)
291 dev->ndisc_ops->fill_addr_option(dev, skb, NDISC_REDIRECT, ha);
292}
293
294static inline void ndisc_ops_prefix_rcv_add_addr(struct net *net,
295 struct net_device *dev,
296 const struct prefix_info *pinfo,
297 struct inet6_dev *in6_dev,
298 struct in6_addr *addr,
299 int addr_type, u32 addr_flags,
300 bool sllao, bool tokenized,
301 __u32 valid_lft,
302 u32 prefered_lft,
303 bool dev_addr_generated)
304{
305 if (dev->ndisc_ops && dev->ndisc_ops->prefix_rcv_add_addr)
306 dev->ndisc_ops->prefix_rcv_add_addr(net, dev, pinfo, in6_dev,
307 addr, addr_type,
308 addr_flags, sllao,
309 tokenized, valid_lft,
310 prefered_lft,
311 dev_addr_generated);
312}
313#endif
314
315
316
317
318
319
320
321static inline int ndisc_addr_option_pad(unsigned short type)
322{
323 switch (type) {
324 case ARPHRD_INFINIBAND: return 2;
325 default: return 0;
326 }
327}
328
329static inline int __ndisc_opt_addr_space(unsigned char addr_len, int pad)
330{
331 return NDISC_OPT_SPACE(addr_len + pad);
332}
333
334#if IS_ENABLED(CONFIG_IPV6)
335static inline int ndisc_opt_addr_space(struct net_device *dev, u8 icmp6_type)
336{
337 return __ndisc_opt_addr_space(dev->addr_len,
338 ndisc_addr_option_pad(dev->type)) +
339 ndisc_ops_opt_addr_space(dev, icmp6_type);
340}
341
342static inline int ndisc_redirect_opt_addr_space(struct net_device *dev,
343 struct neighbour *neigh,
344 u8 *ops_data_buf,
345 u8 **ops_data)
346{
347 return __ndisc_opt_addr_space(dev->addr_len,
348 ndisc_addr_option_pad(dev->type)) +
349 ndisc_ops_redirect_opt_addr_space(dev, neigh, ops_data_buf,
350 ops_data);
351}
352#endif
353
354static inline u8 *__ndisc_opt_addr_data(struct nd_opt_hdr *p,
355 unsigned char addr_len, int prepad)
356{
357 u8 *lladdr = (u8 *)(p + 1);
358 int lladdrlen = p->nd_opt_len << 3;
359 if (lladdrlen != __ndisc_opt_addr_space(addr_len, prepad))
360 return NULL;
361 return lladdr + prepad;
362}
363
364static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
365 struct net_device *dev)
366{
367 return __ndisc_opt_addr_data(p, dev->addr_len,
368 ndisc_addr_option_pad(dev->type));
369}
370
371static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
372{
373 const u32 *p32 = pkey;
374
375 return (((p32[0] ^ hash32_ptr(dev)) * hash_rnd[0]) +
376 (p32[1] * hash_rnd[1]) +
377 (p32[2] * hash_rnd[2]) +
378 (p32[3] * hash_rnd[3]));
379}
380
381static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey)
382{
383 return ___neigh_lookup_noref(&nd_tbl, neigh_key_eq128, ndisc_hashfn, pkey, dev);
384}
385
386static inline
387struct neighbour *__ipv6_neigh_lookup_noref_stub(struct net_device *dev,
388 const void *pkey)
389{
390 return ___neigh_lookup_noref(ipv6_stub->nd_tbl, neigh_key_eq128,
391 ndisc_hashfn, pkey, dev);
392}
393
394static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, const void *pkey)
395{
396 struct neighbour *n;
397
398 rcu_read_lock_bh();
399 n = __ipv6_neigh_lookup_noref(dev, pkey);
400 if (n && !refcount_inc_not_zero(&n->refcnt))
401 n = NULL;
402 rcu_read_unlock_bh();
403
404 return n;
405}
406
407static inline void __ipv6_confirm_neigh(struct net_device *dev,
408 const void *pkey)
409{
410 struct neighbour *n;
411
412 rcu_read_lock_bh();
413 n = __ipv6_neigh_lookup_noref(dev, pkey);
414 if (n) {
415 unsigned long now = jiffies;
416
417
418 if (READ_ONCE(n->confirmed) != now)
419 WRITE_ONCE(n->confirmed, now);
420 }
421 rcu_read_unlock_bh();
422}
423
424static inline void __ipv6_confirm_neigh_stub(struct net_device *dev,
425 const void *pkey)
426{
427 struct neighbour *n;
428
429 rcu_read_lock_bh();
430 n = __ipv6_neigh_lookup_noref_stub(dev, pkey);
431 if (n) {
432 unsigned long now = jiffies;
433
434
435 if (READ_ONCE(n->confirmed) != now)
436 WRITE_ONCE(n->confirmed, now);
437 }
438 rcu_read_unlock_bh();
439}
440
441
442static inline struct neighbour *ip_neigh_gw6(struct net_device *dev,
443 const void *addr)
444{
445 struct neighbour *neigh;
446
447 neigh = __ipv6_neigh_lookup_noref_stub(dev, addr);
448 if (unlikely(!neigh))
449 neigh = __neigh_create(ipv6_stub->nd_tbl, addr, dev, false);
450
451 return neigh;
452}
453
454int ndisc_init(void);
455int ndisc_late_init(void);
456
457void ndisc_late_cleanup(void);
458void ndisc_cleanup(void);
459
460int ndisc_rcv(struct sk_buff *skb);
461
462void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
463 const struct in6_addr *daddr, const struct in6_addr *saddr,
464 u64 nonce);
465
466void ndisc_send_rs(struct net_device *dev,
467 const struct in6_addr *saddr, const struct in6_addr *daddr);
468void ndisc_send_na(struct net_device *dev, const struct in6_addr *daddr,
469 const struct in6_addr *solicited_addr,
470 bool router, bool solicited, bool override, bool inc_opt);
471
472void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target);
473
474int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev,
475 int dir);
476
477void ndisc_update(const struct net_device *dev, struct neighbour *neigh,
478 const u8 *lladdr, u8 new, u32 flags, u8 icmp6_type,
479 struct ndisc_options *ndopts);
480
481
482
483
484int igmp6_init(void);
485int igmp6_late_init(void);
486
487void igmp6_cleanup(void);
488void igmp6_late_cleanup(void);
489
490int igmp6_event_query(struct sk_buff *skb);
491
492int igmp6_event_report(struct sk_buff *skb);
493
494
495#ifdef CONFIG_SYSCTL
496int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write,
497 void *buffer, size_t *lenp, loff_t *ppos);
498int ndisc_ifinfo_sysctl_strategy(struct ctl_table *ctl,
499 void __user *oldval, size_t __user *oldlenp,
500 void __user *newval, size_t newlen);
501#endif
502
503void inet6_ifinfo_notify(int event, struct inet6_dev *idev);
504
505#endif
506