addrconf_core.c revision 034dfc5df99eb8d263211524983b1a737b25c06b
18c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki/*
28c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki * IPv6 library code, needed by static components when full IPv6 support is
38c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki * not configured or static.
48c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki */
58c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
6bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h>
78c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki#include <net/ipv6.h>
86da334ee0c101fc5ecf62f2b1e11b1524be7b159Eric Dumazet#include <net/addrconf.h>
98c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
108c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
118c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
1295c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazetstatic inline unsigned int ipv6_addr_scope2type(unsigned int scope)
138c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki{
14d94d34a0664b296fd1593a96ccc9c97a94dfd43dEldad Zack	switch (scope) {
158c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	case IPV6_ADDR_SCOPE_NODELOCAL:
168c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
178c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			IPV6_ADDR_LOOPBACK);
188c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	case IPV6_ADDR_SCOPE_LINKLOCAL:
198c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
208c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			IPV6_ADDR_LINKLOCAL);
218c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	case IPV6_ADDR_SCOPE_SITELOCAL:
228c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
238c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			IPV6_ADDR_SITELOCAL);
248c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	}
258c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	return IPV6_ADDR_SCOPE_TYPE(scope);
268c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki}
278c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
288c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideakiint __ipv6_addr_type(const struct in6_addr *addr)
298c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki{
308c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	__be32 st;
318c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
328c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	st = addr->s6_addr32[0];
338c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
348c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	/* Consider all addresses with the first three bits different of
358c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	   000 and 111 as unicasts.
368c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	 */
378c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
388c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	    (st & htonl(0xE0000000)) != htonl(0xE0000000))
398c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		return (IPV6_ADDR_UNICAST |
408c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
418c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
428c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
438c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		/* multicast */
448c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		/* addr-select 3.1 */
458c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		return (IPV6_ADDR_MULTICAST |
468c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
478c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	}
488c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
498c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
508c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
518c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));		/* addr-select 3.1 */
528c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
538c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
548c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL));		/* addr-select 3.1 */
55c61a7d10efbd187ab9bb54871238ebd1dfcacd44Dave Johnson	if ((st & htonl(0xFE000000)) == htonl(0xFC000000))
56c61a7d10efbd187ab9bb54871238ebd1dfcacd44Dave Johnson		return (IPV6_ADDR_UNICAST |
57c61a7d10efbd187ab9bb54871238ebd1dfcacd44Dave Johnson			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));			/* RFC 4193 */
588c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
598c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
608c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		if (addr->s6_addr32[2] == 0) {
618c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			if (addr->s6_addr32[3] == 0)
628c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki				return IPV6_ADDR_ANY;
638c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
648c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			if (addr->s6_addr32[3] == htonl(0x00000001))
658c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki				return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
668c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki					IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));	/* addr-select 3.4 */
678c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
688c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
698c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki				IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.3 */
708c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		}
718c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
728c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		if (addr->s6_addr32[2] == htonl(0x0000ffff))
738c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki			return (IPV6_ADDR_MAPPED |
748c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki				IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.3 */
758c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki	}
768c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
7745bb00609022ecf1d97e083666c68c74d237b799Ulrich Weber	return (IPV6_ADDR_UNICAST |
788c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki		IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.4 */
798c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki}
807401055b58e557362dfcaa65a581db1d1e972439David S. MillerEXPORT_SYMBOL(__ipv6_addr_type);
818c14b7ce22a7ddd9fe1b1c852c4015633ec3efecYOSHIFUJI Hideaki
82f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wangstatic ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
83f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang
84f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wangint register_inet6addr_notifier(struct notifier_block *nb)
85f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang{
86f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang	return atomic_notifier_chain_register(&inet6addr_chain, nb);
87f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang}
88f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong WangEXPORT_SYMBOL(register_inet6addr_notifier);
89f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang
90f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wangint unregister_inet6addr_notifier(struct notifier_block *nb)
91f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang{
92f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang	return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
93f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang}
94f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong WangEXPORT_SYMBOL(unregister_inet6addr_notifier);
95f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang
96f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wangint inet6addr_notifier_call_chain(unsigned long val, void *v)
97f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang{
98f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang	return atomic_notifier_call_chain(&inet6addr_chain, val, v);
99f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong Wang}
100f88c91ddba958e9a5dd4a5ee8c52a0faa790f586Cong WangEXPORT_SYMBOL(inet6addr_notifier_call_chain);
1015f81bd2e5d804ca93f3ec8873451b22d2f454721Cong Wang
1025f81bd2e5d804ca93f3ec8873451b22d2f454721Cong Wangconst struct ipv6_stub *ipv6_stub __read_mostly;
1035f81bd2e5d804ca93f3ec8873451b22d2f454721Cong WangEXPORT_SYMBOL_GPL(ipv6_stub);
104034dfc5df99eb8d263211524983b1a737b25c06bCong Wang
105034dfc5df99eb8d263211524983b1a737b25c06bCong Wang/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
106034dfc5df99eb8d263211524983b1a737b25c06bCong Wangconst struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
107034dfc5df99eb8d263211524983b1a737b25c06bCong WangEXPORT_SYMBOL(in6addr_loopback);
108034dfc5df99eb8d263211524983b1a737b25c06bCong Wangconst struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
109034dfc5df99eb8d263211524983b1a737b25c06bCong WangEXPORT_SYMBOL(in6addr_any);
110034dfc5df99eb8d263211524983b1a737b25c06bCong Wangconst struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
111034dfc5df99eb8d263211524983b1a737b25c06bCong WangEXPORT_SYMBOL(in6addr_linklocal_allnodes);
112034dfc5df99eb8d263211524983b1a737b25c06bCong Wangconst struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
113034dfc5df99eb8d263211524983b1a737b25c06bCong WangEXPORT_SYMBOL(in6addr_linklocal_allrouters);
114034dfc5df99eb8d263211524983b1a737b25c06bCong Wangconst struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
115034dfc5df99eb8d263211524983b1a737b25c06bCong WangEXPORT_SYMBOL(in6addr_interfacelocal_allnodes);
116034dfc5df99eb8d263211524983b1a737b25c06bCong Wangconst struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
117034dfc5df99eb8d263211524983b1a737b25c06bCong WangEXPORT_SYMBOL(in6addr_interfacelocal_allrouters);
118034dfc5df99eb8d263211524983b1a737b25c06bCong Wangconst struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
119034dfc5df99eb8d263211524983b1a737b25c06bCong WangEXPORT_SYMBOL(in6addr_sitelocal_allrouters);
120