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