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