2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 21:45:37 +00:00

[master] Finish merge of trac4268a (DHCPv4 fields)

This commit is contained in:
Francis Dupont
2016-04-27 13:32:59 +02:00
11 changed files with 1277 additions and 608 deletions

View File

@@ -1,3 +1,8 @@
1107. [func] fdupont
Added support for extracting constant length fields from a DHCPv4
packet.
(Trac #4268, git xxx)
1106. [func] sar
Added support for accessing DHCPv6 packet fields message type
and transaction id in a classification expression.

View File

@@ -152,56 +152,145 @@
<thead>
<row>
<entry>Name</entry>
<entry>Example</entry>
<entry>Example expression</entry>
<entry>Example value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row><entry>String</entry><entry>'example'</entry><entry>A string</entry></row>
<row><entry>Hex String</entry><entry>0XABCD</entry><entry>A hexadecimal string</entry></row>
<row><entry>IP Address</entry><entry>10.0.0.1</entry><entry>An IP address</entry></row>
<row><entry>Integer</entry><entry>123</entry><entry>An integer value</entry></row>
<row>
<entry>String literal</entry>
<entry>'example'</entry>
<entry>'example'</entry>
<entry>A string</entry>
</row>
<row>
<entry>Hexadecimal string literal</entry>
<entry>0x5a7d</entry>
<entry>'Z}'</entry>
<entry>A hexadecimal string</entry>
</row>
<row>
<entry>IP address literal</entry>
<entry>10.0.0.1</entry>
<entry>0x0a000001</entry>
<entry>An IP address</entry>
</row>
<row>
<entry>Integer literal</entry>
<entry>123</entry>
<entry>'123'</entry>
<entry>An integer value</entry>
</row>
<row></row>
<row>
<entry>Binary content of the option</entry>
<entry>option[123].hex</entry>
<entry>'(content of the option)'</entry>
<entry>The value of the option with given code from the
packet as hex</entry>
</row>
<!-- Text option not fully defined yet, leave it out
<row><entry>Option Text</entry><entry>option[code].text</entry><entry>The value of the option with code "code" from the packet as text</entry></row>
<row>
<entry>Option Text</entry>
<entry>option[123].text</entry>
<entry>'foobar'</entry>
<entry>The value of the option with given code from the
packet as text</entry>
</row>
-->
<row><entry>Option Hex</entry><entry>option[code].hex</entry><entry>The value of the option with code "code" from the packet as hex</entry></row>
<row><entry>Option Exist</entry><entry>option[code].exist</entry><entry>If the option with code "code" is present in the packet "true" else "false"</entry></row>
<row><entry>DHCPv4 Relay Agent
sub-option</entry><entry>relay4[code].hex</entry><entry>The value of
sub-option with code "code" from the DHCPv4 Relay Agent Information option
(option 82)</entry></row>
<row>
<row>
<entry>Option existence</entry>
<entry>option[123].exist</entry>
<entry>'true'</entry>
<entry>If the option with given code is present in the
packet "true" else "false"</entry>
</row>
<row>
<entry>DHCPv4 relay agent sub-option</entry>
<entry>relay4[123].hex</entry>
<entry>'(content of the RAI sub-option)'</entry>
<entry>The value of sub-option with given code from the
DHCPv4 Relay Agent Information option (option 82)</entry>
</row>
<row>
<entry>DHCPv6 Relay Options</entry>
<entry>relay6[nest].option[code].hex</entry>
<!-- <entry>Value of the option</entry> -->
<entry>The value of the option with code "code" from the relay encapsulation "nest"</entry>
</row>
<row>
<!-- <entry>Value of the option</entry> -->
<entry>The value of the option with code "code" from the
relay encapsulation "nest"</entry>
</row>
<row>
<entry>DHCPv6 Relay Peer Address</entry>
<entry>relay6[nest].peeraddr</entry>
<!-- <entry>2001:DB8::1</entry> -->n
<entry>The value of the peer address field from the relay encapsulation "nest"</entry>
</row>
<row>
<!-- <entry>2001:DB8::1</entry> -->n
<entry>The value of the peer address field from the
relay encapsulation "nest"</entry>
</row>
<row>
<entry>DHCPv6 Relay Link Address</entry>
<entry>relay6[nest].linkaddr</entry>
<!-- <entry>2001:DB8::1</entry> -->n
<entry>The value of the link address field from the relay encapsulation "nest"</entry>
</row>
<row>
<!-- <entry>2001:DB8::1</entry> -->n
<entry>The value of the link address field from the
relay encapsulation "nest"</entry>
</row>
<row>
<entry>Hardware address in DHCPv4 packet</entry>
<entry>pkt4.mac</entry>
<entry>0x010203040506</entry>
<entry>The value of the chaddr field of the DHCPv4 packet, hlen (0 to 16) bytes</entry>
</row>
<row>
<entry>Hardware length in DHCPv4 packet</entry>
<entry>pkt4.hlen</entry>
<entry>0x00000006</entry>
<entry>The value of the hlen field of the DHCPv4 packet padded to 4 bytes</entry>
</row>
<row>
<entry>Hardware type in DHCPv4 packet</entry>
<entry>pkt4.htype</entry>
<entry>0x0000007b</entry>
<entry>The value of the htype field of the DHCPv4 packet padded to 4 bytes</entry>
</row>
<row>
<entry>ciaddr field in DHCPv4 packet</entry>
<entry>pkt4.ciaddr</entry>
<entry>192.0.2.1</entry>
<entry>The value of the ciaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
</row>
<row>
<entry>giaddr field in DHCPv4 packet</entry>
<entry>pkt4.giaddr</entry>
<entry>192.0.2.1</entry>
<entry>The value of the giaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
</row>
<row>
<entry>yiaddr field in DHCPv4 packet</entry>
<entry>pkt4.yiaddr</entry>
<entry>192.0.2.1</entry>
<entry>The value of the yiaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
</row>
<row>
<entry>siaddr field in DHCPv4 packet</entry>
<entry>pkt4.siaddr</entry>
<entry>192.0.2.1</entry>
<entry>The value of the siaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
</row>
<row>
<entry>Message Type in DHCPv6 packet</entry>
<entry>pkt6.msgtype</entry>
<!-- <entry>1</entry>
-->
<entry>The value of the message type field in the DHCPv6 packet.</entry>
</row>
<row>
<!-- <entry>1</entry> -->
<entry>The value of the message type field in the DHCPv6
packet.</entry>
</row>
<row>
<entry>Transaction ID in DHCPv6 packet</entry>
<entry>pkt6.transid</entry>
<!-- <entry>12345</entry>
-->
<entry>The value of the transaction id in the DHCPv6 packet.</entry>
</row>
<!-- <entry>12345</entry> -->
<entry>The value of the transaction id in the DHCPv6
packet.</entry>
</row>
</tbody>
</tgroup>
</table>
@@ -221,14 +310,14 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option
</para>
<para>
"option[code].hex" extracts the value of the option with the given code
"option[code].hex" extracts the value of the option with the code "code"
from the incoming packet. If the packet doesn't contain the option, it
returns the empty string. The string is presented as a byte string of
the option payload without the type code or length fields.
</para>
<para>
"option[code].exist" checks if an option with the given code is present
"option[code].exist" checks if an option with the code "code" is present
in the incoming packet. It can be used with empty options.
</para>
@@ -261,6 +350,10 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option
"option", for instance "relay6[nest].option[code].exists" is supported.
</para>
<para>
Expressions starting with pkt4 can be used only in DHCPv4.
</para>
<para>
"pkt6" refers to information from the client request. To access any
information from an intermediate relay use "relay6". "pkt6.msgtype"

File diff suppressed because it is too large Load Diff

View File

@@ -149,6 +149,14 @@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]*
"text" return isc::eval::EvalParser::make_TEXT(loc);
"hex" return isc::eval::EvalParser::make_HEX(loc);
"exists" return isc::eval::EvalParser::make_EXISTS(loc);
"pkt4" return isc::eval::EvalParser::make_PKT4(loc);
"mac" return isc::eval::EvalParser::make_CHADDR(loc);
"hlen" return isc::eval::EvalParser::make_HLEN(loc);
"htype" return isc::eval::EvalParser::make_HTYPE(loc);
"ciaddr" return isc::eval::EvalParser::make_CIADDR(loc);
"giaddr" return isc::eval::EvalParser::make_GIADDR(loc);
"yiaddr" return isc::eval::EvalParser::make_YIADDR(loc);
"siaddr" return isc::eval::EvalParser::make_SIADDR(loc);
"substring" return isc::eval::EvalParser::make_SUBSTRING(loc);
"all" return isc::eval::EvalParser::make_ALL(loc);
"concat" return isc::eval::EvalParser::make_CONCAT(loc);

View File

@@ -251,31 +251,35 @@ namespace isc { namespace eval {
{
switch (that.type_get ())
{
case 37: // option_repr_type
case 45: // option_repr_type
value.move< TokenOption::RepresentationType > (that.value);
break;
case 42: // pkt6_field
case 46: // pkt4_field
value.move< TokenPkt4::FieldType > (that.value);
break;
case 51: // pkt6_field
value.move< TokenPkt6::FieldType > (that.value);
break;
case 40: // relay6_field
case 49: // relay6_field
value.move< TokenRelay6Field::FieldType > (that.value);
break;
case 27: // "constant string"
case 28: // "integer"
case 29: // "constant hexstring"
case 30: // "option name"
case 31: // "ip address"
case 35: // "constant string"
case 36: // "integer"
case 37: // "constant hexstring"
case 38: // "option name"
case 39: // "ip address"
value.move< std::string > (that.value);
break;
case 36: // option_code
case 44: // option_code
value.move< uint16_t > (that.value);
break;
case 41: // nest_level
case 50: // nest_level
value.move< uint8_t > (that.value);
break;
@@ -294,31 +298,35 @@ namespace isc { namespace eval {
state = that.state;
switch (that.type_get ())
{
case 37: // option_repr_type
case 45: // option_repr_type
value.copy< TokenOption::RepresentationType > (that.value);
break;
case 42: // pkt6_field
case 46: // pkt4_field
value.copy< TokenPkt4::FieldType > (that.value);
break;
case 51: // pkt6_field
value.copy< TokenPkt6::FieldType > (that.value);
break;
case 40: // relay6_field
case 49: // relay6_field
value.copy< TokenRelay6Field::FieldType > (that.value);
break;
case 27: // "constant string"
case 28: // "integer"
case 29: // "constant hexstring"
case 30: // "option name"
case 31: // "ip address"
case 35: // "constant string"
case 36: // "integer"
case 37: // "constant hexstring"
case 38: // "option name"
case 39: // "ip address"
value.copy< std::string > (that.value);
break;
case 36: // option_code
case 44: // option_code
value.copy< uint16_t > (that.value);
break;
case 41: // nest_level
case 50: // nest_level
value.copy< uint8_t > (that.value);
break;
@@ -358,74 +366,81 @@ namespace isc { namespace eval {
<< yysym.location << ": ";
switch (yytype)
{
case 27: // "constant string"
case 35: // "constant string"
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 366 "parser.cc" // lalr1.cc:636
#line 374 "parser.cc" // lalr1.cc:636
break;
case 28: // "integer"
case 36: // "integer"
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 373 "parser.cc" // lalr1.cc:636
#line 381 "parser.cc" // lalr1.cc:636
break;
case 29: // "constant hexstring"
case 37: // "constant hexstring"
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 380 "parser.cc" // lalr1.cc:636
#line 388 "parser.cc" // lalr1.cc:636
break;
case 30: // "option name"
case 38: // "option name"
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 387 "parser.cc" // lalr1.cc:636
#line 395 "parser.cc" // lalr1.cc:636
break;
case 31: // "ip address"
case 39: // "ip address"
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 394 "parser.cc" // lalr1.cc:636
#line 402 "parser.cc" // lalr1.cc:636
break;
case 36: // option_code
case 44: // option_code
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< uint16_t > (); }
#line 401 "parser.cc" // lalr1.cc:636
#line 409 "parser.cc" // lalr1.cc:636
break;
case 37: // option_repr_type
case 45: // option_repr_type
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
#line 408 "parser.cc" // lalr1.cc:636
#line 416 "parser.cc" // lalr1.cc:636
break;
case 40: // relay6_field
case 46: // pkt4_field
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< TokenPkt4::FieldType > (); }
#line 423 "parser.cc" // lalr1.cc:636
break;
case 49: // relay6_field
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< TokenRelay6Field::FieldType > (); }
#line 415 "parser.cc" // lalr1.cc:636
#line 430 "parser.cc" // lalr1.cc:636
break;
case 41: // nest_level
case 50: // nest_level
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< uint8_t > (); }
#line 422 "parser.cc" // lalr1.cc:636
#line 437 "parser.cc" // lalr1.cc:636
break;
case 42: // pkt6_field
case 51: // pkt6_field
#line 82 "parser.yy" // lalr1.cc:636
#line 91 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< TokenPkt6::FieldType > (); }
#line 429 "parser.cc" // lalr1.cc:636
#line 444 "parser.cc" // lalr1.cc:636
break;
@@ -625,31 +640,35 @@ namespace isc { namespace eval {
when using variants. */
switch (yyr1_[yyn])
{
case 37: // option_repr_type
case 45: // option_repr_type
yylhs.value.build< TokenOption::RepresentationType > ();
break;
case 42: // pkt6_field
case 46: // pkt4_field
yylhs.value.build< TokenPkt4::FieldType > ();
break;
case 51: // pkt6_field
yylhs.value.build< TokenPkt6::FieldType > ();
break;
case 40: // relay6_field
case 49: // relay6_field
yylhs.value.build< TokenRelay6Field::FieldType > ();
break;
case 27: // "constant string"
case 28: // "integer"
case 29: // "constant hexstring"
case 30: // "option name"
case 31: // "ip address"
case 35: // "constant string"
case 36: // "integer"
case 37: // "constant hexstring"
case 38: // "option name"
case 39: // "ip address"
yylhs.value.build< std::string > ();
break;
case 36: // option_code
case 44: // option_code
yylhs.value.build< uint16_t > ();
break;
case 41: // nest_level
case 50: // nest_level
yylhs.value.build< uint8_t > ();
break;
@@ -671,52 +690,52 @@ namespace isc { namespace eval {
switch (yyn)
{
case 4:
#line 96 "parser.yy" // lalr1.cc:859
#line 105 "parser.yy" // lalr1.cc:859
{
TokenPtr neg(new TokenNot());
ctx.expression.push_back(neg);
}
#line 680 "parser.cc" // lalr1.cc:859
#line 699 "parser.cc" // lalr1.cc:859
break;
case 5:
#line 101 "parser.yy" // lalr1.cc:859
#line 110 "parser.yy" // lalr1.cc:859
{
TokenPtr neg(new TokenAnd());
ctx.expression.push_back(neg);
}
#line 689 "parser.cc" // lalr1.cc:859
#line 708 "parser.cc" // lalr1.cc:859
break;
case 6:
#line 106 "parser.yy" // lalr1.cc:859
#line 115 "parser.yy" // lalr1.cc:859
{
TokenPtr neg(new TokenOr());
ctx.expression.push_back(neg);
}
#line 698 "parser.cc" // lalr1.cc:859
#line 717 "parser.cc" // lalr1.cc:859
break;
case 7:
#line 111 "parser.yy" // lalr1.cc:859
#line 120 "parser.yy" // lalr1.cc:859
{
TokenPtr eq(new TokenEqual());
ctx.expression.push_back(eq);
}
#line 707 "parser.cc" // lalr1.cc:859
#line 726 "parser.cc" // lalr1.cc:859
break;
case 8:
#line 116 "parser.yy" // lalr1.cc:859
#line 125 "parser.yy" // lalr1.cc:859
{
TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
ctx.expression.push_back(opt);
}
#line 716 "parser.cc" // lalr1.cc:859
#line 735 "parser.cc" // lalr1.cc:859
break;
case 9:
#line 121 "parser.yy" // lalr1.cc:859
#line 130 "parser.yy" // lalr1.cc:859
{
switch (ctx.getUniverse()) {
case Option::V4:
@@ -736,11 +755,11 @@ namespace isc { namespace eval {
error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
}
}
#line 740 "parser.cc" // lalr1.cc:859
#line 759 "parser.cc" // lalr1.cc:859
break;
case 10:
#line 141 "parser.yy" // lalr1.cc:859
#line 150 "parser.yy" // lalr1.cc:859
{
switch (ctx.getUniverse()) {
case Option::V6:
@@ -754,47 +773,47 @@ namespace isc { namespace eval {
error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
}
}
#line 758 "parser.cc" // lalr1.cc:859
#line 777 "parser.cc" // lalr1.cc:859
break;
case 11:
#line 157 "parser.yy" // lalr1.cc:859
#line 166 "parser.yy" // lalr1.cc:859
{
TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(str);
}
#line 767 "parser.cc" // lalr1.cc:859
#line 786 "parser.cc" // lalr1.cc:859
break;
case 12:
#line 162 "parser.yy" // lalr1.cc:859
#line 171 "parser.yy" // lalr1.cc:859
{
TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(hex);
}
#line 776 "parser.cc" // lalr1.cc:859
#line 795 "parser.cc" // lalr1.cc:859
break;
case 13:
#line 167 "parser.yy" // lalr1.cc:859
#line 176 "parser.yy" // lalr1.cc:859
{
TokenPtr ip(new TokenIpAddress(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(ip);
}
#line 785 "parser.cc" // lalr1.cc:859
#line 804 "parser.cc" // lalr1.cc:859
break;
case 14:
#line 172 "parser.yy" // lalr1.cc:859
#line 181 "parser.yy" // lalr1.cc:859
{
TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ()));
ctx.expression.push_back(opt);
}
#line 794 "parser.cc" // lalr1.cc:859
#line 813 "parser.cc" // lalr1.cc:859
break;
case 15:
#line 177 "parser.yy" // lalr1.cc:859
#line 186 "parser.yy" // lalr1.cc:859
{
switch (ctx.getUniverse()) {
case Option::V4:
@@ -814,11 +833,11 @@ namespace isc { namespace eval {
error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
}
}
#line 818 "parser.cc" // lalr1.cc:859
#line 837 "parser.cc" // lalr1.cc:859
break;
case 16:
#line 198 "parser.yy" // lalr1.cc:859
#line 207 "parser.yy" // lalr1.cc:859
{
switch (ctx.getUniverse()) {
case Option::V6:
@@ -832,11 +851,11 @@ namespace isc { namespace eval {
error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
}
}
#line 836 "parser.cc" // lalr1.cc:859
#line 855 "parser.cc" // lalr1.cc:859
break;
case 17:
#line 213 "parser.yy" // lalr1.cc:859
#line 222 "parser.yy" // lalr1.cc:859
{
switch (ctx.getUniverse()) {
case Option::V6:
@@ -850,129 +869,194 @@ namespace isc { namespace eval {
error(yystack_[5].location, "relay6 can only be used in DHCPv6.");
}
}
#line 854 "parser.cc" // lalr1.cc:859
#line 873 "parser.cc" // lalr1.cc:859
break;
case 18:
#line 229 "parser.yy" // lalr1.cc:859
#line 237 "parser.yy" // lalr1.cc:859
{
TokenPtr sub(new TokenSubstring());
ctx.expression.push_back(sub);
TokenPtr pkt4_field(new TokenPkt4(yystack_[0].value.as< TokenPkt4::FieldType > ()));
ctx.expression.push_back(pkt4_field);
}
#line 863 "parser.cc" // lalr1.cc:859
#line 882 "parser.cc" // lalr1.cc:859
break;
case 19:
#line 234 "parser.yy" // lalr1.cc:859
{
TokenPtr conc(new TokenConcat());
ctx.expression.push_back(conc);
}
#line 872 "parser.cc" // lalr1.cc:859
break;
case 20:
#line 239 "parser.yy" // lalr1.cc:859
#line 242 "parser.yy" // lalr1.cc:859
{
TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ()));
ctx.expression.push_back(pkt6_field);
}
#line 881 "parser.cc" // lalr1.cc:859
#line 891 "parser.cc" // lalr1.cc:859
break;
case 20:
#line 247 "parser.yy" // lalr1.cc:859
{
TokenPtr sub(new TokenSubstring());
ctx.expression.push_back(sub);
}
#line 900 "parser.cc" // lalr1.cc:859
break;
case 21:
#line 246 "parser.yy" // lalr1.cc:859
#line 252 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
TokenPtr conc(new TokenConcat());
ctx.expression.push_back(conc);
}
#line 889 "parser.cc" // lalr1.cc:859
#line 909 "parser.cc" // lalr1.cc:859
break;
case 22:
#line 250 "parser.yy" // lalr1.cc:859
#line 259 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
}
#line 897 "parser.cc" // lalr1.cc:859
#line 917 "parser.cc" // lalr1.cc:859
break;
case 23:
#line 256 "parser.yy" // lalr1.cc:859
#line 263 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
}
#line 905 "parser.cc" // lalr1.cc:859
#line 925 "parser.cc" // lalr1.cc:859
break;
case 24:
#line 260 "parser.yy" // lalr1.cc:859
#line 269 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
}
#line 913 "parser.cc" // lalr1.cc:859
#line 933 "parser.cc" // lalr1.cc:859
break;
case 25:
#line 266 "parser.yy" // lalr1.cc:859
#line 273 "parser.yy" // lalr1.cc:859
{
TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(str);
yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
}
#line 922 "parser.cc" // lalr1.cc:859
#line 941 "parser.cc" // lalr1.cc:859
break;
case 26:
#line 273 "parser.yy" // lalr1.cc:859
#line 279 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CHADDR;
}
#line 949 "parser.cc" // lalr1.cc:859
break;
case 27:
#line 283 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HLEN;
}
#line 957 "parser.cc" // lalr1.cc:859
break;
case 28:
#line 287 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HTYPE;
}
#line 965 "parser.cc" // lalr1.cc:859
break;
case 29:
#line 291 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CIADDR;
}
#line 973 "parser.cc" // lalr1.cc:859
break;
case 30:
#line 295 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::GIADDR;
}
#line 981 "parser.cc" // lalr1.cc:859
break;
case 31:
#line 299 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::YIADDR;
}
#line 989 "parser.cc" // lalr1.cc:859
break;
case 32:
#line 303 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::SIADDR;
}
#line 997 "parser.cc" // lalr1.cc:859
break;
case 33:
#line 309 "parser.yy" // lalr1.cc:859
{
TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(str);
}
#line 931 "parser.cc" // lalr1.cc:859
#line 1006 "parser.cc" // lalr1.cc:859
break;
case 27:
#line 278 "parser.yy" // lalr1.cc:859
case 34:
#line 316 "parser.yy" // lalr1.cc:859
{
TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(str);
}
#line 1015 "parser.cc" // lalr1.cc:859
break;
case 35:
#line 321 "parser.yy" // lalr1.cc:859
{
TokenPtr str(new TokenString("all"));
ctx.expression.push_back(str);
}
#line 940 "parser.cc" // lalr1.cc:859
#line 1024 "parser.cc" // lalr1.cc:859
break;
case 28:
#line 284 "parser.yy" // lalr1.cc:859
case 36:
#line 327 "parser.yy" // lalr1.cc:859
{ yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::PEERADDR; }
#line 946 "parser.cc" // lalr1.cc:859
#line 1030 "parser.cc" // lalr1.cc:859
break;
case 29:
#line 285 "parser.yy" // lalr1.cc:859
case 37:
#line 328 "parser.yy" // lalr1.cc:859
{ yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::LINKADDR; }
#line 952 "parser.cc" // lalr1.cc:859
#line 1036 "parser.cc" // lalr1.cc:859
break;
case 30:
#line 289 "parser.yy" // lalr1.cc:859
case 38:
#line 332 "parser.yy" // lalr1.cc:859
{
yylhs.value.as< uint8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as< std::string > (), yystack_[0].location);
}
#line 960 "parser.cc" // lalr1.cc:859
#line 1044 "parser.cc" // lalr1.cc:859
break;
case 31:
#line 297 "parser.yy" // lalr1.cc:859
case 39:
#line 340 "parser.yy" // lalr1.cc:859
{ yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE; }
#line 966 "parser.cc" // lalr1.cc:859
#line 1050 "parser.cc" // lalr1.cc:859
break;
case 32:
#line 298 "parser.yy" // lalr1.cc:859
case 40:
#line 341 "parser.yy" // lalr1.cc:859
{ yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::TRANSID; }
#line 972 "parser.cc" // lalr1.cc:859
#line 1056 "parser.cc" // lalr1.cc:859
break;
#line 976 "parser.cc" // lalr1.cc:859
#line 1060 "parser.cc" // lalr1.cc:859
default:
break;
}
@@ -1227,117 +1311,124 @@ namespace isc { namespace eval {
}
const signed char EvalParser::yypact_ninf_ = -54;
const signed char EvalParser::yypact_ninf_ = -62;
const signed char EvalParser::yytable_ninf_ = -1;
const signed char
EvalParser::yypact_[] =
{
29, 29, 29, -12, -4, 7, 21, 30, 32, -54,
-54, -54, 13, 10, 46, 16, -54, -3, -3, 9,
52, 52, 42, -54, 29, 29, 52, -54, -54, -54,
40, 54, -54, 56, 43, 59, 60, 55, 58, -54,
-54, -54, -54, 72, -54, 66, 68, 69, -3, -3,
9, 61, 52, 25, 28, -1, 71, 73, 75, -54,
65, 87, -54, -54, -54, -54, -54, -54, 78, -54,
-54, -54, 77, 79, 80, -14, -54, -3, 33, 33,
6, -54, -54, 90, 82, 84, -54, 83, -3, 47,
85, -54, -54, 86, 33
14, 14, 14, 6, 17, 18, 21, 41, 44, 48,
-62, -62, -62, 72, 20, 66, 29, -62, 12, 12,
16, 36, 45, 45, -24, -62, 14, 14, 45, -62,
-62, -62, 60, 63, -62, 73, -62, -62, -62, -62,
-62, -62, -62, -62, 67, 69, 75, 61, 62, -62,
-62, -62, -62, 84, -62, 77, 78, 79, 12, 12,
16, 64, 45, -3, 52, -1, 81, 82, 83, -62,
71, 95, -62, -62, -62, -62, -62, -62, 88, -62,
-62, -62, 87, 89, 90, -23, -62, 12, 49, 49,
9, -62, -62, 100, 92, 94, -62, 93, 12, 68,
96, -62, -62, 97, 49
};
const unsigned char
EvalParser::yydefact_[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 11,
12, 13, 0, 2, 0, 0, 4, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 3, 21, 22,
0, 0, 30, 0, 0, 0, 0, 0, 0, 31,
32, 20, 5, 6, 7, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
0, 0, 23, 24, 8, 14, 9, 15, 0, 28,
29, 17, 0, 0, 0, 0, 19, 0, 0, 0,
0, 27, 26, 0, 0, 0, 18, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11, 12, 13, 0, 2, 0, 0, 4, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 3,
22, 23, 0, 0, 38, 0, 26, 27, 28, 29,
30, 31, 32, 18, 0, 0, 0, 0, 0, 39,
40, 19, 5, 6, 7, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 33,
0, 0, 24, 25, 8, 14, 9, 15, 0, 36,
37, 17, 0, 0, 0, 0, 21, 0, 0, 0,
0, 35, 34, 0, 0, 0, 20, 0, 0, 0,
0, 10, 16, 0, 0
};
const signed char
EvalParser::yypgoto_[] =
{
-54, -54, 4, -17, -18, -53, -54, -54, -54, 51,
-54
-62, -62, 3, -21, -19, -61, -62, -62, -62, -62,
50, -62
};
const signed char
EvalParser::yydefgoto_[] =
{
-1, 12, 13, 14, 30, 65, 60, 83, 71, 33,
41
-1, 13, 14, 15, 32, 75, 43, 70, 93, 81,
35, 51
};
const unsigned char
EvalParser::yytable_[] =
{
31, 67, 17, 37, 38, 15, 16, 81, 68, 44,
18, 69, 70, 23, 82, 85, 24, 25, 69, 70,
27, 19, 24, 25, 20, 28, 67, 29, 42, 43,
56, 57, 1, 21, 2, 61, 92, 32, 3, 4,
5, 92, 62, 63, 64, 62, 63, 66, 22, 6,
62, 63, 7, 8, 26, 45, 9, 48, 10, 84,
11, 34, 35, 36, 62, 63, 91, 39, 40, 46,
90, 47, 6, 49, 50, 7, 8, 51, 24, 9,
52, 10, 53, 11, 54, 55, 72, 75, 73, 59,
74, 76, 77, 78, 86, 79, 80, 87, 88, 89,
93, 58, 94
33, 47, 48, 77, 16, 17, 91, 54, 78, 49,
50, 79, 80, 92, 72, 73, 74, 1, 95, 2,
18, 79, 80, 3, 4, 5, 26, 27, 77, 52,
53, 19, 20, 29, 6, 26, 27, 21, 102, 66,
67, 71, 7, 102, 22, 8, 9, 23, 30, 10,
31, 11, 34, 12, 44, 45, 46, 36, 37, 38,
39, 40, 41, 42, 24, 6, 72, 73, 94, 72,
73, 76, 25, 7, 28, 55, 8, 9, 56, 100,
10, 58, 11, 59, 12, 72, 73, 101, 57, 60,
26, 61, 62, 63, 64, 65, 82, 83, 84, 86,
69, 85, 87, 88, 96, 89, 90, 97, 98, 99,
68, 103, 0, 104
};
const unsigned char
const signed char
EvalParser::yycheck_[] =
{
18, 54, 14, 20, 21, 1, 2, 21, 9, 26,
14, 12, 13, 0, 28, 9, 6, 7, 12, 13,
4, 14, 6, 7, 3, 28, 79, 30, 24, 25,
48, 49, 3, 3, 5, 52, 89, 28, 9, 10,
11, 94, 17, 18, 19, 17, 18, 19, 16, 20,
17, 18, 23, 24, 8, 15, 27, 14, 29, 77,
31, 9, 10, 11, 17, 18, 19, 25, 26, 15,
88, 15, 20, 14, 14, 23, 24, 22, 6, 27,
22, 29, 16, 31, 16, 16, 15, 22, 15, 28,
15, 4, 14, 16, 4, 16, 16, 15, 14, 16,
15, 50, 16
19, 22, 23, 64, 1, 2, 29, 28, 9, 33,
34, 12, 13, 36, 17, 18, 19, 3, 9, 5,
14, 12, 13, 9, 10, 11, 6, 7, 89, 26,
27, 14, 14, 4, 20, 6, 7, 16, 99, 58,
59, 62, 28, 104, 3, 31, 32, 3, 36, 35,
38, 37, 36, 39, 9, 10, 11, 21, 22, 23,
24, 25, 26, 27, 16, 20, 17, 18, 87, 17,
18, 19, 0, 28, 8, 15, 31, 32, 15, 98,
35, 14, 37, 14, 39, 17, 18, 19, 15, 14,
6, 30, 30, 16, 16, 16, 15, 15, 15, 4,
36, 30, 14, 16, 4, 16, 16, 15, 14, 16,
60, 15, -1, 16
};
const unsigned char
EvalParser::yystos_[] =
{
0, 3, 5, 9, 10, 11, 20, 23, 24, 27,
29, 31, 33, 34, 35, 34, 34, 14, 14, 14,
3, 3, 16, 0, 6, 7, 8, 4, 28, 30,
36, 36, 28, 41, 9, 10, 11, 35, 35, 25,
26, 42, 34, 34, 35, 15, 15, 15, 14, 14,
14, 22, 22, 16, 16, 16, 36, 36, 41, 28,
38, 35, 17, 18, 19, 37, 19, 37, 9, 12,
13, 40, 15, 15, 15, 22, 4, 14, 16, 16,
16, 21, 28, 39, 36, 9, 4, 15, 14, 16,
36, 19, 37, 15, 16
0, 3, 5, 9, 10, 11, 20, 28, 31, 32,
35, 37, 39, 41, 42, 43, 42, 42, 14, 14,
14, 16, 3, 3, 16, 0, 6, 7, 8, 4,
36, 38, 44, 44, 36, 50, 21, 22, 23, 24,
25, 26, 27, 46, 9, 10, 11, 43, 43, 33,
34, 51, 42, 42, 43, 15, 15, 15, 14, 14,
14, 30, 30, 16, 16, 16, 44, 44, 50, 36,
47, 43, 17, 18, 19, 45, 19, 45, 9, 12,
13, 49, 15, 15, 15, 30, 4, 14, 16, 16,
16, 29, 36, 48, 44, 9, 4, 15, 14, 16,
44, 19, 45, 15, 16
};
const unsigned char
EvalParser::yyr1_[] =
{
0, 32, 33, 34, 34, 34, 34, 34, 34, 34,
34, 35, 35, 35, 35, 35, 35, 35, 35, 35,
35, 36, 36, 37, 37, 38, 39, 39, 40, 40,
41, 42, 42
0, 40, 41, 42, 42, 42, 42, 42, 42, 42,
42, 43, 43, 43, 43, 43, 43, 43, 43, 43,
43, 43, 44, 44, 45, 45, 46, 46, 46, 46,
46, 46, 46, 47, 48, 48, 49, 49, 50, 51,
51
};
const unsigned char
EvalParser::yyr2_[] =
{
0, 2, 1, 3, 2, 3, 3, 3, 6, 6,
11, 1, 1, 1, 6, 6, 11, 6, 8, 6,
3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1
11, 1, 1, 1, 6, 6, 11, 6, 3, 3,
8, 6, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1
};
@@ -1350,22 +1441,25 @@ namespace isc { namespace eval {
"\"end of file\"", "error", "$undefined", "\"(\"", "\")\"", "\"not\"",
"\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"relay6\"",
"\"peeraddr\"", "\"linkaddr\"", "\"[\"", "\"]\"", "\".\"", "\"text\"",
"\"hex\"", "\"exists\"", "\"substring\"", "\"all\"", "\",\"",
"\"concat\"", "\"pkt6\"", "\"msgtype\"", "\"transid\"",
"\"constant string\"", "\"integer\"", "\"constant hexstring\"",
"\"option name\"", "\"ip address\"", "$accept", "expression",
"bool_expr", "string_expr", "option_code", "option_repr_type",
"start_expr", "length_expr", "relay6_field", "nest_level", "pkt6_field", YY_NULLPTR
"\"hex\"", "\"exists\"", "\"pkt4\"", "\"mac\"", "\"hlen\"", "\"htype\"",
"\"ciaddr\"", "\"giaddr\"", "\"yiaddr\"", "\"siaddr\"", "\"substring\"",
"\"all\"", "\",\"", "\"concat\"", "\"pkt6\"", "\"msgtype\"",
"\"transid\"", "\"constant string\"", "\"integer\"",
"\"constant hexstring\"", "\"option name\"", "\"ip address\"", "$accept",
"expression", "bool_expr", "string_expr", "option_code",
"option_repr_type", "pkt4_field", "start_expr", "length_expr",
"relay6_field", "nest_level", "pkt6_field", YY_NULLPTR
};
#if YYDEBUG
const unsigned short int
EvalParser::yyrline_[] =
{
0, 91, 91, 94, 95, 100, 105, 110, 115, 120,
140, 156, 161, 166, 171, 176, 197, 212, 228, 233,
238, 245, 249, 255, 259, 265, 272, 277, 284, 285,
288, 297, 298
0, 100, 100, 103, 104, 109, 114, 119, 124, 129,
149, 165, 170, 175, 180, 185, 206, 221, 236, 241,
246, 251, 258, 262, 268, 272, 278, 282, 286, 290,
294, 298, 302, 308, 315, 320, 327, 328, 331, 340,
341
};
// Print the state stack on the debug stream.
@@ -1400,8 +1494,8 @@ namespace isc { namespace eval {
#line 13 "parser.yy" // lalr1.cc:1167
} } // isc::eval
#line 1404 "parser.cc" // lalr1.cc:1167
#line 301 "parser.yy" // lalr1.cc:1168
#line 1498 "parser.cc" // lalr1.cc:1167
#line 344 "parser.yy" // lalr1.cc:1168
void
isc::eval::EvalParser::error(const location_type& loc,

View File

@@ -40,7 +40,7 @@
#ifndef YY_YY_PARSER_H_INCLUDED
# define YY_YY_PARSER_H_INCLUDED
// // "%code requires" blocks.
#line 16 "parser.yy" // lalr1.cc:377
#line 16 "parser.yy" // lalr1.cc:392
#include <string>
#include <eval/token.h>
@@ -51,7 +51,7 @@
using namespace isc::dhcp;
using namespace isc::eval;
#line 55 "parser.h" // lalr1.cc:377
#line 55 "parser.h" // lalr1.cc:392
# include <cassert>
# include <cstdlib> // std::abort
@@ -126,9 +126,9 @@ using namespace isc::eval;
# define YYDEBUG 1
#endif
#line 13 "parser.yy" // lalr1.cc:377
#line 13 "parser.yy" // lalr1.cc:392
namespace isc { namespace eval {
#line 132 "parser.h" // lalr1.cc:377
#line 132 "parser.h" // lalr1.cc:392
@@ -298,24 +298,27 @@ namespace isc { namespace eval {
// option_repr_type
char dummy1[sizeof(TokenOption::RepresentationType)];
// pkt4_field
char dummy2[sizeof(TokenPkt4::FieldType)];
// pkt6_field
char dummy2[sizeof(TokenPkt6::FieldType)];
char dummy3[sizeof(TokenPkt6::FieldType)];
// relay6_field
char dummy3[sizeof(TokenRelay6Field::FieldType)];
char dummy4[sizeof(TokenRelay6Field::FieldType)];
// "constant string"
// "integer"
// "constant hexstring"
// "option name"
// "ip address"
char dummy4[sizeof(std::string)];
char dummy5[sizeof(std::string)];
// option_code
char dummy5[sizeof(uint16_t)];
char dummy6[sizeof(uint16_t)];
// nest_level
char dummy6[sizeof(uint8_t)];
char dummy7[sizeof(uint8_t)];
};
/// Symbol semantic values.
@@ -356,18 +359,26 @@ namespace isc { namespace eval {
TOKEN_TEXT = 272,
TOKEN_HEX = 273,
TOKEN_EXISTS = 274,
TOKEN_SUBSTRING = 275,
TOKEN_ALL = 276,
TOKEN_COMA = 277,
TOKEN_CONCAT = 278,
TOKEN_PKT6 = 279,
TOKEN_MSGTYPE = 280,
TOKEN_TRANSID = 281,
TOKEN_STRING = 282,
TOKEN_INTEGER = 283,
TOKEN_HEXSTRING = 284,
TOKEN_OPTION_NAME = 285,
TOKEN_IP_ADDRESS = 286
TOKEN_PKT4 = 275,
TOKEN_CHADDR = 276,
TOKEN_HLEN = 277,
TOKEN_HTYPE = 278,
TOKEN_CIADDR = 279,
TOKEN_GIADDR = 280,
TOKEN_YIADDR = 281,
TOKEN_SIADDR = 282,
TOKEN_SUBSTRING = 283,
TOKEN_ALL = 284,
TOKEN_COMA = 285,
TOKEN_CONCAT = 286,
TOKEN_PKT6 = 287,
TOKEN_MSGTYPE = 288,
TOKEN_TRANSID = 289,
TOKEN_STRING = 290,
TOKEN_INTEGER = 291,
TOKEN_HEXSTRING = 292,
TOKEN_OPTION_NAME = 293,
TOKEN_IP_ADDRESS = 294
};
};
@@ -407,6 +418,8 @@ namespace isc { namespace eval {
basic_symbol (typename Base::kind_type t, const TokenOption::RepresentationType v, const location_type& l);
basic_symbol (typename Base::kind_type t, const TokenPkt4::FieldType v, const location_type& l);
basic_symbol (typename Base::kind_type t, const TokenPkt6::FieldType v, const location_type& l);
basic_symbol (typename Base::kind_type t, const TokenRelay6Field::FieldType v, const location_type& l);
@@ -556,6 +569,38 @@ namespace isc { namespace eval {
symbol_type
make_EXISTS (const location_type& l);
static inline
symbol_type
make_PKT4 (const location_type& l);
static inline
symbol_type
make_CHADDR (const location_type& l);
static inline
symbol_type
make_HLEN (const location_type& l);
static inline
symbol_type
make_HTYPE (const location_type& l);
static inline
symbol_type
make_CIADDR (const location_type& l);
static inline
symbol_type
make_GIADDR (const location_type& l);
static inline
symbol_type
make_YIADDR (const location_type& l);
static inline
symbol_type
make_SIADDR (const location_type& l);
static inline
symbol_type
make_SUBSTRING (const location_type& l);
@@ -689,7 +734,7 @@ namespace isc { namespace eval {
// number is the opposite. If YYTABLE_NINF, syntax error.
static const unsigned char yytable_[];
static const unsigned char yycheck_[];
static const signed char yycheck_[];
// YYSTOS[STATE-NUM] -- The (internal number of the) accessing
// symbol of state STATE-NUM.
@@ -809,12 +854,12 @@ namespace isc { namespace eval {
enum
{
yyeof_ = 0,
yylast_ = 102, ///< Last index in yytable_.
yynnts_ = 11, ///< Number of nonterminal symbols.
yyfinal_ = 23, ///< Termination state number.
yylast_ = 113, ///< Last index in yytable_.
yynnts_ = 12, ///< Number of nonterminal symbols.
yyfinal_ = 25, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
yyntokens_ = 32 ///< Number of tokens.
yyntokens_ = 40 ///< Number of tokens.
};
@@ -859,9 +904,10 @@ namespace isc { namespace eval {
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39
};
const unsigned int user_token_number_max_ = 286;
const unsigned int user_token_number_max_ = 294;
const token_number_type undef_token_ = 2;
if (static_cast<int>(t) <= yyeof_)
@@ -894,31 +940,35 @@ namespace isc { namespace eval {
{
switch (other.type_get ())
{
case 37: // option_repr_type
case 45: // option_repr_type
value.copy< TokenOption::RepresentationType > (other.value);
break;
case 42: // pkt6_field
case 46: // pkt4_field
value.copy< TokenPkt4::FieldType > (other.value);
break;
case 51: // pkt6_field
value.copy< TokenPkt6::FieldType > (other.value);
break;
case 40: // relay6_field
case 49: // relay6_field
value.copy< TokenRelay6Field::FieldType > (other.value);
break;
case 27: // "constant string"
case 28: // "integer"
case 29: // "constant hexstring"
case 30: // "option name"
case 31: // "ip address"
case 35: // "constant string"
case 36: // "integer"
case 37: // "constant hexstring"
case 38: // "option name"
case 39: // "ip address"
value.copy< std::string > (other.value);
break;
case 36: // option_code
case 44: // option_code
value.copy< uint16_t > (other.value);
break;
case 41: // nest_level
case 50: // nest_level
value.copy< uint8_t > (other.value);
break;
@@ -939,31 +989,35 @@ namespace isc { namespace eval {
(void) v;
switch (this->type_get ())
{
case 37: // option_repr_type
case 45: // option_repr_type
value.copy< TokenOption::RepresentationType > (v);
break;
case 42: // pkt6_field
case 46: // pkt4_field
value.copy< TokenPkt4::FieldType > (v);
break;
case 51: // pkt6_field
value.copy< TokenPkt6::FieldType > (v);
break;
case 40: // relay6_field
case 49: // relay6_field
value.copy< TokenRelay6Field::FieldType > (v);
break;
case 27: // "constant string"
case 28: // "integer"
case 29: // "constant hexstring"
case 30: // "option name"
case 31: // "ip address"
case 35: // "constant string"
case 36: // "integer"
case 37: // "constant hexstring"
case 38: // "option name"
case 39: // "ip address"
value.copy< std::string > (v);
break;
case 36: // option_code
case 44: // option_code
value.copy< uint16_t > (v);
break;
case 41: // nest_level
case 50: // nest_level
value.copy< uint8_t > (v);
break;
@@ -989,6 +1043,13 @@ namespace isc { namespace eval {
, location (l)
{}
template <typename Base>
EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const TokenPkt4::FieldType v, const location_type& l)
: Base (t)
, value (v)
, location (l)
{}
template <typename Base>
EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const TokenPkt6::FieldType v, const location_type& l)
: Base (t)
@@ -1050,31 +1111,35 @@ namespace isc { namespace eval {
// Type destructor.
switch (yytype)
{
case 37: // option_repr_type
case 45: // option_repr_type
value.template destroy< TokenOption::RepresentationType > ();
break;
case 42: // pkt6_field
case 46: // pkt4_field
value.template destroy< TokenPkt4::FieldType > ();
break;
case 51: // pkt6_field
value.template destroy< TokenPkt6::FieldType > ();
break;
case 40: // relay6_field
case 49: // relay6_field
value.template destroy< TokenRelay6Field::FieldType > ();
break;
case 27: // "constant string"
case 28: // "integer"
case 29: // "constant hexstring"
case 30: // "option name"
case 31: // "ip address"
case 35: // "constant string"
case 36: // "integer"
case 37: // "constant hexstring"
case 38: // "option name"
case 39: // "ip address"
value.template destroy< std::string > ();
break;
case 36: // option_code
case 44: // option_code
value.template destroy< uint16_t > ();
break;
case 41: // nest_level
case 50: // nest_level
value.template destroy< uint8_t > ();
break;
@@ -1101,31 +1166,35 @@ namespace isc { namespace eval {
super_type::move(s);
switch (this->type_get ())
{
case 37: // option_repr_type
case 45: // option_repr_type
value.move< TokenOption::RepresentationType > (s.value);
break;
case 42: // pkt6_field
case 46: // pkt4_field
value.move< TokenPkt4::FieldType > (s.value);
break;
case 51: // pkt6_field
value.move< TokenPkt6::FieldType > (s.value);
break;
case 40: // relay6_field
case 49: // relay6_field
value.move< TokenRelay6Field::FieldType > (s.value);
break;
case 27: // "constant string"
case 28: // "integer"
case 29: // "constant hexstring"
case 30: // "option name"
case 31: // "ip address"
case 35: // "constant string"
case 36: // "integer"
case 37: // "constant hexstring"
case 38: // "option name"
case 39: // "ip address"
value.move< std::string > (s.value);
break;
case 36: // option_code
case 44: // option_code
value.move< uint16_t > (s.value);
break;
case 41: // nest_level
case 50: // nest_level
value.move< uint8_t > (s.value);
break;
@@ -1187,7 +1256,7 @@ namespace isc { namespace eval {
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286
285, 286, 287, 288, 289, 290, 291, 292, 293, 294
};
return static_cast<token_type> (yytoken_number_[type]);
}
@@ -1300,6 +1369,54 @@ namespace isc { namespace eval {
return symbol_type (token::TOKEN_EXISTS, l);
}
EvalParser::symbol_type
EvalParser::make_PKT4 (const location_type& l)
{
return symbol_type (token::TOKEN_PKT4, l);
}
EvalParser::symbol_type
EvalParser::make_CHADDR (const location_type& l)
{
return symbol_type (token::TOKEN_CHADDR, l);
}
EvalParser::symbol_type
EvalParser::make_HLEN (const location_type& l)
{
return symbol_type (token::TOKEN_HLEN, l);
}
EvalParser::symbol_type
EvalParser::make_HTYPE (const location_type& l)
{
return symbol_type (token::TOKEN_HTYPE, l);
}
EvalParser::symbol_type
EvalParser::make_CIADDR (const location_type& l)
{
return symbol_type (token::TOKEN_CIADDR, l);
}
EvalParser::symbol_type
EvalParser::make_GIADDR (const location_type& l)
{
return symbol_type (token::TOKEN_GIADDR, l);
}
EvalParser::symbol_type
EvalParser::make_YIADDR (const location_type& l)
{
return symbol_type (token::TOKEN_YIADDR, l);
}
EvalParser::symbol_type
EvalParser::make_SIADDR (const location_type& l)
{
return symbol_type (token::TOKEN_SIADDR, l);
}
EvalParser::symbol_type
EvalParser::make_SUBSTRING (const location_type& l)
{
@@ -1373,9 +1490,9 @@ namespace isc { namespace eval {
}
#line 13 "parser.yy" // lalr1.cc:377
#line 13 "parser.yy" // lalr1.cc:392
} } // isc::eval
#line 1379 "parser.h" // lalr1.cc:377
#line 1496 "parser.h" // lalr1.cc:392

View File

@@ -54,6 +54,14 @@ using namespace isc::eval;
TEXT "text"
HEX "hex"
EXISTS "exists"
PKT4 "pkt4"
CHADDR "mac"
HLEN "hlen"
HTYPE "htype"
CIADDR "ciaddr"
GIADDR "giaddr"
YIADDR "yiaddr"
SIADDR "siaddr"
SUBSTRING "substring"
ALL "all"
COMA ","
@@ -73,6 +81,7 @@ using namespace isc::eval;
%type <TokenOption::RepresentationType> option_repr_type
%type <TokenRelay6Field::FieldType> relay6_field
%type <uint8_t> nest_level
%type <TokenPkt4::FieldType> pkt4_field
%type <TokenPkt6::FieldType> pkt6_field
%left OR
@@ -224,7 +233,16 @@ string_expr : STRING
}
}
| PKT4 "." pkt4_field
{
TokenPtr pkt4_field(new TokenPkt4($3));
ctx.expression.push_back(pkt4_field);
}
| PKT6 "." pkt6_field
{
TokenPtr pkt6_field(new TokenPkt6($3));
ctx.expression.push_back(pkt6_field);
}
| SUBSTRING "(" string_expr "," start_expr "," length_expr ")"
{
TokenPtr sub(new TokenSubstring());
@@ -235,11 +253,6 @@ string_expr : STRING
TokenPtr conc(new TokenConcat());
ctx.expression.push_back(conc);
}
| PKT6 "." pkt6_field
{
TokenPtr pkt6_field(new TokenPkt6($3));
ctx.expression.push_back(pkt6_field);
}
;
option_code : INTEGER
@@ -262,6 +275,36 @@ option_repr_type : TEXT
}
;
pkt4_field : CHADDR
{
$$ = TokenPkt4::CHADDR;
}
| HLEN
{
$$ = TokenPkt4::HLEN;
}
| HTYPE
{
$$ = TokenPkt4::HTYPE;
}
| CIADDR
{
$$ = TokenPkt4::CIADDR;
}
| GIADDR
{
$$ = TokenPkt4::GIADDR;
}
| YIADDR
{
$$ = TokenPkt4::YIADDR;
}
| SIADDR
{
$$ = TokenPkt4::SIADDR;
}
;
start_expr : INTEGER
{
TokenPtr str(new TokenString($1));

View File

@@ -132,6 +132,51 @@ public:
}
}
/// @brief checks if the given token is Pkt4 of specified type
/// @param token token to be checked
/// @param type expected type of the Pkt4 field
void checkTokenPkt4(const TokenPtr& token, TokenPkt4::FieldType type) {
ASSERT_TRUE(token);
boost::shared_ptr<TokenPkt4> pkt =
boost::dynamic_pointer_cast<TokenPkt4>(token);
ASSERT_TRUE(pkt);
EXPECT_EQ(type, pkt->getType());
}
/// @brief Test that verifies access to the DHCPv4 packet fields.
///
/// This test attempts to parse the expression, will check if the number
/// of tokens is exactly as expected and then will try to verify if the
/// first token represents the expected field in DHCPv4 packet.
///
/// @param expr expression to be parsed
/// @param exp_type expected field type to be parsed
/// @param exp_tokens expected number of tokens
void testPkt4Field(std::string expr,
TokenPkt4::FieldType exp_type,
int exp_tokens) {
EvalContext eval(Option::V4);
// Parse the expression.
try {
parsed_ = eval.parseString(expr);
}
catch (const EvalParseError& ex) {
FAIL() << "Exception thrown: " << ex.what();
return;
}
// Parsing should succeed and return a token.
EXPECT_TRUE(parsed_);
// There should be exactly the expected number of tokens.
ASSERT_EQ(exp_tokens, eval.expression.size());
// Check that the first token is TokenPkt4 instance and has correct type.
checkTokenPkt4(eval.expression.at(0), exp_type);
}
/// @brief checks if the given token is a substring operator
void checkTokenSubstring(const TokenPtr& token) {
ASSERT_TRUE(token);
@@ -585,6 +630,41 @@ TEST_F(EvalContextTest, relay4Error) {
"<string>:1.1-6: relay4 can only be used in DHCPv4.");
}
// Tests whether chaddr field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldChaddr) {
testPkt4Field("pkt4.mac == 0x000102030405", TokenPkt4::CHADDR, 3);
}
// Tests whether hlen field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldHlen) {
testPkt4Field("pkt4.hlen == 0x6", TokenPkt4::HLEN, 3);
}
// Tests whether htype field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldHtype) {
testPkt4Field("pkt4.htype == 0x1", TokenPkt4::HTYPE, 3);
}
// Tests whether ciaddr field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldCiaddr) {
testPkt4Field("pkt4.ciaddr == 192.0.2.1", TokenPkt4::CIADDR, 3);
}
// Tests whether giaddr field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldGiaddr) {
testPkt4Field("pkt4.giaddr == 192.0.2.1", TokenPkt4::GIADDR, 3);
}
// Tests whether yiaddr field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldYiaddr) {
testPkt4Field("pkt4.yiaddr == 192.0.2.1", TokenPkt4::YIADDR, 3);
}
// Tests whether siaddr field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldSiaddr) {
testPkt4Field("pkt4.siaddr == 192.0.2.1", TokenPkt4::SIADDR, 3);
}
// Tests whether message type field in DHCPv6 can be accessed.
TEST_F(EvalContextTest, pkt6FieldMsgtype) {
testPkt6Field("pkt6.msgtype == '1'", TokenPkt6::MSGTYPE, 3);
@@ -790,6 +870,7 @@ TEST_F(EvalContextTest, scanErrors) {
checkError("foo", "<string>:1.1: Invalid character: f");
checkError(" bar", "<string>:1.2: Invalid character: b");
checkError("relay[12].hex == 'foo'", "<string>:1.1: Invalid character: r");
checkError("pkt4.ziaddr", "<string>:1.6: Invalid character: z");
}
// Tests some scanner/parser error cases

View File

@@ -20,6 +20,7 @@
using namespace std;
using namespace isc::dhcp;
using namespace isc::asiolink;
namespace {
@@ -708,6 +709,86 @@ TEST_F(TokenTest, relay4RAIOnly) {
EXPECT_EQ("false", values_.top());
}
// Verifies if the DHCPv4 packet fields can be extracted.
TEST_F(TokenTest, pkt4Fields) {
pkt4_->setGiaddr(IOAddress("192.0.2.1"));
pkt4_->setCiaddr(IOAddress("192.0.2.2"));
pkt4_->setYiaddr(IOAddress("192.0.2.3"));
pkt4_->setSiaddr(IOAddress("192.0.2.4"));
// We're setting hardware address to uncommon (7 bytes rather than 6 and
// hardware type 123) HW address. We'll use it in hlen and htype checks.
HWAddrPtr hw(new HWAddr(HWAddr::fromText("01:02:03:04:05:06:07", 123)));
pkt4_->setHWAddr(hw);
// Check hardware address field.
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::CHADDR)));
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
uint8_t expected_hw[] = { 1, 2, 3, 4, 5, 6, 7 };
ASSERT_EQ(7, values_.top().size());
EXPECT_EQ(0, memcmp(expected_hw, &values_.top()[0], 7));
// Check hlen value field.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::HLEN)));
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
ASSERT_EQ(4, values_.top().size());
uint32_t expected_hlen = htonl(7);
EXPECT_EQ(0, memcmp(&expected_hlen, &values_.top()[0], 4));
// Check htype value.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::HTYPE)));
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
ASSERT_EQ(4, values_.top().size());
uint32_t expected_htype = htonl(123);
EXPECT_EQ(0, memcmp(&expected_htype, &values_.top()[0], 4));
// Check giaddr value.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::GIADDR)));
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
uint8_t expected_addr[] = { 192, 0, 2, 1 };
ASSERT_EQ(4, values_.top().size());
EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
// Check ciaddr value.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::CIADDR)));
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
expected_addr[3] = 2;
ASSERT_EQ(4, values_.top().size());
EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
// Check yiaddr value.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::YIADDR)));
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
expected_addr[3] = 3;
ASSERT_EQ(4, values_.top().size());
EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
// Check siaddr value.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::SIADDR)));
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
expected_addr[3] = 4;
ASSERT_EQ(4, values_.top().size());
EXPECT_EQ(0, memcmp(expected_addr, &values_.top()[0], 4));
// Check a DHCPv6 packet throws.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::HLEN)));
EXPECT_THROW(t_->evaluate(*pkt6_, values_), EvalTypeError);
}
// This test checks if a token representing an == operator is able to
// compare two values (with incorrectly built stack).
TEST_F(TokenTest, optionEqualInvalid) {

View File

@@ -8,6 +8,7 @@
#include <eval/eval_log.h>
#include <util/encode/hex.h>
#include <asiolink/io_address.h>
#include <dhcp/pkt4.h>
#include <boost/lexical_cast.hpp>
#include <dhcp/pkt6.h>
#include <cstring>
@@ -124,6 +125,77 @@ OptionPtr TokenRelay4Option::getOption(const Pkt& pkt) {
return (rai->getOption(option_code_));
}
void
TokenPkt4::evaluate(const Pkt& pkt, ValueStack& values) {
vector<uint8_t> binary;
try {
// Check if it's a Pkt4. If it's not, the dynamic_cast will throw
// std::bad_cast (failed dynamic_cast returns NULL for pointers and
// throws for references).
const Pkt4& pkt4 = dynamic_cast<const Pkt4&>(pkt);
switch (type_) {
case CHADDR: {
HWAddrPtr hwaddr = pkt4.getHWAddr();
if (!hwaddr) {
// This should never happen. Every Pkt4 should always have
// a hardware address.
isc_throw(EvalTypeError,
"Packet does not have hardware address");
}
binary = hwaddr->hwaddr_;
break;
}
case GIADDR:
binary = pkt4.getGiaddr().toBytes();
break;
case CIADDR:
binary = pkt4.getCiaddr().toBytes();
break;
case YIADDR:
binary = pkt4.getYiaddr().toBytes();
break;
case SIADDR:
binary = pkt4.getSiaddr().toBytes();
break;
case HLEN:
// Pad the uint8_t field to 4 bytes.
binary.push_back(0);
binary.push_back(0);
binary.push_back(0);
binary.push_back(pkt4.getHlen());
break;
case HTYPE:
// Pad the uint8_t field to 4 bytes.
binary.push_back(0);
binary.push_back(0);
binary.push_back(0);
binary.push_back(pkt4.getHtype());
break;
default:
isc_throw(EvalTypeError, "Bad field specified: "
<< static_cast<int>(type_) );
}
} catch (const std::bad_cast&) {
isc_throw(EvalTypeError, "Specified packet is not a Pkt4");
}
string value;
value.resize(binary.size());
if (!binary.empty()) {
memmove(&value[0], &binary[0], binary.size());
}
values.push(value);
}
void
TokenEqual::evaluate(const Pkt& /*pkt*/, ValueStack& values) {

View File

@@ -288,6 +288,61 @@ protected:
virtual OptionPtr getOption(const Pkt& pkt);
};
/// @brief Token that represents fields of a DHCPv4 packet.
///
/// For example in the expression pkt4.chaddr == 0x0102030405
/// this token represents the pkt4.chaddr expression.
///
/// Currently supported fields are:
/// - chaddr (client hardware address, hlen [0..16] octets)
/// - giaddr (relay agent IP address, 4 octets)
/// - ciaddr (client IP address, 4 octets)
/// - yiaddr ('your' (client) IP address, 4 octets)
/// - siaddr (next server IP address, 4 octets)
/// - hlen (hardware address length, padded to 4 octets)
/// - htype (hardware address type, padded to 4 octets)
class TokenPkt4 : public Token {
public:
/// @brief enum value that determines the field.
enum FieldType {
CHADDR, ///< chaddr field (up to 16 bytes link-layer address)
GIADDR, ///< giaddr (IPv4 address)
CIADDR, ///< ciaddr (IPv4 address)
YIADDR, ///< yiaddr (IPv4 address)
SIADDR, ///< siaddr (IPv4 address)
HLEN, ///< hlen (hardware address length)
HTYPE ///< htype (hardware address type)
};
/// @brief Constructor (does nothing)
TokenPkt4(const FieldType type)
: type_(type) {}
/// @brief Gets a value from the specified packet.
///
/// Evaluation uses fields available in the packet. It does not require
/// any values to be present on the stack.
///
/// @throw EvalTypeError when called for DHCPv6 packet
///
/// @param pkt - fields will be extracted from here
/// @param values - stack of values (1 result will be pushed)
void evaluate(const Pkt& pkt, ValueStack& values);
/// @brief Returns field type
///
/// This method is used only in tests.
/// @return type of the field.
FieldType getType() {
return (type_);
}
private:
/// @brief Specifies field of the DHCPv4 packet
FieldType type_;
};
/// @brief Token that represents equality operator (compares two other tokens)
///
/// For example in the expression option[vendor-class].text == "MSFT"