| .. | .. |
|---|
| 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); |
|---|