![Guy Harris](/assets/img/avatar_default.png)
master-branch libpcap now generates a reentrant Flex scanner and Bison/Berkeley YACC parser for capture filter expressions, so it requires versions of Flex and Bison/Berkeley YACC that support that. We might as well do the same. For libwiretap, it means we could actually have multiple K12 text or Ascend/Lucent text files open at the same time. For libwireshark, it might not be as useful, as we only read configuration files at startup (which should only happen once, in one thread) or on demand (in which case, if we ever support multiple threads running libwireshark, we'd need a mutex to ensure that only one file reads it), but it's still the right thing to do. We also require a version of Flex that can write out a header file, so we change the runlex script to generate the header file ourselves. This means we require a version of Flex new enough to support --header-file. Clean up some other stuff encountered in the process. Change-Id: Id23078c6acea549a52fc687779bb55d715b55c16 Reviewed-on: https://code.wireshark.org/review/14719 Reviewed-by: Guy Harris <guy@alum.mit.edu>
402 lines
11 KiB
Text
402 lines
11 KiB
Text
/*
|
|
* We want a reentrant scanner.
|
|
*/
|
|
%option reentrant
|
|
|
|
/*
|
|
* We don't use input, so don't generate code for it.
|
|
*/
|
|
%option noinput
|
|
|
|
/*
|
|
* We don't use unput, so don't generate code for it.
|
|
*/
|
|
%option nounput
|
|
|
|
/*
|
|
* We don't read interactively from the terminal.
|
|
*/
|
|
%option never-interactive
|
|
|
|
/*
|
|
* We want to stop processing when we get to the end of the input.
|
|
*/
|
|
%option noyywrap
|
|
|
|
/*
|
|
* The type for the state we keep for a scanner.
|
|
*/
|
|
%option extra-type="Mate_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
|
|
|
|
/*
|
|
* Prefix scanner routines with "Mate_" rather than "yy", so this scanner
|
|
* can coexist with other scanners.
|
|
*/
|
|
%option prefix="Mate_"
|
|
|
|
%{
|
|
|
|
/* mate_parser.l
|
|
* lexical analyzer for MATE configuration files
|
|
*
|
|
* Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "mate.h"
|
|
#include "mate_grammar.h"
|
|
|
|
#include <wsutil/file_util.h>
|
|
|
|
#ifdef _WIN32
|
|
/* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
|
|
/* with YY_INPUT code generated by flex versions such as 2.5.35. */
|
|
#pragma warning (disable:4018)
|
|
#endif
|
|
|
|
void MateParser(void*,int, gchar*, mate_config* matecfg);
|
|
#if (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 16))
|
|
void *MateParserAlloc(void *(*)(gsize));
|
|
#else
|
|
void *MateParserAlloc(void *(*)(gulong));
|
|
#endif
|
|
void MateParserFree( void*, void(*)(void*) );
|
|
void MateParseTrace(FILE*,char*);
|
|
|
|
#define MAX_INCLUDE_DEPTH 10
|
|
typedef struct {
|
|
mate_config* mc;
|
|
|
|
mate_config_frame* current_frame;
|
|
|
|
void* pParser;
|
|
|
|
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
|
|
int include_stack_ptr;
|
|
} Mate_scanner_state_t;
|
|
|
|
#define MATE_PARSE(token_type) MateParser(yyextra->pParser, (token_type), g_strdup(yytext), yyextra->mc);
|
|
|
|
/*
|
|
* Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
|
|
*/
|
|
#ifdef _WIN32
|
|
#define YY_NO_UNISTD_H
|
|
#endif
|
|
|
|
static void free_config_frame(mate_config_frame *frame) {
|
|
g_free(frame->filename);
|
|
g_free(frame);
|
|
}
|
|
|
|
#define YY_USER_INIT BEGIN OUTSIDE;
|
|
|
|
/*
|
|
* 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 Mate_alloc(size, yyscanner) (void *)malloc(size)
|
|
#define Mate_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
|
|
#define Mate_free(ptr, yyscanner) free((char *)ptr)
|
|
|
|
%}
|
|
|
|
pdu_kw Pdu
|
|
gop_kw Gop
|
|
gog_kw Gog
|
|
transform_kw Transform
|
|
match_kw Match
|
|
always_kw Always
|
|
strict_kw Strict
|
|
every_kw Every
|
|
loose_kw Loose
|
|
replace_kw Replace
|
|
insert_kw Insert
|
|
gop_tree_kw GopTree
|
|
member_kw Member
|
|
on_kw On
|
|
start_kw Start
|
|
stop_kw Stop
|
|
extra_kw Extra
|
|
show_tree_kw ShowTree
|
|
show_times_kw ShowTimes
|
|
expiration_kw Expiration
|
|
idle_timeout_kw IdleTimeout
|
|
lifetime_kw Lifetime
|
|
no_tree_kw NoTree
|
|
pdu_tree_kw PduTree
|
|
frame_tree_kw FrameTree
|
|
basic_tree_kw BasicTree
|
|
true_kw [Tt][Rr][Uu][Ee]
|
|
false_kw [Ff][Aa][Ll][Ss][Ee]
|
|
proto_kw Proto
|
|
payload_kw Payload
|
|
transport_kw Transport
|
|
criteria_kw Criteria
|
|
accept_kw Accept
|
|
reject_kw Reject
|
|
extract_kw Extract
|
|
from_kw From
|
|
drop_unassigned_kw DropUnassigned
|
|
discard_pdu_data_kw DiscardPduData
|
|
last_pdu_kw LastPdu
|
|
done_kw Done
|
|
filename_kw Filename
|
|
debug_kw Debug
|
|
level_kw Level
|
|
default_kw Default
|
|
|
|
|
|
open_parens "("
|
|
close_parens ")"
|
|
open_brace "{"
|
|
close_brace "}"
|
|
comma ","
|
|
semicolon ";"
|
|
slash "/"
|
|
pipe "|"
|
|
|
|
integer [0-9]+
|
|
floating ([0-9]+\.[0-9]+)
|
|
doted_ip [0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?
|
|
colonized [0-9A-Fa-f:]*[:][0-9A-Fa-f:]*
|
|
|
|
name [a-z][-\.a-zA-Z0-9_]*
|
|
avp_operator [$^~=<>!]
|
|
quote ["]
|
|
not_quoted [^"]*
|
|
|
|
include "#include"
|
|
filename [-A-Za-z0-9_/.]+
|
|
|
|
whitespace [[:blank:]\r]+
|
|
newline \n
|
|
|
|
comment "//"[^\n]*\n
|
|
|
|
blk_cmnt_start "/*"
|
|
cmnt_char .
|
|
blk_cmnt_stop "*/"
|
|
|
|
%START OUTSIDE QUOTED INCLUDING COMMENT
|
|
%%
|
|
|
|
{newline} yyextra->current_frame->linenum++;
|
|
{whitespace} ;
|
|
|
|
<OUTSIDE>{include} BEGIN INCLUDING;
|
|
|
|
<INCLUDING>{filename} {
|
|
if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH )
|
|
g_error("dtd_preparse: include files nested too deeply");
|
|
|
|
yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
|
|
yyin = ws_fopen( yytext, "r" );
|
|
|
|
if (!yyin) {
|
|
Mate__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
|
|
|
|
/* coverity[negative_sink] */
|
|
Mate__switch_to_buffer(yyextra->include_stack[--yyextra->include_stack_ptr], yyscanner);
|
|
|
|
if (errno)
|
|
g_string_append_printf(yyextra->mc->config_error, "Mate parser: Could not open file: '%s': %s", yytext, g_strerror(errno) );
|
|
|
|
} else {
|
|
|
|
yyextra->current_frame = (mate_config_frame *)g_malloc(sizeof(mate_config_frame));
|
|
yyextra->current_frame->filename = g_strdup(yytext);
|
|
yyextra->current_frame->linenum = 1;
|
|
|
|
g_ptr_array_add(yyextra->mc->config_stack,yyextra->current_frame);
|
|
|
|
Mate__switch_to_buffer(Mate__create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
|
|
}
|
|
|
|
BEGIN OUTSIDE;
|
|
}
|
|
|
|
<<EOF>> {
|
|
/* coverity[check_after_sink] */
|
|
if ( --yyextra->include_stack_ptr < 0 ) {
|
|
yyterminate();
|
|
} else {
|
|
Mate__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
|
|
Mate__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
|
|
|
|
free_config_frame(yyextra->current_frame);
|
|
yyextra->current_frame = (mate_config_frame *)g_ptr_array_remove_index(yyextra->mc->config_stack,yyextra->mc->config_stack->len-1);
|
|
}
|
|
}
|
|
|
|
<OUTSIDE>{comment} ;
|
|
|
|
<OUTSIDE>{blk_cmnt_start} BEGIN COMMENT;
|
|
<COMMENT>{cmnt_char} ;
|
|
<COMMENT>{blk_cmnt_stop} BEGIN OUTSIDE;
|
|
|
|
<OUTSIDE>{pdu_kw} MATE_PARSE(TOKEN_PDU_KW);
|
|
<OUTSIDE>{gop_kw} MATE_PARSE(TOKEN_GOP_KW);
|
|
<OUTSIDE>{gog_kw} MATE_PARSE(TOKEN_GOG_KW);
|
|
<OUTSIDE>{transform_kw} MATE_PARSE(TOKEN_TRANSFORM_KW);
|
|
<OUTSIDE>{match_kw} MATE_PARSE(TOKEN_MATCH_KW);
|
|
<OUTSIDE>{strict_kw} MATE_PARSE(TOKEN_STRICT_KW);
|
|
<OUTSIDE>{every_kw} MATE_PARSE(TOKEN_EVERY_KW);
|
|
<OUTSIDE>{loose_kw} MATE_PARSE(TOKEN_LOOSE_KW);
|
|
<OUTSIDE>{replace_kw} MATE_PARSE(TOKEN_REPLACE_KW);
|
|
<OUTSIDE>{insert_kw} MATE_PARSE(TOKEN_INSERT_KW);
|
|
<OUTSIDE>{gop_tree_kw} MATE_PARSE(TOKEN_GOP_TREE_KW);
|
|
<OUTSIDE>{member_kw} MATE_PARSE(TOKEN_MEMBER_KW);
|
|
<OUTSIDE>{on_kw} MATE_PARSE(TOKEN_ON_KW);
|
|
<OUTSIDE>{start_kw} MATE_PARSE(TOKEN_START_KW);
|
|
<OUTSIDE>{stop_kw} MATE_PARSE(TOKEN_STOP_KW);
|
|
<OUTSIDE>{extra_kw} MATE_PARSE(TOKEN_EXTRA_KW);
|
|
<OUTSIDE>{show_tree_kw} MATE_PARSE(TOKEN_SHOW_TREE_KW);
|
|
<OUTSIDE>{show_times_kw} MATE_PARSE(TOKEN_SHOW_TIMES_KW);
|
|
<OUTSIDE>{expiration_kw} MATE_PARSE(TOKEN_EXPIRATION_KW);
|
|
<OUTSIDE>{idle_timeout_kw} MATE_PARSE(TOKEN_IDLE_TIMEOUT_KW);
|
|
<OUTSIDE>{lifetime_kw} MATE_PARSE(TOKEN_LIFETIME_KW);
|
|
<OUTSIDE>{no_tree_kw} MATE_PARSE(TOKEN_NO_TREE_KW);
|
|
<OUTSIDE>{pdu_tree_kw} MATE_PARSE(TOKEN_PDU_TREE_KW);
|
|
<OUTSIDE>{frame_tree_kw} MATE_PARSE(TOKEN_FRAME_TREE_KW);
|
|
<OUTSIDE>{basic_tree_kw} MATE_PARSE(TOKEN_BASIC_TREE_KW);
|
|
<OUTSIDE>{true_kw} MATE_PARSE(TOKEN_TRUE_KW);
|
|
<OUTSIDE>{false_kw} MATE_PARSE(TOKEN_FALSE_KW);
|
|
<OUTSIDE>{proto_kw} MATE_PARSE(TOKEN_PROTO_KW);
|
|
<OUTSIDE>{payload_kw} MATE_PARSE(TOKEN_PAYLOAD_KW);
|
|
<OUTSIDE>{transport_kw} MATE_PARSE(TOKEN_TRANSPORT_KW);
|
|
<OUTSIDE>{criteria_kw} MATE_PARSE(TOKEN_CRITERIA_KW);
|
|
<OUTSIDE>{accept_kw} MATE_PARSE(TOKEN_ACCEPT_KW);
|
|
<OUTSIDE>{reject_kw} MATE_PARSE(TOKEN_REJECT_KW);
|
|
<OUTSIDE>{extract_kw} MATE_PARSE(TOKEN_EXTRACT_KW);
|
|
<OUTSIDE>{from_kw} MATE_PARSE(TOKEN_FROM_KW);
|
|
<OUTSIDE>{drop_unassigned_kw} MATE_PARSE(TOKEN_DROP_UNASSIGNED_KW);
|
|
<OUTSIDE>{discard_pdu_data_kw} MATE_PARSE(TOKEN_DISCARD_PDU_DATA_KW);
|
|
<OUTSIDE>{last_pdu_kw} MATE_PARSE(TOKEN_LAST_PDU_KW);
|
|
<OUTSIDE>{done_kw} MATE_PARSE(TOKEN_DONE_KW);
|
|
<OUTSIDE>{filename_kw} MATE_PARSE(TOKEN_FILENAME_KW);
|
|
<OUTSIDE>{debug_kw} MATE_PARSE(TOKEN_DEBUG_KW);
|
|
<OUTSIDE>{level_kw} MATE_PARSE(TOKEN_LEVEL_KW);
|
|
<OUTSIDE>{default_kw} MATE_PARSE(TOKEN_DEFAULT_KW);
|
|
|
|
<OUTSIDE>{open_parens} MATE_PARSE(TOKEN_OPEN_PARENS);
|
|
<OUTSIDE>{close_parens} MATE_PARSE(TOKEN_CLOSE_PARENS);
|
|
<OUTSIDE>{open_brace} MATE_PARSE(TOKEN_OPEN_BRACE);
|
|
<OUTSIDE>{close_brace} MATE_PARSE(TOKEN_CLOSE_BRACE);
|
|
<OUTSIDE>{comma} MATE_PARSE(TOKEN_COMMA);
|
|
<OUTSIDE>{semicolon} MATE_PARSE(TOKEN_SEMICOLON);
|
|
<OUTSIDE>{slash} MATE_PARSE(TOKEN_SLASH);
|
|
<OUTSIDE>{pipe} MATE_PARSE(TOKEN_PIPE);
|
|
|
|
<OUTSIDE>{integer} MATE_PARSE(TOKEN_INTEGER);
|
|
<OUTSIDE>{floating} MATE_PARSE(TOKEN_FLOATING);
|
|
<OUTSIDE>{doted_ip} MATE_PARSE(TOKEN_DOTED_IP);
|
|
<OUTSIDE>{colonized} MATE_PARSE(TOKEN_COLONIZED);
|
|
<OUTSIDE>{name} MATE_PARSE(TOKEN_NAME);
|
|
<OUTSIDE>{avp_operator} MATE_PARSE(TOKEN_AVP_OPERATOR);
|
|
|
|
|
|
<OUTSIDE>{quote} BEGIN QUOTED;
|
|
<QUOTED>{not_quoted} MATE_PARSE(TOKEN_QUOTED);
|
|
<QUOTED>{quote} BEGIN OUTSIDE;
|
|
|
|
%%
|
|
|
|
extern gboolean mate_load_config(const gchar* filename, mate_config* mc) {
|
|
FILE *in;
|
|
yyscan_t scanner;
|
|
Mate_scanner_state_t state;
|
|
volatile gboolean status = TRUE;
|
|
|
|
in = ws_fopen(filename,"r");
|
|
|
|
if (!in) {
|
|
g_string_append_printf(mc->config_error,"Mate parser: Could not open file: '%s', error: %s", filename, g_strerror(errno) );
|
|
return FALSE;
|
|
}
|
|
|
|
if (Mate_lex_init(&scanner) != 0) {
|
|
g_string_append_printf(mc->config_error, "Mate parse: Could not initialize scanner: %s", g_strerror(errno));
|
|
fclose(in);
|
|
return FALSE;
|
|
}
|
|
|
|
Mate_set_in(in, scanner);
|
|
|
|
mc->config_stack = g_ptr_array_new();
|
|
|
|
state.mc = mc;
|
|
|
|
state.current_frame = (mate_config_frame *)g_malloc(sizeof(mate_config_frame));
|
|
state.current_frame->filename = g_strdup(filename);
|
|
state.current_frame->linenum = 1;
|
|
|
|
g_ptr_array_add(mc->config_stack,state.current_frame);
|
|
|
|
state.pParser = MateParserAlloc(g_malloc);
|
|
|
|
state.include_stack_ptr = 0;
|
|
|
|
/* Associate the state with the scanner */
|
|
Mate_set_extra(&state, scanner);
|
|
|
|
/* MateParserTrace(stdout,""); */
|
|
|
|
TRY {
|
|
Mate_lex(scanner);
|
|
|
|
/* Inform parser that end of input has reached. */
|
|
MateParser(state.pParser, 0, NULL, mc);
|
|
|
|
MateParserFree(state.pParser, g_free);
|
|
} CATCH(MateConfigError) {
|
|
status = FALSE;
|
|
} CATCH_ALL {
|
|
status = FALSE;
|
|
g_string_append_printf(mc->config_error,"An unexpected error occurred");
|
|
}
|
|
ENDTRY;
|
|
|
|
Mate_lex_destroy(scanner);
|
|
fclose(in);
|
|
|
|
g_ptr_array_foreach(mc->config_stack, (GFunc)free_config_frame, NULL);
|
|
g_ptr_array_free(mc->config_stack, FALSE);
|
|
|
|
return status;
|
|
}
|