18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *	inet6 interface/address list definitions
48c2ecf20Sopenharmony_ci *	Linux INET6 implementation
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci *	Authors:
78c2ecf20Sopenharmony_ci *	Pedro Roque		<roque@di.fc.ul.pt>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#ifndef _NET_IF_INET6_H
118c2ecf20Sopenharmony_ci#define _NET_IF_INET6_H
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <net/snmp.h>
148c2ecf20Sopenharmony_ci#include <linux/ipv6.h>
158c2ecf20Sopenharmony_ci#include <linux/refcount.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/* inet6_dev.if_flags */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define IF_RA_OTHERCONF	0x80
208c2ecf20Sopenharmony_ci#define IF_RA_MANAGED	0x40
218c2ecf20Sopenharmony_ci#define IF_RA_RCVD	0x20
228c2ecf20Sopenharmony_ci#define IF_RS_SENT	0x10
238c2ecf20Sopenharmony_ci#define IF_READY	0x80000000
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cienum {
268c2ecf20Sopenharmony_ci	INET6_IFADDR_STATE_PREDAD,
278c2ecf20Sopenharmony_ci	INET6_IFADDR_STATE_DAD,
288c2ecf20Sopenharmony_ci	INET6_IFADDR_STATE_POSTDAD,
298c2ecf20Sopenharmony_ci	INET6_IFADDR_STATE_ERRDAD,
308c2ecf20Sopenharmony_ci	INET6_IFADDR_STATE_DEAD,
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistruct inet6_ifaddr {
348c2ecf20Sopenharmony_ci	struct in6_addr		addr;
358c2ecf20Sopenharmony_ci	__u32			prefix_len;
368c2ecf20Sopenharmony_ci	__u32			rt_priority;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	/* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
398c2ecf20Sopenharmony_ci	__u32			valid_lft;
408c2ecf20Sopenharmony_ci	__u32			prefered_lft;
418c2ecf20Sopenharmony_ci	refcount_t		refcnt;
428c2ecf20Sopenharmony_ci	spinlock_t		lock;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	int			state;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	__u32			flags;
478c2ecf20Sopenharmony_ci	__u8			dad_probes;
488c2ecf20Sopenharmony_ci	__u8			stable_privacy_retry;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	__u16			scope;
518c2ecf20Sopenharmony_ci	__u64			dad_nonce;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	unsigned long		cstamp;	/* created timestamp */
548c2ecf20Sopenharmony_ci	unsigned long		tstamp; /* updated timestamp */
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	struct delayed_work	dad_work;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	struct inet6_dev	*idev;
598c2ecf20Sopenharmony_ci	struct fib6_info	*rt;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	struct hlist_node	addr_lst;
628c2ecf20Sopenharmony_ci	struct list_head	if_list;
638c2ecf20Sopenharmony_ci	/*
648c2ecf20Sopenharmony_ci	 * Used to safely traverse idev->addr_list in process context
658c2ecf20Sopenharmony_ci	 * if the idev->lock needed to protect idev->addr_list cannot be held.
668c2ecf20Sopenharmony_ci	 * In that case, add the items to this list temporarily and iterate
678c2ecf20Sopenharmony_ci	 * without holding idev->lock.
688c2ecf20Sopenharmony_ci	 * See addrconf_ifdown and dev_forward_change.
698c2ecf20Sopenharmony_ci	 */
708c2ecf20Sopenharmony_ci	struct list_head	if_list_aux;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	struct list_head	tmp_list;
738c2ecf20Sopenharmony_ci	struct inet6_ifaddr	*ifpub;
748c2ecf20Sopenharmony_ci	int			regen_count;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	bool			tokenized;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	struct rcu_head		rcu;
798c2ecf20Sopenharmony_ci	struct in6_addr		peer_addr;
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistruct ip6_sf_socklist {
838c2ecf20Sopenharmony_ci	unsigned int		sl_max;
848c2ecf20Sopenharmony_ci	unsigned int		sl_count;
858c2ecf20Sopenharmony_ci	struct in6_addr		sl_addr[];
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci#define IP6_SFLSIZE(count)	(sizeof(struct ip6_sf_socklist) + \
898c2ecf20Sopenharmony_ci	(count) * sizeof(struct in6_addr))
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#define IP6_SFBLOCK	10	/* allocate this many at once */
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistruct ipv6_mc_socklist {
948c2ecf20Sopenharmony_ci	struct in6_addr		addr;
958c2ecf20Sopenharmony_ci	int			ifindex;
968c2ecf20Sopenharmony_ci	unsigned int		sfmode;		/* MCAST_{INCLUDE,EXCLUDE} */
978c2ecf20Sopenharmony_ci	struct ipv6_mc_socklist __rcu *next;
988c2ecf20Sopenharmony_ci	rwlock_t		sflock;
998c2ecf20Sopenharmony_ci	struct ip6_sf_socklist	*sflist;
1008c2ecf20Sopenharmony_ci	struct rcu_head		rcu;
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistruct ip6_sf_list {
1048c2ecf20Sopenharmony_ci	struct ip6_sf_list	*sf_next;
1058c2ecf20Sopenharmony_ci	struct in6_addr		sf_addr;
1068c2ecf20Sopenharmony_ci	unsigned long		sf_count[2];	/* include/exclude counts */
1078c2ecf20Sopenharmony_ci	unsigned char		sf_gsresp;	/* include in g & s response? */
1088c2ecf20Sopenharmony_ci	unsigned char		sf_oldin;	/* change state */
1098c2ecf20Sopenharmony_ci	unsigned char		sf_crcount;	/* retrans. left to send */
1108c2ecf20Sopenharmony_ci};
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci#define MAF_TIMER_RUNNING	0x01
1138c2ecf20Sopenharmony_ci#define MAF_LAST_REPORTER	0x02
1148c2ecf20Sopenharmony_ci#define MAF_LOADED		0x04
1158c2ecf20Sopenharmony_ci#define MAF_NOREPORT		0x08
1168c2ecf20Sopenharmony_ci#define MAF_GSQUERY		0x10
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistruct ifmcaddr6 {
1198c2ecf20Sopenharmony_ci	struct in6_addr		mca_addr;
1208c2ecf20Sopenharmony_ci	struct inet6_dev	*idev;
1218c2ecf20Sopenharmony_ci	struct ifmcaddr6	*next;
1228c2ecf20Sopenharmony_ci	struct ip6_sf_list	*mca_sources;
1238c2ecf20Sopenharmony_ci	struct ip6_sf_list	*mca_tomb;
1248c2ecf20Sopenharmony_ci	unsigned int		mca_sfmode;
1258c2ecf20Sopenharmony_ci	unsigned char		mca_crcount;
1268c2ecf20Sopenharmony_ci	unsigned long		mca_sfcount[2];
1278c2ecf20Sopenharmony_ci	struct timer_list	mca_timer;
1288c2ecf20Sopenharmony_ci	unsigned int		mca_flags;
1298c2ecf20Sopenharmony_ci	int			mca_users;
1308c2ecf20Sopenharmony_ci	refcount_t		mca_refcnt;
1318c2ecf20Sopenharmony_ci	spinlock_t		mca_lock;
1328c2ecf20Sopenharmony_ci	unsigned long		mca_cstamp;
1338c2ecf20Sopenharmony_ci	unsigned long		mca_tstamp;
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci/* Anycast stuff */
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct ipv6_ac_socklist {
1398c2ecf20Sopenharmony_ci	struct in6_addr		acl_addr;
1408c2ecf20Sopenharmony_ci	int			acl_ifindex;
1418c2ecf20Sopenharmony_ci	struct ipv6_ac_socklist *acl_next;
1428c2ecf20Sopenharmony_ci};
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistruct ifacaddr6 {
1458c2ecf20Sopenharmony_ci	struct in6_addr		aca_addr;
1468c2ecf20Sopenharmony_ci	struct fib6_info	*aca_rt;
1478c2ecf20Sopenharmony_ci	struct ifacaddr6	*aca_next;
1488c2ecf20Sopenharmony_ci	struct hlist_node	aca_addr_lst;
1498c2ecf20Sopenharmony_ci	int			aca_users;
1508c2ecf20Sopenharmony_ci	refcount_t		aca_refcnt;
1518c2ecf20Sopenharmony_ci	unsigned long		aca_cstamp;
1528c2ecf20Sopenharmony_ci	unsigned long		aca_tstamp;
1538c2ecf20Sopenharmony_ci	struct rcu_head		rcu;
1548c2ecf20Sopenharmony_ci};
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci#define	IFA_HOST	IPV6_ADDR_LOOPBACK
1578c2ecf20Sopenharmony_ci#define	IFA_LINK	IPV6_ADDR_LINKLOCAL
1588c2ecf20Sopenharmony_ci#define	IFA_SITE	IPV6_ADDR_SITELOCAL
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistruct ipv6_devstat {
1618c2ecf20Sopenharmony_ci	struct proc_dir_entry	*proc_dir_entry;
1628c2ecf20Sopenharmony_ci	DEFINE_SNMP_STAT(struct ipstats_mib, ipv6);
1638c2ecf20Sopenharmony_ci	DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev);
1648c2ecf20Sopenharmony_ci	DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev);
1658c2ecf20Sopenharmony_ci};
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistruct inet6_dev {
1688c2ecf20Sopenharmony_ci	struct net_device	*dev;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	struct list_head	addr_list;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	struct ifmcaddr6	*mc_list;
1738c2ecf20Sopenharmony_ci	struct ifmcaddr6	*mc_tomb;
1748c2ecf20Sopenharmony_ci	spinlock_t		mc_lock;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	unsigned char		mc_qrv;		/* Query Robustness Variable */
1778c2ecf20Sopenharmony_ci	unsigned char		mc_gq_running;
1788c2ecf20Sopenharmony_ci	unsigned char		mc_ifc_count;
1798c2ecf20Sopenharmony_ci	unsigned char		mc_dad_count;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	unsigned long		mc_v1_seen;	/* Max time we stay in MLDv1 mode */
1828c2ecf20Sopenharmony_ci	unsigned long		mc_qi;		/* Query Interval */
1838c2ecf20Sopenharmony_ci	unsigned long		mc_qri;		/* Query Response Interval */
1848c2ecf20Sopenharmony_ci	unsigned long		mc_maxdelay;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	struct timer_list	mc_gq_timer;	/* general query timer */
1878c2ecf20Sopenharmony_ci	struct timer_list	mc_ifc_timer;	/* interface change timer */
1888c2ecf20Sopenharmony_ci	struct timer_list	mc_dad_timer;	/* dad complete mc timer */
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	struct ifacaddr6	*ac_list;
1918c2ecf20Sopenharmony_ci	rwlock_t		lock;
1928c2ecf20Sopenharmony_ci	refcount_t		refcnt;
1938c2ecf20Sopenharmony_ci	__u32			if_flags;
1948c2ecf20Sopenharmony_ci	int			dead;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	u32			desync_factor;
1978c2ecf20Sopenharmony_ci	struct list_head	tempaddr_list;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	struct in6_addr		token;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	struct neigh_parms	*nd_parms;
2028c2ecf20Sopenharmony_ci	struct ipv6_devconf	cnf;
2038c2ecf20Sopenharmony_ci	struct ipv6_devstat	stats;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	struct timer_list	rs_timer;
2068c2ecf20Sopenharmony_ci	__s32			rs_interval;	/* in jiffies */
2078c2ecf20Sopenharmony_ci	__u8			rs_probes;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	unsigned long		tstamp; /* ipv6InterfaceTable update timestamp */
2108c2ecf20Sopenharmony_ci	struct rcu_head		rcu;
2118c2ecf20Sopenharmony_ci};
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	/*
2168c2ecf20Sopenharmony_ci	 *	+-------+-------+-------+-------+-------+-------+
2178c2ecf20Sopenharmony_ci	 *      |   33  |   33  | DST13 | DST14 | DST15 | DST16 |
2188c2ecf20Sopenharmony_ci	 *      +-------+-------+-------+-------+-------+-------+
2198c2ecf20Sopenharmony_ci	 */
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	buf[0]= 0x33;
2228c2ecf20Sopenharmony_ci	buf[1]= 0x33;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32));
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	buf[0] = 0x00;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic inline void ipv6_ib_mc_map(const struct in6_addr *addr,
2338c2ecf20Sopenharmony_ci				  const unsigned char *broadcast, char *buf)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	unsigned char scope = broadcast[5] & 0xF;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	buf[0]  = 0;		/* Reserved */
2388c2ecf20Sopenharmony_ci	buf[1]  = 0xff;		/* Multicast QPN */
2398c2ecf20Sopenharmony_ci	buf[2]  = 0xff;
2408c2ecf20Sopenharmony_ci	buf[3]  = 0xff;
2418c2ecf20Sopenharmony_ci	buf[4]  = 0xff;
2428c2ecf20Sopenharmony_ci	buf[5]  = 0x10 | scope;	/* scope from broadcast address */
2438c2ecf20Sopenharmony_ci	buf[6]  = 0x60;		/* IPv6 signature */
2448c2ecf20Sopenharmony_ci	buf[7]  = 0x1b;
2458c2ecf20Sopenharmony_ci	buf[8]  = broadcast[8];	/* P_Key */
2468c2ecf20Sopenharmony_ci	buf[9]  = broadcast[9];
2478c2ecf20Sopenharmony_ci	memcpy(buf + 10, addr->s6_addr + 6, 10);
2488c2ecf20Sopenharmony_ci}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistatic inline int ipv6_ipgre_mc_map(const struct in6_addr *addr,
2518c2ecf20Sopenharmony_ci				    const unsigned char *broadcast, char *buf)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) {
2548c2ecf20Sopenharmony_ci		memcpy(buf, broadcast, 4);
2558c2ecf20Sopenharmony_ci	} else {
2568c2ecf20Sopenharmony_ci		/* v4mapped? */
2578c2ecf20Sopenharmony_ci		if ((addr->s6_addr32[0] | addr->s6_addr32[1] |
2588c2ecf20Sopenharmony_ci		     (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0)
2598c2ecf20Sopenharmony_ci			return -EINVAL;
2608c2ecf20Sopenharmony_ci		memcpy(buf, &addr->s6_addr32[3], 4);
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci	return 0;
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci#endif
266