From: Francis Dupont Date: Thu, 26 Nov 2015 14:20:12 +0000 (+0100) Subject: [4204fd] Applied my proposed changes X-Git-Tag: trac4204fd_reverted~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c4cd450f033dd9806c7dced9e4878d1b33adf3f6;p=thirdparty%2Fkea.git [4204fd] Applied my proposed changes --- diff --git a/doc/guide/classify.xml b/doc/guide/classify.xml index 02317cb95a..b6916de425 100644 --- a/doc/guide/classify.xml +++ b/doc/guide/classify.xml @@ -161,7 +161,7 @@ Hex String0XABCDA hexadecimal string Integer123An integer value Option Textoption[code].textThe value of the option with code "code" from the packet as text -Option Hexoption[code].hexThe value of the option with code "code" from the packet as hex +Option Binoption[code].binThe value of the option with code "code" from the packet as binary @@ -178,8 +178,8 @@ "option[code]" extracts the value of the option with the given code from the incoming packet. If the packet doesn't contain the option, it - returns the empty string. The string can be presented as text or hex - with the ".text" or ".hex" modifiers. In both cases only the payload + returns the empty string. The string can be presented as text or binary + with the ".text" or ".bin" modifiers. In both cases only the payload is presented; the type code and length fields are not included. @@ -297,7 +297,7 @@ "client-classes": [ { "name": "Client_enterprise", - "test": "substring(option[2].hex,0,6) == 0x0002AABBCCDD'", + "test": "substring(option[2].bin,0,6) == 0x0002AABBCCDD'", "option-data": [ { "name": "dns-servers", @@ -370,7 +370,7 @@ "client-classes": [ { "name": "Client_enterprise", - "test": "substring(option[2].hex,0,6) == 0x0002AABBCCDD'", + "test": "substring(option[2].bin,0,6) == 0x0002AABBCCDD'", "option-data": [ { "name": "dns-servers", diff --git a/doc/guide/dhcp6-srv.xml b/doc/guide/dhcp6-srv.xml index f95f254dc1..e7c8fc20e4 100644 --- a/doc/guide/dhcp6-srv.xml +++ b/doc/guide/dhcp6-srv.xml @@ -1615,7 +1615,7 @@ should include options from the isc option space: "client-classes": [ { "name": "Client_enterprise", - "test": "substring(option[2].hex,0,6) == 0x0002AABBCCDD'", + "test": "substring(option[2].bin,0,6) == 0x0002AABBCCDD'", "option-data": [ { "name": "dns-servers", diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index b798b84b5f..e944c0ac49 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -1766,6 +1766,101 @@ TEST_F(Dhcpv4SrvTest, matchClassification) { EXPECT_FALSE(opt3); } +// Checks if client packets are classified properly using match expressions +// using option names +TEST_F(Dhcpv4SrvTest, matchClassificationOptionName) { + NakedDhcpv4Srv srv(0); + + // The router class matches incoming packets with foo in a host-name + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ] }, " + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"valid-lifetime\": 4000, " + "\"subnet4\": [ " + "{ \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ], " + " \"subnet\": \"192.0.2.0/24\" } ], " + "\"client-classes\": [ " + "{ \"name\": \"router\", " + " \"test\": \"option[host-name].text == 'foo'\" } ] }"; + + ElementPtr json = Element::fromJSON(config); + ConstElementPtr status; + + // Configure the server and make sure the config is accepted + EXPECT_NO_THROW(status = configureDhcp4Server(srv, json)); + ASSERT_TRUE(status); + comment_ = config::parseAnswer(rcode_, status); + ASSERT_EQ(0, rcode_); + + CfgMgr::instance().commit(); + + // Create a packet with enough to select the subnet + Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 1234)); + query->setRemoteAddr(IOAddress("192.0.2.1")); + + // Create and add a host-name option to the query + OptionStringPtr hostname(new OptionString(Option::V4, 12, "foo")); + ASSERT_TRUE(hostname); + query->addOption(hostname); + + // Classify packets + srv.classifyPacket(query); + + // The queey should be in the router class + EXPECT_TRUE(query->inClass("router")); +} + +// Checks if client packets are classified properly using match expressions +// using option names and definitions +TEST_F(Dhcpv4SrvTest, matchClassificationOptionDef) { + NakedDhcpv4Srv srv(0); + + // The router class matches incoming packets with foo in a defined + // option + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ] }, " + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"valid-lifetime\": 4000, " + "\"subnet4\": [ " + "{ \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ], " + " \"subnet\": \"192.0.2.0/24\" } ], " + "\"client-classes\": [ " + "{ \"name\": \"router\", " + " \"test\": \"option[my-host-name].text == 'foo'\" } ], " + "\"option-def\": [ {" + " \"name\": \"my-host-name\", " + " \"code\": 250, " + " \"type\": \"string\" } ] }"; + + ElementPtr json = Element::fromJSON(config); + ConstElementPtr status; + + // Configure the server and make sure the config is accepted + EXPECT_NO_THROW(status = configureDhcp4Server(srv, json)); + ASSERT_TRUE(status); + comment_ = config::parseAnswer(rcode_, status); + ASSERT_EQ(0, rcode_); + + CfgMgr::instance().commit(); + + // Create a packet with enough to select the subnet + Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 1234)); + query->setRemoteAddr(IOAddress("192.0.2.1")); + + // Create and add a my-host-name option to the query + OptionStringPtr hostname(new OptionString(Option::V4, 250, "foo")); + ASSERT_TRUE(hostname); + query->addOption(hostname); + + // Classify packets + srv.classifyPacket(query); + + // The queey should be in the router class + EXPECT_TRUE(query->inClass("router")); +} + // Checks subnet options have the priority over class options TEST_F(Dhcpv4SrvTest, subnetClassPriority) { IfaceMgrTestConfig test_config(true); diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc index e3b0f3372b..62220082fa 100644 --- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc @@ -1837,6 +1837,7 @@ TEST_F(Dhcpv6SrvTest, docsisClientClassification) { } // Checks if client packets are classified properly using match expressions. +// Note option names and definitions are used. TEST_F(Dhcpv6SrvTest, matchClassification) { IfaceMgrTestConfig test_config(true); @@ -1866,7 +1867,7 @@ TEST_F(Dhcpv6SrvTest, matchClassification) { " \"option-data\": [" " { \"name\": \"ipv6-forwarding\", " " \"data\": \"true\" } ], " - " \"test\": \"option[1234].text == 'foo'\" } ] }"; + " \"test\": \"option[host-name].text == 'foo'\" } ] }"; ASSERT_NO_THROW(configure(config)); // Create packets with enough to select the subnet diff --git a/src/lib/dhcp/option.cc b/src/lib/dhcp/option.cc index 4caf4bb488..c571a9f43e 100644 --- a/src/lib/dhcp/option.cc +++ b/src/lib/dhcp/option.cc @@ -229,7 +229,7 @@ Option::toBinary(const bool include_header) { pack(buf); } catch (const std::exception &ex) { - isc_throw(OutOfRange, "unable to obtain hexadecimal representation" + isc_throw(OutOfRange, "unable to obtain binary representation" " of option " << getType() << ": " << ex.what()); } const uint8_t* option_data = static_cast(buf.getData()); diff --git a/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc b/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc index eb71b2c551..ed2e36e433 100644 --- a/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc +++ b/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc @@ -182,19 +182,19 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName4) { "hundred4"); } -// Verifies that given a valid expression using .hex operator for option, the +// Verifies that given a valid expression using .bin operator for option, the // ExpressionParser produces an Expression which can be evaluated against // a v4 packet. -TEST_F(ExpressionParserTest, validExpressionWithHex4) { - testValidExpression(Option::V4, "\"option[12].hex == 0x68756E6472656434\"", +TEST_F(ExpressionParserTest, validExpressionWithBin4) { + testValidExpression(Option::V4, "\"option[12].bin == 0x68756E6472656434\"", "hundred4"); } -// Verifies that the option name can be used together with .hex operator in +// Verifies that the option name can be used together with .bin operator in // the evaluated expression. -TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex4) { +TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndBin4) { testValidExpression(Option::V4, - "\"option[host-name].text == 0x68756E6472656434\"", + "\"option[host-name].bin == 0x68756E6472656434\"", "hundred4"); } @@ -212,19 +212,19 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName6) { "hundred6"); } -// Verifies that given a valid expression using .hex operator for option, the +// Verifies that given a valid expression using .bin operator for option, the // ExpressionParser produces an Expression which can be evaluated against // a v6 packet. -TEST_F(ExpressionParserTest, validExpressionWithHex6) { - testValidExpression(Option::V6, "\"option[59].hex == 0x68756E6472656436\"", +TEST_F(ExpressionParserTest, validExpressionWithBin6) { + testValidExpression(Option::V6, "\"option[59].bin == 0x68756E6472656436\"", "hundred6"); } -// Verifies that the option name can be used together with .hex operator in +// Verifies that the option name can be used together with .bin operator in // the evaluated expression. -TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex6) { +TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndBin6) { testValidExpression(Option::V6, - "\"option[bootfile-url].text == 0x68756E6472656436\"", + "\"option[bootfile-url].bin == 0x68756E6472656436\"", "hundred6"); } diff --git a/src/lib/eval/eval.dox b/src/lib/eval/eval.dox index 8ab107a5a8..f8c3cd31fa 100644 --- a/src/lib/eval/eval.dox +++ b/src/lib/eval/eval.dox @@ -85,9 +85,9 @@ 19. TokenPtr opt(new TokenOption($3, TokenOption::TEXTUAL)); 20. ctx.expression.push_back(opt); 21. } -22. | OPTION '[' INTEGER ']' DOT HEX +22. | OPTION '[' INTEGER ']' DOT BIN 23. { -24. TokenPtr opt(new TokenOption($3, TokenOption::HEXADECIMAL)); +24. TokenPtr opt(new TokenOption($3, TokenOption::BINARY)); 25. ctx.expression.push_back(opt); 26. } 27. ; @@ -99,7 +99,7 @@ single token or an expression "token == token" (EQUAL has been defined as "==" elsewhere). Token is further defined in lines 7-22: it may either be a string (lines 7-11), a hex string (lines 12-16), option in the textual format (lines 17-21) -or option in a hexadecimal format (lines 22-26). +or option in the binary format (lines 22-26). When the actual case is determined, the respective C++ action is executed. For example, if the token is a string, the TokenString class is instantiated with the appropriate value and put onto the expression vector. diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index 35653efe6a..b579e13658 100644 --- a/src/lib/eval/lexer.cc +++ b/src/lib/eval/lexer.cc @@ -18,7 +18,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 +#define YY_FLEX_SUBMINOR_VERSION 39 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -72,7 +72,6 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; -typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; @@ -80,7 +79,6 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -111,6 +109,8 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif +#endif /* ! C99 */ + #endif /* ! FLEXINT_H */ /* %endif */ @@ -225,11 +225,18 @@ extern FILE *yyin, *yyout; */ #define YY_LESS_LINENO(n) \ do { \ - yy_size_t yyl;\ + int yyl;\ for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ }while(0) + #define YY_LINENO_REWIND_TO(dst) \ + do {\ + const char *p;\ + for ( p = yy_cp-1; p >= (dst); --p)\ + if ( *p == '\n' )\ + --yylineno;\ + }while(0) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ @@ -420,7 +427,7 @@ void yyfree (void * ); /* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ /* Begin user sect3 */ -#define yywrap(n) 1 +#define yywrap() 1 #define YY_SKIP_YYWRAP #define FLEX_DEBUG @@ -438,6 +445,8 @@ int yylineno = 1; extern char *yytext; #define yytext_ptr yytext +/* %% [1.5] DFA */ + /* %if-c-only Standard (non-C++) definition */ static yy_state_type yy_get_previous_state (void ); @@ -453,7 +462,7 @@ static void yy_fatal_error (yyconst char msg[] ); #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ - yyleng = (yy_size_t) (yy_cp - yy_bp); \ + yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ @@ -469,27 +478,27 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_acclist[84] = +static yyconst flex_int16_t yy_acclist[90] = { 0, 21, 19, 20, 1, 19, 20, 2, 20, 19, 20, - 13, 19, 20, 14, 19, 20, 17, 19, 20, 19, - 20, 12, 19, 20, 5, 19, 20, 5, 19, 20, - 19, 20, 19, 20, 15, 19, 20, 16, 19, 20, - 19, 20, 19, 20, 19, 20, 19, 20, 19, 20, - 1, 2, 3, 5, 6,16402,16402,16402,16402,16402, - 16402, 4, 8210, 11,16402, 9,16402,16402,16402,16402, - 16402,16402, 8,16402,16402,16402, 7,16402,16402,16402, - 16402, 10,16402 + 14, 19, 20, 15, 19, 20, 18, 19, 20, 19, + 20, 13, 19, 20, 5, 19, 20, 5, 19, 20, + 19, 20, 19, 20,16390, 16, 19, 20, 17, 19, + 20, 19, 20,16390, 19, 20,16390, 19, 20,16390, + 19, 20,16390, 19, 20,16390, 1, 2, 3, 5, + 7,16390, 8198,16390,16390,16390,16390,16390, 4, 12, + 16390, 10,16390,16390,16390,16390,16390,16390, 9,16390, + 16390,16390, 8,16390,16390,16390,16390, 11,16390 } ; -static yyconst flex_int16_t yy_accept[57] = +static yyconst flex_int16_t yy_accept[58] = { 0, 1, 1, 1, 2, 4, 7, 9, 11, 14, 17, - 20, 22, 25, 28, 31, 33, 35, 38, 41, 43, - 45, 47, 49, 51, 52, 53, 53, 54, 55, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 63, 64, - 66, 68, 69, 70, 71, 72, 73, 75, 76, 77, - 79, 80, 81, 82, 84, 84 + 20, 22, 25, 28, 31, 33, 36, 39, 42, 45, + 48, 51, 54, 57, 58, 59, 59, 60, 61, 61, + 62, 62, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 72, 74, 75, 76, 77, 78, 79, 81, 82, + 83, 85, 86, 87, 88, 90, 90 } ; static yyconst flex_int32_t yy_ec[256] = @@ -505,8 +514,8 @@ static yyconst flex_int32_t yy_ec[256] = 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 16, 1, 17, 1, 18, 1, 19, 20, 13, 13, - 21, 13, 22, 23, 24, 14, 14, 25, 14, 26, - 27, 28, 14, 29, 30, 31, 32, 14, 14, 33, + 21, 13, 22, 14, 23, 14, 14, 24, 14, 25, + 26, 27, 14, 28, 29, 30, 31, 14, 14, 32, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -524,74 +533,72 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[34] = +static yyconst flex_int32_t yy_meta[33] = { 0, - 1, 1, 2, 1, 1, 1, 1, 3, 1, 4, - 4, 1, 4, 3, 3, 1, 1, 3, 4, 4, - 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3 + 1, 2, 3, 1, 1, 1, 1, 2, 1, 4, + 4, 1, 4, 2, 2, 1, 2, 2, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2 } ; -static yyconst flex_int16_t yy_base[59] = +static yyconst flex_int16_t yy_base[60] = { 0, - 0, 0, 121, 122, 118, 116, 110, 122, 122, 122, - 24, 122, 26, 28, 98, 0, 122, 122, 77, 79, - 67, 61, 63, 68, 50, 47, 122, 32, 0, 122, - 38, 43, 44, 45, 46, 47, 0, 48, 122, 50, - 52, 54, 55, 56, 72, 73, 77, 79, 80, 81, - 84, 86, 89, 90, 122, 112, 114, 40 + 0, 0, 113, 114, 110, 108, 106, 114, 114, 114, + 23, 114, 25, 27, 97, 37, 114, 114, 56, 18, + 19, 20, 26, 106, 104, 102, 114, 38, 0, 114, + 50, 51, 81, 114, 80, 35, 32, 41, 39, 0, + 79, 78, 46, 48, 52, 55, 54, 76, 61, 59, + 73, 65, 66, 70, 69, 114, 94, 97, 62 } ; -static yyconst flex_int16_t yy_def[59] = +static yyconst flex_int16_t yy_def[60] = { 0, - 55, 1, 55, 55, 55, 55, 56, 55, 55, 55, - 55, 55, 55, 55, 55, 57, 55, 55, 57, 57, - 57, 57, 57, 55, 55, 56, 55, 55, 58, 55, - 57, 57, 57, 57, 57, 57, 58, 55, 55, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 0, 55, 55, 55 + 56, 1, 56, 56, 56, 56, 57, 56, 56, 56, + 56, 56, 56, 56, 56, 58, 56, 56, 58, 19, + 19, 19, 19, 56, 56, 57, 56, 56, 59, 56, + 56, 19, 19, 56, 19, 19, 19, 19, 19, 59, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 56, 56, 56 } ; -static yyconst flex_int16_t yy_nxt[156] = +static yyconst flex_int16_t yy_nxt[147] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 16, 16, 17, 18, 4, 19, 16, - 16, 16, 20, 16, 16, 16, 21, 16, 16, 22, - 23, 16, 16, 28, 28, 28, 28, 28, 28, 38, - 29, 28, 28, 37, 38, 38, 38, 38, 38, 38, - 27, 38, 25, 38, 39, 38, 38, 38, 29, 39, - 39, 39, 39, 39, 39, 43, 39, 40, 39, 24, - 39, 39, 39, 38, 38, 42, 41, 45, 38, 44, - 38, 38, 38, 36, 46, 38, 47, 38, 39, 39, - 38, 38, 35, 39, 34, 39, 39, 39, 48, 33, - - 39, 32, 39, 49, 50, 39, 39, 52, 51, 30, - 54, 53, 26, 27, 26, 26, 31, 31, 25, 24, - 55, 3, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55 + 14, 15, 16, 16, 16, 17, 18, 4, 19, 20, + 16, 16, 16, 16, 16, 21, 16, 16, 22, 23, + 16, 16, 28, 28, 28, 28, 28, 28, 31, 29, + 36, 33, 33, 33, 32, 37, 39, 28, 28, 33, + 38, 31, 56, 34, 32, 33, 29, 31, 33, 42, + 44, 43, 33, 32, 33, 40, 34, 56, 46, 33, + 45, 33, 34, 32, 33, 33, 47, 33, 33, 35, + 49, 48, 33, 50, 33, 51, 52, 53, 33, 33, + 54, 55, 33, 33, 26, 26, 33, 26, 33, 33, + + 33, 33, 33, 41, 33, 27, 25, 24, 30, 27, + 25, 24, 56, 3, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56 } ; -static yyconst flex_int16_t yy_chk[156] = +static yyconst flex_int16_t yy_chk[147] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 11, 11, 13, 13, 14, 14, 31, - 13, 28, 28, 58, 32, 33, 34, 35, 36, 38, - 26, 40, 25, 41, 31, 42, 43, 44, 13, 32, - 33, 34, 35, 36, 38, 35, 40, 32, 41, 24, - 42, 43, 44, 45, 46, 34, 33, 42, 47, 36, - 48, 49, 50, 23, 43, 51, 44, 52, 45, 46, - 53, 54, 22, 47, 21, 48, 49, 50, 45, 20, - - 51, 19, 52, 46, 48, 53, 54, 51, 49, 15, - 53, 52, 56, 7, 56, 56, 57, 57, 6, 5, - 3, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55 + 1, 1, 11, 11, 13, 13, 14, 14, 16, 13, + 20, 20, 21, 22, 16, 21, 23, 28, 28, 23, + 22, 31, 32, 16, 16, 37, 13, 19, 36, 36, + 38, 37, 39, 19, 38, 59, 31, 32, 43, 43, + 39, 44, 19, 19, 32, 45, 44, 47, 46, 19, + 46, 45, 50, 47, 49, 49, 50, 52, 52, 53, + 53, 54, 55, 54, 57, 57, 51, 57, 58, 48, + + 58, 42, 41, 35, 33, 26, 25, 24, 15, 7, + 6, 5, 3, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56 } ; /* Table of booleans, true if rule could match eol. */ @@ -605,8 +612,8 @@ int yy_flex_debug = 1; static yyconst flex_int16_t yy_rule_linenum[20] = { 0, - 83, 87, 93, 103, 109, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 136, 143 + 83, 87, 93, 103, 109, 123, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 143 } ; static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; @@ -688,7 +695,7 @@ static isc::eval::location loc; // by moving it ahead by yyleng bytes. yyleng specifies the length of the // currently matched token. #define YY_USER_ACTION loc.columns(yyleng); -#line 692 "lexer.cc" +#line 699 "lexer.cc" #define INITIAL 0 @@ -806,7 +813,7 @@ static int input (void ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO fwrite( yytext, yyleng, 1, yyout ) +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) /* %endif */ /* %if-c++-only C++ definition */ /* %endif */ @@ -821,7 +828,7 @@ static int input (void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - yy_size_t n; \ + size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -927,17 +934,6 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -/* %% [7.0] user's declarations go here */ -#line 76 "lexer.ll" - - - - // Code run each time yylex is called. - loc.step(); - - -#line 940 "lexer.cc" - if ( !(yy_init) ) { (yy_init) = 1; @@ -978,6 +974,18 @@ YY_DECL yy_load_buffer_state( ); } + { +/* %% [7.0] user's declarations go here */ +#line 76 "lexer.ll" + + + + // Code run each time yylex is called. + loc.step(); + + +#line 988 "lexer.cc" + while ( 1 ) /* loops until end-of-file is reached */ { /* %% [8.0] yymore()-related code goes here */ @@ -1000,24 +1008,23 @@ YY_DECL yy_match: do { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 56 ) + if ( yy_current_state >= 57 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; *(yy_state_ptr)++ = yy_current_state; ++yy_cp; } - while ( yy_current_state != 55 ); + while ( yy_current_state != 56 ); yy_find_action: /* %% [10.0] code to find the action number goes here */ yy_current_state = *--(yy_state_ptr); (yy_lp) = yy_accept[yy_current_state]; -goto find_rule; /* Shut up GCC warning -Wall */ find_rule: /* we branch to this label when backing up */ for ( ; ; ) /* until we find what rule we matched */ { @@ -1150,72 +1157,72 @@ YY_RULE_SETUP case 6: YY_RULE_SETUP #line 123 "lexer.ll" -return isc::eval::EvalParser::make_EQUAL(loc); +{ + // This string specifies option name starting with a letter + // and further containing letters, digits, hyphens and + // underscores and finishing by letters or digits. + return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc); +} YY_BREAK case 7: YY_RULE_SETUP -#line 124 "lexer.ll" -return isc::eval::EvalParser::make_OPTION(loc); +#line 130 "lexer.ll" +return isc::eval::EvalParser::make_EQUAL(loc); YY_BREAK case 8: YY_RULE_SETUP -#line 125 "lexer.ll" -return isc::eval::EvalParser::make_TEXT(loc); +#line 131 "lexer.ll" +return isc::eval::EvalParser::make_OPTION(loc); YY_BREAK case 9: YY_RULE_SETUP -#line 126 "lexer.ll" -return isc::eval::EvalParser::make_HEX(loc); +#line 132 "lexer.ll" +return isc::eval::EvalParser::make_TEXT(loc); YY_BREAK case 10: YY_RULE_SETUP -#line 127 "lexer.ll" -return isc::eval::EvalParser::make_SUBSTRING(loc); +#line 133 "lexer.ll" +return isc::eval::EvalParser::make_BIN(loc); YY_BREAK case 11: YY_RULE_SETUP -#line 128 "lexer.ll" -return isc::eval::EvalParser::make_ALL(loc); +#line 134 "lexer.ll" +return isc::eval::EvalParser::make_SUBSTRING(loc); YY_BREAK case 12: YY_RULE_SETUP -#line 129 "lexer.ll" -return isc::eval::EvalParser::make_DOT(loc); +#line 135 "lexer.ll" +return isc::eval::EvalParser::make_ALL(loc); YY_BREAK case 13: YY_RULE_SETUP -#line 130 "lexer.ll" -return isc::eval::EvalParser::make_LPAREN(loc); +#line 136 "lexer.ll" +return isc::eval::EvalParser::make_DOT(loc); YY_BREAK case 14: YY_RULE_SETUP -#line 131 "lexer.ll" -return isc::eval::EvalParser::make_RPAREN(loc); +#line 137 "lexer.ll" +return isc::eval::EvalParser::make_LPAREN(loc); YY_BREAK case 15: YY_RULE_SETUP -#line 132 "lexer.ll" -return isc::eval::EvalParser::make_LBRACKET(loc); +#line 138 "lexer.ll" +return isc::eval::EvalParser::make_RPAREN(loc); YY_BREAK case 16: YY_RULE_SETUP -#line 133 "lexer.ll" -return isc::eval::EvalParser::make_RBRACKET(loc); +#line 139 "lexer.ll" +return isc::eval::EvalParser::make_LBRACKET(loc); YY_BREAK case 17: YY_RULE_SETUP -#line 134 "lexer.ll" -return isc::eval::EvalParser::make_COMA(loc); +#line 140 "lexer.ll" +return isc::eval::EvalParser::make_RBRACKET(loc); YY_BREAK case 18: YY_RULE_SETUP -#line 136 "lexer.ll" -{ - // This string specifies option name starting with a letter - // and further containing letters, digits, hyphens and - // underscores. - return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc); -} +#line 141 "lexer.ll" +return isc::eval::EvalParser::make_COMA(loc); YY_BREAK case 19: YY_RULE_SETUP @@ -1231,7 +1238,7 @@ YY_RULE_SETUP #line 145 "lexer.ll" ECHO; YY_BREAK -#line 1235 "lexer.cc" +#line 1242 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1361,6 +1368,7 @@ ECHO; "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ + } /* end of user's declarations */ } /* end of yylex */ /* %ok-for-header */ @@ -1511,7 +1519,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 56 ) + if ( yy_current_state >= 57 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1539,15 +1547,15 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 56 ) + if ( yy_current_state >= 57 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 55); + yy_is_jam = (yy_current_state == 56); if ( ! yy_is_jam ) *(yy_state_ptr)++ = yy_current_state; - return yy_is_jam ? 0 : yy_current_state; + return yy_is_jam ? 0 : yy_current_state; } /* %if-c-only */ @@ -1606,7 +1614,7 @@ static int yy_get_next_buffer (void) case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) - return 0; + return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; @@ -1770,17 +1778,6 @@ static void yy_load_buffer_state (void) yyfree((void *) b ); } -/* %if-c-only */ - -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* %endif */ - -/* %if-c++-only */ -/* %endif */ - /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. @@ -2021,8 +2018,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) /* %if-c-only */ /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ @@ -2030,7 +2027,8 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len { YY_BUFFER_STATE b; char *buf; - yy_size_t n, i; + yy_size_t n; + yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index c037874115..39830c9a02 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -120,10 +120,17 @@ blank [ \t] return isc::eval::EvalParser::make_INTEGER(tmp, loc); } +[A-Za-z]([-_A-Za-z0-9]*[A-Za-z0-9])?/{blank}*] { + // This string specifies option name starting with a letter + // and further containing letters, digits, hyphens and + // underscores and finishing by letters or digits. + return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc); +} + "==" return isc::eval::EvalParser::make_EQUAL(loc); "option" return isc::eval::EvalParser::make_OPTION(loc); "text" return isc::eval::EvalParser::make_TEXT(loc); -"hex" return isc::eval::EvalParser::make_HEX(loc); +"bin" return isc::eval::EvalParser::make_BIN(loc); "substring" return isc::eval::EvalParser::make_SUBSTRING(loc); "all" return isc::eval::EvalParser::make_ALL(loc); "." return isc::eval::EvalParser::make_DOT(loc); @@ -133,13 +140,6 @@ blank [ \t] "]" return isc::eval::EvalParser::make_RBRACKET(loc); "," return isc::eval::EvalParser::make_COMA(loc); -[A-Za-z][A-Za-z0-9_\-]+/{blank}*] { - // This string specifies option name starting with a letter - // and further containing letters, digits, hyphens and - // underscores. - return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc); -} - . driver.error (loc, "Invalid character: " + std::string(yytext)); <> return isc::eval::EvalParser::make_END(loc); %% diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index 46f902eb45..85325455a7 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -643,7 +643,7 @@ namespace isc { namespace eval { #line 134 "parser.yy" // lalr1.cc:859 { uint16_t numeric_code = convert_option_code(yystack_[3].value.as< std::string > (), yystack_[3].location, ctx); - TokenPtr opt(new TokenOption(numeric_code, TokenOption::HEXADECIMAL)); + TokenPtr opt(new TokenOption(numeric_code, TokenOption::BINARY)); ctx.expression.push_back(opt); } #line 650 "parser.cc" // lalr1.cc:859 @@ -659,7 +659,7 @@ namespace isc { namespace eval { TokenOption::TEXTUAL)); ctx.expression.push_back(opt); - } catch (const std::exception& ex) { + } catch (const isc::BadValue& ex) { ctx.error(yystack_[3].location, ex.what()); } } @@ -673,10 +673,10 @@ namespace isc { namespace eval { // This may result in exception if the specified // name is unknown. TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), option_universe, - TokenOption::HEXADECIMAL)); + TokenOption::BINARY)); ctx.expression.push_back(opt); - } catch (const std::exception& ex) { + } catch (const isc::BadValue& ex) { ctx.error(yystack_[3].location, ex.what()); } } @@ -1058,7 +1058,7 @@ namespace isc { namespace eval { const EvalParser::yytname_[] = { "\"end of file\"", "error", "$undefined", "\"==\"", "\"option\"", - "\"substring\"", "\"text\"", "\"hex\"", "\"all\"", "\".\"", "\",\"", + "\"substring\"", "\"text\"", "\"bin\"", "\"all\"", "\".\"", "\",\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", "\"constant string\"", "\"integer\"", "\"constant hexstring\"", "\"option name\"", "TOKEN", "$accept", "expression", "bool_expr", "string_expr", "start_expr", "length_expr", YY_NULLPTR diff --git a/src/lib/eval/parser.h b/src/lib/eval/parser.h index 309daf747f..5e65956dcd 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -328,7 +328,7 @@ namespace isc { namespace eval { TOKEN_OPTION = 259, TOKEN_SUBSTRING = 260, TOKEN_TEXT = 261, - TOKEN_HEX = 262, + TOKEN_BIN = 262, TOKEN_ALL = 263, TOKEN_DOT = 264, TOKEN_COMA = 265, @@ -469,7 +469,7 @@ namespace isc { namespace eval { static inline symbol_type - make_HEX (const location_type& l); + make_BIN (const location_type& l); static inline symbol_type @@ -1021,9 +1021,9 @@ namespace isc { namespace eval { } EvalParser::symbol_type - EvalParser::make_HEX (const location_type& l) + EvalParser::make_BIN (const location_type& l) { - return symbol_type (token::TOKEN_HEX, l); + return symbol_type (token::TOKEN_BIN, l); } EvalParser::symbol_type diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index e462cb63d6..fca13da948 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -51,7 +51,7 @@ using namespace isc::eval; OPTION "option" SUBSTRING "substring" TEXT "text" - HEX "hex" + BIN "bin" ALL "all" DOT "." COMA "," @@ -130,10 +130,10 @@ string_expr : STRING TokenPtr opt(new TokenOption(numeric_code, TokenOption::TEXTUAL)); ctx.expression.push_back(opt); } - | OPTION "[" INTEGER "]" DOT HEX + | OPTION "[" INTEGER "]" DOT BIN { uint16_t numeric_code = convert_option_code($3, @3, ctx); - TokenPtr opt(new TokenOption(numeric_code, TokenOption::HEXADECIMAL)); + TokenPtr opt(new TokenOption(numeric_code, TokenOption::BINARY)); ctx.expression.push_back(opt); } | OPTION "[" OPTION_NAME "]" DOT TEXT @@ -145,20 +145,20 @@ string_expr : STRING TokenOption::TEXTUAL)); ctx.expression.push_back(opt); - } catch (const std::exception& ex) { + } catch (const isc::BadValue& ex) { ctx.error(@3, ex.what()); } } - | OPTION "[" OPTION_NAME "]" DOT HEX + | OPTION "[" OPTION_NAME "]" DOT BIN { try { // This may result in exception if the specified // name is unknown. TokenPtr opt(new TokenOption($3, option_universe, - TokenOption::HEXADECIMAL)); + TokenOption::BINARY)); ctx.expression.push_back(opt); - } catch (const std::exception& ex) { + } catch (const isc::BadValue& ex) { ctx.error(@3, ex.what()); } } diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index a305d76286..9be0a4ad2b 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -227,11 +227,11 @@ TEST_F(EvalContextTest, optionWithNameAndWhitespace) { checkTokenOption(eval.expression.at(0), 12); } -// Test parsing of an option represented as hexadecimal string. -TEST_F(EvalContextTest, optionHex) { +// Test parsing of an option represented as binary string. +TEST_F(EvalContextTest, optionBin) { EvalContext eval(Option::V4); - EXPECT_NO_THROW(parsed_ = eval.parseString("option[123].hex == 0x666F6F")); + EXPECT_NO_THROW(parsed_ = eval.parseString("option[123].bin == 0x666F6F")); EXPECT_TRUE(parsed_); ASSERT_EQ(3, eval.expression.size()); checkTokenOption(eval.expression.at(0), 123); @@ -292,6 +292,11 @@ TEST_F(EvalContextTest, scanParseErrors) { " expecting ."); checkError("option[123].text < 'foo'", ":1.18: Invalid" " character: <"); + checkError("option[-ab].text", ":1.8: Invalid character: -"); + checkError("option[0ab].text", + ":1.9-10: syntax error, unexpected option name, " + "expecting ]"); + checkError("option[ab_].bin", ":1.8: Invalid character: a"); checkError("substring('foo',12345678901234567890,1)", ":1.17-36: Failed to convert 12345678901234567890 " "to an integer."); @@ -311,6 +316,10 @@ TEST_F(EvalContextTest, parseErrors) { checkError("option(10) == 'ab'", ":1.7: syntax error, " "unexpected (, expecting ["); + checkError("option['ab'].text == 'foo'", + ":1.8-11: syntax error, " + "unexpected constant string, " + "expecting integer or option name"); checkError("option[ab].text == 'foo'", ":1.8-9: option 'ab' is not defined"); checkError("option[0xa].text == 'ab'", diff --git a/src/lib/eval/tests/evaluate_unittest.cc b/src/lib/eval/tests/evaluate_unittest.cc index d404b12830..ccd6e227b6 100644 --- a/src/lib/eval/tests/evaluate_unittest.cc +++ b/src/lib/eval/tests/evaluate_unittest.cc @@ -209,13 +209,13 @@ TEST_F(EvaluateTest, packet) { EXPECT_FALSE(result_); } -// A test which compares option value represented in hexadecimal format. +// A test which compares option value represented in binary format. TEST_F(EvaluateTest, optionHex) { TokenPtr toption; TokenPtr tstring; TokenPtr tequal; - ASSERT_NO_THROW(toption.reset(new TokenOption(100, TokenOption::HEXADECIMAL))); + ASSERT_NO_THROW(toption.reset(new TokenOption(100, TokenOption::BINARY))); e_.push_back(toption); ASSERT_NO_THROW(tstring.reset(new TokenString("hundred4"))); e_.push_back(tstring); diff --git a/src/lib/eval/tests/token_unittest.cc b/src/lib/eval/tests/token_unittest.cc index 39ca7f3889..3194933f5b 100644 --- a/src/lib/eval/tests/token_unittest.cc +++ b/src/lib/eval/tests/token_unittest.cc @@ -325,14 +325,14 @@ TEST_F(TokenTest, optionWithNameString4) { // This test checks if a token representing option value is able to extract // the option from an IPv4 packet and properly store its value in a -// hexadecimal format. -TEST_F(TokenTest, optionHexString4) { +// binary format. +TEST_F(TokenTest, optionBinString4) { TokenPtr found; TokenPtr not_found; // The packets we use have option 100 with a string in them. - ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::HEXADECIMAL))); - ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::HEXADECIMAL))); + ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::BINARY))); + ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::BINARY))); // This should evaluate to the content of the option 100 (i.e. "hundred4") ASSERT_NO_THROW(found->evaluate(*pkt4_, values_)); @@ -354,8 +354,8 @@ TEST_F(TokenTest, optionHexString4) { // This test checks if a token representing an option identified by name is // able to extract this option from an IPv4 packet and properly store its -// value in the hexadecimal format. -TEST_F(TokenTest, optionWithNameHexString4) { +// value in the binary format. +TEST_F(TokenTest, optionWithNameBinString4) { // Create definition of option 100 to provide a mapping between option // code and option name. ASSERT_NO_THROW(createOptionDefinitions4()); @@ -364,7 +364,7 @@ TEST_F(TokenTest, optionWithNameHexString4) { // map the option name to its code. TokenPtr token; ASSERT_NO_THROW(token.reset(new TokenOption("name-hundred4", Option::V4, - TokenOption::HEXADECIMAL))); + TokenOption::BINARY))); // Evaluate option in the packet. ASSERT_NO_THROW(token->evaluate(*pkt4_, values_)); @@ -426,15 +426,15 @@ TEST_F(TokenTest, optionWithNameString6) { // This test checks if a token representing an option value is able to extract -// the option from an IPv6 packet and properly store its value in hexadecimal +// the option from an IPv6 packet and properly store its value in binary // format. -TEST_F(TokenTest, optionHexString6) { +TEST_F(TokenTest, optionBinString6) { TokenPtr found; TokenPtr not_found; // The packets we use have option 100 with a string in them. - ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::HEXADECIMAL))); - ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::HEXADECIMAL))); + ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::BINARY))); + ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::BINARY))); // This should evaluate to the content of the option 100 (i.e. "hundred6") ASSERT_NO_THROW(found->evaluate(*pkt6_, values_)); @@ -456,8 +456,8 @@ TEST_F(TokenTest, optionHexString6) { // This test checks if a token representing an option identified by name is // able to extract this option from an IPv6 packet and properly store its -// value in the hexadecimal format. -TEST_F(TokenTest, optionWithNameHexString6) { +// value in the binary format. +TEST_F(TokenTest, optionWithNameBinString6) { // Create definition of option 100 to provide a mapping between option // code and option name. ASSERT_NO_THROW(createOptionDefinitions6()); @@ -466,7 +466,7 @@ TEST_F(TokenTest, optionWithNameHexString6) { // map the option name to its code. TokenPtr token; ASSERT_NO_THROW(token.reset(new TokenOption("name-hundred6", Option::V6, - TokenOption::HEXADECIMAL))); + TokenOption::BINARY))); // Evaluate option in the packet. ASSERT_NO_THROW(token->evaluate(*pkt6_, values_)); diff --git a/src/lib/eval/token.cc b/src/lib/eval/token.cc index 4cbae9568b..0a5a425d07 100644 --- a/src/lib/eval/token.cc +++ b/src/lib/eval/token.cc @@ -93,7 +93,10 @@ TokenOption::evaluate(const Pkt& pkt, ValueStack& values) { opt_str = opt->toString(); } else { std::vector binary = opt->toBinary(); - opt_str.assign(binary.begin(), binary.end()); + opt_str.resize(binary.size()); + if (!binary.empty()) { + memmove(&opt_str[0], &binary[0], binary.size()); + } } } diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h index 4592958a79..870b88b666 100644 --- a/src/lib/eval/token.h +++ b/src/lib/eval/token.h @@ -153,13 +153,13 @@ public: /// @brief Token representation type. /// /// There are many possible ways in which option can be presented. - /// Currently the textual and hexadecimal representations are + /// Currently the textual and binary representations are /// supported. The type of representation is specified in the /// constructor and it affects the value generated by the /// @c TokenOption::evaluate function. enum RepresentationType { TEXTUAL, - HEXADECIMAL + BINARY }; /// @brief Constructor that takes an option code as a parameter @@ -177,6 +177,7 @@ public: /// @param option_name Name of the option to be represented. /// @param option_universe Option universe: DHCPv4 or DHCPv6. /// @param rep_type Token representation type. + /// @throw BadValue when the option_name cannot be resolved TokenOption(const std::string& option_name, const Option::Universe& option_universe, const RepresentationType& rep_type);