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