mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00
Merge remote-tracking branch 'origin/topic/jsiwek/subnet-literal-const'
* origin/topic/jsiwek/subnet-literal-const: Add parsing rules for IPv4/IPv6 subnet literal constants, addresses #888 Closes #888.
This commit is contained in:
commit
7ddbca8b35
12 changed files with 107 additions and 36 deletions
5
CHANGES
5
CHANGES
|
@ -1,4 +1,9 @@
|
|||
|
||||
2.1-86 | 2012-10-24 15:37:11 -0700
|
||||
|
||||
* Add parsing rules for IPv4/IPv6 subnet literal constants.
|
||||
Addresses #888. (Jon Siwek)
|
||||
|
||||
2.1-84 | 2012-10-19 15:12:56 -0700
|
||||
|
||||
* Added a BiF strptime() to wrap the corresponding C function. (Seth
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.1-84
|
||||
2.1-86
|
||||
|
|
|
@ -248,10 +248,10 @@ IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length)
|
|||
prefix.Mask(this->length);
|
||||
}
|
||||
|
||||
IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length)
|
||||
IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length, bool len_is_v6_relative)
|
||||
: prefix(addr)
|
||||
{
|
||||
if ( prefix.GetFamily() == IPv4 )
|
||||
if ( prefix.GetFamily() == IPv4 && ! len_is_v6_relative )
|
||||
{
|
||||
if ( length > 32 )
|
||||
reporter->InternalError("Bad IPAddr(v4) IPPrefix length : %d",
|
||||
|
|
|
@ -496,8 +496,15 @@ public:
|
|||
* @param addr The IP address.
|
||||
*
|
||||
* @param length The prefix length in the range from 0 to 128
|
||||
*
|
||||
* @param len_is_v6_relative Whether \a length is relative to the full
|
||||
* 128 bits of an IPv6 address. If false and \a addr is an IPv4
|
||||
* address, then \a length is expected to range from 0 to 32. If true
|
||||
* \a length is expected to range from 0 to 128 even if \a addr is IPv4,
|
||||
* meaning that the mask is to apply to the IPv4-mapped-IPv6 representation.
|
||||
*/
|
||||
IPPrefix(const IPAddr& addr, uint8_t length);
|
||||
IPPrefix(const IPAddr& addr, uint8_t length,
|
||||
bool len_is_v6_relative = false);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
|
|
|
@ -11,16 +11,6 @@
|
|||
#include "rule-parse.h"
|
||||
|
||||
int rules_line_number = 0;
|
||||
|
||||
static string extract_ipv6(string s)
|
||||
{
|
||||
if ( s.substr(0, 3) == "[0x" )
|
||||
s = s.substr(3, s.find("]") - 3);
|
||||
else
|
||||
s = s.substr(1, s.find("]") - 1);
|
||||
|
||||
return s;
|
||||
}
|
||||
%}
|
||||
|
||||
%x PS
|
||||
|
@ -49,15 +39,14 @@ PID ([0-9a-zA-Z_-]|"::")+
|
|||
}
|
||||
|
||||
{IP6} {
|
||||
rules_lval.prefixval = new IPPrefix(IPAddr(extract_ipv6(yytext)), 128);
|
||||
rules_lval.prefixval = new IPPrefix(IPAddr(extract_ip(yytext)), 128, true);
|
||||
return TOK_IP6;
|
||||
}
|
||||
|
||||
{IP6}{OWS}"/"{OWS}{D} {
|
||||
char* l = strchr(yytext, '/');
|
||||
*l++ = '\0';
|
||||
int len = atoi(l);
|
||||
rules_lval.prefixval = new IPPrefix(IPAddr(extract_ipv6(yytext)), len);
|
||||
int len = 0;
|
||||
string ip = extract_ip_and_len(yytext, &len);
|
||||
rules_lval.prefixval = new IPPrefix(IPAddr(ip), len, true);
|
||||
return TOK_IP6;
|
||||
}
|
||||
|
||||
|
|
31
src/scan.l
31
src/scan.l
|
@ -148,6 +148,7 @@ D [0-9]+
|
|||
HEX [0-9a-fA-F]+
|
||||
IDCOMPONENT [A-Za-z_][A-Za-z_0-9]*
|
||||
ID {IDCOMPONENT}(::{IDCOMPONENT})*
|
||||
IP6 ("["({HEX}:){7}{HEX}"]")|("["0x{HEX}({HEX}|:)*"::"({HEX}|:)*"]")|("["({HEX}|:)*"::"({HEX}|:)*"]")|("["({HEX}|:)*"::"({HEX}|:)*({D}"."){3}{D}"]")
|
||||
FILE [^ \t\n]+
|
||||
PREFIX [^ \t\n]+
|
||||
FLOAT (({D}*"."?{D})|({D}"."?{D}*))([eE][-+]?{D})?
|
||||
|
@ -229,21 +230,23 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+))
|
|||
}
|
||||
|
||||
/* IPv6 literal constant patterns */
|
||||
"["({HEX}:){7}{HEX}"]" {
|
||||
string s(yytext+1);
|
||||
RET_CONST(new AddrVal(s.erase(s.size()-1)))
|
||||
{IP6} {
|
||||
RET_CONST(new AddrVal(extract_ip(yytext)))
|
||||
}
|
||||
"["0x{HEX}({HEX}|:)*"::"({HEX}|:)*"]" {
|
||||
string s(yytext+3);
|
||||
RET_CONST(new AddrVal(s.erase(s.size()-1)))
|
||||
|
||||
{IP6}{OWS}"/"{OWS}{D} {
|
||||
int len = 0;
|
||||
string ip = extract_ip_and_len(yytext, &len);
|
||||
RET_CONST(new SubNetVal(IPPrefix(IPAddr(ip), len, true)))
|
||||
}
|
||||
"["({HEX}|:)*"::"({HEX}|:)*"]" {
|
||||
string s(yytext+1);
|
||||
RET_CONST(new AddrVal(s.erase(s.size()-1)))
|
||||
}
|
||||
"["({HEX}|:)*"::"({HEX}|:)*({D}"."){3}{D}"]" {
|
||||
string s(yytext+1);
|
||||
RET_CONST(new AddrVal(s.erase(s.size()-1)))
|
||||
|
||||
/* IPv4 literal constant patterns */
|
||||
({D}"."){3}{D} RET_CONST(new AddrVal(yytext))
|
||||
|
||||
({D}"."){3}{D}{OWS}"/"{OWS}{D} {
|
||||
int len = 0;
|
||||
string ip = extract_ip_and_len(yytext, &len);
|
||||
RET_CONST(new SubNetVal(IPPrefix(IPAddr(ip), len)))
|
||||
}
|
||||
|
||||
[!%*/+\-,:;<=>?()\[\]{}~$|] return yytext[0];
|
||||
|
@ -484,8 +487,6 @@ F RET_CONST(new Val(false, TYPE_BOOL))
|
|||
{FLOAT}{OWS}msec(s?) RET_CONST(new IntervalVal(atof(yytext),Milliseconds))
|
||||
{FLOAT}{OWS}usec(s?) RET_CONST(new IntervalVal(atof(yytext),Microseconds))
|
||||
|
||||
({D}"."){3}{D} RET_CONST(new AddrVal(yytext))
|
||||
|
||||
"0x"{HEX}+ RET_CONST(new Val(static_cast<bro_uint_t>(strtoull(yytext, 0, 16)), TYPE_COUNT))
|
||||
|
||||
{H}("."{H})+ RET_CONST(dns_mgr->LookupHost(yytext))
|
||||
|
|
34
src/util.cc
34
src/util.cc
|
@ -43,6 +43,40 @@
|
|||
#include "Net.h"
|
||||
#include "Reporter.h"
|
||||
|
||||
/**
|
||||
* Return IP address without enclosing brackets and any leading 0x.
|
||||
*/
|
||||
std::string extract_ip(const std::string& i)
|
||||
{
|
||||
std::string s(skip_whitespace(i.c_str()));
|
||||
if ( s.size() > 0 && s[0] == '[' )
|
||||
s.erase(0, 1);
|
||||
|
||||
if ( s.size() > 1 && s.substr(0, 2) == "0x" )
|
||||
s.erase(0, 2);
|
||||
|
||||
size_t pos = 0;
|
||||
if ( (pos = s.find(']')) != std::string::npos )
|
||||
s = s.substr(0, pos);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a subnet string, return IP address and subnet length separately.
|
||||
*/
|
||||
std::string extract_ip_and_len(const std::string& i, int* len)
|
||||
{
|
||||
size_t pos = i.find('/');
|
||||
if ( pos == std::string::npos )
|
||||
return i;
|
||||
|
||||
if ( len )
|
||||
*len = atoi(i.substr(pos + 1).c_str());
|
||||
|
||||
return extract_ip(i.substr(0, pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a string, unescapes all characters that are escaped as hex codes
|
||||
* (\x##) and turns them into the equivalent ascii-codes. Returns a string
|
||||
|
|
|
@ -91,6 +91,9 @@ void delete_each(T* t)
|
|||
delete *it;
|
||||
}
|
||||
|
||||
std::string extract_ip(const std::string& i);
|
||||
std::string extract_ip_and_len(const std::string& i, int* len);
|
||||
|
||||
std::string get_unescaped_string(const std::string& str);
|
||||
std::string get_escaped_string(const std::string& str, bool escape_all);
|
||||
|
||||
|
|
|
@ -13,3 +13,5 @@ IPv6 address not case-sensitive (PASS)
|
|||
size of IPv6 address (PASS)
|
||||
IPv6 address type inference (PASS)
|
||||
IPv4 and IPv6 address inequality (PASS)
|
||||
IPv4-mapped-IPv6 equality to IPv4 (PASS)
|
||||
IPv4-mapped-IPv6 is IPv4 (PASS)
|
||||
|
|
|
@ -10,3 +10,11 @@ IPv6 subnet !in operator (PASS)
|
|||
IPv6 subnet type inference (PASS)
|
||||
IPv4 and IPv6 subnet inequality (PASS)
|
||||
IPv4 address and IPv6 subnet (PASS)
|
||||
IPv4 in IPv4-mapped-IPv6 subnet (PASS)
|
||||
IPv6 !in IPv4-mapped-IPv6 subnet (PASS)
|
||||
IPv4-mapped-IPv6 in IPv4-mapped-IPv6 subnet (PASS)
|
||||
IPv4-mapped-IPv6 subnet equality (PASS)
|
||||
subnet literal const whitespace (PASS)
|
||||
subnet literal const whitespace (PASS)
|
||||
subnet literal const whitespace (PASS)
|
||||
subnet literal const whitespace (PASS)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# @TEST-EXEC: bro %INPUT >out
|
||||
# @TEST-EXEC: bro -b %INPUT >out
|
||||
# @TEST-EXEC: btest-diff out
|
||||
|
||||
function test_case(msg: string, expect: bool)
|
||||
|
@ -43,5 +43,10 @@ event bro_init()
|
|||
|
||||
test_case( "IPv4 and IPv6 address inequality", a1 != b1 );
|
||||
|
||||
# IPv4-mapped-IPv6 (internally treated as IPv4)
|
||||
local c1: addr = [::ffff:1.2.3.4];
|
||||
|
||||
test_case( "IPv4-mapped-IPv6 equality to IPv4", c1 == 1.2.3.4 );
|
||||
test_case( "IPv4-mapped-IPv6 is IPv4", is_v4_addr(c1) == T );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# @TEST-EXEC: bro %INPUT >out
|
||||
# @TEST-EXEC: bro -b %INPUT >out
|
||||
# @TEST-EXEC: btest-diff out
|
||||
|
||||
function test_case(msg: string, expect: bool)
|
||||
|
@ -43,5 +43,22 @@ event bro_init()
|
|||
test_case( "IPv4 and IPv6 subnet inequality", s1 != t1 );
|
||||
test_case( "IPv4 address and IPv6 subnet", a1 !in t2 );
|
||||
|
||||
# IPv4-mapped-IPv6 subnets
|
||||
local u1: subnet = [::ffff:0:0]/96;
|
||||
|
||||
test_case( "IPv4 in IPv4-mapped-IPv6 subnet", 1.2.3.4 in u1 );
|
||||
test_case( "IPv6 !in IPv4-mapped-IPv6 subnet", [fe80::1] !in u1 );
|
||||
test_case( "IPv4-mapped-IPv6 in IPv4-mapped-IPv6 subnet",
|
||||
[::ffff:1.2.3.4] in u1 );
|
||||
test_case( "IPv4-mapped-IPv6 subnet equality",
|
||||
[::ffff:1.2.3.4]/112 == 1.2.0.0/16 );
|
||||
test_case( "subnet literal const whitespace",
|
||||
[::ffff:1.2.3.4] / 112 == 1.2.0.0 / 16 );
|
||||
test_case( "subnet literal const whitespace",
|
||||
[::ffff:1.2.3.4]/ 128 == 1.2.3.4/ 32 );
|
||||
test_case( "subnet literal const whitespace",
|
||||
[::ffff:1.2.3.4] /96 == 1.2.3.4 /0 );
|
||||
test_case( "subnet literal const whitespace",
|
||||
[::ffff:1.2.3.4] / 92 == [::fffe:1.2.3.4] / 92 );
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue