diff --git a/src/dns.h b/src/dns.h index 4398778..94771db 100644 --- a/src/dns.h +++ b/src/dns.h @@ -38,8 +38,6 @@ #include "packet_handler.h" #include -#define IPPROTO_ICMP 1 - namespace se { extern char visible_char_map[256]; diff --git a/src/packet_handler.h b/src/packet_handler.h index 849240a..12e6608 100644 --- a/src/packet_handler.h +++ b/src/packet_handler.h @@ -42,8 +42,6 @@ #include #include "sql.h" -#define IPPROTO_ICMP 1 - namespace se { class Table; diff --git a/src/sql.cpp b/src/sql.cpp index b608cef..8eff638 100644 --- a/src/sql.cpp +++ b/src/sql.cpp @@ -2118,6 +2118,11 @@ OP* OP::compile(const std::vector &tables, const std::vector &sear m_t = Coltype::_text; ret = new Trim_func(*this); } + if (cmpi(get_token(),"subnet") ) + { + m_t = Coltype::_text; + ret = new Subnet_func(*this); + } if (cmpi(get_token(),"rsplit") && m_param[1]) { m_t = Coltype::_text; diff --git a/src/sql.h b/src/sql.h index 6b6a19f..226f061 100644 --- a/src/sql.h +++ b/src/sql.h @@ -50,7 +50,7 @@ #include "stdarg.h" #include "refcountstring.h" #include "variant.h" - +#include #ifdef WIN32 #define snprintf _snprintf @@ -58,6 +58,11 @@ #define RE_LEN 64 +#ifndef AF_INET +#define AF_INET 2 +#define AF_INET6 10 +#endif + namespace se { extern int g_allocs; @@ -926,6 +931,107 @@ class Rsplit_func : public OP } }; +class Subnet_func : public OP +{ + public: + Subnet_func(const OP &op): OP(op) + { + } + void evaluate(Row **rows, Variant &v) + { + char sep='\0'; + Variant str, num; + RefCountStringHandle blank(RefCountString::construct("")); + int af; + + m_param[0]->evaluate(rows, str); + RefCountStringHandle address(str.get_text()); + const char *addr_str = (*address)->data; + int addr_len = strlen(addr_str); + char buf[40]; + + if (!addr_len) + { + v = *blank; + return; + } + for (int i=0; ievaluate(rows, num); + mask_len=num.get_int(); + } else { + throw Error("missing IPv4 mask length argument to subnet()"); + } + addr_size = 32; + af = AF_INET; + } else { // sep == ':' + if (m_param[2]) { + m_param[2]->evaluate(rows, num); + mask_len=num.get_int(); + } else { + throw Error("missing IPv6 mask length argument to subnet()"); + } + addr_size = 128; + af = AF_INET6; + } + if (mask_len > addr_size) { + v = *address; + return; + } + + // Masking code... + if (af == AF_INET) { + uint8_t sa[4]; + uint8_t mask[4] = {0,0,0,0}; + inet_pton(af, addr_str, sa); + + for (int i = mask_len, j = 0; i > 0; i -= 8, ++j) + mask[ j ] = i >= 8 ? 0xff + : (uint8_t)(( 0xffU << ( 8 - i ) ) & 0xffU ); + + for (int i = 0; i < addr_size/8; i++) { + sa[i] = sa[i] & mask[i]; + } + inet_ntop(af, sa, buf, 40); + } else { + uint8_t sa[16]; + uint8_t mask[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + inet_pton(af, addr_str, sa); + + for (int i = mask_len, j = 0; i > 0; i -= 8, ++j) + mask[ j ] = i >= 8 ? 0xff + : (uint8_t)(( 0xffU << ( 8 - i ) ) & 0xffU ); + + for (int i = 0; i < addr_size/8; i++) { + sa[i] = sa[i] & mask[i]; + } + + inet_ntop(af, sa, buf, 40); + } + + RefCountStringHandle res(RefCountString::construct(buf)); + v = *res; + } +}; + class Len_func : public OP { public: diff --git a/src/tcp.h b/src/tcp.h index 5cbefe8..7d3df86 100644 --- a/src/tcp.h +++ b/src/tcp.h @@ -39,8 +39,6 @@ #ifndef ETHERTYPE_IPV6 #define ETHERTYPE_IPV6 0x86dd #endif -#define IPPROTO_TCP 6 -#define IPPROTO_UDP 17 namespace se {