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