.. | .. |
---|
49 | 49 | struct in6_addr prefix; |
---|
50 | 50 | }; |
---|
51 | 51 | |
---|
| 52 | +#include <linux/ipv6.h> |
---|
52 | 53 | #include <linux/netdevice.h> |
---|
53 | 54 | #include <net/if_inet6.h> |
---|
54 | 55 | #include <net/ipv6.h> |
---|
.. | .. |
---|
89 | 90 | int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr); |
---|
90 | 91 | #endif |
---|
91 | 92 | |
---|
| 93 | +int ipv6_chk_rpl_srh_loop(struct net *net, const struct in6_addr *segs, |
---|
| 94 | + unsigned char nsegs); |
---|
| 95 | + |
---|
92 | 96 | bool ipv6_chk_custom_prefix(const struct in6_addr *addr, |
---|
93 | 97 | const unsigned int prefix_len, |
---|
94 | 98 | struct net_device *dev); |
---|
95 | 99 | |
---|
96 | 100 | int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev); |
---|
| 101 | + |
---|
| 102 | +struct net_device *ipv6_dev_find(struct net *net, const struct in6_addr *addr, |
---|
| 103 | + struct net_device *dev); |
---|
97 | 104 | |
---|
98 | 105 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, |
---|
99 | 106 | const struct in6_addr *addr, |
---|
.. | .. |
---|
201 | 208 | /* |
---|
202 | 209 | * multicast prototypes (mcast.c) |
---|
203 | 210 | */ |
---|
| 211 | +static inline bool ipv6_mc_may_pull(struct sk_buff *skb, |
---|
| 212 | + unsigned int len) |
---|
| 213 | +{ |
---|
| 214 | + if (skb_transport_offset(skb) + ipv6_transport_len(skb) < len) |
---|
| 215 | + return false; |
---|
| 216 | + |
---|
| 217 | + return pskb_may_pull(skb, len); |
---|
| 218 | +} |
---|
| 219 | + |
---|
204 | 220 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, |
---|
205 | 221 | const struct in6_addr *addr); |
---|
206 | 222 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, |
---|
.. | .. |
---|
219 | 235 | void ipv6_mc_remap(struct inet6_dev *idev); |
---|
220 | 236 | void ipv6_mc_init_dev(struct inet6_dev *idev); |
---|
221 | 237 | void ipv6_mc_destroy_dev(struct inet6_dev *idev); |
---|
222 | | -int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed); |
---|
| 238 | +int ipv6_mc_check_mld(struct sk_buff *skb); |
---|
223 | 239 | void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp); |
---|
224 | 240 | |
---|
225 | 241 | bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, |
---|
226 | 242 | const struct in6_addr *src_addr); |
---|
227 | 243 | |
---|
228 | 244 | void ipv6_mc_dad_complete(struct inet6_dev *idev); |
---|
229 | | - |
---|
230 | | -/* A stub used by vxlan module. This is ugly, ideally these |
---|
231 | | - * symbols should be built into the core kernel. |
---|
232 | | - */ |
---|
233 | | -struct ipv6_stub { |
---|
234 | | - int (*ipv6_sock_mc_join)(struct sock *sk, int ifindex, |
---|
235 | | - const struct in6_addr *addr); |
---|
236 | | - int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex, |
---|
237 | | - const struct in6_addr *addr); |
---|
238 | | - struct dst_entry *(*ipv6_dst_lookup_flow)(struct net *net, |
---|
239 | | - const struct sock *sk, |
---|
240 | | - struct flowi6 *fl6, |
---|
241 | | - const struct in6_addr *final_dst); |
---|
242 | | - |
---|
243 | | - struct fib6_table *(*fib6_get_table)(struct net *net, u32 id); |
---|
244 | | - struct fib6_info *(*fib6_lookup)(struct net *net, int oif, |
---|
245 | | - struct flowi6 *fl6, int flags); |
---|
246 | | - struct fib6_info *(*fib6_table_lookup)(struct net *net, |
---|
247 | | - struct fib6_table *table, |
---|
248 | | - int oif, struct flowi6 *fl6, |
---|
249 | | - int flags); |
---|
250 | | - struct fib6_info *(*fib6_multipath_select)(const struct net *net, |
---|
251 | | - struct fib6_info *f6i, |
---|
252 | | - struct flowi6 *fl6, int oif, |
---|
253 | | - const struct sk_buff *skb, |
---|
254 | | - int strict); |
---|
255 | | - u32 (*ip6_mtu_from_fib6)(struct fib6_info *f6i, struct in6_addr *daddr, |
---|
256 | | - struct in6_addr *saddr); |
---|
257 | | - |
---|
258 | | - void (*udpv6_encap_enable)(void); |
---|
259 | | - void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr, |
---|
260 | | - const struct in6_addr *solicited_addr, |
---|
261 | | - bool router, bool solicited, bool override, bool inc_opt); |
---|
262 | | - struct neigh_table *nd_tbl; |
---|
263 | | -}; |
---|
264 | | -extern const struct ipv6_stub *ipv6_stub __read_mostly; |
---|
265 | | - |
---|
266 | | -/* A stub used by bpf helpers. Similarly ugly as ipv6_stub */ |
---|
267 | | -struct ipv6_bpf_stub { |
---|
268 | | - int (*inet6_bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len, |
---|
269 | | - bool force_bind_address_no_port, bool with_lock); |
---|
270 | | -}; |
---|
271 | | -extern const struct ipv6_bpf_stub *ipv6_bpf_stub __read_mostly; |
---|
272 | 245 | |
---|
273 | 246 | /* |
---|
274 | 247 | * identify MLD packets for MLD filter exceptions |
---|
.. | .. |
---|
327 | 300 | const struct in6_addr *addr); |
---|
328 | 301 | bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev, |
---|
329 | 302 | const struct in6_addr *addr); |
---|
| 303 | +int ipv6_anycast_init(void); |
---|
| 304 | +void ipv6_anycast_cleanup(void); |
---|
330 | 305 | |
---|
331 | 306 | /* Device notifier */ |
---|
332 | 307 | int register_inet6addr_notifier(struct notifier_block *nb); |
---|
.. | .. |
---|
350 | 325 | static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev) |
---|
351 | 326 | { |
---|
352 | 327 | return rcu_dereference_rtnl(dev->ip6_ptr); |
---|
| 328 | +} |
---|
| 329 | + |
---|
| 330 | +/** |
---|
| 331 | + * __in6_dev_stats_get - get inet6_dev pointer for stats |
---|
| 332 | + * @dev: network device |
---|
| 333 | + * @skb: skb for original incoming interface if neeeded |
---|
| 334 | + * |
---|
| 335 | + * Caller must hold rcu_read_lock or RTNL, because this function |
---|
| 336 | + * does not take a reference on the inet6_dev. |
---|
| 337 | + */ |
---|
| 338 | +static inline struct inet6_dev *__in6_dev_stats_get(const struct net_device *dev, |
---|
| 339 | + const struct sk_buff *skb) |
---|
| 340 | +{ |
---|
| 341 | + if (netif_is_l3_master(dev)) |
---|
| 342 | + dev = dev_get_by_index_rcu(dev_net(dev), inet6_iif(skb)); |
---|
| 343 | + return __in6_dev_get(dev); |
---|
353 | 344 | } |
---|
354 | 345 | |
---|
355 | 346 | /** |
---|
.. | .. |
---|
421 | 412 | refcount_inc(&idev->refcnt); |
---|
422 | 413 | } |
---|
423 | 414 | |
---|
| 415 | +/* called with rcu_read_lock held */ |
---|
| 416 | +static inline bool ip6_ignore_linkdown(const struct net_device *dev) |
---|
| 417 | +{ |
---|
| 418 | + const struct inet6_dev *idev = __in6_dev_get(dev); |
---|
| 419 | + |
---|
| 420 | + if (unlikely(!idev)) |
---|
| 421 | + return true; |
---|
| 422 | + |
---|
| 423 | + return !!idev->cnf.ignore_routes_with_linkdown; |
---|
| 424 | +} |
---|
| 425 | + |
---|
424 | 426 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp); |
---|
425 | 427 | |
---|
426 | 428 | static inline void in6_ifa_put(struct inet6_ifaddr *ifp) |
---|
.. | .. |
---|
456 | 458 | static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr) |
---|
457 | 459 | { |
---|
458 | 460 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 |
---|
459 | | - __be64 *p = (__be64 *)addr; |
---|
| 461 | + __be64 *p = (__force __be64 *)addr; |
---|
460 | 462 | return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL; |
---|
461 | 463 | #else |
---|
462 | 464 | return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | |
---|
.. | .. |
---|
468 | 470 | static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr) |
---|
469 | 471 | { |
---|
470 | 472 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 |
---|
471 | | - __be64 *p = (__be64 *)addr; |
---|
| 473 | + __be64 *p = (__force __be64 *)addr; |
---|
472 | 474 | return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL; |
---|
473 | 475 | #else |
---|
474 | 476 | return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | |
---|
.. | .. |
---|
485 | 487 | static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr) |
---|
486 | 488 | { |
---|
487 | 489 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 |
---|
488 | | - __be64 *p = (__be64 *)addr; |
---|
| 490 | + __be64 *p = (__force __be64 *)addr; |
---|
489 | 491 | return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | |
---|
490 | 492 | ((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) & |
---|
491 | 493 | cpu_to_be64(0xffffffffff000000UL))) == 0UL; |
---|
.. | .. |
---|
497 | 499 | #endif |
---|
498 | 500 | } |
---|
499 | 501 | |
---|
| 502 | +static inline bool ipv6_addr_is_all_snoopers(const struct in6_addr *addr) |
---|
| 503 | +{ |
---|
| 504 | +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 |
---|
| 505 | + __be64 *p = (__force __be64 *)addr; |
---|
| 506 | + |
---|
| 507 | + return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | |
---|
| 508 | + (p[1] ^ cpu_to_be64(0x6a))) == 0UL; |
---|
| 509 | +#else |
---|
| 510 | + return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | |
---|
| 511 | + addr->s6_addr32[1] | addr->s6_addr32[2] | |
---|
| 512 | + (addr->s6_addr32[3] ^ htonl(0x0000006a))) == 0; |
---|
| 513 | +#endif |
---|
| 514 | +} |
---|
| 515 | + |
---|
500 | 516 | #ifdef CONFIG_PROC_FS |
---|
501 | 517 | int if6_proc_init(void); |
---|
502 | 518 | void if6_proc_exit(void); |
---|