]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - net/ipv6/addrconf_core.c
vxlan: add ipv6 route short circuit support
[mirror_ubuntu-zesty-kernel.git] / net / ipv6 / addrconf_core.c
CommitLineData
8c14b7ce
YH
1/*
2 * IPv6 library code, needed by static components when full IPv6 support is
3 * not configured or static.
4 */
5
bc3b2d7f 6#include <linux/export.h>
8c14b7ce 7#include <net/ipv6.h>
6da334ee 8#include <net/addrconf.h>
8c14b7ce
YH
9
10#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16)
11
95c96174 12static inline unsigned int ipv6_addr_scope2type(unsigned int scope)
8c14b7ce 13{
d94d34a0 14 switch (scope) {
8c14b7ce
YH
15 case IPV6_ADDR_SCOPE_NODELOCAL:
16 return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
17 IPV6_ADDR_LOOPBACK);
18 case IPV6_ADDR_SCOPE_LINKLOCAL:
19 return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
20 IPV6_ADDR_LINKLOCAL);
21 case IPV6_ADDR_SCOPE_SITELOCAL:
22 return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
23 IPV6_ADDR_SITELOCAL);
24 }
25 return IPV6_ADDR_SCOPE_TYPE(scope);
26}
27
28int __ipv6_addr_type(const struct in6_addr *addr)
29{
30 __be32 st;
31
32 st = addr->s6_addr32[0];
33
34 /* Consider all addresses with the first three bits different of
35 000 and 111 as unicasts.
36 */
37 if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
38 (st & htonl(0xE0000000)) != htonl(0xE0000000))
39 return (IPV6_ADDR_UNICAST |
40 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
41
42 if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
43 /* multicast */
44 /* addr-select 3.1 */
45 return (IPV6_ADDR_MULTICAST |
46 ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
47 }
48
49 if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
50 return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
51 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */
52 if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
53 return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
54 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */
c61a7d10
DJ
55 if ((st & htonl(0xFE000000)) == htonl(0xFC000000))
56 return (IPV6_ADDR_UNICAST |
57 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* RFC 4193 */
8c14b7ce
YH
58
59 if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
60 if (addr->s6_addr32[2] == 0) {
61 if (addr->s6_addr32[3] == 0)
62 return IPV6_ADDR_ANY;
63
64 if (addr->s6_addr32[3] == htonl(0x00000001))
65 return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
66 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */
67
68 return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
69 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
70 }
71
72 if (addr->s6_addr32[2] == htonl(0x0000ffff))
73 return (IPV6_ADDR_MAPPED |
74 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
75 }
76
45bb0060 77 return (IPV6_ADDR_UNICAST |
8c14b7ce
YH
78 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */
79}
7401055b 80EXPORT_SYMBOL(__ipv6_addr_type);
8c14b7ce 81
f88c91dd
CW
82static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
83
84int register_inet6addr_notifier(struct notifier_block *nb)
85{
86 return atomic_notifier_chain_register(&inet6addr_chain, nb);
87}
88EXPORT_SYMBOL(register_inet6addr_notifier);
89
90int unregister_inet6addr_notifier(struct notifier_block *nb)
91{
92 return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
93}
94EXPORT_SYMBOL(unregister_inet6addr_notifier);
95
96int inet6addr_notifier_call_chain(unsigned long val, void *v)
97{
98 return atomic_notifier_call_chain(&inet6addr_chain, val, v);
99}
100EXPORT_SYMBOL(inet6addr_notifier_call_chain);
5f81bd2e
CW
101
102const struct ipv6_stub *ipv6_stub __read_mostly;
103EXPORT_SYMBOL_GPL(ipv6_stub);
034dfc5d
CW
104
105/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
106const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
107EXPORT_SYMBOL(in6addr_loopback);
108const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
109EXPORT_SYMBOL(in6addr_any);
110const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
111EXPORT_SYMBOL(in6addr_linklocal_allnodes);
112const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
113EXPORT_SYMBOL(in6addr_linklocal_allrouters);
114const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
115EXPORT_SYMBOL(in6addr_interfacelocal_allnodes);
116const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
117EXPORT_SYMBOL(in6addr_interfacelocal_allrouters);
118const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
119EXPORT_SYMBOL(in6addr_sitelocal_allrouters);