root/net/ipv6/addrconf_core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipv6_addr_scope2type
  2. __ipv6_addr_type
  3. register_inet6addr_notifier
  4. unregister_inet6addr_notifier
  5. inet6addr_notifier_call_chain
  6. register_inet6addr_validator_notifier
  7. unregister_inet6addr_validator_notifier
  8. inet6addr_validator_notifier_call_chain
  9. eafnosupport_ipv6_dst_lookup_flow
  10. eafnosupport_ipv6_route_input
  11. eafnosupport_fib6_get_table
  12. eafnosupport_fib6_table_lookup
  13. eafnosupport_fib6_lookup
  14. eafnosupport_fib6_select_path
  15. eafnosupport_ip6_mtu_from_fib6
  16. eafnosupport_fib6_nh_init
  17. eafnosupport_ip6_del_rt
  18. snmp6_free_dev
  19. in6_dev_finish_destroy_rcu
  20. in6_dev_finish_destroy

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

/* [<][>][^][v][top][bottom][index][help] */