diff options
| author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2007-02-22 02:25:42 +0900 | 
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2007-02-26 11:42:52 -0800 | 
| commit | 8c14b7ce22a7ddd9fe1b1c852c4015633ec3efec (patch) | |
| tree | acdf622ee0691c93242f37863c91169657637fa2 /net/ipv6/addrconf_core.c | |
| parent | f4b9479dc5a1b0e1ca8666053f0d932baddc619d (diff) | |
| download | olio-linux-3.10-8c14b7ce22a7ddd9fe1b1c852c4015633ec3efec.tar.xz olio-linux-3.10-8c14b7ce22a7ddd9fe1b1c852c4015633ec3efec.zip  | |
[IPV6] ADDRCONF: Statically link __ipv6_addr_type() for sunrpc subsystem.
Link __ipv6_addr_type() statically for sunrpc code even if IPv6 is
built as module.
Signed-off-by: YOSHIFUJI Hidaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net/ipv6/addrconf_core.c')
| -rw-r--r-- | net/ipv6/addrconf_core.c | 75 | 
1 files changed, 75 insertions, 0 deletions
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c new file mode 100644 index 00000000000..644e0c742f9 --- /dev/null +++ b/net/ipv6/addrconf_core.c @@ -0,0 +1,75 @@ +/* + * 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 */ + +	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 */ +	} + +	return (IPV6_ADDR_RESERVED | +		IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.4 */ +} +  |