linux/net/ipv6/addrconf_core.c
<<
>>
Prefs
   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 */
  17void (*__fib6_flush_trees)(struct net *);
  18EXPORT_SYMBOL(__fib6_flush_trees);
  19
  20#define IPV6_ADDR_SCOPE_TYPE(scope)     ((scope) << 16)
  21
  22static 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
  38int __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}
  90EXPORT_SYMBOL(__ipv6_addr_type);
  91
  92static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
  93static BLOCKING_NOTIFIER_HEAD(inet6addr_validator_chain);
  94
  95int register_inet6addr_notifier(struct notifier_block *nb)
  96{
  97        return atomic_notifier_chain_register(&inet6addr_chain, nb);
  98}
  99EXPORT_SYMBOL(register_inet6addr_notifier);
 100
 101int unregister_inet6addr_notifier(struct notifier_block *nb)
 102{
 103        return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
 104}
 105EXPORT_SYMBOL(unregister_inet6addr_notifier);
 106
 107int inet6addr_notifier_call_chain(unsigned long val, void *v)
 108{
 109        return atomic_notifier_call_chain(&inet6addr_chain, val, v);
 110}
 111EXPORT_SYMBOL(inet6addr_notifier_call_chain);
 112
 113int register_inet6addr_validator_notifier(struct notifier_block *nb)
 114{
 115        return blocking_notifier_chain_register(&inet6addr_validator_chain, nb);
 116}
 117EXPORT_SYMBOL(register_inet6addr_validator_notifier);
 118
 119int unregister_inet6addr_validator_notifier(struct notifier_block *nb)
 120{
 121        return blocking_notifier_chain_unregister(&inet6addr_validator_chain,
 122                                                  nb);
 123}
 124EXPORT_SYMBOL(unregister_inet6addr_validator_notifier);
 125
 126int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
 127{
 128        return blocking_notifier_call_chain(&inet6addr_validator_chain, val, v);
 129}
 130EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
 131
 132static 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
 140static int eafnosupport_ipv6_route_input(struct sk_buff *skb)
 141{
 142        return -EAFNOSUPPORT;
 143}
 144
 145static struct fib6_table *eafnosupport_fib6_get_table(struct net *net, u32 id)
 146{
 147        return NULL;
 148}
 149
 150static int
 151eafnosupport_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
 158static int
 159eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
 160                         struct fib6_result *res, int flags)
 161{
 162        return -EAFNOSUPPORT;
 163}
 164
 165static void
 166eafnosupport_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
 172static u32
 173eafnosupport_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
 180static 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
 188static int eafnosupport_ip6_del_rt(struct net *net, struct fib6_info *rt,
 189                                   bool skip_notify)
 190{
 191        return -EAFNOSUPPORT;
 192}
 193
 194static int eafnosupport_ipv6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
 195                                      int (*output)(struct net *, struct sock *, struct sk_buff *))
 196{
 197        kfree_skb(skb);
 198        return -EAFNOSUPPORT;
 199}
 200
 201static struct net_device *eafnosupport_ipv6_dev_find(struct net *net, const struct in6_addr *addr,
 202                                                     struct net_device *dev)
 203{
 204        return ERR_PTR(-EAFNOSUPPORT);
 205}
 206
 207const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
 208        .ipv6_dst_lookup_flow = eafnosupport_ipv6_dst_lookup_flow,
 209        .ipv6_route_input  = eafnosupport_ipv6_route_input,
 210        .fib6_get_table    = eafnosupport_fib6_get_table,
 211        .fib6_table_lookup = eafnosupport_fib6_table_lookup,
 212        .fib6_lookup       = eafnosupport_fib6_lookup,
 213        .fib6_select_path  = eafnosupport_fib6_select_path,
 214        .ip6_mtu_from_fib6 = eafnosupport_ip6_mtu_from_fib6,
 215        .fib6_nh_init      = eafnosupport_fib6_nh_init,
 216        .ip6_del_rt        = eafnosupport_ip6_del_rt,
 217        .ipv6_fragment     = eafnosupport_ipv6_fragment,
 218        .ipv6_dev_find     = eafnosupport_ipv6_dev_find,
 219};
 220EXPORT_SYMBOL_GPL(ipv6_stub);
 221
 222/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
 223const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
 224EXPORT_SYMBOL(in6addr_loopback);
 225const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 226EXPORT_SYMBOL(in6addr_any);
 227const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
 228EXPORT_SYMBOL(in6addr_linklocal_allnodes);
 229const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
 230EXPORT_SYMBOL(in6addr_linklocal_allrouters);
 231const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
 232EXPORT_SYMBOL(in6addr_interfacelocal_allnodes);
 233const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
 234EXPORT_SYMBOL(in6addr_interfacelocal_allrouters);
 235const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
 236EXPORT_SYMBOL(in6addr_sitelocal_allrouters);
 237
 238static void snmp6_free_dev(struct inet6_dev *idev)
 239{
 240        kfree(idev->stats.icmpv6msgdev);
 241        kfree(idev->stats.icmpv6dev);
 242        free_percpu(idev->stats.ipv6);
 243}
 244
 245static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
 246{
 247        struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
 248
 249        snmp6_free_dev(idev);
 250        kfree(idev);
 251}
 252
 253/* Nobody refers to this device, we may destroy it. */
 254
 255void in6_dev_finish_destroy(struct inet6_dev *idev)
 256{
 257        struct net_device *dev = idev->dev;
 258
 259        WARN_ON(!list_empty(&idev->addr_list));
 260        WARN_ON(rcu_access_pointer(idev->mc_list));
 261        WARN_ON(timer_pending(&idev->rs_timer));
 262
 263#ifdef NET_REFCNT_DEBUG
 264        pr_debug("%s: %s\n", __func__, dev ? dev->name : "NIL");
 265#endif
 266        dev_put(dev);
 267        if (!idev->dead) {
 268                pr_warn("Freeing alive inet6 device %p\n", idev);
 269                return;
 270        }
 271        call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
 272}
 273EXPORT_SYMBOL(in6_dev_finish_destroy);
 274