summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-16 15:00:15 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-16 15:00:15 -0400
commit102b0865cb4a4c2d17dea7ba4e9717a7a6a6049f (patch)
treed24b735891377de6a04a2e9d942d9e2405822de6
parenta793dc2b29e199d9512f8d22e005900fb986b146 (diff)
downloadinfinitytier-102b0865cb4a4c2d17dea7ba4e9717a7a6a6049f.tar.gz
infinitytier-102b0865cb4a4c2d17dea7ba4e9717a7a6a6049f.zip
Filter work, adding toString() and main evaluation function.
-rw-r--r--node/Defaults.cpp7
-rw-r--r--node/Defaults.hpp6
-rw-r--r--node/Filter.cpp298
-rw-r--r--node/Filter.hpp75
4 files changed, 287 insertions, 99 deletions
diff --git a/node/Defaults.cpp b/node/Defaults.cpp
index f1454796..d5990600 100644
--- a/node/Defaults.cpp
+++ b/node/Defaults.cpp
@@ -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())
{
}
diff --git a/node/Defaults.hpp b/node/Defaults.hpp
index b9c8ecf5..3493c5a8 100644
--- a/node/Defaults.hpp
+++ b/node/Defaults.hpp
@@ -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;
diff --git a/node/Filter.cpp b/node/Filter.cpp
index 5cd295c3..d7d177b1 100644
--- a/node/Filter.cpp
+++ b/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";
+ }
+ 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";
}
- 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;
+}
+
+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
diff --git a/node/Filter.hpp b/node/Filter.hpp
index 861603f0..0af52864 100644
--- a/node/Filter.hpp
+++ b/node/Filter.hpp
@@ -33,6 +33,7 @@
#include <string>
#include <vector>
#include <utility>
+#include <stdexcept>
#include "Mutex.hpp"
#include "Range.hpp"
@@ -130,6 +131,14 @@ 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
*
* This behaves as an immutable value object.
@@ -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
+ throw(std::invalid_argument);
+
+ /**
+ * @return Human readable representation of rule
*/
- bool operator()(unsigned int etype,const void *data,unsigned int len) const;
+ 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();
-private:
- const RuntimeEnvironment *_r;
+ /**
+ * 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:
std::vector<Entry> _chain;
Mutex _chain_m;
};