2007-02-21 20:25:42 +03:00
/*
* IPv6 library code , needed by static components when full IPv6 support is
* not configured or static .
*/
# include <net/ipv6.h>
# define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16)
static inline unsigned ipv6_addr_scope2type ( unsigned scope )
{
switch ( scope ) {
case IPV6_ADDR_SCOPE_NODELOCAL :
return ( IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_NODELOCAL ) |
IPV6_ADDR_LOOPBACK ) ;
case IPV6_ADDR_SCOPE_LINKLOCAL :
return ( IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_LINKLOCAL ) |
IPV6_ADDR_LINKLOCAL ) ;
case IPV6_ADDR_SCOPE_SITELOCAL :
return ( IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_SITELOCAL ) |
IPV6_ADDR_SITELOCAL ) ;
}
return IPV6_ADDR_SCOPE_TYPE ( scope ) ;
}
int __ipv6_addr_type ( const struct in6_addr * addr )
{
__be32 st ;
st = addr - > s6_addr32 [ 0 ] ;
/* Consider all addresses with the first three bits different of
000 and 111 as unicasts .
*/
if ( ( st & htonl ( 0xE0000000 ) ) ! = htonl ( 0x00000000 ) & &
( st & htonl ( 0xE0000000 ) ) ! = htonl ( 0xE0000000 ) )
return ( IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_GLOBAL ) ) ;
if ( ( st & htonl ( 0xFF000000 ) ) = = htonl ( 0xFF000000 ) ) {
/* multicast */
/* addr-select 3.1 */
return ( IPV6_ADDR_MULTICAST |
ipv6_addr_scope2type ( IPV6_ADDR_MC_SCOPE ( addr ) ) ) ;
}
if ( ( st & htonl ( 0xFFC00000 ) ) = = htonl ( 0xFE800000 ) )
return ( IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_LINKLOCAL ) ) ; /* addr-select 3.1 */
if ( ( st & htonl ( 0xFFC00000 ) ) = = htonl ( 0xFEC00000 ) )
return ( IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_SITELOCAL ) ) ; /* addr-select 3.1 */
2007-07-31 04:19:31 +04:00
if ( ( st & htonl ( 0xFE000000 ) ) = = htonl ( 0xFC000000 ) )
return ( IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_GLOBAL ) ) ; /* RFC 4193 */
2007-02-21 20:25:42 +03:00
if ( ( addr - > s6_addr32 [ 0 ] | addr - > s6_addr32 [ 1 ] ) = = 0 ) {
if ( addr - > s6_addr32 [ 2 ] = = 0 ) {
if ( addr - > s6_addr32 [ 3 ] = = 0 )
return IPV6_ADDR_ANY ;
if ( addr - > s6_addr32 [ 3 ] = = htonl ( 0x00000001 ) )
return ( IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_LINKLOCAL ) ) ; /* addr-select 3.4 */
return ( IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_GLOBAL ) ) ; /* addr-select 3.3 */
}
if ( addr - > s6_addr32 [ 2 ] = = htonl ( 0x0000ffff ) )
return ( IPV6_ADDR_MAPPED |
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_GLOBAL ) ) ; /* addr-select 3.3 */
}
2010-02-26 02:28:58 +03:00
return ( IPV6_ADDR_UNICAST |
2007-02-21 20:25:42 +03:00
IPV6_ADDR_SCOPE_TYPE ( IPV6_ADDR_SCOPE_GLOBAL ) ) ; /* addr-select 3.4 */
}
2007-02-22 10:26:56 +03:00
EXPORT_SYMBOL ( __ipv6_addr_type ) ;
2007-02-21 20:25:42 +03:00