Filter.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <stdint.h>
  31. #include <algorithm>
  32. #include "RuntimeEnvironment.hpp"
  33. #include "Logger.hpp"
  34. #include "Filter.hpp"
  35. #include "Utils.hpp"
  36. namespace ZeroTier {
  37. const char *const Filter::UNKNOWN_NAME = "(unknown)";
  38. const Range<unsigned int> Filter::ANY;
  39. static inline Range<unsigned int> __parseRange(char *r)
  40. throw(std::invalid_argument)
  41. {
  42. char *saveptr = (char *)0;
  43. unsigned int a = 0;
  44. unsigned int b = 0;
  45. unsigned int fn = 0;
  46. for(char *f=Utils::stok(r,"-",&saveptr);(f);f=Utils::stok((char *)0,"-",&saveptr)) {
  47. if (*f) {
  48. switch(fn++) {
  49. case 0:
  50. if (*f != '*')
  51. a = b = (unsigned int)strtoul(f,(char **)0,10);
  52. break;
  53. case 1:
  54. if (*f != '*')
  55. b = (unsigned int)strtoul(f,(char **)0,10);
  56. break;
  57. default:
  58. throw std::invalid_argument("rule range must be <int>, <int>-<int>, or *");
  59. }
  60. }
  61. }
  62. return Range<unsigned int>(a,b);
  63. }
  64. Filter::Rule::Rule(const char *s)
  65. throw(std::invalid_argument)
  66. {
  67. char *saveptr = (char *)0;
  68. char tmp[256];
  69. if (!Utils::scopy(tmp,sizeof(tmp),s))
  70. throw std::invalid_argument("rule string too long");
  71. unsigned int fn = 0;
  72. for(char *f=Utils::stok(tmp,";",&saveptr);(f);f=Utils::stok((char *)0,";",&saveptr)) {
  73. if (*f) {
  74. switch(fn++) {
  75. case 0:
  76. _etherType = __parseRange(f);
  77. break;
  78. case 1:
  79. _protocol = __parseRange(f);
  80. break;
  81. case 2:
  82. _port = __parseRange(f);
  83. break;
  84. default:
  85. throw std::invalid_argument("rule string has unknown extra fields");
  86. }
  87. }
  88. }
  89. if (fn != 3)
  90. throw std::invalid_argument("rule string must contain 3 fields");
  91. }
  92. bool Filter::Rule::operator()(unsigned int etype,const void *data,unsigned int len) const
  93. throw(std::invalid_argument)
  94. {
  95. if ((!_etherType)||(_etherType(etype))) { // ethertype is ANY, or matches
  96. // Ethertype determines meaning of protocol and port
  97. switch(etype) {
  98. case ZT_ETHERTYPE_IPV4:
  99. if (len > 20) {
  100. if ((!_protocol)||(_protocol(((const uint8_t *)data)[9]))) { // protocol is ANY or match
  101. if (!_port) // port is ANY
  102. return true;
  103. // Don't match on fragments beyond fragment 0. If we've blocked
  104. // fragment 0, further fragments will fall on deaf ears anyway.
  105. if ((Utils::ntoh(((const uint16_t *)data)[3]) & 0x1fff))
  106. return false;
  107. // Internet header length determines where data begins, in multiples of 32 bits
  108. unsigned int ihl = 4 * (((const uint8_t *)data)[0] & 0x0f);
  109. switch(((const uint8_t *)data)[9]) { // port's meaning depends on IP protocol
  110. case ZT_IPPROTO_ICMP:
  111. // For ICMP, port is ICMP type
  112. return _port(((const uint8_t *)data)[ihl]);
  113. case ZT_IPPROTO_TCP:
  114. case ZT_IPPROTO_UDP:
  115. case ZT_IPPROTO_SCTP:
  116. case ZT_IPPROTO_UDPLITE:
  117. // For these, port is destination port. Protocol designers were
  118. // nice enough to put the field in the same place.
  119. return _port(((const uint16_t *)data)[(ihl / 2) + 1]);
  120. default:
  121. // port has no meaning for other IP types, so ignore it
  122. return true;
  123. }
  124. return false; // no match on port
  125. }
  126. } else throw std::invalid_argument("undersized IPv4 packet");
  127. break;
  128. case ZT_ETHERTYPE_IPV6:
  129. if (len > 40) {
  130. int nextHeader = ((const uint8_t *)data)[6];
  131. unsigned int pos = 40;
  132. while ((pos < len)&&(nextHeader >= 0)&&(nextHeader != 59)) { // 59 == no next header
  133. fprintf(stderr,"[rule] V6: start header parse, header %.2x pos %d\n",nextHeader,pos);
  134. switch(nextHeader) {
  135. case 0: // hop-by-hop options
  136. case 60: // destination options
  137. case 43: // routing
  138. case 135: // mobility (mobile IPv6 options)
  139. if (_protocol((unsigned int)nextHeader))
  140. return true; // match if our goal was to match any of these
  141. nextHeader = ((const uint8_t *)data)[pos];
  142. pos += 8 + (8 * ((const uint8_t *)data)[pos + 1]);
  143. break;
  144. case 44: // fragment
  145. if (_protocol(44))
  146. return true; // match if our goal was to match fragments
  147. nextHeader = ((const uint8_t *)data)[pos];
  148. pos += 8;
  149. break;
  150. case ZT_IPPROTO_AH: // AH
  151. return _protocol(ZT_IPPROTO_AH); // true if AH is matched protocol, otherwise false since packet will be IPsec
  152. case ZT_IPPROTO_ESP: // ESP
  153. return _protocol(ZT_IPPROTO_ESP); // true if ESP is matched protocol, otherwise false since packet will be IPsec
  154. case ZT_IPPROTO_ICMPV6:
  155. // Only match ICMPv6 if we've selected it specifically
  156. if (_protocol(ZT_IPPROTO_ICMPV6)) {
  157. // Port is interpreted as ICMPv6 type
  158. if ((!_port)||(_port(((const uint8_t *)data)[pos])))
  159. return true;
  160. }
  161. break;
  162. case ZT_IPPROTO_TCP:
  163. case ZT_IPPROTO_UDP:
  164. case ZT_IPPROTO_SCTP:
  165. case ZT_IPPROTO_UDPLITE:
  166. // If we encounter any of these, match if protocol matches or is wildcard as
  167. // we'll consider these the "real payload" if present.
  168. if ((!_protocol)||(_protocol(nextHeader))) {
  169. if ((!_port)||(_port(((const uint16_t *)data)[(pos / 2) + 1])))
  170. return true; // protocol matches or is ANY, port is ANY or matches
  171. }
  172. break;
  173. default: {
  174. char foo[128];
  175. Utils::snprintf(foo,sizeof(foo),"unrecognized IPv6 header type %d",(int)nextHeader);
  176. throw std::invalid_argument(foo);
  177. }
  178. }
  179. fprintf(stderr,"[rule] V6: end header parse, next header %.2x, new pos %d\n",nextHeader,pos);
  180. }
  181. } else throw std::invalid_argument("undersized IPv6 packet");
  182. break;
  183. default:
  184. // For other ethertypes, protocol and port are ignored. What would they mean?
  185. return true;
  186. }
  187. }
  188. return false;
  189. }
  190. std::string Filter::Rule::toString() const
  191. {
  192. char buf[128];
  193. std::string s;
  194. switch(_etherType.magnitude()) {
  195. case 0:
  196. s.push_back('*');
  197. break;
  198. case 1:
  199. Utils::snprintf(buf,sizeof(buf),"%u",_etherType.start);
  200. s.append(buf);
  201. break;
  202. default:
  203. Utils::snprintf(buf,sizeof(buf),"%u-%u",_etherType.start,_etherType.end);
  204. s.append(buf);
  205. break;
  206. }
  207. s.push_back(';');
  208. switch(_protocol.magnitude()) {
  209. case 0:
  210. s.push_back('*');
  211. break;
  212. case 1:
  213. Utils::snprintf(buf,sizeof(buf),"%u",_protocol.start);
  214. s.append(buf);
  215. break;
  216. default:
  217. Utils::snprintf(buf,sizeof(buf),"%u-%u",_protocol.start,_protocol.end);
  218. s.append(buf);
  219. break;
  220. }
  221. s.push_back(';');
  222. switch(_port.magnitude()) {
  223. case 0:
  224. s.push_back('*');
  225. break;
  226. case 1:
  227. Utils::snprintf(buf,sizeof(buf),"%u",_port.start);
  228. s.append(buf);
  229. break;
  230. default:
  231. Utils::snprintf(buf,sizeof(buf),"%u-%u",_port.start,_port.end);
  232. s.append(buf);
  233. break;
  234. }
  235. return s;
  236. }
  237. Filter::Filter(const char *s)
  238. throw(std::invalid_argument)
  239. {
  240. char tmp[16384];
  241. if (!Utils::scopy(tmp,sizeof(tmp),s))
  242. throw std::invalid_argument("filter string too long");
  243. char *saveptr = (char *)0;
  244. unsigned int fn = 0;
  245. for(char *f=Utils::stok(tmp,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
  246. try {
  247. _rules.push_back(Rule(f));
  248. ++fn;
  249. } catch (std::invalid_argument &exc) {
  250. char tmp[256];
  251. Utils::snprintf(tmp,sizeof(tmp),"invalid rule at index %u: %s",fn,exc.what());
  252. throw std::invalid_argument(tmp);
  253. }
  254. }
  255. std::sort(_rules.begin(),_rules.end());
  256. }
  257. std::string Filter::toString() const
  258. {
  259. std::string s;
  260. for(std::vector<Rule>::const_iterator r(_rules.begin());r!=_rules.end();++r) {
  261. if (s.length() > 0)
  262. s.push_back(',');
  263. s.append(r->toString());
  264. }
  265. return s;
  266. }
  267. void Filter::add(const Rule &r)
  268. {
  269. for(std::vector<Rule>::iterator rr(_rules.begin());rr!=_rules.end();++rr) {
  270. if (r == *rr)
  271. return;
  272. }
  273. _rules.push_back(r);
  274. std::sort(_rules.begin(),_rules.end());
  275. }
  276. const char *Filter::etherTypeName(const unsigned int etherType)
  277. throw()
  278. {
  279. switch(etherType) {
  280. case ZT_ETHERTYPE_IPV4: return "ETHERTYPE_IPV4";
  281. case ZT_ETHERTYPE_ARP: return "ETHERTYPE_ARP";
  282. case ZT_ETHERTYPE_RARP: return "ETHERTYPE_RARP";
  283. case ZT_ETHERTYPE_ATALK: return "ETHERTYPE_ATALK";
  284. case ZT_ETHERTYPE_AARP: return "ETHERTYPE_AARP";
  285. case ZT_ETHERTYPE_IPX_A: return "ETHERTYPE_IPX_A";
  286. case ZT_ETHERTYPE_IPX_B: return "ETHERTYPE_IPX_B";
  287. case ZT_ETHERTYPE_IPV6: return "ETHERTYPE_IPV6";
  288. }
  289. return UNKNOWN_NAME;
  290. }
  291. const char *Filter::ipProtocolName(const unsigned int ipp)
  292. throw()
  293. {
  294. switch(ipp) {
  295. case ZT_IPPROTO_ICMP: return "IPPROTO_ICMP";
  296. case ZT_IPPROTO_IGMP: return "IPPROTO_IGMP";
  297. case ZT_IPPROTO_TCP: return "IPPROTO_TCP";
  298. case ZT_IPPROTO_UDP: return "IPPROTO_UDP";
  299. case ZT_IPPROTO_GRE: return "IPPROTO_GRE";
  300. case ZT_IPPROTO_ESP: return "IPPROTO_ESP";
  301. case ZT_IPPROTO_AH: return "IPPROTO_AH";
  302. case ZT_IPPROTO_ICMPV6: return "IPPROTO_ICMPV6";
  303. case ZT_IPPROTO_OSPF: return "IPPROTO_OSPF";
  304. case ZT_IPPROTO_IPIP: return "IPPROTO_IPIP";
  305. case ZT_IPPROTO_IPCOMP: return "IPPROTO_IPCOMP";
  306. case ZT_IPPROTO_L2TP: return "IPPROTO_L2TP";
  307. case ZT_IPPROTO_SCTP: return "IPPROTO_SCTP";
  308. case ZT_IPPROTO_FC: return "IPPROTO_FC";
  309. case ZT_IPPROTO_UDPLITE: return "IPPROTO_UDPLITE";
  310. case ZT_IPPROTO_HIP: return "IPPROTO_HIP";
  311. }
  312. return UNKNOWN_NAME;
  313. }
  314. const char *Filter::icmpTypeName(const unsigned int icmpType)
  315. throw()
  316. {
  317. switch(icmpType) {
  318. case ZT_ICMP_ECHO_REPLY: return "ICMP_ECHO_REPLY";
  319. case ZT_ICMP_DESTINATION_UNREACHABLE: return "ICMP_DESTINATION_UNREACHABLE";
  320. case ZT_ICMP_SOURCE_QUENCH: return "ICMP_SOURCE_QUENCH";
  321. case ZT_ICMP_REDIRECT: return "ICMP_REDIRECT";
  322. case ZT_ICMP_ALTERNATE_HOST_ADDRESS: return "ICMP_ALTERNATE_HOST_ADDRESS";
  323. case ZT_ICMP_ECHO_REQUEST: return "ICMP_ECHO_REQUEST";
  324. case ZT_ICMP_ROUTER_ADVERTISEMENT: return "ICMP_ROUTER_ADVERTISEMENT";
  325. case ZT_ICMP_ROUTER_SOLICITATION: return "ICMP_ROUTER_SOLICITATION";
  326. case ZT_ICMP_TIME_EXCEEDED: return "ICMP_TIME_EXCEEDED";
  327. case ZT_ICMP_BAD_IP_HEADER: return "ICMP_BAD_IP_HEADER";
  328. case ZT_ICMP_TIMESTAMP: return "ICMP_TIMESTAMP";
  329. case ZT_ICMP_TIMESTAMP_REPLY: return "ICMP_TIMESTAMP_REPLY";
  330. case ZT_ICMP_INFORMATION_REQUEST: return "ICMP_INFORMATION_REQUEST";
  331. case ZT_ICMP_INFORMATION_REPLY: return "ICMP_INFORMATION_REPLY";
  332. case ZT_ICMP_ADDRESS_MASK_REQUEST: return "ICMP_ADDRESS_MASK_REQUEST";
  333. case ZT_ICMP_ADDRESS_MASK_REPLY: return "ICMP_ADDRESS_MASK_REPLY";
  334. case ZT_ICMP_TRACEROUTE: return "ICMP_TRACEROUTE";
  335. case ZT_ICMP_MOBILE_HOST_REDIRECT: return "ICMP_MOBILE_HOST_REDIRECT";
  336. case ZT_ICMP_MOBILE_REGISTRATION_REQUEST: return "ICMP_MOBILE_REGISTRATION_REQUEST";
  337. case ZT_ICMP_MOBILE_REGISTRATION_REPLY: return "ICMP_MOBILE_REGISTRATION_REPLY";
  338. }
  339. return UNKNOWN_NAME;
  340. }
  341. const char *Filter::icmp6TypeName(const unsigned int icmp6Type)
  342. throw()
  343. {
  344. switch(icmp6Type) {
  345. case ZT_ICMP6_DESTINATION_UNREACHABLE: return "ICMP6_DESTINATION_UNREACHABLE";
  346. case ZT_ICMP6_PACKET_TOO_BIG: return "ICMP6_PACKET_TOO_BIG";
  347. case ZT_ICMP6_TIME_EXCEEDED: return "ICMP6_TIME_EXCEEDED";
  348. case ZT_ICMP6_PARAMETER_PROBLEM: return "ICMP6_PARAMETER_PROBLEM";
  349. case ZT_ICMP6_ECHO_REQUEST: return "ICMP6_ECHO_REQUEST";
  350. case ZT_ICMP6_ECHO_REPLY: return "ICMP6_ECHO_REPLY";
  351. case ZT_ICMP6_MULTICAST_LISTENER_QUERY: return "ICMP6_MULTICAST_LISTENER_QUERY";
  352. case ZT_ICMP6_MULTICAST_LISTENER_REPORT: return "ICMP6_MULTICAST_LISTENER_REPORT";
  353. case ZT_ICMP6_MULTICAST_LISTENER_DONE: return "ICMP6_MULTICAST_LISTENER_DONE";
  354. case ZT_ICMP6_ROUTER_SOLICITATION: return "ICMP6_ROUTER_SOLICITATION";
  355. case ZT_ICMP6_ROUTER_ADVERTISEMENT: return "ICMP6_ROUTER_ADVERTISEMENT";
  356. case ZT_ICMP6_NEIGHBOR_SOLICITATION: return "ICMP6_NEIGHBOR_SOLICITATION";
  357. case ZT_ICMP6_NEIGHBOR_ADVERTISEMENT: return "ICMP6_NEIGHBOR_ADVERTISEMENT";
  358. case ZT_ICMP6_REDIRECT_MESSAGE: return "ICMP6_REDIRECT_MESSAGE";
  359. case ZT_ICMP6_ROUTER_RENUMBERING: return "ICMP6_ROUTER_RENUMBERING";
  360. case ZT_ICMP6_NODE_INFORMATION_QUERY: return "ICMP6_NODE_INFORMATION_QUERY";
  361. case ZT_ICMP6_NODE_INFORMATION_RESPONSE: return "ICMP6_NODE_INFORMATION_RESPONSE";
  362. case ZT_ICMP6_INV_NEIGHBOR_SOLICITATION: return "ICMP6_INV_NEIGHBOR_SOLICITATION";
  363. case ZT_ICMP6_INV_NEIGHBOR_ADVERTISEMENT: return "ICMP6_INV_NEIGHBOR_ADVERTISEMENT";
  364. case ZT_ICMP6_MLDV2: return "ICMP6_MLDV2";
  365. case ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST: return "ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST";
  366. case ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY: return "ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY";
  367. case ZT_ICMP6_MOBILE_PREFIX_SOLICITATION: return "ICMP6_MOBILE_PREFIX_SOLICITATION";
  368. case ZT_ICMP6_MOBILE_PREFIX_ADVERTISEMENT: return "ICMP6_MOBILE_PREFIX_ADVERTISEMENT";
  369. case ZT_ICMP6_CERTIFICATION_PATH_SOLICITATION: return "ICMP6_CERTIFICATION_PATH_SOLICITATION";
  370. case ZT_ICMP6_CERTIFICATION_PATH_ADVERTISEMENT: return "ICMP6_CERTIFICATION_PATH_ADVERTISEMENT";
  371. case ZT_ICMP6_MULTICAST_ROUTER_ADVERTISEMENT: return "ICMP6_MULTICAST_ROUTER_ADVERTISEMENT";
  372. case ZT_ICMP6_MULTICAST_ROUTER_SOLICITATION: return "ICMP6_MULTICAST_ROUTER_SOLICITATION";
  373. case ZT_ICMP6_MULTICAST_ROUTER_TERMINATION: return "ICMP6_MULTICAST_ROUTER_TERMINATION";
  374. case ZT_ICMP6_RPL_CONTROL_MESSAGE: return "ICMP6_RPL_CONTROL_MESSAGE";
  375. }
  376. return UNKNOWN_NAME;
  377. }
  378. } // namespace ZeroTier