Commit e95f32eb authored by Francis Dupont's avatar Francis Dupont

[master] Finish merge of trac4268a (DHCPv4 fields)

parents f531624a 0b30f90d
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.
......
......@@ -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 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>
<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>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>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>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>Transaction ID in DHCPv6 packet</entry>
<entry>pkt6.transid</entry>
<!-- <entry>12345</entry>
<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>
-->
<entry>The value of the transaction id in the DHCPv6 packet.</entry>
</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>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>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>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>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>
</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"
......
This diff is collapsed.
......@@ -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);
......
This diff is collapsed.
......@@ -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)
{