From ca6962112f89a9742f4346c8f65818f461d59cbc Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Tue, 22 Mar 2016 02:54:04 +0000 Subject: [PATCH 1/7] [trac4269] Add code for handling constant length fields in DHCPv6 messages --- src/lib/eval/lexer.cc | 292 ++++++++++++++++++++---------------- src/lib/eval/lexer.ll | 4 + src/lib/eval/parser.cc | 331 +++++++++++++++++++++++------------------ src/lib/eval/parser.h | 138 ++++++++++++----- src/lib/eval/parser.yy | 13 ++ src/lib/eval/token.cc | 34 +++++ src/lib/eval/token.h | 44 ++++++ 7 files changed, 548 insertions(+), 308 deletions(-) diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index 1be686c8bc..7a99903c39 100644 --- a/src/lib/eval/lexer.cc +++ b/src/lib/eval/lexer.cc @@ -483,8 +483,8 @@ static void yy_fatal_error (yyconst char msg[] ); (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ -#define YY_NUM_RULES 26 -#define YY_END_OF_BUFFER 27 +#define YY_NUM_RULES 29 +#define YY_END_OF_BUFFER 30 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -492,35 +492,40 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_acclist[128] = +static yyconst flex_int16_t yy_acclist[152] = { 0, - 27, 25, 26, 1, 25, 26, 2, 26, 25, 26, - 20, 25, 26, 21, 25, 26, 24, 25, 26, 25, - 26, 19, 25, 26, 5, 25, 26, 5, 25, 26, - 25, 26, 25, 26,16390, 22, 25, 26, 23, 25, - 26, 25, 26,16390, 25, 26,16390, 25, 26,16390, - 25, 26,16390, 25, 26,16390, 25, 26,16390, 25, - 26,16390, 25, 26,16390, 25, 26,16390, 1, 2, - 3, 5, 7,16390, 8198,16390,16390,16390,16390,16390, - 16390,16390, 18,16390,16390,16390,16390, 4, 14,16390, - 17,16390,16390,16390, 11,16390, 16,16390,16390,16390, + 30, 28, 29, 1, 28, 29, 2, 29, 28, 29, + 20, 28, 29, 21, 28, 29, 24, 28, 29, 28, + 29, 19, 28, 29, 5, 28, 29, 5, 28, 29, + 28, 29, 28, 29,16390, 22, 28, 29, 23, 28, + 29, 28, 29,16390, 28, 29,16390, 28, 29,16390, + 28, 29,16390, 28, 29,16390, 28, 29,16390, 28, + 29,16390, 28, 29,16390, 28, 29,16390, 28, 29, + 16390, 28, 29,16390, 1, 2, 3, 5, 7,16390, + 8198,16390,16390,16390,16390,16390,16390,16390,16390, 18, + 16390,16390,16390,16390,16390,16390, 4, 14,16390, 17, - 16390,16390,16390,16390,16390,16390,16390, 10,16390,16390, - 16390,16390,16390,16390, 15,16390, 12,16390, 8,16390, - 9,16390,16390,16390,16390, 13,16390 + 16390,16390,16390, 11,16390,16390, 16,16390,16390,16390, + 16390,16390,16390,16390,16390,16390,16390,16390, 25,16390, + 16390,16390, 10,16390,16390,16390,16390,16390,16390,16390, + 16390,16390, 15,16390, 12,16390,16390, 8,16390, 9, + 16390,16390,16390, 26,16390,16390, 27,16390,16390, 13, + 16390 } ; -static yyconst flex_int16_t yy_accept[82] = +static yyconst flex_int16_t yy_accept[99] = { 0, 1, 1, 1, 2, 4, 7, 9, 11, 14, 17, 20, 22, 25, 28, 31, 33, 36, 39, 42, 45, - 48, 51, 54, 57, 60, 63, 66, 69, 70, 71, - 71, 72, 73, 73, 74, 74, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, - 89, 91, 93, 94, 95, 97, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 110, 111, 112, 113, - 114, 115, 117, 119, 121, 123, 124, 125, 126, 128, - 128 + 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, + 76, 77, 77, 78, 79, 79, 80, 80, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, + 93, 94, 95, 96, 97, 98, 100, 102, 103, 104, + 106, 107, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 121, 122, 123, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 135, 137, 138, 140, 142, + 143, 144, 146, 147, 149, 150, 152, 152 + } ; static yyconst YY_CHAR yy_ec[256] = @@ -530,15 +535,15 @@ static yyconst YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4, 5, 6, 1, 1, 7, 8, 9, 1, 10, 11, 11, - 11, 12, 11, 11, 11, 11, 11, 1, 1, 1, - 13, 1, 1, 1, 14, 14, 14, 14, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 16, 15, 15, - 17, 1, 18, 1, 19, 1, 20, 21, 22, 23, + 11, 12, 11, 13, 11, 11, 11, 1, 1, 1, + 14, 1, 1, 1, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 17, 16, 16, + 18, 1, 19, 1, 20, 1, 21, 22, 23, 24, - 24, 14, 25, 26, 27, 15, 15, 28, 15, 29, - 30, 31, 15, 32, 33, 34, 35, 15, 15, 36, - 37, 15, 1, 1, 1, 1, 1, 1, 1, 1, + 25, 15, 26, 27, 28, 16, 29, 30, 31, 32, + 33, 34, 16, 35, 36, 37, 38, 16, 16, 39, + 40, 16, 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, 1, 1, 1, 1, 1, @@ -555,118 +560,140 @@ static yyconst YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst YY_CHAR yy_meta[38] = +static yyconst YY_CHAR yy_meta[41] = { 0, 1, 2, 3, 1, 1, 1, 1, 2, 1, 4, - 4, 4, 1, 4, 2, 2, 1, 2, 2, 4, - 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2 + 4, 4, 4, 1, 5, 2, 6, 1, 2, 2, + 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 6, 2 } ; -static yyconst flex_uint16_t yy_base[84] = +static yyconst flex_uint16_t yy_base[102] = { 0, - 0, 0, 202, 219, 167, 155, 138, 219, 219, 219, - 28, 219, 31, 34, 94, 46, 219, 219, 66, 22, - 27, 29, 31, 44, 42, 51, 53, 103, 80, 74, - 219, 77, 0, 219, 88, 90, 68, 219, 70, 81, - 72, 84, 86, 92, 95, 74, 88, 104, 99, 0, - 102, 108, 112, 110, 116, 118, 121, 131, 124, 127, - 134, 136, 138, 143, 145, 147, 149, 153, 156, 175, - 160, 162, 165, 167, 169, 172, 177, 182, 180, 219, - 211, 214, 58 + 0, 0, 122, 289, 103, 82, 70, 289, 289, 289, + 31, 289, 28, 36, 59, 49, 289, 289, 68, 23, + 33, 29, 28, 45, 49, 60, 61, 64, 74, 64, + 59, 46, 289, 100, 0, 289, 105, 112, 50, 289, + 65, 93, 71, 88, 89, 100, 97, 103, 106, 109, + 113, 125, 119, 129, 0, 122, 130, 133, 134, 137, + 141, 142, 147, 155, 159, 152, 160, 151, 172, 164, + 168, 173, 177, 180, 181, 184, 185, 192, 195, 196, + 202, 207, 203, 212, 211, 215, 221, 218, 222, 227, + 232, 228, 231, 235, 240, 239, 289, 272, 275, 280, + + 283 } ; -static yyconst flex_int16_t yy_def[84] = +static yyconst flex_int16_t yy_def[102] = { 0, - 80, 1, 80, 80, 80, 80, 81, 80, 80, 80, - 80, 80, 80, 80, 80, 82, 80, 80, 82, 19, - 19, 19, 19, 19, 19, 19, 19, 80, 80, 81, - 80, 80, 83, 80, 80, 19, 19, 80, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 83, + 97, 1, 97, 97, 97, 97, 98, 97, 97, 97, + 97, 97, 99, 97, 97, 100, 97, 97, 100, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 97, + 97, 98, 97, 97, 101, 97, 97, 19, 19, 97, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 101, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, - 80, 80, 80 + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 97, 97, 97, + + 97 } ; -static yyconst flex_uint16_t yy_nxt[257] = +static yyconst flex_uint16_t yy_nxt[330] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 14, 15, 16, 16, 16, 17, 18, 4, 19, - 16, 20, 16, 21, 16, 22, 16, 16, 23, 24, - 16, 25, 26, 27, 16, 16, 16, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 33, 35, 35, 37, - 37, 41, 43, 36, 37, 37, 37, 37, 37, 37, - 44, 50, 42, 38, 36, 47, 33, 35, 35, 37, - 37, 37, 37, 36, 45, 46, 49, 31, 37, 37, - 37, 37, 29, 38, 36, 48, 32, 32, 32, 35, - 35, 80, 80, 39, 40, 37, 37, 51, 37, 37, + 14, 14, 14, 15, 16, 16, 16, 17, 18, 4, + 19, 16, 20, 16, 21, 16, 22, 16, 16, 16, + 23, 24, 25, 26, 27, 28, 29, 16, 16, 16, + 34, 34, 34, 34, 35, 34, 34, 34, 34, 33, + 37, 37, 39, 45, 39, 43, 38, 39, 39, 39, + 39, 31, 39, 46, 39, 30, 35, 40, 38, 37, + 37, 44, 36, 33, 39, 38, 39, 47, 39, 39, + 39, 39, 48, 49, 31, 51, 40, 38, 50, 39, + 39, 39, 39, 39, 56, 39, 39, 41, 53, 42, - 53, 37, 37, 52, 28, 38, 34, 80, 37, 37, - 54, 37, 37, 37, 37, 58, 37, 37, 37, 37, - 37, 55, 37, 37, 59, 56, 37, 37, 57, 37, - 37, 37, 37, 61, 60, 37, 37, 37, 37, 37, - 37, 31, 62, 37, 37, 37, 37, 63, 37, 37, - 64, 37, 37, 67, 37, 37, 65, 29, 37, 37, - 66, 37, 37, 37, 37, 37, 37, 69, 28, 68, - 37, 37, 37, 37, 37, 37, 37, 37, 71, 70, - 37, 37, 72, 37, 74, 73, 75, 37, 37, 37, - 37, 76, 37, 37, 37, 37, 37, 37, 77, 37, + 39, 52, 58, 39, 30, 39, 37, 37, 54, 34, + 34, 34, 34, 97, 97, 59, 57, 39, 39, 39, + 39, 97, 39, 40, 39, 61, 39, 60, 39, 39, + 97, 39, 39, 62, 39, 39, 97, 39, 39, 63, + 39, 39, 65, 39, 39, 64, 66, 97, 39, 68, + 39, 39, 97, 39, 39, 69, 39, 67, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 73, 39, 70, + 39, 39, 39, 39, 72, 97, 39, 71, 39, 74, + 39, 39, 77, 39, 39, 97, 39, 75, 39, 39, + 39, 39, 78, 39, 97, 39, 76, 39, 97, 39, - 37, 80, 37, 37, 37, 78, 79, 37, 37, 37, - 37, 30, 30, 80, 30, 37, 37, 37, 3, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80 + 79, 39, 39, 39, 39, 81, 39, 80, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 83, 89, 82, + 84, 39, 97, 39, 39, 39, 39, 39, 85, 87, + 86, 39, 39, 88, 39, 97, 39, 90, 39, 91, + 39, 39, 39, 39, 39, 92, 39, 39, 97, 39, + 39, 39, 39, 39, 93, 94, 39, 39, 39, 39, + 39, 39, 95, 39, 39, 96, 39, 97, 39, 39, + 39, 39, 32, 32, 97, 32, 32, 32, 34, 97, + 34, 39, 39, 39, 39, 39, 55, 55, 3, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97 } ; -static yyconst flex_int16_t yy_chk[257] = +static yyconst flex_int16_t yy_chk[330] = { 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, 1, 1, 1, 1, 11, 11, 11, - 13, 13, 13, 14, 14, 14, 13, 16, 16, 20, - 20, 20, 22, 16, 21, 21, 22, 22, 23, 23, - 23, 83, 21, 16, 16, 25, 13, 19, 19, 25, - 25, 24, 24, 19, 24, 24, 27, 30, 26, 26, - 27, 27, 29, 19, 19, 26, 32, 32, 32, 35, - 35, 36, 36, 19, 19, 37, 37, 39, 39, 41, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 11, 11, 11, 13, 14, 14, 14, 14, 32, + 16, 16, 20, 22, 20, 20, 16, 23, 22, 23, + 22, 31, 21, 23, 21, 30, 13, 16, 16, 19, + 19, 21, 15, 7, 24, 19, 24, 24, 25, 39, + 25, 39, 25, 25, 6, 27, 19, 19, 26, 26, + 27, 26, 27, 28, 41, 28, 41, 19, 29, 19, - 41, 46, 46, 40, 28, 35, 15, 36, 40, 40, - 42, 42, 42, 43, 43, 47, 47, 36, 36, 44, - 44, 43, 45, 45, 48, 44, 49, 49, 45, 51, - 51, 48, 48, 53, 49, 52, 52, 54, 54, 53, - 53, 7, 54, 55, 55, 56, 56, 57, 57, 57, - 58, 59, 59, 61, 60, 60, 59, 6, 58, 58, - 60, 61, 61, 62, 62, 63, 63, 63, 5, 62, - 64, 64, 65, 65, 66, 66, 67, 67, 65, 64, - 68, 68, 67, 69, 69, 68, 70, 71, 71, 72, - 72, 71, 73, 73, 74, 74, 75, 75, 76, 76, + 43, 28, 43, 29, 5, 29, 37, 37, 29, 34, + 34, 34, 34, 38, 38, 44, 42, 44, 45, 44, + 45, 3, 42, 37, 42, 46, 47, 45, 47, 46, + 38, 46, 48, 47, 48, 49, 0, 49, 50, 48, + 50, 38, 51, 38, 51, 50, 52, 0, 53, 54, + 53, 56, 0, 56, 52, 58, 52, 53, 54, 57, + 54, 57, 58, 59, 58, 59, 60, 64, 60, 59, + 61, 62, 61, 62, 63, 0, 63, 61, 63, 65, + 68, 66, 68, 66, 64, 0, 64, 66, 65, 67, + 65, 67, 69, 70, 0, 70, 67, 71, 0, 71, - 76, 3, 70, 70, 77, 77, 78, 79, 79, 78, - 78, 81, 81, 0, 81, 82, 82, 82, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80 + 70, 69, 72, 69, 72, 72, 73, 71, 73, 74, + 75, 74, 75, 76, 77, 76, 77, 75, 82, 74, + 77, 78, 0, 78, 79, 80, 79, 80, 78, 80, + 79, 81, 83, 81, 83, 0, 82, 83, 82, 84, + 85, 84, 85, 84, 86, 87, 86, 88, 0, 88, + 87, 89, 87, 89, 90, 91, 90, 92, 90, 92, + 93, 91, 93, 91, 94, 95, 94, 0, 96, 95, + 96, 95, 98, 98, 0, 98, 98, 98, 99, 0, + 99, 100, 100, 100, 100, 100, 101, 101, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[27] = +static yyconst flex_int32_t yy_rule_can_match_eol[30] = { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, }; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; extern int yy_flex_debug; int yy_flex_debug = 1; -static yyconst flex_int16_t yy_rule_linenum[26] = +static yyconst flex_int16_t yy_rule_linenum[29] = { 0, 78, 82, 88, 98, 104, 118, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 144 + 139, 140, 141, 142, 144, 145, 146, 148 } ; static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; @@ -743,7 +770,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 747 "lexer.cc" +#line 774 "lexer.cc" #define INITIAL 0 @@ -1040,7 +1067,7 @@ YY_DECL loc.step(); -#line 1044 "lexer.cc" +#line 1071 "lexer.cc" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1068,14 +1095,14 @@ yy_match: 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 >= 81 ) + if ( yy_current_state >= 98 ) 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 != 80 ); + while ( yy_current_state != 97 ); yy_find_action: /* %% [10.0] code to find the action number goes here */ @@ -1138,13 +1165,13 @@ do_action: /* This label is used only to access EOF actions. */ { if ( yy_act == 0 ) fprintf( stderr, "--scanner backing up\n" ); - else if ( yy_act < 26 ) + else if ( yy_act < 29 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 26 ) + else if ( yy_act == 29 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 27 ) + else if ( yy_act == 30 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1314,18 +1341,33 @@ return isc::eval::EvalParser::make_COMA(loc); case 25: YY_RULE_SETUP #line 144 "lexer.ll" -driver.error (loc, "Invalid character: " + std::string(yytext)); - YY_BREAK -case YY_STATE_EOF(INITIAL): -#line 145 "lexer.ll" -return isc::eval::EvalParser::make_END(loc); +return isc::eval::EvalParser::make_PKT6(loc); YY_BREAK case 26: YY_RULE_SETUP +#line 145 "lexer.ll" +return isc::eval::EvalParser::make_MSGTYPE(loc); + YY_BREAK +case 27: +YY_RULE_SETUP #line 146 "lexer.ll" +return isc::eval::EvalParser::make_TRANSID(loc); + YY_BREAK +case 28: +YY_RULE_SETUP +#line 148 "lexer.ll" +driver.error (loc, "Invalid character: " + std::string(yytext)); + YY_BREAK +case YY_STATE_EOF(INITIAL): +#line 149 "lexer.ll" +return isc::eval::EvalParser::make_END(loc); + YY_BREAK +case 29: +YY_RULE_SETUP +#line 150 "lexer.ll" ECHO; YY_BREAK -#line 1329 "lexer.cc" +#line 1371 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1610,7 +1652,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 >= 81 ) + if ( yy_current_state >= 98 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1638,11 +1680,11 @@ 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 >= 81 ) + if ( yy_current_state >= 98 ) 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 == 80); + yy_is_jam = (yy_current_state == 97); if ( ! yy_is_jam ) *(yy_state_ptr)++ = yy_current_state; @@ -2408,7 +2450,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 146 "lexer.ll" +#line 150 "lexer.ll" diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 0ad7285eba..b93a40c454 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -141,6 +141,10 @@ blank [ \t] "]" return isc::eval::EvalParser::make_RBRACKET(loc); "," return isc::eval::EvalParser::make_COMA(loc); +"pkt6" return isc::eval::EvalParser::make_PKT6(loc); +"msgtype" return isc::eval::EvalParser::make_MSGTYPE(loc); +"transid" return isc::eval::EvalParser::make_TRANSID(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 0effbea998..e89dab1532 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -251,18 +251,22 @@ namespace isc { namespace eval { { switch (that.type_get ()) { - case 30: // option_repr_type + case 33: // option_repr_type value.move< TokenOption::RepresentationType > (that.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" + case 36: // pkt6_field + value.move< TokenPkt6::FieldType > (that.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" value.move< std::string > (that.value); break; - case 29: // option_code + case 32: // option_code value.move< uint16_t > (that.value); break; @@ -281,18 +285,22 @@ namespace isc { namespace eval { state = that.state; switch (that.type_get ()) { - case 30: // option_repr_type + case 33: // option_repr_type value.copy< TokenOption::RepresentationType > (that.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" + case 36: // pkt6_field + value.copy< TokenPkt6::FieldType > (that.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" value.copy< std::string > (that.value); break; - case 29: // option_code + case 32: // option_code value.copy< uint16_t > (that.value); break; @@ -332,46 +340,53 @@ namespace isc { namespace eval { << yysym.location << ": "; switch (yytype) { - case 21: // "constant string" + case 24: // "constant string" -#line 72 "parser.yy" // lalr1.cc:636 +#line 76 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 340 "parser.cc" // lalr1.cc:636 +#line 348 "parser.cc" // lalr1.cc:636 break; - case 22: // "integer" + case 25: // "integer" -#line 72 "parser.yy" // lalr1.cc:636 +#line 76 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 347 "parser.cc" // lalr1.cc:636 +#line 355 "parser.cc" // lalr1.cc:636 break; - case 23: // "constant hexstring" + case 26: // "constant hexstring" -#line 72 "parser.yy" // lalr1.cc:636 +#line 76 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 354 "parser.cc" // lalr1.cc:636 +#line 362 "parser.cc" // lalr1.cc:636 break; - case 24: // "option name" + case 27: // "option name" -#line 72 "parser.yy" // lalr1.cc:636 +#line 76 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 361 "parser.cc" // lalr1.cc:636 +#line 369 "parser.cc" // lalr1.cc:636 break; - case 29: // option_code + case 32: // option_code -#line 72 "parser.yy" // lalr1.cc:636 +#line 76 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< uint16_t > (); } -#line 368 "parser.cc" // lalr1.cc:636 +#line 376 "parser.cc" // lalr1.cc:636 break; - case 30: // option_repr_type + case 33: // option_repr_type -#line 72 "parser.yy" // lalr1.cc:636 +#line 76 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); } -#line 375 "parser.cc" // lalr1.cc:636 +#line 383 "parser.cc" // lalr1.cc:636 + break; + + case 36: // pkt6_field + +#line 76 "parser.yy" // lalr1.cc:636 + { yyoutput << yysym.value.template as< TokenPkt6::FieldType > (); } +#line 390 "parser.cc" // lalr1.cc:636 break; @@ -571,18 +586,22 @@ namespace isc { namespace eval { when using variants. */ switch (yyr1_[yyn]) { - case 30: // option_repr_type + case 33: // option_repr_type yylhs.value.build< TokenOption::RepresentationType > (); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" + case 36: // pkt6_field + yylhs.value.build< TokenPkt6::FieldType > (); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" yylhs.value.build< std::string > (); break; - case 29: // option_code + case 32: // option_code yylhs.value.build< uint16_t > (); break; @@ -604,52 +623,52 @@ namespace isc { namespace eval { switch (yyn) { case 4: -#line 86 "parser.yy" // lalr1.cc:859 +#line 90 "parser.yy" // lalr1.cc:859 { TokenPtr neg(new TokenNot()); ctx.expression.push_back(neg); } -#line 613 "parser.cc" // lalr1.cc:859 +#line 632 "parser.cc" // lalr1.cc:859 break; case 5: -#line 91 "parser.yy" // lalr1.cc:859 +#line 95 "parser.yy" // lalr1.cc:859 { TokenPtr neg(new TokenAnd()); ctx.expression.push_back(neg); } -#line 622 "parser.cc" // lalr1.cc:859 +#line 641 "parser.cc" // lalr1.cc:859 break; case 6: -#line 96 "parser.yy" // lalr1.cc:859 +#line 100 "parser.yy" // lalr1.cc:859 { TokenPtr neg(new TokenOr()); ctx.expression.push_back(neg); } -#line 631 "parser.cc" // lalr1.cc:859 +#line 650 "parser.cc" // lalr1.cc:859 break; case 7: -#line 101 "parser.yy" // lalr1.cc:859 +#line 105 "parser.yy" // lalr1.cc:859 { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); } -#line 640 "parser.cc" // lalr1.cc:859 +#line 659 "parser.cc" // lalr1.cc:859 break; case 8: -#line 106 "parser.yy" // lalr1.cc:859 +#line 110 "parser.yy" // lalr1.cc:859 { TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS)); ctx.expression.push_back(opt); } -#line 649 "parser.cc" // lalr1.cc:859 +#line 668 "parser.cc" // lalr1.cc:859 break; case 9: -#line 111 "parser.yy" // lalr1.cc:859 +#line 115 "parser.yy" // lalr1.cc:859 { switch (ctx.getUniverse()) { case Option::V4: @@ -669,38 +688,47 @@ namespace isc { namespace eval { error(yystack_[5].location, "relay4 can only be used in DHCPv4."); } } -#line 673 "parser.cc" // lalr1.cc:859 +#line 692 "parser.cc" // lalr1.cc:859 break; case 10: -#line 133 "parser.yy" // lalr1.cc:859 +#line 135 "parser.yy" // lalr1.cc:859 + { + TokenPtr pkt6field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ())); + ctx.expression.push_back(pkt6field); + } +#line 701 "parser.cc" // lalr1.cc:859 + break; + + case 11: +#line 142 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 682 "parser.cc" // lalr1.cc:859 +#line 710 "parser.cc" // lalr1.cc:859 break; - case 11: -#line 138 "parser.yy" // lalr1.cc:859 + case 12: +#line 147 "parser.yy" // lalr1.cc:859 { TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(hex); } -#line 691 "parser.cc" // lalr1.cc:859 +#line 719 "parser.cc" // lalr1.cc:859 break; - case 12: -#line 143 "parser.yy" // lalr1.cc:859 + case 13: +#line 152 "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 700 "parser.cc" // lalr1.cc:859 +#line 728 "parser.cc" // lalr1.cc:859 break; - case 13: -#line 148 "parser.yy" // lalr1.cc:859 + case 14: +#line 157 "parser.yy" // lalr1.cc:859 { switch (ctx.getUniverse()) { case Option::V4: @@ -720,88 +748,100 @@ namespace isc { namespace eval { error(yystack_[5].location, "relay4 can only be used in DHCPv4."); } } -#line 724 "parser.cc" // lalr1.cc:859 +#line 752 "parser.cc" // lalr1.cc:859 break; - case 14: -#line 168 "parser.yy" // lalr1.cc:859 + case 15: +#line 177 "parser.yy" // lalr1.cc:859 { TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } -#line 733 "parser.cc" // lalr1.cc:859 +#line 761 "parser.cc" // lalr1.cc:859 break; - case 15: -#line 173 "parser.yy" // lalr1.cc:859 + case 16: +#line 182 "parser.yy" // lalr1.cc:859 { TokenPtr conc(new TokenConcat()); ctx.expression.push_back(conc); } -#line 742 "parser.cc" // lalr1.cc:859 - break; - - case 16: -#line 180 "parser.yy" // lalr1.cc:859 - { - yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location); - } -#line 750 "parser.cc" // lalr1.cc:859 +#line 770 "parser.cc" // lalr1.cc:859 break; case 17: -#line 184 "parser.yy" // lalr1.cc:859 +#line 189 "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 758 "parser.cc" // lalr1.cc:859 +#line 778 "parser.cc" // lalr1.cc:859 break; case 18: -#line 190 "parser.yy" // lalr1.cc:859 +#line 193 "parser.yy" // lalr1.cc:859 { - yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL; - } -#line 766 "parser.cc" // lalr1.cc:859 + yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location); + } +#line 786 "parser.cc" // lalr1.cc:859 break; case 19: -#line 194 "parser.yy" // lalr1.cc:859 +#line 199 "parser.yy" // lalr1.cc:859 { - yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL; + yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL; } -#line 774 "parser.cc" // lalr1.cc:859 +#line 794 "parser.cc" // lalr1.cc:859 break; case 20: -#line 200 "parser.yy" // lalr1.cc:859 +#line 203 "parser.yy" // lalr1.cc:859 + { + yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL; + } +#line 802 "parser.cc" // lalr1.cc:859 + break; + + case 21: +#line 209 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 783 "parser.cc" // lalr1.cc:859 +#line 811 "parser.cc" // lalr1.cc:859 break; - case 21: -#line 207 "parser.yy" // lalr1.cc:859 + case 22: +#line 216 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 792 "parser.cc" // lalr1.cc:859 +#line 820 "parser.cc" // lalr1.cc:859 break; - case 22: -#line 212 "parser.yy" // lalr1.cc:859 + case 23: +#line 221 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString("all")); ctx.expression.push_back(str); } -#line 801 "parser.cc" // lalr1.cc:859 +#line 829 "parser.cc" // lalr1.cc:859 + break; + + case 24: +#line 227 "parser.yy" // lalr1.cc:859 + { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE; } +#line 835 "parser.cc" // lalr1.cc:859 + break; + + case 25: +#line 228 "parser.yy" // lalr1.cc:859 + { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::TRANSID; } +#line 841 "parser.cc" // lalr1.cc:859 break; -#line 805 "parser.cc" // lalr1.cc:859 +#line 845 "parser.cc" // lalr1.cc:859 default: break; } @@ -1056,98 +1096,98 @@ namespace isc { namespace eval { } - const signed char EvalParser::yypact_ninf_ = -29; + const signed char EvalParser::yypact_ninf_ = -42; const signed char EvalParser::yytable_ninf_ = -1; const signed char EvalParser::yypact_[] = { - -1, -1, -1, 1, 10, 28, 36, -29, -29, 32, - 0, 41, 29, -29, -7, -7, 17, 17, -29, -1, - -1, 17, -29, -29, -29, 38, 39, 42, 43, 37, - 40, -29, 46, -29, 44, 45, -7, -7, 47, 17, - 27, 30, 48, 49, -29, 51, 58, -29, -29, -29, - -29, -29, -29, 50, 52, -4, -29, 33, 33, -29, - -29, 60, -29 + -1, -1, -1, 10, 13, 35, 45, 39, -42, -42, + 26, 6, 46, 11, -42, 12, 12, 23, 23, 19, + -42, -1, -1, 23, -42, -42, -42, 41, 43, 47, + 48, 37, 38, -42, -42, -42, -42, 54, -42, 49, + 50, 12, 12, 40, 23, 20, 30, 52, 55, -42, + 42, 62, -42, -42, -42, -42, -42, -42, 56, 57, + -11, -42, 36, 36, -42, -42, 64, -42 }; const unsigned char EvalParser::yydefact_[] = { - 0, 0, 0, 0, 0, 0, 0, 10, 11, 0, - 2, 0, 0, 4, 0, 0, 0, 0, 1, 0, - 0, 0, 3, 16, 17, 0, 0, 0, 0, 0, - 0, 5, 6, 7, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 20, 0, 0, 18, 19, 8, - 12, 9, 13, 0, 0, 0, 15, 0, 0, 22, - 21, 0, 14 + 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, + 0, 2, 0, 0, 4, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 17, 18, 0, 0, 0, + 0, 0, 0, 24, 25, 10, 5, 6, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 0, 0, 19, 20, 8, 13, 9, 14, 0, 0, + 0, 16, 0, 0, 23, 22, 0, 15 }; const signed char EvalParser::yypgoto_[] = { - -29, -29, 9, -16, -12, -28, -29, -29 + -42, -42, 9, -17, -13, -41, -42, -42, -42 }; const signed char EvalParser::yydefgoto_[] = { - -1, 9, 10, 11, 25, 50, 45, 61 + -1, 10, 11, 12, 27, 55, 50, 66, 35 }; const unsigned char EvalParser::yytable_[] = { - 29, 30, 1, 26, 2, 33, 19, 20, 3, 4, - 12, 13, 14, 52, 59, 23, 5, 24, 60, 6, - 7, 15, 8, 46, 42, 43, 27, 28, 31, 32, - 52, 16, 18, 22, 5, 19, 20, 6, 7, 17, - 8, 47, 48, 49, 47, 48, 51, 47, 48, 21, - 34, 35, 19, 36, 37, 0, 38, 40, 41, 39, - 53, 54, 56, 57, 62, 58, 0, 0, 0, 44, - 55 + 31, 32, 1, 28, 2, 57, 38, 64, 3, 4, + 13, 14, 21, 22, 65, 24, 5, 21, 22, 6, + 7, 15, 57, 8, 16, 9, 20, 51, 47, 48, + 36, 37, 29, 30, 52, 53, 54, 25, 17, 26, + 5, 33, 34, 6, 52, 53, 56, 8, 18, 9, + 52, 53, 19, 39, 23, 40, 43, 44, 41, 42, + 21, 60, 45, 46, 58, 49, 61, 59, 67, 62, + 63 }; - const signed char + const unsigned char EvalParser::yycheck_[] = { - 16, 17, 3, 15, 5, 21, 6, 7, 9, 10, - 1, 2, 11, 41, 18, 22, 17, 24, 22, 20, - 21, 11, 23, 39, 36, 37, 9, 10, 19, 20, - 58, 3, 0, 4, 17, 6, 7, 20, 21, 3, - 23, 14, 15, 16, 14, 15, 16, 14, 15, 8, - 12, 12, 6, 11, 11, -1, 19, 13, 13, 19, - 12, 12, 4, 13, 4, 13, -1, -1, -1, 22, - 19 + 17, 18, 3, 16, 5, 46, 23, 18, 9, 10, + 1, 2, 6, 7, 25, 4, 17, 6, 7, 20, + 21, 11, 63, 24, 11, 26, 0, 44, 41, 42, + 21, 22, 9, 10, 14, 15, 16, 25, 3, 27, + 17, 22, 23, 20, 14, 15, 16, 24, 3, 26, + 14, 15, 13, 12, 8, 12, 19, 19, 11, 11, + 6, 19, 13, 13, 12, 25, 4, 12, 4, 13, + 13 }; const unsigned char EvalParser::yystos_[] = { - 0, 3, 5, 9, 10, 17, 20, 21, 23, 26, - 27, 28, 27, 27, 11, 11, 3, 3, 0, 6, - 7, 8, 4, 22, 24, 29, 29, 9, 10, 28, - 28, 27, 27, 28, 12, 12, 11, 11, 19, 19, - 13, 13, 29, 29, 22, 31, 28, 14, 15, 16, - 30, 16, 30, 12, 12, 19, 4, 13, 13, 18, - 22, 32, 4 + 0, 3, 5, 9, 10, 17, 20, 21, 24, 26, + 29, 30, 31, 30, 30, 11, 11, 3, 3, 13, + 0, 6, 7, 8, 4, 25, 27, 32, 32, 9, + 10, 31, 31, 22, 23, 36, 30, 30, 31, 12, + 12, 11, 11, 19, 19, 13, 13, 32, 32, 25, + 34, 31, 14, 15, 16, 33, 16, 33, 12, 12, + 19, 4, 13, 13, 18, 25, 35, 4 }; const unsigned char EvalParser::yyr1_[] = { - 0, 25, 26, 27, 27, 27, 27, 27, 27, 27, - 28, 28, 28, 28, 28, 28, 29, 29, 30, 30, - 31, 32, 32 + 0, 28, 29, 30, 30, 30, 30, 30, 30, 30, + 30, 31, 31, 31, 31, 31, 31, 32, 32, 33, + 33, 34, 35, 35, 36, 36 }; const unsigned char EvalParser::yyr2_[] = { 0, 2, 1, 3, 2, 3, 3, 3, 6, 6, - 1, 1, 6, 6, 8, 6, 1, 1, 1, 1, - 1, 1, 1 + 3, 1, 1, 6, 6, 8, 6, 1, 1, 1, + 1, 1, 1, 1, 1, 1 }; @@ -1160,19 +1200,20 @@ namespace isc { namespace eval { "\"end of file\"", "error", "$undefined", "\"(\"", "\")\"", "\"not\"", "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"[\"", "\"]\"", "\".\"", "\"text\"", "\"hex\"", "\"exists\"", "\"substring\"", - "\"all\"", "\",\"", "\"concat\"", "\"constant string\"", "\"integer\"", + "\"all\"", "\",\"", "\"concat\"", "\"pkt6\"", "\"msgtype\"", + "\"transid\"", "\"constant string\"", "\"integer\"", "\"constant hexstring\"", "\"option name\"", "$accept", "expression", "bool_expr", "string_expr", "option_code", "option_repr_type", - "start_expr", "length_expr", YY_NULLPTR + "start_expr", "length_expr", "pkt6_field", YY_NULLPTR }; #if YYDEBUG const unsigned char EvalParser::yyrline_[] = { - 0, 81, 81, 84, 85, 90, 95, 100, 105, 110, - 132, 137, 142, 147, 167, 172, 179, 183, 189, 193, - 199, 206, 211 + 0, 85, 85, 88, 89, 94, 99, 104, 109, 114, + 134, 141, 146, 151, 156, 176, 181, 188, 192, 198, + 202, 208, 215, 220, 227, 228 }; // Print the state stack on the debug stream. @@ -1207,8 +1248,8 @@ namespace isc { namespace eval { #line 13 "parser.yy" // lalr1.cc:1167 } } // isc::eval -#line 1211 "parser.cc" // lalr1.cc:1167 -#line 218 "parser.yy" // lalr1.cc:1168 +#line 1252 "parser.cc" // lalr1.cc:1167 +#line 231 "parser.yy" // lalr1.cc:1168 void isc::eval::EvalParser::error(const location_type& loc, diff --git a/src/lib/eval/parser.h b/src/lib/eval/parser.h index 27e4a4320b..a6bf07cd5c 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -298,14 +298,17 @@ namespace isc { namespace eval { // option_repr_type char dummy1[sizeof(TokenOption::RepresentationType)]; + // pkt6_field + char dummy2[sizeof(TokenPkt6::FieldType)]; + // "constant string" // "integer" // "constant hexstring" // "option name" - char dummy2[sizeof(std::string)]; + char dummy3[sizeof(std::string)]; // option_code - char dummy3[sizeof(uint16_t)]; + char dummy4[sizeof(uint16_t)]; }; /// Symbol semantic values. @@ -347,10 +350,13 @@ namespace isc { namespace eval { TOKEN_ALL = 273, TOKEN_COMA = 274, TOKEN_CONCAT = 275, - TOKEN_STRING = 276, - TOKEN_INTEGER = 277, - TOKEN_HEXSTRING = 278, - TOKEN_OPTION_NAME = 279 + TOKEN_PKT6 = 276, + TOKEN_MSGTYPE = 277, + TOKEN_TRANSID = 278, + TOKEN_STRING = 279, + TOKEN_INTEGER = 280, + TOKEN_HEXSTRING = 281, + TOKEN_OPTION_NAME = 282 }; }; @@ -390,6 +396,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 TokenPkt6::FieldType v, const location_type& l); + basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l); basic_symbol (typename Base::kind_type t, const uint16_t v, const location_type& l); @@ -537,6 +545,18 @@ namespace isc { namespace eval { symbol_type make_CONCAT (const location_type& l); + static inline + symbol_type + make_PKT6 (const location_type& l); + + static inline + symbol_type + make_MSGTYPE (const location_type& l); + + static inline + symbol_type + make_TRANSID (const location_type& l); + static inline symbol_type make_STRING (const std::string& v, const location_type& l); @@ -638,7 +658,7 @@ namespace isc { namespace eval { // number is the opposite. If YYTABLE_NINF, syntax error. static const unsigned char yytable_[]; - static const signed char yycheck_[]; + static const unsigned char yycheck_[]; // YYSTOS[STATE-NUM] -- The (internal number of the) accessing // symbol of state STATE-NUM. @@ -759,11 +779,11 @@ namespace isc { namespace eval { { yyeof_ = 0, yylast_ = 70, ///< Last index in yytable_. - yynnts_ = 8, ///< Number of nonterminal symbols. - yyfinal_ = 18, ///< Termination state number. + yynnts_ = 9, ///< Number of nonterminal symbols. + yyfinal_ = 20, ///< Termination state number. yyterror_ = 1, yyerrcode_ = 256, - yyntokens_ = 25 ///< Number of tokens. + yyntokens_ = 28 ///< Number of tokens. }; @@ -807,9 +827,10 @@ namespace isc { namespace eval { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27 }; - const unsigned int user_token_number_max_ = 279; + const unsigned int user_token_number_max_ = 282; const token_number_type undef_token_ = 2; if (static_cast(t) <= yyeof_) @@ -842,18 +863,22 @@ namespace isc { namespace eval { { switch (other.type_get ()) { - case 30: // option_repr_type + case 33: // option_repr_type value.copy< TokenOption::RepresentationType > (other.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" + case 36: // pkt6_field + value.copy< TokenPkt6::FieldType > (other.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" value.copy< std::string > (other.value); break; - case 29: // option_code + case 32: // option_code value.copy< uint16_t > (other.value); break; @@ -874,18 +899,22 @@ namespace isc { namespace eval { (void) v; switch (this->type_get ()) { - case 30: // option_repr_type + case 33: // option_repr_type value.copy< TokenOption::RepresentationType > (v); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" + case 36: // pkt6_field + value.copy< TokenPkt6::FieldType > (v); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" value.copy< std::string > (v); break; - case 29: // option_code + case 32: // option_code value.copy< uint16_t > (v); break; @@ -911,6 +940,13 @@ namespace isc { namespace eval { , location (l) {} + template + EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const TokenPkt6::FieldType v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} + template EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l) : Base (t) @@ -951,18 +987,22 @@ namespace isc { namespace eval { // Type destructor. switch (yytype) { - case 30: // option_repr_type + case 33: // option_repr_type value.template destroy< TokenOption::RepresentationType > (); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" + case 36: // pkt6_field + value.template destroy< TokenPkt6::FieldType > (); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" value.template destroy< std::string > (); break; - case 29: // option_code + case 32: // option_code value.template destroy< uint16_t > (); break; @@ -989,18 +1029,22 @@ namespace isc { namespace eval { super_type::move(s); switch (this->type_get ()) { - case 30: // option_repr_type + case 33: // option_repr_type value.move< TokenOption::RepresentationType > (s.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" + case 36: // pkt6_field + value.move< TokenPkt6::FieldType > (s.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" value.move< std::string > (s.value); break; - case 29: // option_code + case 32: // option_code value.move< uint16_t > (s.value); break; @@ -1061,7 +1105,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 + 275, 276, 277, 278, 279, 280, 281, 282 }; return static_cast (yytoken_number_[type]); } @@ -1180,6 +1224,24 @@ namespace isc { namespace eval { return symbol_type (token::TOKEN_CONCAT, l); } + EvalParser::symbol_type + EvalParser::make_PKT6 (const location_type& l) + { + return symbol_type (token::TOKEN_PKT6, l); + } + + EvalParser::symbol_type + EvalParser::make_MSGTYPE (const location_type& l) + { + return symbol_type (token::TOKEN_MSGTYPE, l); + } + + EvalParser::symbol_type + EvalParser::make_TRANSID (const location_type& l) + { + return symbol_type (token::TOKEN_TRANSID, l); + } + EvalParser::symbol_type EvalParser::make_STRING (const std::string& v, const location_type& l) { @@ -1207,7 +1269,7 @@ namespace isc { namespace eval { #line 13 "parser.yy" // lalr1.cc:377 } } // isc::eval -#line 1211 "parser.h" // lalr1.cc:377 +#line 1273 "parser.h" // lalr1.cc:377 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index 6e4b21670a..97324009ef 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -55,6 +55,9 @@ using namespace isc::eval; ALL "all" COMA "," CONCAT "concat" + PKT6 "pkt6" + MSGTYPE "msgtype" + TRANSID "transid" ; %token STRING "constant string" @@ -64,6 +67,7 @@ using namespace isc::eval; %type option_code %type option_repr_type +%type pkt6_field %left OR %left AND @@ -127,6 +131,11 @@ bool_expr : "(" bool_expr ")" error(@1, "relay4 can only be used in DHCPv4."); } } + | PKT6 "." pkt6_field + { + TokenPtr pkt6field(new TokenPkt6($3)); + ctx.expression.push_back(pkt6field); + } ; string_expr : STRING @@ -215,6 +224,10 @@ length_expr : INTEGER } ; +pkt6_field:MSGTYPE { $$ = TokenPkt6::MSGTYPE; } + | TRANSID { $$ = TokenPkt6::TRANSID; } + ; + %% void isc::eval::EvalParser::error(const location_type& loc, diff --git a/src/lib/eval/token.cc b/src/lib/eval/token.cc index 041b30feb9..05b784ec7b 100644 --- a/src/lib/eval/token.cc +++ b/src/lib/eval/token.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -273,3 +274,36 @@ TokenOr::evaluate(const Pkt& /*pkt*/, ValueStack& values) { values.push("false"); } } + +void +TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) { + + try { + // Check if it's a Pkt6. If it's not the dynamic_cast will throw + // std::bad_cast (failed dynamic_cast returns NULL for pointers and + // throws for references). + const Pkt6& pkt6 = dynamic_cast(pkt); + + switch (type_) { + case MSGTYPE: { + // msg type is an uint8_t integer. We need to represent it as a string. + stringstream tmp; + tmp << static_cast(pkt6.getType()); + values.push(tmp.str()); + return; + } + case TRANSID: { + // transaction id is an uint32_t integer. We need to represent it as a string. + stringstream tmp; + tmp << static_cast(pkt6.getTransid()); + values.push(tmp.str()); + return; + } + default: + isc_throw(EvalTypeError, "Bad filed specified: " + << static_cast(type_) ); + } + } catch (const std::bad_cast&) { + isc_throw(EvalTypeError, "Specified packet is not Pkt6"); + } +}; diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h index eb29a06e02..598b968ad9 100644 --- a/src/lib/eval/token.h +++ b/src/lib/eval/token.h @@ -444,6 +444,50 @@ public: void evaluate(const Pkt& pkt, ValueStack& values); }; +/// @brief Token that represents fields of DHCPv6 packet. +/// +/// For example in the expression pkt6.msgtype == "1" +/// this token represents the message type of the DHCPv6 packet +/// +/// Currently supported fields are: +/// - msgtype +/// - transid +class TokenPkt6 : public Token { +public: + /// @brief enum value that determins the field. + enum FieldType { + MSGTYPE, ///< msg type + TRANSID ///< transaction id (integer but manipulated as as string) + }; + + /// @brief Constructor (does nothing) + TokenPkt6(const FieldType type) + : type_(type) {} + + /// @brief Gets a value of the specified packet. + /// + /// The evaluation uses fields that are availabe in the packet. It does not + /// require any values to be present on the stack. + /// + /// @throw EvalTypeError when called for a DHCPv4 packet + /// + /// @param pkt - packet from which to extract the fields + /// @param values - stack of values, 1 result will be pushed + void evaluate(const Pkt& pkt, ValueStack& values); + + /// @breif 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 DHCPv6 packet to get + FieldType type_; +}; + }; // end of isc::dhcp namespace }; // end of isc namespace From f6c8fa1b54958b5d292a562d987b968cb30c6736 Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Mon, 21 Mar 2016 21:50:08 -0700 Subject: [PATCH 2/7] [trac4269] Add unit tests and move the parse code to the right place --- src/lib/eval/parser.yy | 10 ++--- src/lib/eval/tests/context_unittest.cc | 56 ++++++++++++++++++++++++++ src/lib/eval/tests/token_unittest.cc | 19 +++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index 97324009ef..ac8a1334a5 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -131,11 +131,6 @@ bool_expr : "(" bool_expr ")" error(@1, "relay4 can only be used in DHCPv4."); } } - | PKT6 "." pkt6_field - { - TokenPtr pkt6field(new TokenPkt6($3)); - ctx.expression.push_back(pkt6field); - } ; string_expr : STRING @@ -183,6 +178,11 @@ string_expr : STRING TokenPtr conc(new TokenConcat()); ctx.expression.push_back(conc); } + | PKT6 "." pkt6_field + { + TokenPtr pkt6field(new TokenPkt6($3)); + ctx.expression.push_back(pkt6field); + } ; option_code : INTEGER diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index 5f1e71e953..72c25adff4 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -123,6 +123,20 @@ public: EXPECT_TRUE(conc); } + /// @brief checks if the given token is Pkt6 of specified type + /// @param token token to be checked + /// @param type expected type of the Pkt6 field + void checkTokenPkt6(const TokenPtr& token, TokenPkt6::FieldType type) { + ASSERT_TRUE(token); + + boost::shared_ptr pkt = + boost::dynamic_pointer_cast(token); + + ASSERT_TRUE(pkt); + + EXPECT_EQ(type, pkt->getType()); + } + /// @brief checks if the given expression raises the expected message /// when it is parsed. void checkError(const string& expr, const string& msg) { @@ -147,6 +161,38 @@ public: universe_ = universe; } + /// @brief Test that verifies access to the DHCPv6 packet fields. + /// + /// This test attempts to parse the expression, will check if the number + /// of tokens is exactly as planned and then will try to verify if the + /// first token represents expected the field in DHCPv6 packet. + /// + /// @param expr expression to be parsed + /// @param exp_type expected field type to be parsed + /// @param exp_tokens expected number of tokens + void testPkt6Field(std::string expr, TokenPkt6::FieldType exp_type, + int exp_tokens) { + EvalContext eval(Option::V6); + + // 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 the requested number of tokens + ASSERT_EQ(exp_tokens, eval.expression.size()); + + // Check that the first token is TokenPkt6 instance and has correct type. + checkTokenPkt6(eval.expression.at(0), exp_type); + } + Option::Universe universe_; bool parsed_; ///< Parsing status }; @@ -334,6 +380,16 @@ TEST_F(EvalContextTest, relay4Error) { ":1.1-6: relay4 can only be used in DHCPv4."); } +// Tests whether message type field in DHCPv6 can be accessed. +TEST_F(EvalContextTest, pkt6FieldMsgtype) { + testPkt6Field("pkt6.msgtype == '1'", TokenPkt6::MSGTYPE, 3); +} + +// Tests whether transaction id field in DHCPv6 can be accessed. +TEST_F(EvalContextTest, pkt6FieldTransid) { + testPkt6Field("pkt6.transid == '1'", TokenPkt6::TRANSID, 3); +} + // Test parsing of logical operators TEST_F(EvalContextTest, logicalOps) { // option.exists diff --git a/src/lib/eval/tests/token_unittest.cc b/src/lib/eval/tests/token_unittest.cc index 5c970f3103..176b267113 100644 --- a/src/lib/eval/tests/token_unittest.cc +++ b/src/lib/eval/tests/token_unittest.cc @@ -967,3 +967,22 @@ TEST_F(TokenTest, concat) { ASSERT_EQ(1, values_.size()); EXPECT_EQ("foobar", values_.top()); } + +// Verifies if the DHCPv6 packet fields can be extracted. +TEST_F(TokenTest, pkt6Fields) { + // The default test creates a v6 DHCPV6_SOLICIT packet with a + // transaction id of 12345. + + // Check the message type + ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE))); + EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_)); + ASSERT_EQ(1, values_.size()); + EXPECT_EQ("1", values_.top()); + + // Check the transaction id field + clearStack(); + ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID))); + EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_)); + ASSERT_EQ(1, values_.size()); + EXPECT_EQ("12345", values_.top()); +} From 72859969fca9aa3077927eaec85f76f037879acc Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Tue, 22 Mar 2016 04:53:21 +0000 Subject: [PATCH 3/7] [trac4269] regen parser.h and parser.cc --- src/lib/eval/parser.cc | 84 +++++++++++++++++++++--------------------- src/lib/eval/parser.h | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index e89dab1532..446fba2236 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -692,19 +692,19 @@ namespace isc { namespace eval { break; case 10: -#line 135 "parser.yy" // lalr1.cc:859 +#line 137 "parser.yy" // lalr1.cc:859 { - TokenPtr pkt6field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ())); - ctx.expression.push_back(pkt6field); - } + TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(str); + } #line 701 "parser.cc" // lalr1.cc:859 break; case 11: #line 142 "parser.yy" // lalr1.cc:859 { - TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); - ctx.expression.push_back(str); + TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(hex); } #line 710 "parser.cc" // lalr1.cc:859 break; @@ -712,23 +712,14 @@ namespace isc { namespace eval { case 12: #line 147 "parser.yy" // lalr1.cc:859 { - TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); - ctx.expression.push_back(hex); + TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ())); + ctx.expression.push_back(opt); } #line 719 "parser.cc" // lalr1.cc:859 break; case 13: #line 152 "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 728 "parser.cc" // lalr1.cc:859 - break; - - case 14: -#line 157 "parser.yy" // lalr1.cc:859 { switch (ctx.getUniverse()) { case Option::V4: @@ -748,14 +739,23 @@ namespace isc { namespace eval { error(yystack_[5].location, "relay4 can only be used in DHCPv4."); } } +#line 743 "parser.cc" // lalr1.cc:859 + break; + + case 14: +#line 172 "parser.yy" // lalr1.cc:859 + { + TokenPtr sub(new TokenSubstring()); + ctx.expression.push_back(sub); + } #line 752 "parser.cc" // lalr1.cc:859 break; case 15: #line 177 "parser.yy" // lalr1.cc:859 { - TokenPtr sub(new TokenSubstring()); - ctx.expression.push_back(sub); + TokenPtr conc(new TokenConcat()); + ctx.expression.push_back(conc); } #line 761 "parser.cc" // lalr1.cc:859 break; @@ -763,8 +763,8 @@ namespace isc { namespace eval { case 16: #line 182 "parser.yy" // lalr1.cc:859 { - TokenPtr conc(new TokenConcat()); - ctx.expression.push_back(conc); + TokenPtr pkt6field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ())); + ctx.expression.push_back(pkt6field); } #line 770 "parser.cc" // lalr1.cc:859 break; @@ -1103,25 +1103,25 @@ namespace isc { namespace eval { const signed char EvalParser::yypact_[] = { - -1, -1, -1, 10, 13, 35, 45, 39, -42, -42, + -1, -1, -1, 10, 13, 35, 45, 40, -42, -42, 26, 6, 46, 11, -42, 12, 12, 23, 23, 19, - -42, -1, -1, 23, -42, -42, -42, 41, 43, 47, - 48, 37, 38, -42, -42, -42, -42, 54, -42, 49, - 50, 12, 12, 40, 23, 20, 30, 52, 55, -42, - 42, 62, -42, -42, -42, -42, -42, -42, 56, 57, - -11, -42, 36, 36, -42, -42, 64, -42 + -42, -1, -1, 23, -42, -42, -42, 43, 44, 47, + 48, 38, 41, -42, -42, -42, -42, 55, -42, 49, + 50, 12, 12, 39, 23, 20, 36, 53, 54, -42, + 51, 63, -42, -42, -42, -42, -42, -42, 56, 58, + -11, -42, 31, 31, -42, -42, 64, -42 }; const unsigned char EvalParser::yydefact_[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 0, 2, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 17, 18, 0, 0, 0, - 0, 0, 0, 24, 25, 10, 5, 6, 7, 0, + 0, 0, 0, 24, 25, 16, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, - 0, 0, 19, 20, 8, 13, 9, 14, 0, 0, - 0, 16, 0, 0, 23, 22, 0, 15 + 0, 0, 19, 20, 8, 12, 9, 13, 0, 0, + 0, 15, 0, 0, 23, 22, 0, 14 }; const signed char @@ -1143,10 +1143,10 @@ namespace isc { namespace eval { 13, 14, 21, 22, 65, 24, 5, 21, 22, 6, 7, 15, 57, 8, 16, 9, 20, 51, 47, 48, 36, 37, 29, 30, 52, 53, 54, 25, 17, 26, - 5, 33, 34, 6, 52, 53, 56, 8, 18, 9, - 52, 53, 19, 39, 23, 40, 43, 44, 41, 42, - 21, 60, 45, 46, 58, 49, 61, 59, 67, 62, - 63 + 5, 33, 34, 6, 7, 52, 53, 8, 18, 9, + 52, 53, 56, 19, 23, 39, 40, 43, 41, 42, + 44, 21, 45, 46, 49, 58, 59, 61, 67, 62, + 60, 63 }; const unsigned char @@ -1156,10 +1156,10 @@ namespace isc { namespace eval { 1, 2, 6, 7, 25, 4, 17, 6, 7, 20, 21, 11, 63, 24, 11, 26, 0, 44, 41, 42, 21, 22, 9, 10, 14, 15, 16, 25, 3, 27, - 17, 22, 23, 20, 14, 15, 16, 24, 3, 26, - 14, 15, 13, 12, 8, 12, 19, 19, 11, 11, - 6, 19, 13, 13, 12, 25, 4, 12, 4, 13, - 13 + 17, 22, 23, 20, 21, 14, 15, 24, 3, 26, + 14, 15, 16, 13, 8, 12, 12, 19, 11, 11, + 19, 6, 13, 13, 25, 12, 12, 4, 4, 13, + 19, 13 }; const unsigned char @@ -1178,7 +1178,7 @@ namespace isc { namespace eval { EvalParser::yyr1_[] = { 0, 28, 29, 30, 30, 30, 30, 30, 30, 30, - 30, 31, 31, 31, 31, 31, 31, 32, 32, 33, + 31, 31, 31, 31, 31, 31, 31, 32, 32, 33, 33, 34, 35, 35, 36, 36 }; @@ -1186,7 +1186,7 @@ namespace isc { namespace eval { EvalParser::yyr2_[] = { 0, 2, 1, 3, 2, 3, 3, 3, 6, 6, - 3, 1, 1, 6, 6, 8, 6, 1, 1, 1, + 1, 1, 6, 6, 8, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; @@ -1212,7 +1212,7 @@ namespace isc { namespace eval { EvalParser::yyrline_[] = { 0, 85, 85, 88, 89, 94, 99, 104, 109, 114, - 134, 141, 146, 151, 156, 176, 181, 188, 192, 198, + 136, 141, 146, 151, 171, 176, 181, 188, 192, 198, 202, 208, 215, 220, 227, 228 }; diff --git a/src/lib/eval/parser.h b/src/lib/eval/parser.h index a6bf07cd5c..ce3adb04bb 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -778,7 +778,7 @@ namespace isc { namespace eval { enum { yyeof_ = 0, - yylast_ = 70, ///< Last index in yytable_. + yylast_ = 71, ///< Last index in yytable_. yynnts_ = 9, ///< Number of nonterminal symbols. yyfinal_ = 20, ///< Termination state number. yyterror_ = 1, From 2a01de22f20dfbfe18f981f6a72e6d7c1bcb65b0 Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Mon, 21 Mar 2016 22:56:07 -0700 Subject: [PATCH 4/7] [trac4269] Add documentation and test for handling pkt4 as input --- doc/guide/classify.xml | 22 ++++++++++++++++++++++ src/lib/eval/tests/token_unittest.cc | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/doc/guide/classify.xml b/doc/guide/classify.xml index e18e993e7e..2aca1e4e31 100644 --- a/doc/guide/classify.xml +++ b/doc/guide/classify.xml @@ -169,6 +169,20 @@ sub-optionrelay4[code].hexThe value of sub-option with code "code" from the DHCPv4 Relay Agent Information option (option 82) + + Message Type in DHCPv6 packet + pkt6.msgtype + + The value of the message type field in the DHCPv6 packet. + + + Transaction ID in DHCPv6 packet + pkt6.transid + + The value of the transaction id in the DHCPv6 packet. + @@ -209,6 +223,14 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option instance "relay4[code].exists" is supported. + + "pkt6" refers to information from the client request. To access any + information from an intermediate relay use "relay6". "pkt6.msgtype" + outputs the string representation of the integer value for the message + type, for example SOLICIT will be '1'. "pkt6.transid" outputs the string + representation of the value of the transaction ID. + + List of Classification Expressions diff --git a/src/lib/eval/tests/token_unittest.cc b/src/lib/eval/tests/token_unittest.cc index 176b267113..bd63f1a68f 100644 --- a/src/lib/eval/tests/token_unittest.cc +++ b/src/lib/eval/tests/token_unittest.cc @@ -985,4 +985,9 @@ TEST_F(TokenTest, pkt6Fields) { EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_)); ASSERT_EQ(1, values_.size()); EXPECT_EQ("12345", values_.top()); + + // Check that working with a v4 packet generates an error + clearStack(); + ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID))); + EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError); } From b079f96f921d39f0b5169a87741256bea82e189a Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Mon, 21 Mar 2016 23:02:51 -0700 Subject: [PATCH 5/7] [trac4269] add ChangeLog entry --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index b8f2e73ea9..1b6f5b8485 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +10xx. [func] sar + Added support for accessing DHCPv6 packet fields message type + and transaction id in a classification expression. + (Trac #4269, git ) + 1089. [func] fdupont Added relay4[X].exists method in classifications that checks whether a sub-option is present in theDHCPv4 RAI (Relay Agent From 75063d9b417eb97d2c973975bd1eb0da5a2fe232 Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Thu, 7 Apr 2016 23:05:50 -0700 Subject: [PATCH 6/7] [trac4269] Update to put 4 byte strings on the value stack for integers --- doc/guide/classify.xml | 10 ++++----- src/lib/eval/tests/token_unittest.cc | 6 ++++-- src/lib/eval/token.cc | 31 ++++++++++++++++++---------- src/lib/eval/token.h | 6 ++++-- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/doc/guide/classify.xml b/doc/guide/classify.xml index 2aca1e4e31..bb9f7a06ae 100644 --- a/doc/guide/classify.xml +++ b/doc/guide/classify.xml @@ -172,14 +172,14 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option Message Type in DHCPv6 packet pkt6.msgtype - The value of the message type field in the DHCPv6 packet. Transaction ID in DHCPv6 packet pkt6.transid - The value of the transaction id in the DHCPv6 packet. @@ -226,9 +226,9 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option "pkt6" refers to information from the client request. To access any information from an intermediate relay use "relay6". "pkt6.msgtype" - outputs the string representation of the integer value for the message - type, for example SOLICIT will be '1'. "pkt6.transid" outputs the string - representation of the value of the transaction ID. + and "pkt6.transid" output a 4 byte binary string for the message type + or transaction id. For example the message type SOLICIT will be + "0x00000001" or simply 1 as in "pkt6.msgtype == 1". diff --git a/src/lib/eval/tests/token_unittest.cc b/src/lib/eval/tests/token_unittest.cc index bd63f1a68f..c47d9e8096 100644 --- a/src/lib/eval/tests/token_unittest.cc +++ b/src/lib/eval/tests/token_unittest.cc @@ -977,14 +977,16 @@ TEST_F(TokenTest, pkt6Fields) { ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE))); EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_)); ASSERT_EQ(1, values_.size()); - EXPECT_EQ("1", values_.top()); + uint32_t expected = htonl(1); + EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4)); // Check the transaction id field clearStack(); ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID))); EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_)); ASSERT_EQ(1, values_.size()); - EXPECT_EQ("12345", values_.top()); + expected = htonl(12345); + EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4)); // Check that working with a v4 packet generates an error clearStack(); diff --git a/src/lib/eval/token.cc b/src/lib/eval/token.cc index 05b784ec7b..9610f4af66 100644 --- a/src/lib/eval/token.cc +++ b/src/lib/eval/token.cc @@ -278,6 +278,7 @@ TokenOr::evaluate(const Pkt& /*pkt*/, ValueStack& values) { void TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) { + vector binary; try { // Check if it's a Pkt6. If it's not the dynamic_cast will throw // std::bad_cast (failed dynamic_cast returns NULL for pointers and @@ -286,24 +287,32 @@ TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) { switch (type_) { case MSGTYPE: { - // msg type is an uint8_t integer. We need to represent it as a string. - stringstream tmp; - tmp << static_cast(pkt6.getType()); - values.push(tmp.str()); - return; + // msg type is an uint8_t integer. We want a 4 byte string so 0 pad. + binary.push_back(0); + binary.push_back(0); + binary.push_back(0); + binary.push_back(pkt6.getType()); + break; } case TRANSID: { - // transaction id is an uint32_t integer. We need to represent it as a string. - stringstream tmp; - tmp << static_cast(pkt6.getTransid()); - values.push(tmp.str()); - return; + // transaction id is an uint32_t integer. We want a 4 byte string so copy + uint32_t transid = pkt6.getTransid(); + binary.push_back(transid >> 24); + binary.push_back((transid >> 16) & 0xFF); + binary.push_back((transid >> 8) & 0xFF); + binary.push_back(transid & 0xFF); + break; } default: - isc_throw(EvalTypeError, "Bad filed specified: " + isc_throw(EvalTypeError, "Bad field specified: " << static_cast(type_) ); } } catch (const std::bad_cast&) { isc_throw(EvalTypeError, "Specified packet is not Pkt6"); } + + string value; + value.resize(binary.size()); + memmove(&value[0], &binary[0], binary.size()); + values.push(value); }; diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h index 598b968ad9..e3a1854e56 100644 --- a/src/lib/eval/token.h +++ b/src/lib/eval/token.h @@ -446,8 +446,10 @@ public: /// @brief Token that represents fields of DHCPv6 packet. /// -/// For example in the expression pkt6.msgtype == "1" -/// this token represents the message type of the DHCPv6 packet +/// For example in the expression pkt6.msgtype == 1 +/// this token represents the message type of the DHCPv6 packet. +/// The integer values are placed on the value stack as 4 byte +/// strings. /// /// Currently supported fields are: /// - msgtype From 7549535b3a868a63ea1adc220daca28efff0e971 Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Thu, 14 Apr 2016 21:24:16 +0000 Subject: [PATCH 7/7] [trac4269] Updates per review comments, basically change some variable names --- src/lib/eval/parser.cc | 4 ++-- src/lib/eval/parser.yy | 4 ++-- src/lib/eval/tests/context_unittest.cc | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index 446fba2236..009fe69348 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -763,8 +763,8 @@ namespace isc { namespace eval { case 16: #line 182 "parser.yy" // lalr1.cc:859 { - TokenPtr pkt6field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ())); - ctx.expression.push_back(pkt6field); + TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ())); + ctx.expression.push_back(pkt6_field); } #line 770 "parser.cc" // lalr1.cc:859 break; diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index ac8a1334a5..67d190b6c0 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -180,8 +180,8 @@ string_expr : STRING } | PKT6 "." pkt6_field { - TokenPtr pkt6field(new TokenPkt6($3)); - ctx.expression.push_back(pkt6field); + TokenPtr pkt6_field(new TokenPkt6($3)); + ctx.expression.push_back(pkt6_field); } ; diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index 72c25adff4..e4ae0c3dcd 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -125,8 +125,9 @@ public: /// @brief checks if the given token is Pkt6 of specified type /// @param token token to be checked - /// @param type expected type of the Pkt6 field - void checkTokenPkt6(const TokenPtr& token, TokenPkt6::FieldType type) { + /// @param exp_type expected type of the Pkt6 field + void checkTokenPkt6(const TokenPtr& token, + TokenPkt6::FieldType exp_type) { ASSERT_TRUE(token); boost::shared_ptr pkt = @@ -134,7 +135,7 @@ public: ASSERT_TRUE(pkt); - EXPECT_EQ(type, pkt->getType()); + EXPECT_EQ(exp_type, pkt->getType()); } /// @brief checks if the given expression raises the expected message