dm table: fix various whitespace issues with recent DAX code
[linux-2.6-microblaze.git] / net / ipv6 / addrconf_core.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * IPv6 library code, needed by static components when full IPv6 support is
4  * not configured or static.
5  */
6
7 #include <linux/export.h>
8 #include <net/ipv6.h>
9 #include <net/ipv6_stubs.h>
10 #include <net/ip.h>
11
12 /* if ipv6 module registers this function is used by xfrm to force all
13  * sockets to relookup their nodes - this is fairly expensive, be
14  * careful
15  */
16 void (*__fib6_flush_trees)(struct net *);
17 EXPORT_SYMBOL(__fib6_flush_trees);
18
19 #define IPV6_ADDR_SCOPE_TYPE(scope)     ((scope) << 16)
20
21 static inline unsigned int ipv6_addr_scope2type(unsigned int scope)
22 {
23         switch (scope) {
24         case IPV6_ADDR_SCOPE_NODELOCAL:
25                 return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
26                         IPV6_ADDR_LOOPBACK);
27         case IPV6_ADDR_SCOPE_LINKLOCAL:
28                 return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
29                         IPV6_ADDR_LINKLOCAL);
30         case IPV6_ADDR_SCOPE_SITELOCAL:
31                 return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
32                         IPV6_ADDR_SITELOCAL);
33         }
34         return IPV6_ADDR_SCOPE_TYPE(scope);
35 }
36
37 int __ipv6_addr_type(const struct in6_addr *addr)
38 {
39         __be32 st;
40
41         st = addr->s6_addr32[0];
42
43         /* Consider all addresses with the first three bits different of
44            000 and 111 as unicasts.
45          */
46         if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
47             (st & htonl(0xE0000000)) != htonl(0xE0000000))
48                 return (IPV6_ADDR_UNICAST |
49                         IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
50
51         if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
52                 /* multicast */
53                 /* addr-select 3.1 */
54                 return (IPV6_ADDR_MULTICAST |
55                         ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
56         }
57
58         if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
59                 return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
60                         IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));               /* addr-select 3.1 */
61         if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
62                 return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
63                         IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL));               /* addr-select 3.1 */
64         if ((st & htonl(0xFE000000)) == htonl(0xFC000000))
65                 return (IPV6_ADDR_UNICAST |
66                         IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));                  /* RFC 4193 */
67
68         if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
69                 if (addr->s6_addr32[2] == 0) {
70                         if (addr->s6_addr32[3] == 0)
71                                 return IPV6_ADDR_ANY;
72
73                         if (addr->s6_addr32[3] == htonl(0x00000001))
74                                 return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
75                                         IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));       /* addr-select 3.4 */
76
77                         return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
78                                 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.3 */
79                 }
80
81                 if (addr->s6_addr32[2] == htonl(0x0000ffff))
82                         return (IPV6_ADDR_MAPPED |
83                                 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.3 */
84         }
85
86         return (IPV6_ADDR_UNICAST |
87                 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));  /* addr-select 3.4 */
88 }
89 EXPORT_SYMBOL(__ipv6_addr_type);
90
91 static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
92 static BLOCKING_NOTIFIER_HEAD(inet6addr_validator_chain);
93
94 int register_inet6addr_notifier(struct notifier_block *nb)
95 {
96         return atomic_notifier_chain_register(&inet6addr_chain, nb);
97 }
98 EXPORT_SYMBOL(register_inet6addr_notifier);
99
100 int unregister_inet6addr_notifier(struct notifier_block *nb)
101 {
102         return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
103 }
104 EXPORT_SYMBOL(unregister_inet6addr_notifier);
105
106 int inet6addr_notifier_call_chain(unsigned long val, void *v)
107 {
108         return atomic_notifier_call_chain(&inet6addr_chain, val, v);
109 }
110 EXPORT_SYMBOL(inet6addr_notifier_call_chain);
111
112 int register_inet6addr_validator_notifier(struct notifier_block *nb)
113 {
114         return blocking_notifier_chain_register(&inet6addr_validator_chain, nb);
115 }
116 EXPORT_SYMBOL(register_inet6addr_validator_notifier);
117
118 int unregister_inet6addr_validator_notifier(struct notifier_block *nb)
119 {
120         return blocking_notifier_chain_unregister(&inet6addr_validator_chain,
121                                                   nb);
122 }
123 EXPORT_SYMBOL(unregister_inet6addr_validator_notifier);
124
125 int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
126 {
127         return blocking_notifier_call_chain(&inet6addr_validator_chain, val, v);
128 }
129 EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
130
131 static int eafnosupport_ipv6_dst_lookup(struct net *net, struct sock *u1,
132                                         struct dst_entry **u2,
133                                         struct flowi6 *u3)
134 {
135         return -EAFNOSUPPORT;
136 }
137
138 static int eafnosupport_ipv6_route_input(struct sk_buff *skb)
139 {
140         return -EAFNOSUPPORT;
141 }
142
143 static struct fib6_table *eafnosupport_fib6_get_table(struct net *net, u32 id)
144 {
145         return NULL;
146 }
147
148 static int
149 eafnosupport_fib6_table_lookup(struct net *net, struct fib6_table *table,
150                                int oif, struct flowi6 *fl6,
151                                struct fib6_result *res, int flags)
152 {
153         return -EAFNOSUPPORT;
154 }
155
156 static int
157 eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
158                          struct fib6_result *res, int flags)
159 {
160         return -EAFNOSUPPORT;
161 }
162
163 static void
164 eafnosupport_fib6_select_path(const struct net *net, struct fib6_result *res,
165                               struct flowi6 *fl6, int oif, bool have_oif_match,
166                               const struct sk_buff *skb, int strict)
167 {
168 }
169
170 static u32
171 eafnosupport_ip6_mtu_from_fib6(const struct fib6_result *res,
172                                const struct in6_addr *daddr,
173                                const struct in6_addr *saddr)
174 {
175         return 0;
176 }
177
178 static int eafnosupport_fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
179                                      struct fib6_config *cfg, gfp_t gfp_flags,
180                                      struct netlink_ext_ack *extack)
181 {
182         NL_SET_ERR_MSG(extack, "IPv6 support not enabled in kernel");
183         return -EAFNOSUPPORT;
184 }
185
186 static int eafnosupport_ip6_del_rt(struct net *net, struct fib6_info *rt)
187 {
188         return -EAFNOSUPPORT;
189 }
190
191 const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
192         .ipv6_dst_lookup   = eafnosupport_ipv6_dst_lookup,
193         .ipv6_route_input  = eafnosupport_ipv6_route_input,
194         .fib6_get_table    = eafnosupport_fib6_get_table,
195         .fib6_table_lookup = eafnosupport_fib6_table_lookup,
196         .fib6_lookup       = eafnosupport_fib6_lookup,
197         .fib6_select_path  = eafnosupport_fib6_select_path,
198         .ip6_mtu_from_fib6 = eafnosupport_ip6_mtu_from_fib6,
199         .fib6_nh_init      = eafnosupport_fib6_nh_init,
200         .ip6_del_rt        = eafnosupport_ip6_del_rt,
201 };
202 EXPORT_SYMBOL_GPL(ipv6_stub);
203
204 /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
205 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
206 EXPORT_SYMBOL(in6addr_loopback);
207 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
208 EXPORT_SYMBOL(in6addr_any);
209 const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
210 EXPORT_SYMBOL(in6addr_linklocal_allnodes);
211 const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
212 EXPORT_SYMBOL(in6addr_linklocal_allrouters);
213 const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
214 EXPORT_SYMBOL(in6addr_interfacelocal_allnodes);
215 const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
216 EXPORT_SYMBOL(in6addr_interfacelocal_allrouters);
217 const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
218 EXPORT_SYMBOL(in6addr_sitelocal_allrouters);
219
220 static void snmp6_free_dev(struct inet6_dev *idev)
221 {
222         kfree(idev->stats.icmpv6msgdev);
223         kfree(idev->stats.icmpv6dev);
224         free_percpu(idev->stats.ipv6);
225 }
226
227 static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
228 {
229         struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
230
231         snmp6_free_dev(idev);
232         kfree(idev);
233 }
234
235 /* Nobody refers to this device, we may destroy it. */
236
237 void in6_dev_finish_destroy(struct inet6_dev *idev)
238 {
239         struct net_device *dev = idev->dev;
240
241         WARN_ON(!list_empty(&idev->addr_list));
242         WARN_ON(idev->mc_list);
243         WARN_ON(timer_pending(&idev->rs_timer));
244
245 #ifdef NET_REFCNT_DEBUG
246         pr_debug("%s: %s\n", __func__, dev ? dev->name : "NIL");
247 #endif
248         dev_put(dev);
249         if (!idev->dead) {
250                 pr_warn("Freeing alive inet6 device %p\n", idev);
251                 return;
252         }
253         call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
254 }
255 EXPORT_SYMBOL(in6_dev_finish_destroy);