xref: /OK3568_Linux_fs/kernel/include/net/addrconf.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef _ADDRCONF_H
3*4882a593Smuzhiyun #define _ADDRCONF_H
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #define MAX_RTR_SOLICITATIONS		-1		/* unlimited */
6*4882a593Smuzhiyun #define RTR_SOLICITATION_INTERVAL	(4*HZ)
7*4882a593Smuzhiyun #define RTR_SOLICITATION_MAX_INTERVAL	(3600*HZ)	/* 1 hour */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #define MIN_VALID_LIFETIME		(2*3600)	/* 2 hours */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #define TEMP_VALID_LIFETIME		(7*86400)
12*4882a593Smuzhiyun #define TEMP_PREFERRED_LIFETIME		(86400)
13*4882a593Smuzhiyun #define REGEN_MAX_RETRY			(3)
14*4882a593Smuzhiyun #define MAX_DESYNC_FACTOR		(600)
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define ADDR_CHECK_FREQUENCY		(120*HZ)
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define IPV6_MAX_ADDRESSES		16
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define ADDRCONF_TIMER_FUZZ_MINUS	(HZ > 50 ? HZ / 50 : 1)
21*4882a593Smuzhiyun #define ADDRCONF_TIMER_FUZZ		(HZ / 4)
22*4882a593Smuzhiyun #define ADDRCONF_TIMER_FUZZ_MAX		(HZ)
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define ADDRCONF_NOTIFY_PRIORITY	0
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include <linux/in.h>
27*4882a593Smuzhiyun #include <linux/in6.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct prefix_info {
30*4882a593Smuzhiyun 	__u8			type;
31*4882a593Smuzhiyun 	__u8			length;
32*4882a593Smuzhiyun 	__u8			prefix_len;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #if defined(__BIG_ENDIAN_BITFIELD)
35*4882a593Smuzhiyun 	__u8			onlink : 1,
36*4882a593Smuzhiyun 			 	autoconf : 1,
37*4882a593Smuzhiyun 				reserved : 6;
38*4882a593Smuzhiyun #elif defined(__LITTLE_ENDIAN_BITFIELD)
39*4882a593Smuzhiyun 	__u8			reserved : 6,
40*4882a593Smuzhiyun 				autoconf : 1,
41*4882a593Smuzhiyun 				onlink : 1;
42*4882a593Smuzhiyun #else
43*4882a593Smuzhiyun #error "Please fix <asm/byteorder.h>"
44*4882a593Smuzhiyun #endif
45*4882a593Smuzhiyun 	__be32			valid;
46*4882a593Smuzhiyun 	__be32			prefered;
47*4882a593Smuzhiyun 	__be32			reserved2;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	struct in6_addr		prefix;
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #include <linux/ipv6.h>
53*4882a593Smuzhiyun #include <linux/netdevice.h>
54*4882a593Smuzhiyun #include <net/if_inet6.h>
55*4882a593Smuzhiyun #include <net/ipv6.h>
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun struct in6_validator_info {
58*4882a593Smuzhiyun 	struct in6_addr		i6vi_addr;
59*4882a593Smuzhiyun 	struct inet6_dev	*i6vi_dev;
60*4882a593Smuzhiyun 	struct netlink_ext_ack	*extack;
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun struct ifa6_config {
64*4882a593Smuzhiyun 	const struct in6_addr	*pfx;
65*4882a593Smuzhiyun 	unsigned int		plen;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	const struct in6_addr	*peer_pfx;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	u32			rt_priority;
70*4882a593Smuzhiyun 	u32			ifa_flags;
71*4882a593Smuzhiyun 	u32			preferred_lft;
72*4882a593Smuzhiyun 	u32			valid_lft;
73*4882a593Smuzhiyun 	u16			scope;
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun int addrconf_init(void);
77*4882a593Smuzhiyun void addrconf_cleanup(void);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun int addrconf_add_ifaddr(struct net *net, void __user *arg);
80*4882a593Smuzhiyun int addrconf_del_ifaddr(struct net *net, void __user *arg);
81*4882a593Smuzhiyun int addrconf_set_dstaddr(struct net *net, void __user *arg);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
84*4882a593Smuzhiyun 		  const struct net_device *dev, int strict);
85*4882a593Smuzhiyun int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
86*4882a593Smuzhiyun 			    const struct net_device *dev, bool skip_dev_check,
87*4882a593Smuzhiyun 			    int strict, u32 banned_flags);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
90*4882a593Smuzhiyun int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
91*4882a593Smuzhiyun #endif
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun int ipv6_chk_rpl_srh_loop(struct net *net, const struct in6_addr *segs,
94*4882a593Smuzhiyun 			  unsigned char nsegs);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
97*4882a593Smuzhiyun 				   const unsigned int prefix_len,
98*4882a593Smuzhiyun 				   struct net_device *dev);
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun struct net_device *ipv6_dev_find(struct net *net, const struct in6_addr *addr,
103*4882a593Smuzhiyun 				 struct net_device *dev);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
106*4882a593Smuzhiyun 				     const struct in6_addr *addr,
107*4882a593Smuzhiyun 				     struct net_device *dev, int strict);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
110*4882a593Smuzhiyun 		       const struct in6_addr *daddr, unsigned int srcprefs,
111*4882a593Smuzhiyun 		       struct in6_addr *saddr);
112*4882a593Smuzhiyun int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
113*4882a593Smuzhiyun 		      u32 banned_flags);
114*4882a593Smuzhiyun int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
115*4882a593Smuzhiyun 		    u32 banned_flags);
116*4882a593Smuzhiyun bool inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,
117*4882a593Smuzhiyun 			  bool match_wildcard);
118*4882a593Smuzhiyun bool inet_rcv_saddr_any(const struct sock *sk);
119*4882a593Smuzhiyun void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);
120*4882a593Smuzhiyun void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun void addrconf_add_linklocal(struct inet6_dev *idev,
123*4882a593Smuzhiyun 			    const struct in6_addr *addr, u32 flags);
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
126*4882a593Smuzhiyun 				 const struct prefix_info *pinfo,
127*4882a593Smuzhiyun 				 struct inet6_dev *in6_dev,
128*4882a593Smuzhiyun 				 const struct in6_addr *addr, int addr_type,
129*4882a593Smuzhiyun 				 u32 addr_flags, bool sllao, bool tokenized,
130*4882a593Smuzhiyun 				 __u32 valid_lft, u32 prefered_lft);
131*4882a593Smuzhiyun 
addrconf_addr_eui48_base(u8 * eui,const char * const addr)132*4882a593Smuzhiyun static inline void addrconf_addr_eui48_base(u8 *eui, const char *const addr)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	memcpy(eui, addr, 3);
135*4882a593Smuzhiyun 	eui[3] = 0xFF;
136*4882a593Smuzhiyun 	eui[4] = 0xFE;
137*4882a593Smuzhiyun 	memcpy(eui + 5, addr + 3, 3);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
addrconf_addr_eui48(u8 * eui,const char * const addr)140*4882a593Smuzhiyun static inline void addrconf_addr_eui48(u8 *eui, const char *const addr)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	addrconf_addr_eui48_base(eui, addr);
143*4882a593Smuzhiyun 	eui[0] ^= 2;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun 
addrconf_ifid_eui48(u8 * eui,struct net_device * dev)146*4882a593Smuzhiyun static inline int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun 	if (dev->addr_len != ETH_ALEN)
149*4882a593Smuzhiyun 		return -1;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	/*
152*4882a593Smuzhiyun 	 * The zSeries OSA network cards can be shared among various
153*4882a593Smuzhiyun 	 * OS instances, but the OSA cards have only one MAC address.
154*4882a593Smuzhiyun 	 * This leads to duplicate address conflicts in conjunction
155*4882a593Smuzhiyun 	 * with IPv6 if more than one instance uses the same card.
156*4882a593Smuzhiyun 	 *
157*4882a593Smuzhiyun 	 * The driver for these cards can deliver a unique 16-bit
158*4882a593Smuzhiyun 	 * identifier for each instance sharing the same card.  It is
159*4882a593Smuzhiyun 	 * placed instead of 0xFFFE in the interface identifier.  The
160*4882a593Smuzhiyun 	 * "u" bit of the interface identifier is not inverted in this
161*4882a593Smuzhiyun 	 * case.  Hence the resulting interface identifier has local
162*4882a593Smuzhiyun 	 * scope according to RFC2373.
163*4882a593Smuzhiyun 	 */
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	addrconf_addr_eui48_base(eui, dev->dev_addr);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	if (dev->dev_id) {
168*4882a593Smuzhiyun 		eui[3] = (dev->dev_id >> 8) & 0xFF;
169*4882a593Smuzhiyun 		eui[4] = dev->dev_id & 0xFF;
170*4882a593Smuzhiyun 	} else {
171*4882a593Smuzhiyun 		eui[0] ^= 2;
172*4882a593Smuzhiyun 	}
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	return 0;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
addrconf_timeout_fixup(u32 timeout,unsigned int unit)177*4882a593Smuzhiyun static inline unsigned long addrconf_timeout_fixup(u32 timeout,
178*4882a593Smuzhiyun 						   unsigned int unit)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	if (timeout == 0xffffffff)
181*4882a593Smuzhiyun 		return ~0UL;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	/*
184*4882a593Smuzhiyun 	 * Avoid arithmetic overflow.
185*4882a593Smuzhiyun 	 * Assuming unit is constant and non-zero, this "if" statement
186*4882a593Smuzhiyun 	 * will go away on 64bit archs.
187*4882a593Smuzhiyun 	 */
188*4882a593Smuzhiyun 	if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit)
189*4882a593Smuzhiyun 		return LONG_MAX / unit;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	return timeout;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
addrconf_finite_timeout(unsigned long timeout)194*4882a593Smuzhiyun static inline int addrconf_finite_timeout(unsigned long timeout)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	return ~timeout;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun /*
200*4882a593Smuzhiyun  *	IPv6 Address Label subsystem (addrlabel.c)
201*4882a593Smuzhiyun  */
202*4882a593Smuzhiyun int ipv6_addr_label_init(void);
203*4882a593Smuzhiyun void ipv6_addr_label_cleanup(void);
204*4882a593Smuzhiyun int ipv6_addr_label_rtnl_register(void);
205*4882a593Smuzhiyun u32 ipv6_addr_label(struct net *net, const struct in6_addr *addr,
206*4882a593Smuzhiyun 		    int type, int ifindex);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun /*
209*4882a593Smuzhiyun  *	multicast prototypes (mcast.c)
210*4882a593Smuzhiyun  */
ipv6_mc_may_pull(struct sk_buff * skb,unsigned int len)211*4882a593Smuzhiyun static inline bool ipv6_mc_may_pull(struct sk_buff *skb,
212*4882a593Smuzhiyun 				    unsigned int len)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	if (skb_transport_offset(skb) + ipv6_transport_len(skb) < len)
215*4882a593Smuzhiyun 		return false;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	return pskb_may_pull(skb, len);
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun int ipv6_sock_mc_join(struct sock *sk, int ifindex,
221*4882a593Smuzhiyun 		      const struct in6_addr *addr);
222*4882a593Smuzhiyun int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
223*4882a593Smuzhiyun 		      const struct in6_addr *addr);
224*4882a593Smuzhiyun void __ipv6_sock_mc_close(struct sock *sk);
225*4882a593Smuzhiyun void ipv6_sock_mc_close(struct sock *sk);
226*4882a593Smuzhiyun bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
227*4882a593Smuzhiyun 		    const struct in6_addr *src_addr);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
230*4882a593Smuzhiyun int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
231*4882a593Smuzhiyun int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
232*4882a593Smuzhiyun void ipv6_mc_up(struct inet6_dev *idev);
233*4882a593Smuzhiyun void ipv6_mc_down(struct inet6_dev *idev);
234*4882a593Smuzhiyun void ipv6_mc_unmap(struct inet6_dev *idev);
235*4882a593Smuzhiyun void ipv6_mc_remap(struct inet6_dev *idev);
236*4882a593Smuzhiyun void ipv6_mc_init_dev(struct inet6_dev *idev);
237*4882a593Smuzhiyun void ipv6_mc_destroy_dev(struct inet6_dev *idev);
238*4882a593Smuzhiyun int ipv6_mc_check_mld(struct sk_buff *skb);
239*4882a593Smuzhiyun void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
242*4882a593Smuzhiyun 			 const struct in6_addr *src_addr);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun void ipv6_mc_dad_complete(struct inet6_dev *idev);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun /*
247*4882a593Smuzhiyun  * identify MLD packets for MLD filter exceptions
248*4882a593Smuzhiyun  */
ipv6_is_mld(struct sk_buff * skb,int nexthdr,int offset)249*4882a593Smuzhiyun static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	struct icmp6hdr *hdr;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	if (nexthdr != IPPROTO_ICMPV6 ||
254*4882a593Smuzhiyun 	    !pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr)))
255*4882a593Smuzhiyun 		return false;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	switch (hdr->icmp6_type) {
260*4882a593Smuzhiyun 	case ICMPV6_MGM_QUERY:
261*4882a593Smuzhiyun 	case ICMPV6_MGM_REPORT:
262*4882a593Smuzhiyun 	case ICMPV6_MGM_REDUCTION:
263*4882a593Smuzhiyun 	case ICMPV6_MLD2_REPORT:
264*4882a593Smuzhiyun 		return true;
265*4882a593Smuzhiyun 	default:
266*4882a593Smuzhiyun 		break;
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun 	return false;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun void addrconf_prefix_rcv(struct net_device *dev,
272*4882a593Smuzhiyun 			 u8 *opt, int len, bool sllao);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun /* Determines into what table to put autoconf PIO/RIO/default routes
275*4882a593Smuzhiyun  * learned on this device.
276*4882a593Smuzhiyun  *
277*4882a593Smuzhiyun  * - If 0, use the same table for every device. This puts routes into
278*4882a593Smuzhiyun  *   one of RT_TABLE_{PREFIX,INFO,DFLT} depending on the type of route
279*4882a593Smuzhiyun  *   (but note that these three are currently all equal to
280*4882a593Smuzhiyun  *   RT6_TABLE_MAIN).
281*4882a593Smuzhiyun  * - If > 0, use the specified table.
282*4882a593Smuzhiyun  * - If < 0, put routes into table dev->ifindex + (-rt_table).
283*4882a593Smuzhiyun  */
284*4882a593Smuzhiyun u32 addrconf_rt_table(const struct net_device *dev, u32 default_table);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /*
287*4882a593Smuzhiyun  *	anycast prototypes (anycast.c)
288*4882a593Smuzhiyun  */
289*4882a593Smuzhiyun int ipv6_sock_ac_join(struct sock *sk, int ifindex,
290*4882a593Smuzhiyun 		      const struct in6_addr *addr);
291*4882a593Smuzhiyun int ipv6_sock_ac_drop(struct sock *sk, int ifindex,
292*4882a593Smuzhiyun 		      const struct in6_addr *addr);
293*4882a593Smuzhiyun void __ipv6_sock_ac_close(struct sock *sk);
294*4882a593Smuzhiyun void ipv6_sock_ac_close(struct sock *sk);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr);
297*4882a593Smuzhiyun int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
298*4882a593Smuzhiyun void ipv6_ac_destroy_dev(struct inet6_dev *idev);
299*4882a593Smuzhiyun bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
300*4882a593Smuzhiyun 			 const struct in6_addr *addr);
301*4882a593Smuzhiyun bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev,
302*4882a593Smuzhiyun 			     const struct in6_addr *addr);
303*4882a593Smuzhiyun int ipv6_anycast_init(void);
304*4882a593Smuzhiyun void ipv6_anycast_cleanup(void);
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun /* Device notifier */
307*4882a593Smuzhiyun int register_inet6addr_notifier(struct notifier_block *nb);
308*4882a593Smuzhiyun int unregister_inet6addr_notifier(struct notifier_block *nb);
309*4882a593Smuzhiyun int inet6addr_notifier_call_chain(unsigned long val, void *v);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun int register_inet6addr_validator_notifier(struct notifier_block *nb);
312*4882a593Smuzhiyun int unregister_inet6addr_validator_notifier(struct notifier_block *nb);
313*4882a593Smuzhiyun int inet6addr_validator_notifier_call_chain(unsigned long val, void *v);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun void inet6_netconf_notify_devconf(struct net *net, int event, int type,
316*4882a593Smuzhiyun 				  int ifindex, struct ipv6_devconf *devconf);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun /**
319*4882a593Smuzhiyun  * __in6_dev_get - get inet6_dev pointer from netdevice
320*4882a593Smuzhiyun  * @dev: network device
321*4882a593Smuzhiyun  *
322*4882a593Smuzhiyun  * Caller must hold rcu_read_lock or RTNL, because this function
323*4882a593Smuzhiyun  * does not take a reference on the inet6_dev.
324*4882a593Smuzhiyun  */
__in6_dev_get(const struct net_device * dev)325*4882a593Smuzhiyun static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	return rcu_dereference_rtnl(dev->ip6_ptr);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun /**
331*4882a593Smuzhiyun  * __in6_dev_stats_get - get inet6_dev pointer for stats
332*4882a593Smuzhiyun  * @dev: network device
333*4882a593Smuzhiyun  * @skb: skb for original incoming interface if neeeded
334*4882a593Smuzhiyun  *
335*4882a593Smuzhiyun  * Caller must hold rcu_read_lock or RTNL, because this function
336*4882a593Smuzhiyun  * does not take a reference on the inet6_dev.
337*4882a593Smuzhiyun  */
__in6_dev_stats_get(const struct net_device * dev,const struct sk_buff * skb)338*4882a593Smuzhiyun static inline struct inet6_dev *__in6_dev_stats_get(const struct net_device *dev,
339*4882a593Smuzhiyun 						    const struct sk_buff *skb)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	if (netif_is_l3_master(dev))
342*4882a593Smuzhiyun 		dev = dev_get_by_index_rcu(dev_net(dev), inet6_iif(skb));
343*4882a593Smuzhiyun 	return __in6_dev_get(dev);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun /**
347*4882a593Smuzhiyun  * __in6_dev_get_safely - get inet6_dev pointer from netdevice
348*4882a593Smuzhiyun  * @dev: network device
349*4882a593Smuzhiyun  *
350*4882a593Smuzhiyun  * This is a safer version of __in6_dev_get
351*4882a593Smuzhiyun  */
__in6_dev_get_safely(const struct net_device * dev)352*4882a593Smuzhiyun static inline struct inet6_dev *__in6_dev_get_safely(const struct net_device *dev)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun 	if (likely(dev))
355*4882a593Smuzhiyun 		return rcu_dereference_rtnl(dev->ip6_ptr);
356*4882a593Smuzhiyun 	else
357*4882a593Smuzhiyun 		return NULL;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun /**
361*4882a593Smuzhiyun  * in6_dev_get - get inet6_dev pointer from netdevice
362*4882a593Smuzhiyun  * @dev: network device
363*4882a593Smuzhiyun  *
364*4882a593Smuzhiyun  * This version can be used in any context, and takes a reference
365*4882a593Smuzhiyun  * on the inet6_dev. Callers must use in6_dev_put() later to
366*4882a593Smuzhiyun  * release this reference.
367*4882a593Smuzhiyun  */
in6_dev_get(const struct net_device * dev)368*4882a593Smuzhiyun static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	struct inet6_dev *idev;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	rcu_read_lock();
373*4882a593Smuzhiyun 	idev = rcu_dereference(dev->ip6_ptr);
374*4882a593Smuzhiyun 	if (idev)
375*4882a593Smuzhiyun 		refcount_inc(&idev->refcnt);
376*4882a593Smuzhiyun 	rcu_read_unlock();
377*4882a593Smuzhiyun 	return idev;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
__in6_dev_nd_parms_get_rcu(const struct net_device * dev)380*4882a593Smuzhiyun static inline struct neigh_parms *__in6_dev_nd_parms_get_rcu(const struct net_device *dev)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	struct inet6_dev *idev = __in6_dev_get(dev);
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	return idev ? idev->nd_parms : NULL;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun void in6_dev_finish_destroy(struct inet6_dev *idev);
388*4882a593Smuzhiyun 
in6_dev_put(struct inet6_dev * idev)389*4882a593Smuzhiyun static inline void in6_dev_put(struct inet6_dev *idev)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun 	if (refcount_dec_and_test(&idev->refcnt))
392*4882a593Smuzhiyun 		in6_dev_finish_destroy(idev);
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
in6_dev_put_clear(struct inet6_dev ** pidev)395*4882a593Smuzhiyun static inline void in6_dev_put_clear(struct inet6_dev **pidev)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	struct inet6_dev *idev = *pidev;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	if (idev) {
400*4882a593Smuzhiyun 		in6_dev_put(idev);
401*4882a593Smuzhiyun 		*pidev = NULL;
402*4882a593Smuzhiyun 	}
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
__in6_dev_put(struct inet6_dev * idev)405*4882a593Smuzhiyun static inline void __in6_dev_put(struct inet6_dev *idev)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	refcount_dec(&idev->refcnt);
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
in6_dev_hold(struct inet6_dev * idev)410*4882a593Smuzhiyun static inline void in6_dev_hold(struct inet6_dev *idev)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	refcount_inc(&idev->refcnt);
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun /* called with rcu_read_lock held */
ip6_ignore_linkdown(const struct net_device * dev)416*4882a593Smuzhiyun static inline bool ip6_ignore_linkdown(const struct net_device *dev)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	const struct inet6_dev *idev = __in6_dev_get(dev);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	if (unlikely(!idev))
421*4882a593Smuzhiyun 		return true;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return !!idev->cnf.ignore_routes_with_linkdown;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
427*4882a593Smuzhiyun 
in6_ifa_put(struct inet6_ifaddr * ifp)428*4882a593Smuzhiyun static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun 	if (refcount_dec_and_test(&ifp->refcnt))
431*4882a593Smuzhiyun 		inet6_ifa_finish_destroy(ifp);
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
__in6_ifa_put(struct inet6_ifaddr * ifp)434*4882a593Smuzhiyun static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	refcount_dec(&ifp->refcnt);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
in6_ifa_hold(struct inet6_ifaddr * ifp)439*4882a593Smuzhiyun static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun 	refcount_inc(&ifp->refcnt);
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun /*
446*4882a593Smuzhiyun  *	compute link-local solicited-node multicast address
447*4882a593Smuzhiyun  */
448*4882a593Smuzhiyun 
addrconf_addr_solict_mult(const struct in6_addr * addr,struct in6_addr * solicited)449*4882a593Smuzhiyun static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
450*4882a593Smuzhiyun 					     struct in6_addr *solicited)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun 	ipv6_addr_set(solicited,
453*4882a593Smuzhiyun 		      htonl(0xFF020000), 0,
454*4882a593Smuzhiyun 		      htonl(0x1),
455*4882a593Smuzhiyun 		      htonl(0xFF000000) | addr->s6_addr32[3]);
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
ipv6_addr_is_ll_all_nodes(const struct in6_addr * addr)458*4882a593Smuzhiyun static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
461*4882a593Smuzhiyun 	__be64 *p = (__force __be64 *)addr;
462*4882a593Smuzhiyun 	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL;
463*4882a593Smuzhiyun #else
464*4882a593Smuzhiyun 	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
465*4882a593Smuzhiyun 		addr->s6_addr32[1] | addr->s6_addr32[2] |
466*4882a593Smuzhiyun 		(addr->s6_addr32[3] ^ htonl(0x00000001))) == 0;
467*4882a593Smuzhiyun #endif
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
ipv6_addr_is_ll_all_routers(const struct in6_addr * addr)470*4882a593Smuzhiyun static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
473*4882a593Smuzhiyun 	__be64 *p = (__force __be64 *)addr;
474*4882a593Smuzhiyun 	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL;
475*4882a593Smuzhiyun #else
476*4882a593Smuzhiyun 	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
477*4882a593Smuzhiyun 		addr->s6_addr32[1] | addr->s6_addr32[2] |
478*4882a593Smuzhiyun 		(addr->s6_addr32[3] ^ htonl(0x00000002))) == 0;
479*4882a593Smuzhiyun #endif
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
ipv6_addr_is_isatap(const struct in6_addr * addr)482*4882a593Smuzhiyun static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun 	return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
ipv6_addr_is_solict_mult(const struct in6_addr * addr)487*4882a593Smuzhiyun static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
490*4882a593Smuzhiyun 	__be64 *p = (__force __be64 *)addr;
491*4882a593Smuzhiyun 	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) |
492*4882a593Smuzhiyun 		((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) &
493*4882a593Smuzhiyun 		 cpu_to_be64(0xffffffffff000000UL))) == 0UL;
494*4882a593Smuzhiyun #else
495*4882a593Smuzhiyun 	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
496*4882a593Smuzhiyun 		addr->s6_addr32[1] |
497*4882a593Smuzhiyun 		(addr->s6_addr32[2] ^ htonl(0x00000001)) |
498*4882a593Smuzhiyun 		(addr->s6_addr[12] ^ 0xff)) == 0;
499*4882a593Smuzhiyun #endif
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
ipv6_addr_is_all_snoopers(const struct in6_addr * addr)502*4882a593Smuzhiyun static inline bool ipv6_addr_is_all_snoopers(const struct in6_addr *addr)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
505*4882a593Smuzhiyun 	__be64 *p = (__force __be64 *)addr;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) |
508*4882a593Smuzhiyun 		(p[1] ^ cpu_to_be64(0x6a))) == 0UL;
509*4882a593Smuzhiyun #else
510*4882a593Smuzhiyun 	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
511*4882a593Smuzhiyun 		addr->s6_addr32[1] | addr->s6_addr32[2] |
512*4882a593Smuzhiyun 		(addr->s6_addr32[3] ^ htonl(0x0000006a))) == 0;
513*4882a593Smuzhiyun #endif
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun #ifdef CONFIG_PROC_FS
517*4882a593Smuzhiyun int if6_proc_init(void);
518*4882a593Smuzhiyun void if6_proc_exit(void);
519*4882a593Smuzhiyun #endif
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun #endif
522