Commit | Line | Data |
---|---|---|
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 YH |
7 | #include <net/ipv6.h> |
8 | ||
9 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) | |
10 | ||
11 | static inline unsigned ipv6_addr_scope2type(unsigned scope) | |
12 | { | |
13 | switch(scope) { | |
14 | case IPV6_ADDR_SCOPE_NODELOCAL: | |
15 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | | |
16 | IPV6_ADDR_LOOPBACK); | |
17 | case IPV6_ADDR_SCOPE_LINKLOCAL: | |
18 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | | |
19 | IPV6_ADDR_LINKLOCAL); | |
20 | case IPV6_ADDR_SCOPE_SITELOCAL: | |
21 | return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | | |
22 | IPV6_ADDR_SITELOCAL); | |
23 | } | |
24 | return IPV6_ADDR_SCOPE_TYPE(scope); | |
25 | } | |
26 | ||
27 | int __ipv6_addr_type(const struct in6_addr *addr) | |
28 | { | |
29 | __be32 st; | |
30 | ||
31 | st = addr->s6_addr32[0]; | |
32 | ||
33 | /* Consider all addresses with the first three bits different of | |
34 | 000 and 111 as unicasts. | |
35 | */ | |
36 | if ((st & htonl(0xE0000000)) != htonl(0x00000000) && | |
37 | (st & htonl(0xE0000000)) != htonl(0xE0000000)) | |
38 | return (IPV6_ADDR_UNICAST | | |
39 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); | |
40 | ||
41 | if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { | |
42 | /* multicast */ | |
43 | /* addr-select 3.1 */ | |
44 | return (IPV6_ADDR_MULTICAST | | |
45 | ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); | |
46 | } | |
47 | ||
48 | if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) | |
49 | return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | | |
50 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ | |
51 | if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) | |
52 | return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | | |
53 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ | |
c61a7d10 DJ |
54 | if ((st & htonl(0xFE000000)) == htonl(0xFC000000)) |
55 | return (IPV6_ADDR_UNICAST | | |
56 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* RFC 4193 */ | |
8c14b7ce YH |
57 | |
58 | if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { | |
59 | if (addr->s6_addr32[2] == 0) { | |
60 | if (addr->s6_addr32[3] == 0) | |
61 | return IPV6_ADDR_ANY; | |
62 | ||
63 | if (addr->s6_addr32[3] == htonl(0x00000001)) | |
64 | return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | | |
65 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ | |
66 | ||
67 | return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | | |
68 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | |
69 | } | |
70 | ||
71 | if (addr->s6_addr32[2] == htonl(0x0000ffff)) | |
72 | return (IPV6_ADDR_MAPPED | | |
73 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ | |
74 | } | |
75 | ||
45bb0060 | 76 | return (IPV6_ADDR_UNICAST | |
8c14b7ce YH |
77 | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ |
78 | } | |
7401055b | 79 | EXPORT_SYMBOL(__ipv6_addr_type); |
8c14b7ce | 80 |