Filter.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * ZeroTier One - Global Peer to Peer Ethernet
  3. * Copyright (C) 2012-2013 ZeroTier Networks LLC
  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_FILTER_HPP
  28. #define _ZT_FILTER_HPP
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <string>
  32. #include <vector>
  33. #include <utility>
  34. #include "Mutex.hpp"
  35. #include "Range.hpp"
  36. /* Ethernet frame types that might be relevant to us */
  37. #define ZT_ETHERTYPE_IPV4 0x0800
  38. #define ZT_ETHERTYPE_ARP 0x0806
  39. #define ZT_ETHERTYPE_RARP 0x8035
  40. #define ZT_ETHERTYPE_ATALK 0x809b
  41. #define ZT_ETHERTYPE_AARP 0x80f3
  42. #define ZT_ETHERTYPE_IPX_A 0x8137
  43. #define ZT_ETHERTYPE_IPX_B 0x8138
  44. #define ZT_ETHERTYPE_IPV6 0x86dd
  45. /* IP protocols we might care about */
  46. #define ZT_IPPROTO_ICMP 0x01
  47. #define ZT_IPPROTO_IGMP 0x02
  48. #define ZT_IPPROTO_TCP 0x06
  49. #define ZT_IPPROTO_UDP 0x11
  50. #define ZT_IPPROTO_RDP 0x1b
  51. #define ZT_IPPROTO_GRE 0x2f
  52. #define ZT_IPPROTO_ESP 0x32
  53. #define ZT_IPPROTO_AH 0x33
  54. #define ZT_IPPROTO_ICMPV6 0x3a
  55. #define ZT_IPPROTO_OSPF 0x59
  56. #define ZT_IPPROTO_IPIP 0x5e
  57. #define ZT_IPPROTO_IPCOMP 0x6c
  58. #define ZT_IPPROTO_L2TP 0x73
  59. #define ZT_IPPROTO_SCTP 0x84
  60. #define ZT_IPPROTO_FC 0x85
  61. #define ZT_IPPROTO_UDPLITE 0x88
  62. #define ZT_IPPROTO_HIP 0x8b
  63. namespace ZeroTier {
  64. class RuntimeEnvironment;
  65. /**
  66. * A simple Ethernet frame level filter supporting basic IP port DENY
  67. */
  68. class Filter
  69. {
  70. public:
  71. /**
  72. * A filter rule
  73. *
  74. * This behaves as an immutable value object.
  75. */
  76. class Rule
  77. {
  78. public:
  79. Rule()
  80. throw() :
  81. _etherType(-1),
  82. _protocol(-1),
  83. _port(-1)
  84. {
  85. }
  86. /**
  87. * Construct a new rule
  88. *
  89. * @param etype Ethernet type or negative for ANY
  90. * @param prot Protocol or negative for ANY (meaning depends on ethertype, e.g. IP protocol numbers)
  91. * @param prt Port or negative for ANY (only applies to some protocols)
  92. */
  93. Rule(int etype,int prot,int prt)
  94. throw() :
  95. _etherType((etype >= 0) ? etype : -1),
  96. _protocol((prot >= 0) ? prot : -1),
  97. _port((prt >= 0) ? prt : -1)
  98. {
  99. }
  100. inline int etherType() const throw() { return _etherType; }
  101. inline int protocol() const throw() { return _protocol; }
  102. inline int port() const throw() { return _port; }
  103. /**
  104. * Test this rule against a frame
  105. *
  106. * @param etype Type of ethernet frame
  107. * @param data Ethernet frame data
  108. * @param len Length of ethernet frame
  109. * @return True if rule matches
  110. */
  111. bool operator()(unsigned int etype,const void *data,unsigned int len) const;
  112. inline bool operator==(const Rule &r) const throw() { return ((_etherType == r._etherType)&&(_protocol == r._protocol)&&(_port == r._port)); }
  113. inline bool operator!=(const Rule &r) const throw() { return !(*this == r); }
  114. inline bool operator<(const Rule &r) const
  115. throw()
  116. {
  117. if (_etherType < r._etherType)
  118. return true;
  119. else if (_etherType == r._etherType) {
  120. if (_protocol < r._protocol)
  121. return true;
  122. else if (_protocol == r._protocol) {
  123. if (_port < r._port)
  124. return true;
  125. }
  126. }
  127. return false;
  128. }
  129. inline bool operator>(const Rule &r) const throw() { return (r < *this); }
  130. inline bool operator<=(const Rule &r) const throw() { return !(r < *this); }
  131. inline bool operator>=(const Rule &r) const throw() { return !(*this < r); }
  132. private:
  133. int _etherType;
  134. int _protocol;
  135. int _port;
  136. };
  137. /**
  138. * Action if a rule matches
  139. */
  140. enum Action
  141. {
  142. ACTION_DENY = 0,
  143. ACTION_ALLOW = 1,
  144. ACTION_LOG = 2
  145. };
  146. /**
  147. * Entry in filter chain
  148. */
  149. struct Entry
  150. {
  151. Entry() {}
  152. Entry(const Rule &r,const Action &a) :
  153. rule(r),
  154. action(a)
  155. {
  156. }
  157. Rule rule;
  158. Action action;
  159. };
  160. Filter(const RuntimeEnvironment *renv);
  161. ~Filter();
  162. /**
  163. * Remove all filter entries
  164. */
  165. inline void clear()
  166. {
  167. Mutex::Lock _l(_chain_m);
  168. _chain.clear();
  169. }
  170. /**
  171. * Append a rule/action pair to this chain
  172. *
  173. * If an identical rule already exists it is removed and a new entry is
  174. * added to the end with the new action. (Two identical rules with the
  175. * same action wouldn't make sense.)
  176. *
  177. * @param r Rule to add
  178. * @param a Action if rule matches
  179. */
  180. void add(const Rule &r,const Action &a);
  181. /**
  182. * @return Number of rules in filter chain
  183. */
  184. inline unsigned int length() const
  185. throw()
  186. {
  187. Mutex::Lock _l(_chain_m);
  188. return _chain.length();
  189. }
  190. /**
  191. * @return Entry in filter chain or null entry if out of bounds
  192. */
  193. inline Entry operator[](const unsigned int i) const
  194. throw()
  195. {
  196. Mutex::Lock _l(_chain_m);
  197. if (i < _chain.length())
  198. return _chain[i];
  199. return Entry();
  200. }
  201. /**
  202. * @param etherType Ethernet type ID
  203. * @return Name of Ethernet protocol (e.g. ARP, IPV4)
  204. */
  205. static const char *etherTypeName(const unsigned int etherType)
  206. throw();
  207. private:
  208. const RuntimeEnvironment *_r;
  209. std::vector<Entry> _chain;
  210. Mutex _chain_m;
  211. };
  212. } // namespace ZeroTier
  213. #endif