PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/net/ipv6/addrconf_core.c

http://github.com/torvalds/linux
C | 257 lines | 202 code | 39 blank | 16 comment | 23 complexity | 37e20ef6e9dafe903a31bdf6a756bdd1 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * IPv6 library code, needed by static components when full IPv6 support is
  4. * not configured or static.
  5. */
  6. #include <linux/export.h>
  7. #include <net/ipv6.h>
  8. #include <net/ipv6_stubs.h>
  9. #include <net/addrconf.h>
  10. #include <net/ip.h>
  11. /* if ipv6 module registers this function is used by xfrm to force all
  12. * sockets to relookup their nodes - this is fairly expensive, be
  13. * careful
  14. */
  15. void (*__fib6_flush_trees)(struct net *);
  16. EXPORT_SYMBOL(__fib6_flush_trees);
  17. #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16)
  18. static inline unsigned int ipv6_addr_scope2type(unsigned int scope)
  19. {
  20. switch (scope) {
  21. case IPV6_ADDR_SCOPE_NODELOCAL:
  22. return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
  23. IPV6_ADDR_LOOPBACK);
  24. case IPV6_ADDR_SCOPE_LINKLOCAL:
  25. return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
  26. IPV6_ADDR_LINKLOCAL);
  27. case IPV6_ADDR_SCOPE_SITELOCAL:
  28. return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
  29. IPV6_ADDR_SITELOCAL);
  30. }
  31. return IPV6_ADDR_SCOPE_TYPE(scope);
  32. }
  33. int __ipv6_addr_type(const struct in6_addr *addr)
  34. {
  35. __be32 st;
  36. st = addr->s6_addr32[0];
  37. /* Consider all addresses with the first three bits different of
  38. 000 and 111 as unicasts.
  39. */
  40. if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
  41. (st & htonl(0xE0000000)) != htonl(0xE0000000))
  42. return (IPV6_ADDR_UNICAST |
  43. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
  44. if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
  45. /* multicast */
  46. /* addr-select 3.1 */
  47. return (IPV6_ADDR_MULTICAST |
  48. ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
  49. }
  50. if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
  51. return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
  52. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */
  53. if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
  54. return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
  55. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */
  56. if ((st & htonl(0xFE000000)) == htonl(0xFC000000))
  57. return (IPV6_ADDR_UNICAST |
  58. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* RFC 4193 */
  59. if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
  60. if (addr->s6_addr32[2] == 0) {
  61. if (addr->s6_addr32[3] == 0)
  62. return IPV6_ADDR_ANY;
  63. if (addr->s6_addr32[3] == htonl(0x00000001))
  64. return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
  65. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */
  66. return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
  67. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
  68. }
  69. if (addr->s6_addr32[2] == htonl(0x0000ffff))
  70. return (IPV6_ADDR_MAPPED |
  71. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
  72. }
  73. return (IPV6_ADDR_UNICAST |
  74. IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */
  75. }
  76. EXPORT_SYMBOL(__ipv6_addr_type);
  77. static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
  78. static BLOCKING_NOTIFIER_HEAD(inet6addr_validator_chain);
  79. int register_inet6addr_notifier(struct notifier_block *nb)
  80. {
  81. return atomic_notifier_chain_register(&inet6addr_chain, nb);
  82. }
  83. EXPORT_SYMBOL(register_inet6addr_notifier);
  84. int unregister_inet6addr_notifier(struct notifier_block *nb)
  85. {
  86. return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
  87. }
  88. EXPORT_SYMBOL(unregister_inet6addr_notifier);
  89. int inet6addr_notifier_call_chain(unsigned long val, void *v)
  90. {
  91. return atomic_notifier_call_chain(&inet6addr_chain, val, v);
  92. }
  93. EXPORT_SYMBOL(inet6addr_notifier_call_chain);
  94. int register_inet6addr_validator_notifier(struct notifier_block *nb)
  95. {
  96. return blocking_notifier_chain_register(&inet6addr_validator_chain, nb);
  97. }
  98. EXPORT_SYMBOL(register_inet6addr_validator_notifier);
  99. int unregister_inet6addr_validator_notifier(struct notifier_block *nb)
  100. {
  101. return blocking_notifier_chain_unregister(&inet6addr_validator_chain,
  102. nb);
  103. }
  104. EXPORT_SYMBOL(unregister_inet6addr_validator_notifier);
  105. int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
  106. {
  107. return blocking_notifier_call_chain(&inet6addr_validator_chain, val, v);
  108. }
  109. EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
  110. static struct dst_entry *eafnosupport_ipv6_dst_lookup_flow(struct net *net,
  111. const struct sock *sk,
  112. struct flowi6 *fl6,
  113. const struct in6_addr *final_dst)
  114. {
  115. return ERR_PTR(-EAFNOSUPPORT);
  116. }
  117. static int eafnosupport_ipv6_route_input(struct sk_buff *skb)
  118. {
  119. return -EAFNOSUPPORT;
  120. }
  121. static struct fib6_table *eafnosupport_fib6_get_table(struct net *net, u32 id)
  122. {
  123. return NULL;
  124. }
  125. static int
  126. eafnosupport_fib6_table_lookup(struct net *net, struct fib6_table *table,
  127. int oif, struct flowi6 *fl6,
  128. struct fib6_result *res, int flags)
  129. {
  130. return -EAFNOSUPPORT;
  131. }
  132. static int
  133. eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
  134. struct fib6_result *res, int flags)
  135. {
  136. return -EAFNOSUPPORT;
  137. }
  138. static void
  139. eafnosupport_fib6_select_path(const struct net *net, struct fib6_result *res,
  140. struct flowi6 *fl6, int oif, bool have_oif_match,
  141. const struct sk_buff *skb, int strict)
  142. {
  143. }
  144. static u32
  145. eafnosupport_ip6_mtu_from_fib6(const struct fib6_result *res,
  146. const struct in6_addr *daddr,
  147. const struct in6_addr *saddr)
  148. {
  149. return 0;
  150. }
  151. static int eafnosupport_fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
  152. struct fib6_config *cfg, gfp_t gfp_flags,
  153. struct netlink_ext_ack *extack)
  154. {
  155. NL_SET_ERR_MSG(extack, "IPv6 support not enabled in kernel");
  156. return -EAFNOSUPPORT;
  157. }
  158. static int eafnosupport_ip6_del_rt(struct net *net, struct fib6_info *rt)
  159. {
  160. return -EAFNOSUPPORT;
  161. }
  162. const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
  163. .ipv6_dst_lookup_flow = eafnosupport_ipv6_dst_lookup_flow,
  164. .ipv6_route_input = eafnosupport_ipv6_route_input,
  165. .fib6_get_table = eafnosupport_fib6_get_table,
  166. .fib6_table_lookup = eafnosupport_fib6_table_lookup,
  167. .fib6_lookup = eafnosupport_fib6_lookup,
  168. .fib6_select_path = eafnosupport_fib6_select_path,
  169. .ip6_mtu_from_fib6 = eafnosupport_ip6_mtu_from_fib6,
  170. .fib6_nh_init = eafnosupport_fib6_nh_init,
  171. .ip6_del_rt = eafnosupport_ip6_del_rt,
  172. };
  173. EXPORT_SYMBOL_GPL(ipv6_stub);
  174. /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
  175. const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
  176. EXPORT_SYMBOL(in6addr_loopback);
  177. const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
  178. EXPORT_SYMBOL(in6addr_any);
  179. const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
  180. EXPORT_SYMBOL(in6addr_linklocal_allnodes);
  181. const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
  182. EXPORT_SYMBOL(in6addr_linklocal_allrouters);
  183. const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
  184. EXPORT_SYMBOL(in6addr_interfacelocal_allnodes);
  185. const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
  186. EXPORT_SYMBOL(in6addr_interfacelocal_allrouters);
  187. const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
  188. EXPORT_SYMBOL(in6addr_sitelocal_allrouters);
  189. static void snmp6_free_dev(struct inet6_dev *idev)
  190. {
  191. kfree(idev->stats.icmpv6msgdev);
  192. kfree(idev->stats.icmpv6dev);
  193. free_percpu(idev->stats.ipv6);
  194. }
  195. static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
  196. {
  197. struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
  198. snmp6_free_dev(idev);
  199. kfree(idev);
  200. }
  201. /* Nobody refers to this device, we may destroy it. */
  202. void in6_dev_finish_destroy(struct inet6_dev *idev)
  203. {
  204. struct net_device *dev = idev->dev;
  205. WARN_ON(!list_empty(&idev->addr_list));
  206. WARN_ON(idev->mc_list);
  207. WARN_ON(timer_pending(&idev->rs_timer));
  208. #ifdef NET_REFCNT_DEBUG
  209. pr_debug("%s: %s\n", __func__, dev ? dev->name : "NIL");
  210. #endif
  211. dev_put(dev);
  212. if (!idev->dead) {
  213. pr_warn("Freeing alive inet6 device %p\n", idev);
  214. return;
  215. }
  216. call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
  217. }
  218. EXPORT_SYMBOL(in6_dev_finish_destroy);