AntiRecursion.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * ZeroTier One - Network Virtualization Everywhere
  3. * Copyright (C) 2011-2015 ZeroTier, Inc.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * --
  19. *
  20. * ZeroTier may be used and distributed under the terms of the GPLv3, which
  21. * are available at: http://www.gnu.org/licenses/gpl-3.0.html
  22. *
  23. * If you would like to embed ZeroTier into a commercial application or
  24. * redistribute it in a modified binary form, please contact ZeroTier Networks
  25. * LLC. Start here: http://www.zerotier.com/
  26. */
  27. #ifndef ZT_ANTIRECURSION_HPP
  28. #define ZT_ANTIRECURSION_HPP
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include "Constants.hpp"
  32. namespace ZeroTier {
  33. #define ZT_ANTIRECURSION_TAIL_LEN 256
  34. /**
  35. * Filter to prevent recursion (ZeroTier-over-ZeroTier)
  36. *
  37. * This works by logging ZeroTier packets that we send. It's then invoked
  38. * again against packets read from local Ethernet taps. If the last N
  39. * bytes representing the ZeroTier packet match in the tap frame, then
  40. * the frame is a re-injection of a frame that we sent and is rejected.
  41. *
  42. * This means that ZeroTier packets simply will not traverse ZeroTier
  43. * networks, which would cause all sorts of weird problems.
  44. *
  45. * NOTE: this is applied to low-level packets before they are sent to
  46. * SocketManager and/or sockets, not to fully assembled packets before
  47. * (possible) fragmentation.
  48. */
  49. class AntiRecursion
  50. {
  51. public:
  52. AntiRecursion()
  53. throw()
  54. {
  55. memset(_history,0,sizeof(_history));
  56. _ptr = 0;
  57. }
  58. /**
  59. * Add an outgoing ZeroTier packet to the circular log
  60. *
  61. * @param data ZT packet data
  62. * @param len Length of packet
  63. */
  64. inline void logOutgoingZT(const void *data,unsigned int len)
  65. throw()
  66. {
  67. ArItem *i = &(_history[_ptr++ % ZT_ANTIRECURSION_HISTORY_SIZE]);
  68. const unsigned int tl = (len > ZT_ANTIRECURSION_TAIL_LEN) ? ZT_ANTIRECURSION_TAIL_LEN : len;
  69. memcpy(i->tail,((const unsigned char *)data) + (len - tl),tl);
  70. i->len = tl;
  71. }
  72. /**
  73. * Check an ethernet frame from a local tap against anti-recursion history
  74. *
  75. * @param data Raw frame data
  76. * @param len Length of frame
  77. * @return True if frame is OK to be passed, false if it's a ZT frame that we sent
  78. */
  79. inline bool checkEthernetFrame(const void *data,unsigned int len)
  80. throw()
  81. {
  82. for(unsigned int h=0;h<ZT_ANTIRECURSION_HISTORY_SIZE;++h) {
  83. ArItem *i = &(_history[h]);
  84. if ((i->len > 0)&&(len >= i->len)&&(!memcmp(((const unsigned char *)data) + (len - i->len),i->tail,i->len)))
  85. return false;
  86. }
  87. return true;
  88. }
  89. private:
  90. struct ArItem
  91. {
  92. unsigned char tail[ZT_ANTIRECURSION_TAIL_LEN];
  93. unsigned int len;
  94. };
  95. ArItem _history[ZT_ANTIRECURSION_HISTORY_SIZE];
  96. volatile unsigned int _ptr;
  97. };
  98. } // namespace ZeroTier
  99. #endif