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