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