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