2016-12-02 19:18:50 +00:00
|
|
|
%top {
|
|
|
|
/* Include this before everything else, for various large-file definitions */
|
|
|
|
#include "config.h"
|
|
|
|
}
|
|
|
|
|
2016-03-31 01:44:01 +00:00
|
|
|
/*
|
|
|
|
* We want a reentrant scanner.
|
|
|
|
*/
|
|
|
|
%option reentrant
|
|
|
|
|
2013-02-10 19:13:07 +00:00
|
|
|
/*
|
|
|
|
* We don't use input, so don't generate code for it.
|
|
|
|
*/
|
|
|
|
%option noinput
|
|
|
|
|
2011-04-23 19:03:05 +00:00
|
|
|
/*
|
|
|
|
* We don't use unput, so don't generate code for it.
|
|
|
|
*/
|
|
|
|
%option nounput
|
|
|
|
|
|
|
|
/*
|
2015-11-05 23:35:04 +00:00
|
|
|
* We don't read interactively from the terminal.
|
2011-04-23 19:03:05 +00:00
|
|
|
*/
|
|
|
|
%option never-interactive
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prefix scanner routines with "df_" rather than "yy", so this scanner
|
|
|
|
* can coexist with other scanners.
|
|
|
|
*/
|
|
|
|
%option prefix="df_"
|
|
|
|
|
2015-12-05 03:52:51 +00:00
|
|
|
/*
|
|
|
|
* We're reading from a string, so we don't need yywrap.
|
|
|
|
*/
|
|
|
|
%option noyywrap
|
|
|
|
|
2016-03-31 01:44:01 +00:00
|
|
|
/*
|
|
|
|
* The type for the state we keep for a scanner.
|
|
|
|
*/
|
|
|
|
%option extra-type="df_scanner_state_t *"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to override the memory allocators so that we don't get
|
|
|
|
* "unused argument" warnings from the yyscanner argument (which
|
|
|
|
* we don't use, as we have a global memory allocator).
|
|
|
|
*
|
|
|
|
* We provide, as macros, our own versions of the routines generated by Flex,
|
|
|
|
* which just call malloc()/realloc()/free() (as the Flex versions do),
|
|
|
|
* discarding the extra argument.
|
|
|
|
*/
|
|
|
|
%option noyyalloc
|
|
|
|
%option noyyrealloc
|
|
|
|
%option noyyfree
|
|
|
|
|
2011-04-23 19:03:05 +00:00
|
|
|
%{
|
2001-02-01 20:31:21 +00:00
|
|
|
/*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2001-02-01 20:31:21 +00:00
|
|
|
* Copyright 2001 Gerald Combs
|
2008-01-31 19:50:38 +00:00
|
|
|
*
|
2018-03-06 14:31:02 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2001-02-01 20:21:25 +00:00
|
|
|
*/
|
|
|
|
|
2001-02-27 19:23:30 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
#include "dfilter-int.h"
|
|
|
|
#include "syntax-tree.h"
|
|
|
|
#include "grammar.h"
|
2006-05-02 14:26:17 +00:00
|
|
|
#include "dfunctions.h"
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2018-02-16 07:17:04 +00:00
|
|
|
/*
|
|
|
|
* Disable diagnostics in the code generated by Flex.
|
|
|
|
*/
|
|
|
|
DIAG_OFF_FLEX
|
2008-04-25 18:26:54 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
#define LVAL df_lval
|
|
|
|
#define LVAL_TYPE stnode_t*
|
|
|
|
#define LVAL_INIT_VAL NULL
|
|
|
|
#define MODNAME df
|
2004-04-25 04:53:42 +00:00
|
|
|
#define FLEX_YY_PREFIX df_
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
#include <lemonflex-head.inc>
|
|
|
|
|
|
|
|
/*#undef YY_NO_UNPUT*/
|
|
|
|
|
2001-02-27 19:23:30 +00:00
|
|
|
static int set_lval(int token, gpointer data);
|
2015-01-18 10:22:19 +00:00
|
|
|
static int set_lval_int(dfwork_t *dfw, int token, char *s);
|
2001-02-27 19:23:30 +00:00
|
|
|
static int simple(int token);
|
2015-01-18 10:22:19 +00:00
|
|
|
static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint);
|
2008-01-31 19:50:38 +00:00
|
|
|
static void mark_lval_deprecated(const char *s);
|
2003-07-25 03:44:05 +00:00
|
|
|
|
2016-03-31 01:44:01 +00:00
|
|
|
/*
|
|
|
|
* Sleazy hack to suppress compiler warnings in yy_fatal_error().
|
|
|
|
*/
|
|
|
|
#define YY_EXIT_FAILURE ((void)yyscanner, 2)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Macros for the allocators, to discard the extra argument.
|
|
|
|
*/
|
|
|
|
#define df_alloc(size, yyscanner) (void *)malloc(size)
|
|
|
|
#define df_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
|
|
|
|
#define df_free(ptr, yyscanner) free((char *)ptr)
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
%}
|
|
|
|
|
2001-03-02 17:04:25 +00:00
|
|
|
%x RANGE_INT
|
|
|
|
%x RANGE_PUNCT
|
2003-07-25 03:44:05 +00:00
|
|
|
%x DQUOTE
|
2016-09-19 01:48:50 +00:00
|
|
|
%x SQUOTE
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
2018-04-17 15:49:17 +00:00
|
|
|
[[:blank:]\n]+ {
|
|
|
|
/* Ignore whitespace, unless set elements are being parsed. Perhaps it
|
|
|
|
* should have used commas from the beginning, but now we are stuck with
|
|
|
|
* whitespace as separators. */
|
|
|
|
if (yyextra->in_set) {
|
|
|
|
return simple(TOKEN_WHITESPACE);
|
|
|
|
}
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"(" return simple(TOKEN_LPAREN);
|
|
|
|
")" return simple(TOKEN_RPAREN);
|
2006-05-02 14:26:17 +00:00
|
|
|
"," return simple(TOKEN_COMMA);
|
2018-04-17 15:49:17 +00:00
|
|
|
|
|
|
|
"{"[[:blank:]\n]* {
|
|
|
|
yyextra->in_set = TRUE;
|
|
|
|
return simple(TOKEN_LBRACE);
|
|
|
|
}
|
|
|
|
[[:blank:]\n]*".."[[:blank:]\n]* return simple(TOKEN_DOTDOT);
|
|
|
|
[[:blank:]\n]*"}" {
|
|
|
|
yyextra->in_set = FALSE;
|
|
|
|
return simple(TOKEN_RBRACE);
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2003-12-06 16:35:20 +00:00
|
|
|
"==" return simple(TOKEN_TEST_EQ);
|
|
|
|
"eq" return simple(TOKEN_TEST_EQ);
|
2008-01-31 19:50:38 +00:00
|
|
|
"!=" {
|
|
|
|
mark_lval_deprecated("!=");
|
|
|
|
return simple(TOKEN_TEST_NE);
|
|
|
|
}
|
|
|
|
"ne" {
|
|
|
|
mark_lval_deprecated("ne");
|
|
|
|
return simple(TOKEN_TEST_NE);
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
">" return simple(TOKEN_TEST_GT);
|
2003-12-06 16:35:20 +00:00
|
|
|
"gt" return simple(TOKEN_TEST_GT);
|
|
|
|
">=" return simple(TOKEN_TEST_GE);
|
|
|
|
"ge" return simple(TOKEN_TEST_GE);
|
2001-02-01 20:21:25 +00:00
|
|
|
"<" return simple(TOKEN_TEST_LT);
|
2003-12-06 16:35:20 +00:00
|
|
|
"lt" return simple(TOKEN_TEST_LT);
|
|
|
|
"<=" return simple(TOKEN_TEST_LE);
|
|
|
|
"le" return simple(TOKEN_TEST_LE);
|
2007-08-11 22:05:44 +00:00
|
|
|
"bitwise_and" return simple(TOKEN_TEST_BITWISE_AND);
|
|
|
|
"&" return simple(TOKEN_TEST_BITWISE_AND);
|
2003-12-06 16:35:20 +00:00
|
|
|
"contains" return simple(TOKEN_TEST_CONTAINS);
|
2007-08-11 22:05:44 +00:00
|
|
|
"~" return simple(TOKEN_TEST_MATCHES);
|
2003-12-06 16:35:20 +00:00
|
|
|
"matches" return simple(TOKEN_TEST_MATCHES);
|
2001-02-01 20:21:25 +00:00
|
|
|
"!" return simple(TOKEN_TEST_NOT);
|
2003-12-06 16:35:20 +00:00
|
|
|
"not" return simple(TOKEN_TEST_NOT);
|
|
|
|
"&&" return simple(TOKEN_TEST_AND);
|
|
|
|
"and" return simple(TOKEN_TEST_AND);
|
|
|
|
"||" return simple(TOKEN_TEST_OR);
|
|
|
|
"or" return simple(TOKEN_TEST_OR);
|
2015-08-19 03:03:41 +00:00
|
|
|
"in" return simple(TOKEN_TEST_IN);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
|
2001-03-02 17:04:25 +00:00
|
|
|
"[" {
|
|
|
|
BEGIN(RANGE_INT);
|
2001-02-01 20:21:25 +00:00
|
|
|
return simple(TOKEN_LBRACKET);
|
|
|
|
}
|
|
|
|
|
2001-03-02 17:04:25 +00:00
|
|
|
<RANGE_INT>[+-]?[[:digit:]]+ {
|
|
|
|
BEGIN(RANGE_PUNCT);
|
2016-03-31 01:44:01 +00:00
|
|
|
return set_lval_int(yyextra->dfw, TOKEN_INTEGER, yytext);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
2003-07-25 03:44:05 +00:00
|
|
|
|
2001-03-02 17:04:25 +00:00
|
|
|
<RANGE_INT>[+-]?0x[[:xdigit:]]+ {
|
|
|
|
BEGIN(RANGE_PUNCT);
|
2016-03-31 01:44:01 +00:00
|
|
|
return set_lval_int(yyextra->dfw, TOKEN_INTEGER, yytext);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2001-03-02 17:04:25 +00:00
|
|
|
<RANGE_INT,RANGE_PUNCT>":" {
|
|
|
|
BEGIN(RANGE_INT);
|
|
|
|
return simple(TOKEN_COLON);
|
|
|
|
}
|
|
|
|
|
|
|
|
<RANGE_PUNCT>"-" {
|
|
|
|
BEGIN(RANGE_INT);
|
|
|
|
return simple(TOKEN_HYPHEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
<RANGE_INT,RANGE_PUNCT>"," {
|
|
|
|
BEGIN(RANGE_INT);
|
|
|
|
return simple(TOKEN_COMMA);
|
|
|
|
}
|
|
|
|
|
|
|
|
<RANGE_INT,RANGE_PUNCT>"]" {
|
2001-02-01 20:21:25 +00:00
|
|
|
BEGIN(INITIAL);
|
|
|
|
return simple(TOKEN_RBRACKET);
|
|
|
|
}
|
|
|
|
|
2004-06-03 07:17:24 +00:00
|
|
|
/* Error if none of the above while scanning a range (slice) */
|
|
|
|
|
|
|
|
<RANGE_PUNCT>[^:\-,\]]+ {
|
2016-03-31 01:44:01 +00:00
|
|
|
dfilter_fail(yyextra->dfw, "Invalid string \"%s\" found while scanning slice.", yytext);
|
2004-06-03 07:17:24 +00:00
|
|
|
return SCAN_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX It would be nice to be able to match an entire non-integer string,
|
|
|
|
* but beware of Flex's "match the most text" rule.
|
|
|
|
*/
|
|
|
|
|
|
|
|
<RANGE_INT>. {
|
2016-03-31 01:44:01 +00:00
|
|
|
dfilter_fail(yyextra->dfw, "Invalid character \"%s\" found while scanning slice; expected integer.", yytext);
|
2004-06-03 07:17:24 +00:00
|
|
|
return SCAN_FAILED;
|
|
|
|
}
|
|
|
|
|
2021-05-30 02:38:12 +00:00
|
|
|
[rR]{0,1}\042 {
|
2016-09-19 01:48:50 +00:00
|
|
|
/* start quote of a quoted string */
|
2003-07-25 03:44:05 +00:00
|
|
|
/* The example of how to scan for strings was taken from
|
|
|
|
the flex 2.5.4 manual, from the section "Start Conditions".
|
|
|
|
See:
|
2004-02-11 22:52:54 +00:00
|
|
|
http://www.gnu.org/software/flex/manual/html_node/flex_11.html */
|
2003-07-25 03:44:05 +00:00
|
|
|
|
|
|
|
BEGIN(DQUOTE);
|
2004-01-07 05:24:04 +00:00
|
|
|
/* A previous filter that failed to compile due to
|
|
|
|
a missing end quote will have left quoted_string set
|
|
|
|
to something. Clear it now that we are starting
|
|
|
|
a new quoted string. */
|
2016-03-31 01:44:01 +00:00
|
|
|
if (yyextra->quoted_string) {
|
|
|
|
g_string_free(yyextra->quoted_string, TRUE);
|
2004-01-07 05:24:04 +00:00
|
|
|
/* Don't set quoted_string to NULL, as we
|
|
|
|
do in other quoted_string-cleanup code, as we're
|
|
|
|
about to set it in the next line. */
|
|
|
|
}
|
2016-03-31 01:44:01 +00:00
|
|
|
yyextra->quoted_string = g_string_new("");
|
2021-05-30 02:38:12 +00:00
|
|
|
if (yytext[0] == 'r' || yytext[0] == 'R') {
|
|
|
|
/*
|
|
|
|
* This is a raw string (like in Python). Rules: 1) The two
|
|
|
|
* escape sequences are \\ and \". 2) Backslashes are
|
|
|
|
* preserved. 3) Double quotes in the string must be escaped.
|
|
|
|
* Corollary: Strings cannot end with an odd number of
|
|
|
|
* backslashes.
|
|
|
|
* Example: r"a\b\x12\"\\" is the string (including the implicit NUL terminator)
|
|
|
|
* {'a', '\\', 'b', '\\', 'x', '1', '2', '\\', '"', '\\'. '\\', '\0'}
|
|
|
|
*/
|
|
|
|
yyextra->raw_string = TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
yyextra->raw_string = FALSE;
|
|
|
|
}
|
2003-07-25 03:44:05 +00:00
|
|
|
}
|
|
|
|
|
2004-02-11 22:52:54 +00:00
|
|
|
<DQUOTE><<EOF>> {
|
|
|
|
/* unterminated string */
|
|
|
|
/* The example of how to handle unclosed strings was taken from
|
|
|
|
the flex 2.5.4 manual, from the section "End-of-file rules".
|
|
|
|
See:
|
|
|
|
http://www.gnu.org/software/flex/manual/html_node/flex_13.html */
|
|
|
|
|
2016-03-31 01:44:01 +00:00
|
|
|
dfilter_fail(yyextra->dfw, "The final quote was missing from a quoted string.");
|
2004-02-11 22:52:54 +00:00
|
|
|
return SCAN_FAILED;
|
|
|
|
}
|
|
|
|
|
2007-08-11 22:05:44 +00:00
|
|
|
<DQUOTE>\042 {
|
2003-07-25 03:44:05 +00:00
|
|
|
/* end quote */
|
2005-03-24 05:27:03 +00:00
|
|
|
int token;
|
2003-07-25 03:44:05 +00:00
|
|
|
BEGIN(INITIAL);
|
2016-03-31 01:44:01 +00:00
|
|
|
token = set_lval(TOKEN_STRING, yyextra->quoted_string->str);
|
|
|
|
g_string_free(yyextra->quoted_string, TRUE);
|
|
|
|
yyextra->quoted_string = NULL;
|
2005-03-24 05:27:03 +00:00
|
|
|
return token;
|
2003-07-25 03:44:05 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2003-07-25 03:44:05 +00:00
|
|
|
<DQUOTE>\\[0-7]{1,3} {
|
|
|
|
/* octal sequence */
|
2021-05-30 02:38:12 +00:00
|
|
|
if (yyextra->raw_string) {
|
|
|
|
g_string_append(yyextra->quoted_string, yytext);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
unsigned long result;
|
|
|
|
result = strtoul(yytext + 1, NULL, 8);
|
dfilter: Disallow embedded NUL bytes in regular strings
When byte escape sequences, that is hex \xhh or octal \0ddd,
are interpreted at the lexical level it is not possible to
use strings with embedded NUL bytes. The NUL byte is interpreted
as a C string terminator. As a consequence, for example, the
strings "AB" and "AB\x00CDE" compare as the same. This leads to
unexpected false matches and a poor user experience.
Disallow embedded NULs for regular strings (strings literals that
do not begin with 'r' or 'R') for this reason.
It is possible to use a raw string instead (eg: r"AB\x00C")
to match embedded NUL bytes, although that only works with regular
expressions. Normal escape rules would also work with regular
expressions (eg: "AB\\x00C"). This is the same string as the previous
one, written in an alternate form. What won't work is "AB\x00C", this
string is synctatically invalid.
So the expression: data matches r"AB\x00C"
will match the bytes {'A', 'B', '\0', '\C'}.
However the expression: data contains r"AB\x00C"
won't match the fvalue above. Because the "contains" operator
doesn't compile a regular expression it literally tries to
contains-match the bytes {'A', 'B', '\\', 'x', '0', '0', 'C'}.
Therefore raw strings are very convenient but it is still necessary
to be aware that the matches operator has an extra level of indirection
than other string operators (same as in Python).
Fixes #16156.
2021-05-30 07:40:30 +00:00
|
|
|
if (result == 0) {
|
|
|
|
g_string_free(yyextra->quoted_string, TRUE);
|
|
|
|
yyextra->quoted_string = NULL;
|
|
|
|
dfilter_fail(yyextra->dfw, "%s (NUL byte) cannot be used with a regular string.", yytext);
|
|
|
|
return SCAN_FAILED;
|
|
|
|
}
|
2021-05-30 02:38:12 +00:00
|
|
|
if (result > 0xff) {
|
|
|
|
g_string_free(yyextra->quoted_string, TRUE);
|
|
|
|
yyextra->quoted_string = NULL;
|
|
|
|
dfilter_fail(yyextra->dfw, "%s is larger than 255.", yytext);
|
|
|
|
return SCAN_FAILED;
|
|
|
|
}
|
|
|
|
g_string_append_c(yyextra->quoted_string, (gchar) result);
|
2003-07-25 03:44:05 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2003-07-25 03:44:05 +00:00
|
|
|
<DQUOTE>\\x[[:xdigit:]]{1,2} {
|
|
|
|
/* hex sequence */
|
2021-05-30 02:38:12 +00:00
|
|
|
if (yyextra->raw_string) {
|
|
|
|
g_string_append(yyextra->quoted_string, yytext);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
unsigned long result;
|
|
|
|
result = strtoul(yytext + 2, NULL, 16);
|
dfilter: Disallow embedded NUL bytes in regular strings
When byte escape sequences, that is hex \xhh or octal \0ddd,
are interpreted at the lexical level it is not possible to
use strings with embedded NUL bytes. The NUL byte is interpreted
as a C string terminator. As a consequence, for example, the
strings "AB" and "AB\x00CDE" compare as the same. This leads to
unexpected false matches and a poor user experience.
Disallow embedded NULs for regular strings (strings literals that
do not begin with 'r' or 'R') for this reason.
It is possible to use a raw string instead (eg: r"AB\x00C")
to match embedded NUL bytes, although that only works with regular
expressions. Normal escape rules would also work with regular
expressions (eg: "AB\\x00C"). This is the same string as the previous
one, written in an alternate form. What won't work is "AB\x00C", this
string is synctatically invalid.
So the expression: data matches r"AB\x00C"
will match the bytes {'A', 'B', '\0', '\C'}.
However the expression: data contains r"AB\x00C"
won't match the fvalue above. Because the "contains" operator
doesn't compile a regular expression it literally tries to
contains-match the bytes {'A', 'B', '\\', 'x', '0', '0', 'C'}.
Therefore raw strings are very convenient but it is still necessary
to be aware that the matches operator has an extra level of indirection
than other string operators (same as in Python).
Fixes #16156.
2021-05-30 07:40:30 +00:00
|
|
|
if (result == 0) {
|
|
|
|
g_string_free(yyextra->quoted_string, TRUE);
|
|
|
|
yyextra->quoted_string = NULL;
|
|
|
|
dfilter_fail(yyextra->dfw, "%s (NUL byte) cannot be used with a regular string.", yytext);
|
|
|
|
return SCAN_FAILED;
|
|
|
|
}
|
2021-05-30 02:38:12 +00:00
|
|
|
g_string_append_c(yyextra->quoted_string, (gchar) result);
|
|
|
|
}
|
2003-07-25 03:44:05 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
|
2003-07-25 03:44:05 +00:00
|
|
|
<DQUOTE>\\. {
|
|
|
|
/* escaped character */
|
2021-05-30 02:38:12 +00:00
|
|
|
if (yyextra->raw_string) {
|
|
|
|
g_string_append(yyextra->quoted_string, yytext);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
g_string_append_c(yyextra->quoted_string, yytext[1]);
|
|
|
|
}
|
2003-07-25 03:44:05 +00:00
|
|
|
}
|
|
|
|
|
2007-08-11 22:05:44 +00:00
|
|
|
<DQUOTE>[^\\\042]+ {
|
2003-07-25 03:44:05 +00:00
|
|
|
/* non-escaped string */
|
2016-03-31 01:44:01 +00:00
|
|
|
g_string_append(yyextra->quoted_string, yytext);
|
2003-07-25 03:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-19 01:48:50 +00:00
|
|
|
\047 {
|
|
|
|
/* start quote of a quoted character value */
|
|
|
|
/* The example of how to scan for strings was taken from
|
|
|
|
the Flex manual, from the section "Start Conditions".
|
|
|
|
See:
|
|
|
|
http://flex.sourceforge.net/manual/Start-Conditions.html#Start-Conditions */
|
|
|
|
|
|
|
|
BEGIN(SQUOTE);
|
|
|
|
/* A previous filter that failed to compile due to
|
|
|
|
a missing end quote will have left quoted_string set
|
|
|
|
to something. Clear it now that we are starting
|
|
|
|
a new quoted string. */
|
|
|
|
if (yyextra->quoted_string) {
|
|
|
|
g_string_free(yyextra->quoted_string, TRUE);
|
|
|
|
/* Don't set quoted_string to NULL, as we
|
|
|
|
do in other quoted_string-cleanup code, as we're
|
|
|
|
about to set it in the next line. */
|
|
|
|
}
|
|
|
|
yyextra->quoted_string = g_string_new("'");
|
|
|
|
}
|
|
|
|
|
|
|
|
<SQUOTE><<EOF>> {
|
|
|
|
/* unterminated character value */
|
|
|
|
/* The example of how to handle unclosed strings was taken from
|
|
|
|
the Flex manual, from the section "End-of-file rules".
|
|
|
|
See:
|
|
|
|
http://flex.sourceforge.net/manual/EOF.html#EOF.html */
|
|
|
|
|
|
|
|
dfilter_fail(yyextra->dfw, "The final quote was missing from a character constant.");
|
|
|
|
return SCAN_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
<SQUOTE>\047 {
|
|
|
|
/* end quote */
|
|
|
|
int token;
|
|
|
|
BEGIN(INITIAL);
|
|
|
|
g_string_append_c(yyextra->quoted_string, '\'');
|
|
|
|
token = set_lval(TOKEN_CHARCONST, yyextra->quoted_string->str);
|
|
|
|
g_string_free(yyextra->quoted_string, TRUE);
|
|
|
|
yyextra->quoted_string = NULL;
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
|
|
|
<SQUOTE>\\. {
|
|
|
|
/* escaped character */
|
|
|
|
g_string_append(yyextra->quoted_string, yytext);
|
|
|
|
}
|
|
|
|
|
|
|
|
<SQUOTE>[^\\\047]+ {
|
|
|
|
/* non-escaped string */
|
|
|
|
g_string_append(yyextra->quoted_string, yytext);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-25 03:44:05 +00:00
|
|
|
|
2015-09-07 01:56:30 +00:00
|
|
|
[-[:alnum:]_\.:]*\/[[:digit:]]+ {
|
2003-07-25 03:44:05 +00:00
|
|
|
/* CIDR */
|
2005-03-24 05:27:03 +00:00
|
|
|
return set_lval(TOKEN_UNPARSED, yytext);
|
2003-07-25 03:44:05 +00:00
|
|
|
}
|
|
|
|
|
2018-04-16 11:02:41 +00:00
|
|
|
([.][-+[:alnum:]_:]+)+[.]{0,2} |
|
|
|
|
[-+[:alnum:]_:]+([.][-+[:alnum:]_:]+)*[.]{0,2} {
|
|
|
|
/* Is it a field name or some other value (float, integer, bytes, ...)? */
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
2010-04-30 21:40:57 +00:00
|
|
|
df_func_def_t *df_func_def;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2018-04-16 11:02:41 +00:00
|
|
|
/* Trailing dot is allowed for floats, but make sure that trailing ".."
|
|
|
|
* is interpreted as a token on its own. */
|
|
|
|
if (strstr(yytext, "..")) {
|
|
|
|
yyless(yyleng-2);
|
|
|
|
}
|
|
|
|
|
2002-04-29 07:55:32 +00:00
|
|
|
hfinfo = proto_registrar_get_byname(yytext);
|
2001-02-01 20:21:25 +00:00
|
|
|
if (hfinfo) {
|
|
|
|
/* Yes, it's a field name */
|
|
|
|
return set_lval(TOKEN_FIELD, hfinfo);
|
|
|
|
}
|
2018-08-28 22:38:33 +00:00
|
|
|
|
|
|
|
hfinfo = proto_registrar_get_byalias(yytext);
|
|
|
|
if (hfinfo) {
|
|
|
|
/* Yes, it's an aliased field name */
|
|
|
|
/* XXX Do we need to make a copy of yytext? dfilter_compile
|
|
|
|
* will dup this later on. */
|
|
|
|
mark_lval_deprecated(yytext);
|
|
|
|
return set_lval(TOKEN_FIELD, hfinfo);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
2018-08-28 22:38:33 +00:00
|
|
|
|
|
|
|
df_func_def = df_func_lookup(yytext);
|
|
|
|
if (df_func_def) {
|
|
|
|
/* Yes, it's a dfilter function */
|
|
|
|
return set_lval(TOKEN_FUNCTION, df_func_def);
|
|
|
|
}
|
|
|
|
/* No match, so treat it as an unparsed string */
|
|
|
|
return set_lval(TOKEN_UNPARSED, yytext);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2001-06-22 16:29:15 +00:00
|
|
|
. {
|
|
|
|
/* Default */
|
2005-03-24 05:27:03 +00:00
|
|
|
return set_lval(TOKEN_UNPARSED, yytext);
|
2001-06-22 16:29:15 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
2018-02-16 07:17:04 +00:00
|
|
|
/*
|
|
|
|
* Turn diagnostics back on, so we check the code that we've written.
|
|
|
|
*/
|
|
|
|
DIAG_ON_FLEX
|
2017-08-18 19:11:47 +00:00
|
|
|
|
2001-02-27 19:23:30 +00:00
|
|
|
static int
|
2001-02-01 20:21:25 +00:00
|
|
|
simple(int token)
|
|
|
|
{
|
|
|
|
switch (token) {
|
|
|
|
case TOKEN_LPAREN:
|
|
|
|
case TOKEN_RPAREN:
|
|
|
|
case TOKEN_LBRACKET:
|
|
|
|
case TOKEN_RBRACKET:
|
2015-08-19 03:03:41 +00:00
|
|
|
case TOKEN_LBRACE:
|
|
|
|
case TOKEN_RBRACE:
|
2001-02-01 20:21:25 +00:00
|
|
|
case TOKEN_COLON:
|
2001-02-27 19:23:30 +00:00
|
|
|
case TOKEN_COMMA:
|
2018-04-14 16:07:22 +00:00
|
|
|
case TOKEN_DOTDOT:
|
2001-03-02 17:04:25 +00:00
|
|
|
case TOKEN_HYPHEN:
|
2018-04-17 15:49:17 +00:00
|
|
|
case TOKEN_WHITESPACE:
|
2001-02-01 20:21:25 +00:00
|
|
|
case TOKEN_TEST_EQ:
|
|
|
|
case TOKEN_TEST_NE:
|
|
|
|
case TOKEN_TEST_GT:
|
|
|
|
case TOKEN_TEST_GE:
|
|
|
|
case TOKEN_TEST_LT:
|
|
|
|
case TOKEN_TEST_LE:
|
2004-02-27 12:00:32 +00:00
|
|
|
case TOKEN_TEST_BITWISE_AND:
|
2003-08-27 15:23:11 +00:00
|
|
|
case TOKEN_TEST_CONTAINS:
|
2003-12-06 16:35:20 +00:00
|
|
|
case TOKEN_TEST_MATCHES:
|
2001-02-01 20:21:25 +00:00
|
|
|
case TOKEN_TEST_NOT:
|
|
|
|
case TOKEN_TEST_AND:
|
|
|
|
case TOKEN_TEST_OR:
|
2015-08-19 03:03:41 +00:00
|
|
|
case TOKEN_TEST_IN:
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
default:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
2001-02-27 19:23:30 +00:00
|
|
|
static int
|
2001-02-01 20:21:25 +00:00
|
|
|
set_lval(int token, gpointer data)
|
|
|
|
{
|
|
|
|
sttype_id_t type_id = STTYPE_UNINITIALIZED;
|
|
|
|
|
|
|
|
switch (token) {
|
|
|
|
case TOKEN_STRING:
|
|
|
|
type_id = STTYPE_STRING;
|
|
|
|
break;
|
2016-09-19 01:48:50 +00:00
|
|
|
case TOKEN_CHARCONST:
|
|
|
|
type_id = STTYPE_CHARCONST;
|
|
|
|
break;
|
2001-02-01 20:21:25 +00:00
|
|
|
case TOKEN_FIELD:
|
|
|
|
type_id = STTYPE_FIELD;
|
|
|
|
break;
|
2003-07-25 03:44:05 +00:00
|
|
|
case TOKEN_UNPARSED:
|
|
|
|
type_id = STTYPE_UNPARSED;
|
|
|
|
break;
|
2006-05-02 14:26:17 +00:00
|
|
|
case TOKEN_FUNCTION:
|
|
|
|
type_id = STTYPE_FUNCTION;
|
|
|
|
break;
|
2001-02-01 20:21:25 +00:00
|
|
|
default:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
stnode_init(df_lval, type_id, data);
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
2001-02-27 19:23:30 +00:00
|
|
|
static int
|
2015-01-18 10:22:19 +00:00
|
|
|
set_lval_int(dfwork_t *dfw, int token, char *s)
|
2001-02-27 19:23:30 +00:00
|
|
|
{
|
|
|
|
sttype_id_t type_id = STTYPE_UNINITIALIZED;
|
2004-06-03 07:36:25 +00:00
|
|
|
gint32 val;
|
2001-02-27 19:23:30 +00:00
|
|
|
|
2015-01-18 10:22:19 +00:00
|
|
|
if (!str_to_gint32(dfw, s, &val)) {
|
2003-07-25 03:44:05 +00:00
|
|
|
return SCAN_FAILED;
|
2008-01-31 19:50:38 +00:00
|
|
|
}
|
2001-02-27 19:23:30 +00:00
|
|
|
|
|
|
|
switch (token) {
|
|
|
|
case TOKEN_INTEGER:
|
|
|
|
type_id = STTYPE_INTEGER;
|
|
|
|
break;
|
|
|
|
default:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2001-02-27 19:23:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
stnode_init_int(df_lval, type_id, val);
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2015-01-18 10:22:19 +00:00
|
|
|
str_to_gint32(dfwork_t *dfw, char *s, gint32* pint)
|
2001-02-27 19:23:30 +00:00
|
|
|
{
|
|
|
|
char *endptr;
|
2004-07-16 23:35:46 +00:00
|
|
|
long integer;
|
2001-02-27 19:23:30 +00:00
|
|
|
|
2004-07-16 23:35:46 +00:00
|
|
|
errno = 0;
|
2004-06-03 07:17:24 +00:00
|
|
|
integer = strtol(s, &endptr, 0);
|
2001-02-27 19:23:30 +00:00
|
|
|
|
2004-07-16 23:35:46 +00:00
|
|
|
if (errno == EINVAL || endptr == s || *endptr != '\0') {
|
2001-02-27 19:23:30 +00:00
|
|
|
/* This isn't a valid number. */
|
2015-01-18 10:22:19 +00:00
|
|
|
dfilter_fail(dfw, "\"%s\" is not a valid number.", s);
|
2001-02-27 19:23:30 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (errno == ERANGE) {
|
2004-06-03 07:17:24 +00:00
|
|
|
if (integer == LONG_MAX) {
|
2015-01-18 10:22:19 +00:00
|
|
|
dfilter_fail(dfw, "\"%s\" causes an integer overflow.", s);
|
2001-02-27 19:23:30 +00:00
|
|
|
}
|
2004-06-03 07:17:24 +00:00
|
|
|
else if (integer == LONG_MIN) {
|
2015-01-18 10:22:19 +00:00
|
|
|
dfilter_fail(dfw, "\"%s\" causes an integer underflow.", s);
|
2004-06-03 07:17:24 +00:00
|
|
|
}
|
2001-02-27 19:23:30 +00:00
|
|
|
else {
|
2004-07-16 23:35:46 +00:00
|
|
|
/*
|
|
|
|
* XXX - can "strtol()" set errno to ERANGE without
|
|
|
|
* returning LONG_MAX or LONG_MIN?
|
|
|
|
*/
|
2015-01-18 10:22:19 +00:00
|
|
|
dfilter_fail(dfw, "\"%s\" is not an integer.", s);
|
2001-02-27 19:23:30 +00:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-07-16 23:35:46 +00:00
|
|
|
if (integer > G_MAXINT32) {
|
|
|
|
/*
|
|
|
|
* Fits in a long, but not in a gint32 (a long might be
|
|
|
|
* 64 bits).
|
|
|
|
*/
|
2015-01-18 10:22:19 +00:00
|
|
|
dfilter_fail(dfw, "\"%s\" causes an integer overflow.", s);
|
2004-07-16 23:35:46 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (integer < G_MININT32) {
|
|
|
|
/*
|
|
|
|
* Fits in a long, but not in a gint32 (a long might be
|
|
|
|
* 64 bits).
|
|
|
|
*/
|
2015-01-18 10:22:19 +00:00
|
|
|
dfilter_fail(dfw, "\"%s\" causes an integer underflow.", s);
|
2004-07-16 23:35:46 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-02-27 19:23:30 +00:00
|
|
|
|
2011-05-17 23:37:27 +00:00
|
|
|
*pint = (gint32)integer;
|
2001-02-27 19:23:30 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-01-31 19:50:38 +00:00
|
|
|
static void
|
|
|
|
mark_lval_deprecated(const char *s)
|
|
|
|
{
|
|
|
|
df_lval->deprecated_token = s;
|
|
|
|
}
|