| .. | .. |
|---|
| 2 | 2 | #ifndef _NDISC_H |
|---|
| 3 | 3 | #define _NDISC_H |
|---|
| 4 | 4 | |
|---|
| 5 | +#include <net/ipv6_stubs.h> |
|---|
| 6 | + |
|---|
| 5 | 7 | /* |
|---|
| 6 | 8 | * ICMP codes for neighbour discovery messages |
|---|
| 7 | 9 | */ |
|---|
| .. | .. |
|---|
| 79 | 81 | struct nd_msg { |
|---|
| 80 | 82 | struct icmp6hdr icmph; |
|---|
| 81 | 83 | struct in6_addr target; |
|---|
| 82 | | - __u8 opt[0]; |
|---|
| 84 | + __u8 opt[]; |
|---|
| 83 | 85 | }; |
|---|
| 84 | 86 | |
|---|
| 85 | 87 | struct rs_msg { |
|---|
| 86 | 88 | struct icmp6hdr icmph; |
|---|
| 87 | | - __u8 opt[0]; |
|---|
| 89 | + __u8 opt[]; |
|---|
| 88 | 90 | }; |
|---|
| 89 | 91 | |
|---|
| 90 | 92 | struct ra_msg { |
|---|
| .. | .. |
|---|
| 97 | 99 | struct icmp6hdr icmph; |
|---|
| 98 | 100 | struct in6_addr target; |
|---|
| 99 | 101 | struct in6_addr dest; |
|---|
| 100 | | - __u8 opt[0]; |
|---|
| 102 | + __u8 opt[]; |
|---|
| 101 | 103 | }; |
|---|
| 102 | 104 | |
|---|
| 103 | 105 | struct nd_opt_hdr { |
|---|
| .. | .. |
|---|
| 381 | 383 | return ___neigh_lookup_noref(&nd_tbl, neigh_key_eq128, ndisc_hashfn, pkey, dev); |
|---|
| 382 | 384 | } |
|---|
| 383 | 385 | |
|---|
| 386 | +static inline |
|---|
| 387 | +struct 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 | + |
|---|
| 384 | 394 | static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, const void *pkey) |
|---|
| 385 | 395 | { |
|---|
| 386 | 396 | struct neighbour *n; |
|---|
| .. | .. |
|---|
| 405 | 415 | unsigned long now = jiffies; |
|---|
| 406 | 416 | |
|---|
| 407 | 417 | /* avoid dirtying neighbour */ |
|---|
| 408 | | - if (n->confirmed != now) |
|---|
| 409 | | - n->confirmed = now; |
|---|
| 418 | + if (READ_ONCE(n->confirmed) != now) |
|---|
| 419 | + WRITE_ONCE(n->confirmed, now); |
|---|
| 410 | 420 | } |
|---|
| 411 | 421 | rcu_read_unlock_bh(); |
|---|
| 422 | +} |
|---|
| 423 | + |
|---|
| 424 | +static 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 | + /* avoid dirtying neighbour */ |
|---|
| 435 | + if (READ_ONCE(n->confirmed) != now) |
|---|
| 436 | + WRITE_ONCE(n->confirmed, now); |
|---|
| 437 | + } |
|---|
| 438 | + rcu_read_unlock_bh(); |
|---|
| 439 | +} |
|---|
| 440 | + |
|---|
| 441 | +/* uses ipv6_stub and is meant for use outside of IPv6 core */ |
|---|
| 442 | +static 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; |
|---|
| 412 | 452 | } |
|---|
| 413 | 453 | |
|---|
| 414 | 454 | int ndisc_init(void); |
|---|
| .. | .. |
|---|
| 454 | 494 | |
|---|
| 455 | 495 | #ifdef CONFIG_SYSCTL |
|---|
| 456 | 496 | int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, |
|---|
| 457 | | - void __user *buffer, size_t *lenp, loff_t *ppos); |
|---|
| 497 | + void *buffer, size_t *lenp, loff_t *ppos); |
|---|
| 458 | 498 | int ndisc_ifinfo_sysctl_strategy(struct ctl_table *ctl, |
|---|
| 459 | 499 | void __user *oldval, size_t __user *oldlenp, |
|---|
| 460 | 500 | void __user *newval, size_t newlen); |
|---|