LinuxNetLink.hpp 3.4 KB

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