mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-18 18:56:24 +00:00
Filter work, adding toString() and main evaluation function.
This commit is contained in:
parent
a793dc2b29
commit
102b0865cb
@ -66,11 +66,16 @@ static inline std::map< Identity,std::vector<InetAddress> > _mkSupernodeMap()
|
||||
return sn;
|
||||
}
|
||||
|
||||
static inline Filter _mkDefaultNodeFilter()
|
||||
{
|
||||
}
|
||||
|
||||
Defaults::Defaults()
|
||||
throw(std::runtime_error) :
|
||||
supernodes(_mkSupernodeMap()),
|
||||
configUrlPrefix("http://api.zerotier.com/one/nc/"),
|
||||
configAuthority("f9f34184ac:1:AwGgrWjb8dARXzruqxiy1+Qf+gz4iM5IMfQTCWrJXkwERdvbvxTPZvtIyitw4gS90TGIxW+e7uJxweg9Vyq5lZJBrg==:QeEQLm9ymLC3EcnIw2OUqufUwb2wgHSAg6wQOXKyhT779p/8Hz5485PZLJCbr/aVHjwzop8APJk9B45Zm0Mb/LEhQTBMH2jvc7qqoYnMCNCO9jpADeMJwMW5e1VFgIObWl9uNjhRbf5/m8dZcn0pKKGwjSoP1QTeVWOC8GkZhE25bUWj")
|
||||
configAuthority("f9f34184ac:1:AwGgrWjb8dARXzruqxiy1+Qf+gz4iM5IMfQTCWrJXkwERdvbvxTPZvtIyitw4gS90TGIxW+e7uJxweg9Vyq5lZJBrg==:QeEQLm9ymLC3EcnIw2OUqufUwb2wgHSAg6wQOXKyhT779p/8Hz5485PZLJCbr/aVHjwzop8APJk9B45Zm0Mb/LEhQTBMH2jvc7qqoYnMCNCO9jpADeMJwMW5e1VFgIObWl9uNjhRbf5/m8dZcn0pKKGwjSoP1QTeVWOC8GkZhE25bUWj"),
|
||||
defaultNodeFilter(_mkDefaultNodeFilter())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <map>
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Filter.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@ -65,6 +66,11 @@ public:
|
||||
* Identity used to encrypt and authenticate configuration from URL
|
||||
*/
|
||||
const std::string configAuthority;
|
||||
|
||||
/**
|
||||
* Default node filter for this platform
|
||||
*/
|
||||
const Filter defaultNodeFilter;
|
||||
};
|
||||
|
||||
extern const Defaults ZT_DEFAULTS;
|
||||
|
298
node/Filter.cpp
298
node/Filter.cpp
@ -25,6 +25,9 @@
|
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "RuntimeEnvironment.hpp"
|
||||
@ -34,21 +37,19 @@
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
const char *const Filter::UNKNOWN_NAME = "(unknown)";
|
||||
|
||||
bool Filter::Rule::operator()(unsigned int etype,const void *data,unsigned int len) const
|
||||
throw(std::invalid_argument)
|
||||
{
|
||||
if ((!_etherType)||(_etherType(etype))) { // ethertype is ANY, or matches
|
||||
// Ethertype determines meaning of protocol and port
|
||||
switch(etype) {
|
||||
default:
|
||||
if ((!_protocol)&&(!_port))
|
||||
return true; // match other ethertypes if protocol and port are ANY, since we don't know what to do with them
|
||||
break;
|
||||
|
||||
case ZT_ETHERTYPE_IPV4:
|
||||
if (len > 20) {
|
||||
if ((!_protocol)||(_protocol(((const uint8_t *)data)[9]))) { // IP protocol
|
||||
if (!_port)
|
||||
return true; // protocol matches or is ANY, port is ANY
|
||||
if ((!_protocol)||(_protocol(((const uint8_t *)data)[9]))) { // protocol is ANY or match
|
||||
if (!_port) // port is ANY
|
||||
return true;
|
||||
|
||||
// Don't match on fragments beyond fragment 0. If we've blocked
|
||||
// fragment 0, further fragments will fall on deaf ears anyway.
|
||||
@ -60,22 +61,27 @@ bool Filter::Rule::operator()(unsigned int etype,const void *data,unsigned int l
|
||||
|
||||
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
|
||||
// For ICMP, port is ICMP type
|
||||
return _port(((const uint8_t *)data)[ihl]);
|
||||
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
|
||||
// For these, port is destination port. Protocol designers were
|
||||
// nice enough to put the field in the same place.
|
||||
return _port(((const uint16_t *)data)[(ihl / 2) + 1]);
|
||||
default:
|
||||
// port has no meaning for other IP types, so ignore it
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // no match on port
|
||||
}
|
||||
}
|
||||
} else throw std::invalid_argument("undersized IPv4 packet");
|
||||
break;
|
||||
|
||||
case ZT_ETHERTYPE_IPV6:
|
||||
if (len > 40) {
|
||||
// see: http://stackoverflow.com/questions/17518951/is-the-ipv6-header-really-this-nutty
|
||||
int nextHeader = ((const uint8_t *)data)[6];
|
||||
unsigned int pos = 40;
|
||||
while ((pos < len)&&(nextHeader >= 0)&&(nextHeader != 59)) { // 59 == no next header
|
||||
@ -102,9 +108,11 @@ bool Filter::Rule::operator()(unsigned int etype,const void *data,unsigned int l
|
||||
case ZT_IPPROTO_ESP: // ESP
|
||||
return _protocol(ZT_IPPROTO_ESP); // true if ESP is matched protocol, otherwise false since packet will be IPsec
|
||||
case ZT_IPPROTO_ICMPV6:
|
||||
if (_protocol(ZT_IPPROTO_ICMPV6)) { // only match ICMPv6 if specified
|
||||
// Only match ICMPv6 if we've selected it specifically
|
||||
if (_protocol(ZT_IPPROTO_ICMPV6)) {
|
||||
// Port is interpreted as ICMPv6 type
|
||||
if ((!_port)||(_port(((const uint8_t *)data)[pos])))
|
||||
return true; // protocol matches, port is ANY or matches ICMP type
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ZT_IPPROTO_TCP:
|
||||
@ -118,25 +126,75 @@ bool Filter::Rule::operator()(unsigned int etype,const void *data,unsigned int l
|
||||
return true; // protocol matches or is ANY, port is ANY or matches
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
char foo[128];
|
||||
sprintf(foo,"unrecognized IPv6 header type %d",(int)nextHeader);
|
||||
throw std::invalid_argument(foo);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,"[rule] V6: end header parse, next header %.2x, new pos %d\n",nextHeader,pos);
|
||||
}
|
||||
}
|
||||
} else throw std::invalid_argument("undersized IPv6 packet");
|
||||
break;
|
||||
|
||||
default:
|
||||
// For other ethertypes, protocol and port are ignored. What would they mean?
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Filter::Filter(const RuntimeEnvironment *renv) :
|
||||
_r(renv)
|
||||
std::string Filter::Rule::toString() const
|
||||
{
|
||||
}
|
||||
char buf[128];
|
||||
std::string s;
|
||||
|
||||
Filter::~Filter()
|
||||
{
|
||||
switch(_etherType.magnitude()) {
|
||||
case 0:
|
||||
s.push_back('*');
|
||||
break;
|
||||
case 1:
|
||||
sprintf(buf,"%u",_etherType.start);
|
||||
s.append(buf);
|
||||
break;
|
||||
default:
|
||||
sprintf(buf,"%u-%u",_etherType.start,_etherType.end);
|
||||
s.append(buf);
|
||||
break;
|
||||
}
|
||||
s.push_back('/');
|
||||
switch(_protocol.magnitude()) {
|
||||
case 0:
|
||||
s.push_back('*');
|
||||
break;
|
||||
case 1:
|
||||
sprintf(buf,"%u",_protocol.start);
|
||||
s.append(buf);
|
||||
break;
|
||||
default:
|
||||
sprintf(buf,"%u-%u",_protocol.start,_protocol.end);
|
||||
s.append(buf);
|
||||
break;
|
||||
}
|
||||
s.push_back('/');
|
||||
switch(_port.magnitude()) {
|
||||
case 0:
|
||||
s.push_back('*');
|
||||
break;
|
||||
case 1:
|
||||
sprintf(buf,"%u",_port.start);
|
||||
s.append(buf);
|
||||
break;
|
||||
default:
|
||||
sprintf(buf,"%u-%u",_port.start,_port.end);
|
||||
s.append(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void Filter::add(const Rule &r,const Action &a)
|
||||
@ -153,60 +211,18 @@ void Filter::add(const Rule &r,const Action &a)
|
||||
|
||||
std::string Filter::toString(const char *sep) const
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
if (!sep)
|
||||
sep = ",";
|
||||
|
||||
std::string s;
|
||||
|
||||
bool first = true;
|
||||
Mutex::Lock _l(_chain_m);
|
||||
for(std::vector<Entry>::const_iterator i(_chain.begin());i!=_chain.end();++i) {
|
||||
bool first = (i == _chain.begin());
|
||||
|
||||
s.push_back('[');
|
||||
|
||||
if (i->rule.etherType()) {
|
||||
if (i->rule.etherType().magnitude() > 1)
|
||||
sprintf(buf,"%u-%u",i->rule.etherType().start,i->rule.etherType().end);
|
||||
else sprintf(buf,"%u",i->rule.etherType().start);
|
||||
s.append(buf);
|
||||
} else s.push_back('*');
|
||||
|
||||
s.push_back(';');
|
||||
|
||||
if (i->rule.protocol()) {
|
||||
if (i->rule.protocol().magnitude() > 1)
|
||||
sprintf(buf,"%u-%u",i->rule.protocol().start,i->rule.protocol().end);
|
||||
else sprintf(buf,"%u",i->rule.protocol().start);
|
||||
s.append(buf);
|
||||
} else s.push_back('*');
|
||||
|
||||
s.push_back(';');
|
||||
|
||||
if (i->rule.port()) {
|
||||
if (i->rule.port().magnitude() > 1)
|
||||
sprintf(buf,"%u-%u",i->rule.port().start,i->rule.port().end);
|
||||
else sprintf(buf,"%u",i->rule.port().start);
|
||||
s.append(buf);
|
||||
} else s.push_back('*');
|
||||
|
||||
s.append("]:");
|
||||
|
||||
switch(i->action) {
|
||||
case ACTION_DENY:
|
||||
s.append("DENY");
|
||||
break;
|
||||
case ACTION_ALLOW:
|
||||
s.append("ALLOW");
|
||||
break;
|
||||
case ACTION_LOG:
|
||||
s.append("LOG");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!first)
|
||||
s.append(sep);
|
||||
s.append(i->rule.toString());
|
||||
if (first)
|
||||
first = false;
|
||||
else s.append(sep);
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -215,27 +231,137 @@ std::string Filter::toString(const char *sep) const
|
||||
const char *Filter::etherTypeName(const unsigned int etherType)
|
||||
throw()
|
||||
{
|
||||
static char tmp[6];
|
||||
switch(etherType) {
|
||||
case ZT_ETHERTYPE_IPV4:
|
||||
return "IPV4";
|
||||
case ZT_ETHERTYPE_ARP:
|
||||
return "ARP";
|
||||
case ZT_ETHERTYPE_RARP:
|
||||
return "RARP";
|
||||
case ZT_ETHERTYPE_ATALK:
|
||||
return "ATALK";
|
||||
case ZT_ETHERTYPE_AARP:
|
||||
return "AARP";
|
||||
case ZT_ETHERTYPE_IPX_A:
|
||||
return "IPX_A";
|
||||
case ZT_ETHERTYPE_IPX_B:
|
||||
return "IPX_B";
|
||||
case ZT_ETHERTYPE_IPV6:
|
||||
return "IPV6";
|
||||
case ZT_ETHERTYPE_IPV4: return "ETHERTYPE_IPV4";
|
||||
case ZT_ETHERTYPE_ARP: return "ETHERTYPE_ARP";
|
||||
case ZT_ETHERTYPE_RARP: return "ETHERTYPE_RARP";
|
||||
case ZT_ETHERTYPE_ATALK: return "ETHERTYPE_ATALK";
|
||||
case ZT_ETHERTYPE_AARP: return "ETHERTYPE_AARP";
|
||||
case ZT_ETHERTYPE_IPX_A: return "ETHERTYPE_IPX_A";
|
||||
case ZT_ETHERTYPE_IPX_B: return "ETHERTYPE_IPX_B";
|
||||
case ZT_ETHERTYPE_IPV6: return "ETHERTYPE_IPV6";
|
||||
}
|
||||
sprintf(tmp,"%.4x",etherType);
|
||||
return tmp; // technically not thread safe, but we're only going to see this in debugging if ever
|
||||
return UNKNOWN_NAME;
|
||||
}
|
||||
|
||||
const char *Filter::ipProtocolName(const unsigned int ipp)
|
||||
throw()
|
||||
{
|
||||
switch(ipp) {
|
||||
case ZT_IPPROTO_ICMP: return "IPPROTO_ICMP";
|
||||
case ZT_IPPROTO_IGMP: return "IPPROTO_IGMP";
|
||||
case ZT_IPPROTO_TCP: return "IPPROTO_TCP";
|
||||
case ZT_IPPROTO_UDP: return "IPPROTO_UDP";
|
||||
case ZT_IPPROTO_GRE: return "IPPROTO_GRE";
|
||||
case ZT_IPPROTO_ESP: return "IPPROTO_ESP";
|
||||
case ZT_IPPROTO_AH: return "IPPROTO_AH";
|
||||
case ZT_IPPROTO_ICMPV6: return "IPPROTO_ICMPV6";
|
||||
case ZT_IPPROTO_OSPF: return "IPPROTO_OSPF";
|
||||
case ZT_IPPROTO_IPIP: return "IPPROTO_IPIP";
|
||||
case ZT_IPPROTO_IPCOMP: return "IPPROTO_IPCOMP";
|
||||
case ZT_IPPROTO_L2TP: return "IPPROTO_L2TP";
|
||||
case ZT_IPPROTO_SCTP: return "IPPROTO_SCTP";
|
||||
case ZT_IPPROTO_FC: return "IPPROTO_FC";
|
||||
case ZT_IPPROTO_UDPLITE: return "IPPROTO_UDPLITE";
|
||||
case ZT_IPPROTO_HIP: return "IPPROTO_HIP";
|
||||
}
|
||||
return UNKNOWN_NAME;
|
||||
}
|
||||
|
||||
const char *Filter::icmpTypeName(const unsigned int icmpType)
|
||||
throw()
|
||||
{
|
||||
switch(icmpType) {
|
||||
case ZT_ICMP_ECHO_REPLY: return "ICMP_ECHO_REPLY";
|
||||
case ZT_ICMP_DESTINATION_UNREACHABLE: return "ICMP_DESTINATION_UNREACHABLE";
|
||||
case ZT_ICMP_SOURCE_QUENCH: return "ICMP_SOURCE_QUENCH";
|
||||
case ZT_ICMP_REDIRECT: return "ICMP_REDIRECT";
|
||||
case ZT_ICMP_ALTERNATE_HOST_ADDRESS: return "ICMP_ALTERNATE_HOST_ADDRESS";
|
||||
case ZT_ICMP_ECHO_REQUEST: return "ICMP_ECHO_REQUEST";
|
||||
case ZT_ICMP_ROUTER_ADVERTISEMENT: return "ICMP_ROUTER_ADVERTISEMENT";
|
||||
case ZT_ICMP_ROUTER_SOLICITATION: return "ICMP_ROUTER_SOLICITATION";
|
||||
case ZT_ICMP_TIME_EXCEEDED: return "ICMP_TIME_EXCEEDED";
|
||||
case ZT_ICMP_BAD_IP_HEADER: return "ICMP_BAD_IP_HEADER";
|
||||
case ZT_ICMP_TIMESTAMP: return "ICMP_TIMESTAMP";
|
||||
case ZT_ICMP_TIMESTAMP_REPLY: return "ICMP_TIMESTAMP_REPLY";
|
||||
case ZT_ICMP_INFORMATION_REQUEST: return "ICMP_INFORMATION_REQUEST";
|
||||
case ZT_ICMP_INFORMATION_REPLY: return "ICMP_INFORMATION_REPLY";
|
||||
case ZT_ICMP_ADDRESS_MASK_REQUEST: return "ICMP_ADDRESS_MASK_REQUEST";
|
||||
case ZT_ICMP_ADDRESS_MASK_REPLY: return "ICMP_ADDRESS_MASK_REPLY";
|
||||
case ZT_ICMP_TRACEROUTE: return "ICMP_TRACEROUTE";
|
||||
case ZT_ICMP_MOBILE_HOST_REDIRECT: return "ICMP_MOBILE_HOST_REDIRECT";
|
||||
case ZT_ICMP_MOBILE_REGISTRATION_REQUEST: return "ICMP_MOBILE_REGISTRATION_REQUEST";
|
||||
case ZT_ICMP_MOBILE_REGISTRATION_REPLY: return "ICMP_MOBILE_REGISTRATION_REPLY";
|
||||
}
|
||||
return UNKNOWN_NAME;
|
||||
}
|
||||
|
||||
const char *Filter::icmp6TypeName(const unsigned int icmp6Type)
|
||||
throw()
|
||||
{
|
||||
switch(icmp6Type) {
|
||||
case ZT_ICMP6_DESTINATION_UNREACHABLE: return "ICMP6_DESTINATION_UNREACHABLE";
|
||||
case ZT_ICMP6_PACKET_TOO_BIG: return "ICMP6_PACKET_TOO_BIG";
|
||||
case ZT_ICMP6_TIME_EXCEEDED: return "ICMP6_TIME_EXCEEDED";
|
||||
case ZT_ICMP6_PARAMETER_PROBLEM: return "ICMP6_PARAMETER_PROBLEM";
|
||||
case ZT_ICMP6_ECHO_REQUEST: return "ICMP6_ECHO_REQUEST";
|
||||
case ZT_ICMP6_ECHO_REPLY: return "ICMP6_ECHO_REPLY";
|
||||
case ZT_ICMP6_MULTICAST_LISTENER_QUERY: return "ICMP6_MULTICAST_LISTENER_QUERY";
|
||||
case ZT_ICMP6_MULTICAST_LISTENER_REPORT: return "ICMP6_MULTICAST_LISTENER_REPORT";
|
||||
case ZT_ICMP6_MULTICAST_LISTENER_DONE: return "ICMP6_MULTICAST_LISTENER_DONE";
|
||||
case ZT_ICMP6_ROUTER_SOLICITATION: return "ICMP6_ROUTER_SOLICITATION";
|
||||
case ZT_ICMP6_ROUTER_ADVERTISEMENT: return "ICMP6_ROUTER_ADVERTISEMENT";
|
||||
case ZT_ICMP6_NEIGHBOR_SOLICITATION: return "ICMP6_NEIGHBOR_SOLICITATION";
|
||||
case ZT_ICMP6_NEIGHBOR_ADVERTISEMENT: return "ICMP6_NEIGHBOR_ADVERTISEMENT";
|
||||
case ZT_ICMP6_REDIRECT_MESSAGE: return "ICMP6_REDIRECT_MESSAGE";
|
||||
case ZT_ICMP6_ROUTER_RENUMBERING: return "ICMP6_ROUTER_RENUMBERING";
|
||||
case ZT_ICMP6_NODE_INFORMATION_QUERY: return "ICMP6_NODE_INFORMATION_QUERY";
|
||||
case ZT_ICMP6_NODE_INFORMATION_RESPONSE: return "ICMP6_NODE_INFORMATION_RESPONSE";
|
||||
case ZT_ICMP6_INV_NEIGHBOR_SOLICITATION: return "ICMP6_INV_NEIGHBOR_SOLICITATION";
|
||||
case ZT_ICMP6_INV_NEIGHBOR_ADVERTISEMENT: return "ICMP6_INV_NEIGHBOR_ADVERTISEMENT";
|
||||
case ZT_ICMP6_MLDV2: return "ICMP6_MLDV2";
|
||||
case ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST: return "ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST";
|
||||
case ZT_ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY: return "ICMP6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY";
|
||||
case ZT_ICMP6_MOBILE_PREFIX_SOLICITATION: return "ICMP6_MOBILE_PREFIX_SOLICITATION";
|
||||
case ZT_ICMP6_MOBILE_PREFIX_ADVERTISEMENT: return "ICMP6_MOBILE_PREFIX_ADVERTISEMENT";
|
||||
case ZT_ICMP6_CERTIFICATION_PATH_SOLICITATION: return "ICMP6_CERTIFICATION_PATH_SOLICITATION";
|
||||
case ZT_ICMP6_CERTIFICATION_PATH_ADVERTISEMENT: return "ICMP6_CERTIFICATION_PATH_ADVERTISEMENT";
|
||||
case ZT_ICMP6_MULTICAST_ROUTER_ADVERTISEMENT: return "ICMP6_MULTICAST_ROUTER_ADVERTISEMENT";
|
||||
case ZT_ICMP6_MULTICAST_ROUTER_SOLICITATION: return "ICMP6_MULTICAST_ROUTER_SOLICITATION";
|
||||
case ZT_ICMP6_MULTICAST_ROUTER_TERMINATION: return "ICMP6_MULTICAST_ROUTER_TERMINATION";
|
||||
case ZT_ICMP6_RPL_CONTROL_MESSAGE: return "ICMP6_RPL_CONTROL_MESSAGE";
|
||||
}
|
||||
return UNKNOWN_NAME;
|
||||
}
|
||||
|
||||
Filter::Action Filter::operator()(const RuntimeEnvironment *_r,unsigned int etherType,const void *frame,unsigned int len) const
|
||||
{
|
||||
Mutex::Lock _l(_chain_m);
|
||||
|
||||
int ruleNo = 0;
|
||||
for(std::vector<Entry>::const_iterator r(_chain.begin());r!=_chain.end();++r,++ruleNo) {
|
||||
try {
|
||||
if (r->rule(etherType,frame,len)) {
|
||||
switch(r->action) {
|
||||
case ACTION_ALLOW:
|
||||
case ACTION_DENY:
|
||||
return r->action;
|
||||
case ACTION_LOG:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (std::invalid_argument &exc) {
|
||||
LOG("filter: unable to parse packet on rule %s (%d): %s",r->rule.toString().c_str(),ruleNo,exc.what());
|
||||
return ACTION_UNPARSEABLE;
|
||||
} catch ( ... ) {
|
||||
LOG("filter: unable to parse packet on rule %s (%d): unknown exception",r->rule.toString().c_str(),ruleNo);
|
||||
return ACTION_UNPARSEABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return ACTION_ALLOW;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "Mutex.hpp"
|
||||
#include "Range.hpp"
|
||||
@ -129,6 +130,14 @@ class RuntimeEnvironment;
|
||||
class Filter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Value returned by etherTypeName, etc. on unknown
|
||||
*
|
||||
* These static methods return precisely this, so a pointer equality
|
||||
* check will work.
|
||||
*/
|
||||
static const char *const UNKNOWN_NAME;
|
||||
|
||||
/**
|
||||
* A filter rule
|
||||
*
|
||||
@ -171,8 +180,15 @@ public:
|
||||
* @param data Ethernet frame data
|
||||
* @param len Length of ethernet frame
|
||||
* @return True if rule matches
|
||||
* @throws std::invalid_argument Frame invalid or not parseable
|
||||
*/
|
||||
bool operator()(unsigned int etype,const void *data,unsigned int len) const;
|
||||
bool operator()(unsigned int etype,const void *data,unsigned int len) const
|
||||
throw(std::invalid_argument);
|
||||
|
||||
/**
|
||||
* @return Human readable representation of rule
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
inline bool operator==(const Rule &r) const throw() { return ((_etherType == r._etherType)&&(_protocol == r._protocol)&&(_port == r._port)); }
|
||||
inline bool operator!=(const Rule &r) const throw() { return !(*this == r); }
|
||||
@ -206,9 +222,10 @@ public:
|
||||
*/
|
||||
enum Action
|
||||
{
|
||||
ACTION_DENY = 0,
|
||||
ACTION_ALLOW = 1,
|
||||
ACTION_LOG = 2
|
||||
ACTION_DENY = 1,
|
||||
ACTION_ALLOW = 2,
|
||||
ACTION_LOG = 3,
|
||||
ACTION_UNPARSEABLE = 4
|
||||
};
|
||||
|
||||
/**
|
||||
@ -227,8 +244,27 @@ public:
|
||||
Action action;
|
||||
};
|
||||
|
||||
Filter(const RuntimeEnvironment *renv);
|
||||
~Filter();
|
||||
Filter() :
|
||||
_chain(),
|
||||
_chain_m()
|
||||
{
|
||||
}
|
||||
|
||||
Filter(const Filter &f) :
|
||||
_chain(),
|
||||
_chain_m()
|
||||
{
|
||||
Mutex::Lock _l(f._chain_m);
|
||||
_chain = f._chain;
|
||||
}
|
||||
|
||||
inline Filter &operator=(const Filter &f)
|
||||
{
|
||||
Mutex::Lock _l1(_chain_m);
|
||||
Mutex::Lock _l2(f._chain_m);
|
||||
_chain = f._chain;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all filter entries
|
||||
@ -281,16 +317,31 @@ public:
|
||||
*/
|
||||
std::string toString(const char *sep = (const char *)0) const;
|
||||
|
||||
/**
|
||||
* @param etherType Ethernet type ID
|
||||
* @return Name of Ethernet protocol (e.g. ARP, IPV4)
|
||||
*/
|
||||
static const char *etherTypeName(const unsigned int etherType)
|
||||
throw();
|
||||
static const char *ipProtocolName(const unsigned int ipp)
|
||||
throw();
|
||||
static const char *icmpTypeName(const unsigned int icmpType)
|
||||
throw();
|
||||
static const char *icmp6TypeName(const unsigned int icmp6Type)
|
||||
throw();
|
||||
|
||||
/**
|
||||
* Match against an Ethernet frame
|
||||
*
|
||||
* Note that ACTION_LOG rules do not terminate rule evaluation and
|
||||
* ACTION_LOG is never returned here as a result. It's primarily for
|
||||
* debugging and rule testing.
|
||||
*
|
||||
* @param _r Runtime environment
|
||||
* @param etherType Ethernet frame type
|
||||
* @param frame Ethernet frame data
|
||||
* @param len Length of frame in bytes
|
||||
* @return Action if matched or ACTION_ALLOW if not matched
|
||||
*/
|
||||
Action operator()(const RuntimeEnvironment *_r,unsigned int etherType,const void *frame,unsigned int len) const;
|
||||
|
||||
private:
|
||||
const RuntimeEnvironment *_r;
|
||||
|
||||
std::vector<Entry> _chain;
|
||||
Mutex _chain_m;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user