summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-08 00:21:43 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-08 00:21:43 -0400
commitf8cfdf973e17f67472f84798672c871f6992ba28 (patch)
tree6b895640a9d138f33c05e267c4ff2dca1b7ef34e /node
parente2a2d33f8f12e7227b35c0cc77f8cc091f32a440 (diff)
downloadinfinitytier-f8cfdf973e17f67472f84798672c871f6992ba28.tar.gz
infinitytier-f8cfdf973e17f67472f84798672c871f6992ba28.zip
More filter work, and doc updates
Diffstat (limited to 'node')
-rw-r--r--node/Filter.cpp49
-rw-r--r--node/Filter.hpp89
2 files changed, 107 insertions, 31 deletions
diff --git a/node/Filter.cpp b/node/Filter.cpp
index df72ccc5..8a41b3f9 100644
--- a/node/Filter.cpp
+++ b/node/Filter.cpp
@@ -30,27 +30,50 @@
#include "RuntimeEnvironment.hpp"
#include "Logger.hpp"
#include "Filter.hpp"
+#include "Utils.hpp"
namespace ZeroTier {
bool Filter::Rule::operator()(unsigned int etype,const void *data,unsigned int len) const
{
- if ((_etherType >= 0)&&(etype != (unsigned int)_etherType))
- return false; // ethertype mismatch
+ if ((!_etherType)||(_etherType(etype))) { // ethertype is ANY, or matches
+ // Ethertype determines meaning of protocol and port
+ switch(etype) {
+ case ZT_ETHERTYPE_IPV4:
+ if (len > 20) {
+ if ((!_protocol)||(_protocol(((const uint8_t *)data)[9]))) { // IP protocol
+ if (!_port)
+ return true; // protocol matches, port is ANY
- switch(etype) {
- case ZT_ETHERTYPE_IPV4:
- if (len < 20)
- return false; // invalid packets don't match
- if ((_protocol >= 0)&&(((const uint8_t *)data)[9] != (uint8_t)(_protocol & 0xff)))
- return false; // IP protocol # mismatch
+ // Don't match on fragments beyond fragment 0. If we've blocked
+ // fragment 0, further fragments will fall on deaf ears anyway.
+ if ((Utils::ntoh(((const uint16_t *)data)[3]) & 0x1fff))
+ return false;
- switch(((const uint8_t *)data)[9]) {
- }
+ // Internet header length determines where data begins, in multiples of 32 bits
+ unsigned int ihl = 4 * (((const uint8_t *)data)[0] & 0x0f);
- break;
- case ZT_ETHERTYPE_IPV6
- break;
+ switch(((const uint8_t *)data)[9]) { // port's meaning depends on IP protocol
+ case ZT_IPPROTO_ICMP:
+ return _port(((const uint8_t *)data)[ihl]); // port = ICMP type
+ case ZT_IPPROTO_TCP:
+ case ZT_IPPROTO_UDP:
+ case ZT_IPPROTO_SCTP:
+ case ZT_IPPROTO_UDPLITE:
+ return _port(((const uint16_t *)data)[(ihl / 2) + 1]); // destination port
+ }
+
+ return false; // no match on port
+ }
+ }
+ break;
+
+ case ZT_ETHERTYPE_IPV6:
+ if (len > 40) {
+ // see: http://stackoverflow.com/questions/17518951/is-the-ipv6-header-really-this-nutty
+ }
+ break;
+ }
}
return false;
diff --git a/node/Filter.hpp b/node/Filter.hpp
index 8f282508..df9f904d 100644
--- a/node/Filter.hpp
+++ b/node/Filter.hpp
@@ -36,7 +36,7 @@
#include "Mutex.hpp"
#include "Range.hpp"
-
+
/* Ethernet frame types that might be relevant to us */
#define ZT_ETHERTYPE_IPV4 0x0800
#define ZT_ETHERTYPE_ARP 0x0806
@@ -52,7 +52,6 @@
#define ZT_IPPROTO_IGMP 0x02
#define ZT_IPPROTO_TCP 0x06
#define ZT_IPPROTO_UDP 0x11
-#define ZT_IPPROTO_RDP 0x1b
#define ZT_IPPROTO_GRE 0x2f
#define ZT_IPPROTO_ESP 0x32
#define ZT_IPPROTO_AH 0x33
@@ -66,6 +65,60 @@
#define ZT_IPPROTO_UDPLITE 0x88
#define ZT_IPPROTO_HIP 0x8b
+/* IPv4 ICMP types */
+#define ZT_ICMP_ECHO_REPLY 0
+#define ZT_ICMP_DESTINATION_UNREACHABLE 3
+#define ZT_ICMP_SOURCE_QUENCH 4
+#define ZT_ICMP_REDIRECT 5
+#define ZT_ICMP_ALTERNATE_HOST_ADDRESS 6
+#define ZT_ICMP_ECHO_REQUEST 8
+#define ZT_ICMP_ROUTER_ADVERTISEMENT 9
+#define ZT_ICMP_ROUTER_SOLICITATION 10
+#define ZT_ICMP_TIME_EXCEEDED 11
+#define ZT_ICMP_BAD_IP_HEADER 12
+#define ZT_ICMP_TIMESTAMP 13
+#define ZT_ICMP_TIMESTAMP_REPLY 14
+#define ZT_ICMP_INFORMATION_REQUEST 15
+#define ZT_ICMP_INFORMATION_REPLY 16
+#define ZT_ICMP_ADDRESS_MASK_REQUEST 17
+#define ZT_ICMP_ADDRESS_MASK_REPLY 18
+#define ZT_ICMP_TRACEROUTE 30
+#define ZT_ICMP_MOBILE_HOST_REDIRECT 32
+#define ZT_ICMP_MOBILE_REGISTRATION_REQUEST 35
+#define ZT_ICMP_MOBILE_REGISTRATION_REPLY 36
+
+/* IPv6 ICMP types */
+#define ZT_ICMP6_DESTINATION_UNREACHABLE 1
+#define ZT_ICMP6_PACKET_TOO_BIG 2
+#define ZT_ICMP6_TIME_EXCEEDED 3
+#define ZT_ICMP6_PARAMETER_PROBLEM 4
+#define ZT_ICMP6_ECHO_REQUEST 128
+#define ZT_ICMP6_ECHO_REPLY 129
+#define ZT_ICMP6_MULTICAST_LISTENER_QUERY 130
+#define ZT_ICMP6_MULTICAST_LISTENER_REPORT 131
+#define ZT_ICMP6_MULTICAST_LISTENER_DONE 132
+#define ZT_ICMP6_ROUTER_SOLICITATION 133
+#define ZT_ICMP6_ROUTER_ADVERTISEMENT 134
+#define ZT_ICMP6_NEIGHBOR_SOLICITATION 135
+#define ZT_ICMP6_NEIGHBOR_ADVERTISEMENT 136
+#define ZT_ICMP6_REDIRECT_MESSAGE 137
+#define ZT_ICMP6_ROUTER_RENUMBERING 138
+#define ZT_ICMP6_NODE_INFORMATION_QUERY 139
+#define ZT_ICMP6_NODE_INFORMATION_RESPONSE 140
+#define ZT_ICMP6_INV_NEIGHBOR_SOLICITATION 141
+#define ZT_ICMP6_INV_NEIGHBOR_ADVERTISEMENT 142
+#define ZT_ICMP6_MLDV2 143
+#define ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST 144
+#define ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY 145
+#define ZT_ICMP6_MOBILE_PREFIX_SOLICITATION 146
+#define ZT_ICMP6_MOBILE_PREFIX_ADVERTISEMENT 147
+#define ZT_ICMP6_CERTIFICATION_PATH_SOLICITATION 148
+#define ZT_ICMP6_CERTIFICATION_PATH_ADVERTISEMENT 149
+#define ZT_ICMP6_MULTICAST_ROUTER_ADVERTISEMENT 151
+#define ZT_ICMP6_MULTICAST_ROUTER_SOLICITATION 152
+#define ZT_ICMP6_MULTICAST_ROUTER_TERMINATION 153
+#define ZT_ICMP6_RPL_CONTROL_MESSAGE 155
+
namespace ZeroTier {
class RuntimeEnvironment;
@@ -86,30 +139,30 @@ public:
public:
Rule()
throw() :
- _etherType(-1),
- _protocol(-1),
- _port(-1)
+ _etherType(),
+ _protocol(),
+ _port()
{
}
/**
* Construct a new rule
*
- * @param etype Ethernet type or negative for ANY
- * @param prot Protocol or negative for ANY (meaning depends on ethertype, e.g. IP protocol numbers)
- * @param prt Port or negative for ANY (only applies to some protocols)
+ * @param etype Ethernet type or empty range for ANY
+ * @param prot Protocol or empty range for ANY (meaning depends on ethertype, e.g. IP protocol numbers)
+ * @param prt Port or empty range for ANY (only applies to some protocols)
*/
- Rule(int etype,int prot,int prt)
+ Rule(const Range<unsigned int> &etype,const Range<unsigned int> &prot,const Range<unsigned int> &prt)
throw() :
- _etherType((etype >= 0) ? etype : -1),
- _protocol((prot >= 0) ? prot : -1),
- _port((prt >= 0) ? prt : -1)
+ _etherType(etype),
+ _protocol(prot),
+ _port(prt)
{
}
- inline int etherType() const throw() { return _etherType; }
- inline int protocol() const throw() { return _protocol; }
- inline int port() const throw() { return _port; }
+ inline const Range<unsigned int> &etherType() const throw() { return _etherType; }
+ inline const Range<unsigned int> &protocol() const throw() { return _protocol; }
+ inline const Range<unsigned int> &port() const throw() { return _port; }
/**
* Test this rule against a frame
@@ -143,9 +196,9 @@ public:
inline bool operator>=(const Rule &r) const throw() { return !(*this < r); }
private:
- int _etherType;
- int _protocol;
- int _port;
+ Range<unsigned int> _etherType;
+ Range<unsigned int> _protocol;
+ Range<unsigned int> _port;
};
/**