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 if ((st & htonl(0xFE000000)) == htonl(0xFC000000)) 54 return (IPV6_ADDR_UNICAST | 55 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* RFC 4193 */ 56 57 if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { 58 if (addr->s6_addr32[2] == 0) { 59 if (addr->s6_addr32[3] == 0) 60 return IPV6_ADDR_ANY; 61 62 if (addr->s6_addr32[3] == htonl(0x00000001)) 63 return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | 64 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ 65 66 return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | 67 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ 68 } 69 70 if (addr->s6_addr32[2] == htonl(0x0000ffff)) 71 return (IPV6_ADDR_MAPPED | 72 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ 73 } 74 75 return (IPV6_ADDR_UNICAST | 76 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ 77 } 78 EXPORT_SYMBOL(__ipv6_addr_type); 79 80