LinuxNetLink.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (c)2019 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2026-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #ifndef ZT_LINUX_NETLINK_HPP
  14. #define ZT_LINUX_NETLINK_HPP
  15. #include "../node/Constants.hpp"
  16. #ifdef __LINUX__
  17. #include <asm/types.h>
  18. #include <linux/rtnetlink.h>
  19. #include <map>
  20. #include <set>
  21. #include <sys/socket.h>
  22. #include <vector>
  23. // #include <linux/if.h>
  24. #include "../node/Hashtable.hpp"
  25. #include "../node/InetAddress.hpp"
  26. #include "../node/MAC.hpp"
  27. #include "../node/Mutex.hpp"
  28. #include "Thread.hpp"
  29. namespace ZeroTier {
  30. /**
  31. * Interface with Linux's RTNETLINK
  32. */
  33. class LinuxNetLink {
  34. private:
  35. LinuxNetLink();
  36. ~LinuxNetLink();
  37. public:
  38. struct Route {
  39. InetAddress target;
  40. InetAddress via;
  41. InetAddress src;
  42. int ifidx;
  43. inline bool operator==(const Route& r) const
  44. {
  45. return ((target == r.target) && (via == r.via) && (src == r.src) && (ifidx == r.ifidx));
  46. }
  47. inline bool operator!=(const Route& r) const
  48. {
  49. return (! (*this == r));
  50. }
  51. inline bool operator<(const Route& r) const
  52. {
  53. if (target < r.target) {
  54. return true;
  55. }
  56. else if (target == r.target) {
  57. if (via < r.via) {
  58. return true;
  59. }
  60. else if (via == r.via) {
  61. if (src < r.src) {
  62. return true;
  63. }
  64. else if (src == r.src) {
  65. return (ifidx < r.ifidx);
  66. }
  67. }
  68. }
  69. return false;
  70. }
  71. inline bool operator>(const Route& r) const
  72. {
  73. return (r < *this);
  74. }
  75. inline bool operator<=(const Route& r) const
  76. {
  77. return ! (r < *this);
  78. }
  79. inline bool operator>=(const Route& r) const
  80. {
  81. return ! (*this < r);
  82. }
  83. };
  84. static LinuxNetLink& getInstance()
  85. {
  86. static LinuxNetLink instance;
  87. return instance;
  88. }
  89. LinuxNetLink(LinuxNetLink const&) = delete;
  90. void operator=(LinuxNetLink const&) = delete;
  91. void addRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName);
  92. void delRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName);
  93. void addAddress(const InetAddress& addr, const char* iface);
  94. void removeAddress(const InetAddress& addr, const char* iface);
  95. bool routeIsSet(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifname);
  96. void threadMain() throw();
  97. private:
  98. int _doRecv(int fd);
  99. void _processMessage(struct nlmsghdr* nlp, int nll);
  100. void _routeAdded(struct nlmsghdr* nlp);
  101. void _routeDeleted(struct nlmsghdr* nlp);
  102. void _linkAdded(struct nlmsghdr* nlp);
  103. void _linkDeleted(struct nlmsghdr* nlp);
  104. void _ipAddressAdded(struct nlmsghdr* nlp);
  105. void _ipAddressDeleted(struct nlmsghdr* nlp);
  106. void _requestInterfaceList();
  107. void _requestIPv4Routes();
  108. void _requestIPv6Routes();
  109. int _indexForInterface(const char* iface);
  110. void _setSocketTimeout(int fd, int seconds = 1);
  111. Thread _t;
  112. bool _running;
  113. uint32_t _seq;
  114. std::map<InetAddress, std::set<LinuxNetLink::Route> > _routes;
  115. Mutex _routes_m;
  116. struct iface_entry {
  117. iface_entry()
  118. {
  119. memset(this, 0, sizeof(iface_entry));
  120. }
  121. int index;
  122. char ifacename[16]; // IFNAMSIZ on Linux == 16
  123. char mac[18];
  124. char mac_bin[6];
  125. unsigned int mtu;
  126. };
  127. Hashtable<int, iface_entry> _interfaces;
  128. Mutex _if_m;
  129. // socket communication vars;
  130. int _fd;
  131. struct sockaddr_nl _la;
  132. };
  133. } // namespace ZeroTier
  134. #endif
  135. #endif // ZT_LINUX_NETLINK_HPPS