162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * inet6 interface/address list definitions 462306a36Sopenharmony_ci * Linux INET6 implementation 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Authors: 762306a36Sopenharmony_ci * Pedro Roque <roque@di.fc.ul.pt> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef _NET_IF_INET6_H 1162306a36Sopenharmony_ci#define _NET_IF_INET6_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <net/snmp.h> 1462306a36Sopenharmony_ci#include <linux/ipv6.h> 1562306a36Sopenharmony_ci#include <linux/refcount.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* inet6_dev.if_flags */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define IF_RA_OTHERCONF 0x80 2062306a36Sopenharmony_ci#define IF_RA_MANAGED 0x40 2162306a36Sopenharmony_ci#define IF_RA_RCVD 0x20 2262306a36Sopenharmony_ci#define IF_RS_SENT 0x10 2362306a36Sopenharmony_ci#define IF_READY 0x80000000 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cienum { 2662306a36Sopenharmony_ci INET6_IFADDR_STATE_PREDAD, 2762306a36Sopenharmony_ci INET6_IFADDR_STATE_DAD, 2862306a36Sopenharmony_ci INET6_IFADDR_STATE_POSTDAD, 2962306a36Sopenharmony_ci INET6_IFADDR_STATE_ERRDAD, 3062306a36Sopenharmony_ci INET6_IFADDR_STATE_DEAD, 3162306a36Sopenharmony_ci}; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistruct inet6_ifaddr { 3462306a36Sopenharmony_ci struct in6_addr addr; 3562306a36Sopenharmony_ci __u32 prefix_len; 3662306a36Sopenharmony_ci __u32 rt_priority; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */ 3962306a36Sopenharmony_ci __u32 valid_lft; 4062306a36Sopenharmony_ci __u32 prefered_lft; 4162306a36Sopenharmony_ci refcount_t refcnt; 4262306a36Sopenharmony_ci spinlock_t lock; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci int state; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci __u32 flags; 4762306a36Sopenharmony_ci __u8 dad_probes; 4862306a36Sopenharmony_ci __u8 stable_privacy_retry; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci __u16 scope; 5162306a36Sopenharmony_ci __u64 dad_nonce; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci unsigned long cstamp; /* created timestamp */ 5462306a36Sopenharmony_ci unsigned long tstamp; /* updated timestamp */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci struct delayed_work dad_work; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci struct inet6_dev *idev; 5962306a36Sopenharmony_ci struct fib6_info *rt; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci struct hlist_node addr_lst; 6262306a36Sopenharmony_ci struct list_head if_list; 6362306a36Sopenharmony_ci /* 6462306a36Sopenharmony_ci * Used to safely traverse idev->addr_list in process context 6562306a36Sopenharmony_ci * if the idev->lock needed to protect idev->addr_list cannot be held. 6662306a36Sopenharmony_ci * In that case, add the items to this list temporarily and iterate 6762306a36Sopenharmony_ci * without holding idev->lock. 6862306a36Sopenharmony_ci * See addrconf_ifdown and dev_forward_change. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ci struct list_head if_list_aux; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci struct list_head tmp_list; 7362306a36Sopenharmony_ci struct inet6_ifaddr *ifpub; 7462306a36Sopenharmony_ci int regen_count; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci bool tokenized; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci u8 ifa_proto; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci struct rcu_head rcu; 8162306a36Sopenharmony_ci struct in6_addr peer_addr; 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistruct ip6_sf_socklist { 8562306a36Sopenharmony_ci unsigned int sl_max; 8662306a36Sopenharmony_ci unsigned int sl_count; 8762306a36Sopenharmony_ci struct rcu_head rcu; 8862306a36Sopenharmony_ci struct in6_addr sl_addr[]; 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define IP6_SFBLOCK 10 /* allocate this many at once */ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistruct ipv6_mc_socklist { 9462306a36Sopenharmony_ci struct in6_addr addr; 9562306a36Sopenharmony_ci int ifindex; 9662306a36Sopenharmony_ci unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */ 9762306a36Sopenharmony_ci struct ipv6_mc_socklist __rcu *next; 9862306a36Sopenharmony_ci struct ip6_sf_socklist __rcu *sflist; 9962306a36Sopenharmony_ci struct rcu_head rcu; 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistruct ip6_sf_list { 10362306a36Sopenharmony_ci struct ip6_sf_list __rcu *sf_next; 10462306a36Sopenharmony_ci struct in6_addr sf_addr; 10562306a36Sopenharmony_ci unsigned long sf_count[2]; /* include/exclude counts */ 10662306a36Sopenharmony_ci unsigned char sf_gsresp; /* include in g & s response? */ 10762306a36Sopenharmony_ci unsigned char sf_oldin; /* change state */ 10862306a36Sopenharmony_ci unsigned char sf_crcount; /* retrans. left to send */ 10962306a36Sopenharmony_ci struct rcu_head rcu; 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define MAF_TIMER_RUNNING 0x01 11362306a36Sopenharmony_ci#define MAF_LAST_REPORTER 0x02 11462306a36Sopenharmony_ci#define MAF_LOADED 0x04 11562306a36Sopenharmony_ci#define MAF_NOREPORT 0x08 11662306a36Sopenharmony_ci#define MAF_GSQUERY 0x10 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistruct ifmcaddr6 { 11962306a36Sopenharmony_ci struct in6_addr mca_addr; 12062306a36Sopenharmony_ci struct inet6_dev *idev; 12162306a36Sopenharmony_ci struct ifmcaddr6 __rcu *next; 12262306a36Sopenharmony_ci struct ip6_sf_list __rcu *mca_sources; 12362306a36Sopenharmony_ci struct ip6_sf_list __rcu *mca_tomb; 12462306a36Sopenharmony_ci unsigned int mca_sfmode; 12562306a36Sopenharmony_ci unsigned char mca_crcount; 12662306a36Sopenharmony_ci unsigned long mca_sfcount[2]; 12762306a36Sopenharmony_ci struct delayed_work mca_work; 12862306a36Sopenharmony_ci unsigned int mca_flags; 12962306a36Sopenharmony_ci int mca_users; 13062306a36Sopenharmony_ci refcount_t mca_refcnt; 13162306a36Sopenharmony_ci unsigned long mca_cstamp; 13262306a36Sopenharmony_ci unsigned long mca_tstamp; 13362306a36Sopenharmony_ci struct rcu_head rcu; 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* Anycast stuff */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistruct ipv6_ac_socklist { 13962306a36Sopenharmony_ci struct in6_addr acl_addr; 14062306a36Sopenharmony_ci int acl_ifindex; 14162306a36Sopenharmony_ci struct ipv6_ac_socklist *acl_next; 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistruct ifacaddr6 { 14562306a36Sopenharmony_ci struct in6_addr aca_addr; 14662306a36Sopenharmony_ci struct fib6_info *aca_rt; 14762306a36Sopenharmony_ci struct ifacaddr6 *aca_next; 14862306a36Sopenharmony_ci struct hlist_node aca_addr_lst; 14962306a36Sopenharmony_ci int aca_users; 15062306a36Sopenharmony_ci refcount_t aca_refcnt; 15162306a36Sopenharmony_ci unsigned long aca_cstamp; 15262306a36Sopenharmony_ci unsigned long aca_tstamp; 15362306a36Sopenharmony_ci struct rcu_head rcu; 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#define IFA_HOST IPV6_ADDR_LOOPBACK 15762306a36Sopenharmony_ci#define IFA_LINK IPV6_ADDR_LINKLOCAL 15862306a36Sopenharmony_ci#define IFA_SITE IPV6_ADDR_SITELOCAL 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistruct ipv6_devstat { 16162306a36Sopenharmony_ci struct proc_dir_entry *proc_dir_entry; 16262306a36Sopenharmony_ci DEFINE_SNMP_STAT(struct ipstats_mib, ipv6); 16362306a36Sopenharmony_ci DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev); 16462306a36Sopenharmony_ci DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev); 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistruct inet6_dev { 16862306a36Sopenharmony_ci struct net_device *dev; 16962306a36Sopenharmony_ci netdevice_tracker dev_tracker; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci struct list_head addr_list; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci struct ifmcaddr6 __rcu *mc_list; 17462306a36Sopenharmony_ci struct ifmcaddr6 __rcu *mc_tomb; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci unsigned char mc_qrv; /* Query Robustness Variable */ 17762306a36Sopenharmony_ci unsigned char mc_gq_running; 17862306a36Sopenharmony_ci unsigned char mc_ifc_count; 17962306a36Sopenharmony_ci unsigned char mc_dad_count; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci unsigned long mc_v1_seen; /* Max time we stay in MLDv1 mode */ 18262306a36Sopenharmony_ci unsigned long mc_qi; /* Query Interval */ 18362306a36Sopenharmony_ci unsigned long mc_qri; /* Query Response Interval */ 18462306a36Sopenharmony_ci unsigned long mc_maxdelay; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci struct delayed_work mc_gq_work; /* general query work */ 18762306a36Sopenharmony_ci struct delayed_work mc_ifc_work; /* interface change work */ 18862306a36Sopenharmony_ci struct delayed_work mc_dad_work; /* dad complete mc work */ 18962306a36Sopenharmony_ci struct delayed_work mc_query_work; /* mld query work */ 19062306a36Sopenharmony_ci struct delayed_work mc_report_work; /* mld report work */ 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci struct sk_buff_head mc_query_queue; /* mld query queue */ 19362306a36Sopenharmony_ci struct sk_buff_head mc_report_queue; /* mld report queue */ 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci spinlock_t mc_query_lock; /* mld query queue lock */ 19662306a36Sopenharmony_ci spinlock_t mc_report_lock; /* mld query report lock */ 19762306a36Sopenharmony_ci struct mutex mc_lock; /* mld global lock */ 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci struct ifacaddr6 *ac_list; 20062306a36Sopenharmony_ci rwlock_t lock; 20162306a36Sopenharmony_ci refcount_t refcnt; 20262306a36Sopenharmony_ci __u32 if_flags; 20362306a36Sopenharmony_ci int dead; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci u32 desync_factor; 20662306a36Sopenharmony_ci struct list_head tempaddr_list; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci struct in6_addr token; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci struct neigh_parms *nd_parms; 21162306a36Sopenharmony_ci struct ipv6_devconf cnf; 21262306a36Sopenharmony_ci struct ipv6_devstat stats; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci struct timer_list rs_timer; 21562306a36Sopenharmony_ci __s32 rs_interval; /* in jiffies */ 21662306a36Sopenharmony_ci __u8 rs_probes; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci unsigned long tstamp; /* ipv6InterfaceTable update timestamp */ 21962306a36Sopenharmony_ci struct rcu_head rcu; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci unsigned int ra_mtu; 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci /* 22762306a36Sopenharmony_ci * +-------+-------+-------+-------+-------+-------+ 22862306a36Sopenharmony_ci * | 33 | 33 | DST13 | DST14 | DST15 | DST16 | 22962306a36Sopenharmony_ci * +-------+-------+-------+-------+-------+-------+ 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci buf[0]= 0x33; 23362306a36Sopenharmony_ci buf[1]= 0x33; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32)); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci buf[0] = 0x00; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic inline void ipv6_ib_mc_map(const struct in6_addr *addr, 24462306a36Sopenharmony_ci const unsigned char *broadcast, char *buf) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci unsigned char scope = broadcast[5] & 0xF; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci buf[0] = 0; /* Reserved */ 24962306a36Sopenharmony_ci buf[1] = 0xff; /* Multicast QPN */ 25062306a36Sopenharmony_ci buf[2] = 0xff; 25162306a36Sopenharmony_ci buf[3] = 0xff; 25262306a36Sopenharmony_ci buf[4] = 0xff; 25362306a36Sopenharmony_ci buf[5] = 0x10 | scope; /* scope from broadcast address */ 25462306a36Sopenharmony_ci buf[6] = 0x60; /* IPv6 signature */ 25562306a36Sopenharmony_ci buf[7] = 0x1b; 25662306a36Sopenharmony_ci buf[8] = broadcast[8]; /* P_Key */ 25762306a36Sopenharmony_ci buf[9] = broadcast[9]; 25862306a36Sopenharmony_ci memcpy(buf + 10, addr->s6_addr + 6, 10); 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic inline int ipv6_ipgre_mc_map(const struct in6_addr *addr, 26262306a36Sopenharmony_ci const unsigned char *broadcast, char *buf) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) { 26562306a36Sopenharmony_ci memcpy(buf, broadcast, 4); 26662306a36Sopenharmony_ci } else { 26762306a36Sopenharmony_ci /* v4mapped? */ 26862306a36Sopenharmony_ci if ((addr->s6_addr32[0] | addr->s6_addr32[1] | 26962306a36Sopenharmony_ci (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0) 27062306a36Sopenharmony_ci return -EINVAL; 27162306a36Sopenharmony_ci memcpy(buf, &addr->s6_addr32[3], 4); 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci return 0; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci#endif 277