diff options
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/Makefile.am | 6 | ||||
-rw-r--r-- | wiretap/ascend-int.h | 43 | ||||
-rw-r--r-- | wiretap/ascend.y | 395 | ||||
-rw-r--r-- | wiretap/ascend_scanner.l | 126 | ||||
-rw-r--r-- | wiretap/ascendtext.c | 133 | ||||
-rw-r--r-- | wiretap/k12text.l | 268 |
6 files changed, 563 insertions, 408 deletions
diff --git a/wiretap/Makefile.am b/wiretap/Makefile.am index e30efcfbbe..597e77d27b 100644 --- a/wiretap/Makefile.am +++ b/wiretap/Makefile.am @@ -53,6 +53,8 @@ libwiretap_generated_la_SOURCES = \ libwiretap_generated_la_CFLAGS = $(GENERATED_CFLAGS) +BUILT_SOURCES = $(GENERATED_HEADER_FILES) + EXTRA_DIST = \ .editorconfig \ README.airmagnet \ @@ -71,11 +73,9 @@ k12text_lex.h : k12text.c ascend_scanner_lex.h : ascend_scanner.c -ascend_scanner.c: ascend.h - ascend.h: ascend.c -ascend.c: ascend.y +ascend.c: $(srcdir)/ascend.y ascend_scanner_lex.h @if [ -z "$(YACC)" ]; then \ echo "Neither bison nor byacc has been found"; \ exit 1; \ diff --git a/wiretap/ascend-int.h b/wiretap/ascend-int.h index 049bf8599d..0d8e70b6d6 100644 --- a/wiretap/ascend-int.h +++ b/wiretap/ascend-int.h @@ -27,31 +27,34 @@ #include <glib.h> #include "ws_symbol_export.h" -extern const gchar *ascend_parse_error; - -/* - * Pointer to the pseudo-header for the current packet. - */ -extern struct ascend_phdr *pseudo_header; - typedef struct { time_t inittime; gboolean adjusted; gint64 next_packet_seek_start; } ascend_t; -/* Here we provide interfaces to make our scanner act and look like lex */ -int ascendlex(void); - -void init_parse_ascend(void); -void ascend_init_lexer(FILE_T fh); -gboolean check_ascend(FILE_T fh, struct wtap_pkthdr *phdr); -typedef enum { - PARSED_RECORD, - PARSED_NONRECORD, - PARSE_FAILED -} parse_t; -parse_t parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, - Buffer *buf, guint length); +typedef struct { + FILE_T fh; + const gchar *ascend_parse_error; + int *err; + gchar **err_info; + struct ascend_phdr *pseudo_header; + guint8 *pkt_data; + + gboolean saw_timestamp; + guint32 timestamp; + + unsigned int bcur; + gint64 first_hexbyte; + guint32 wirelen; + guint32 caplen; + time_t secs; + guint32 usecs; +} ascend_state_t; +#define YY_EXTRA_TYPE ascend_state_t * + +extern int +run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd, + ascend_state_t *parser_state, int *err, gchar **err_info); #endif /* ! __ASCEND_INT_H__ */ diff --git a/wiretap/ascend.y b/wiretap/ascend.y index dc30a9e78f..31f9cbc88e 100644 --- a/wiretap/ascend.y +++ b/wiretap/ascend.y @@ -1,3 +1,28 @@ +/* + * We want a reentrant parser. + */ +%pure-parser + +/* + * We also want a reentrant scanner, so we have to pass the + * handle for the reentrant scanner to the parser, and the + * parser has to pass it to the lexical analyzer. + * + * We use void * rather than yyscan_t because, at least with some + * versions of Flex and Bison, if you use yyscan_t in %parse-param and + * %lex-param, you have to include the ascend_lex_scanner.h before + * ascend.h to get yyscan_t declared, and you have to include ascend.h + * before ascend_lex_scanner.h to get YYSTYPE declared. Using void * + * breaks the cycle; the Flex documentation says yyscan_t is just a void *. + */ +%parse-param {void *yyscanner} +%lex-param {void *yyscanner} + +/* + * And we need to pass the parser state to the scanner. + */ +%parse-param {ascend_state_t *parser_state} + %{ /* ascend.y * @@ -135,22 +160,13 @@ XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octet #include <wsutil/buffer.h> #include "ascendtext.h" #include "ascend-int.h" +#include "ascend.h" +#include "ascend_scanner_lex.h" #include "file_wrappers.h" #define NO_USER "<none>" -int yyparse(FILE_T fh); -void yyerror(FILE_T fh _U_, const char *); - -const gchar *ascend_parse_error; - -static unsigned int bcur; -static guint32 start_time, usecs, caplen, wirelen; -static time_t secs; -struct ascend_phdr *pseudo_header; -static guint8 *pkt_data; -static gint64 first_hexbyte; - +extern void yyerror (void *yyscanner, ascend_state_t *state, FILE_T fh _U_, const char *s); %} %union { @@ -208,19 +224,19 @@ PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @ */ deferred_isdn_hdr: isdn_prefix decnum SLASH_SUFFIX KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen += $11; - caplen += $11; - secs = $9; - usecs = $10; - if (pseudo_header != NULL) { - pseudo_header->type = $1; - pseudo_header->sess = $2; - pseudo_header->call_num[0] = '\0'; - pseudo_header->chunk = 0; - pseudo_header->task = $7; + parser_state->wirelen += $11; + parser_state->caplen += $11; + parser_state->secs = $9; + parser_state->usecs = $10; + if (parser_state->pseudo_header != NULL) { + parser_state->pseudo_header->type = $1; + parser_state->pseudo_header->sess = $2; + parser_state->pseudo_header->call_num[0] = '\0'; + parser_state->pseudo_header->chunk = 0; + parser_state->pseudo_header->task = $7; } /* because we have two data groups */ - first_hexbyte = 0; + parser_state->first_hexbyte = 0; } ; @@ -230,18 +246,18 @@ PRI-XMIT-19: (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1 PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00 */ isdn_hdr: isdn_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen = $10; - caplen = $10; - secs = $8; - usecs = $9; - if (pseudo_header != NULL) { - pseudo_header->type = $1; - pseudo_header->sess = $2; - pseudo_header->call_num[0] = '\0'; - pseudo_header->chunk = 0; - pseudo_header->task = $6; + parser_state->wirelen = $10; + parser_state->caplen = $10; + parser_state->secs = $8; + parser_state->usecs = $9; + if (parser_state->pseudo_header != NULL) { + parser_state->pseudo_header->type = $1; + parser_state->pseudo_header->sess = $2; + parser_state->pseudo_header->call_num[0] = '\0'; + parser_state->pseudo_header->chunk = 0; + parser_state->pseudo_header->task = $6; } - first_hexbyte = 0; + parser_state->first_hexbyte = 0; } ; @@ -251,15 +267,15 @@ ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa */ ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen = $10; - caplen = $10; - secs = $8; - usecs = $9; - if (pseudo_header != NULL) { - pseudo_header->type = $1; - pseudo_header->call_num[0] = '\0'; - pseudo_header->chunk = 0; - pseudo_header->task = $6; + parser_state->wirelen = $10; + parser_state->caplen = $10; + parser_state->secs = $8; + parser_state->usecs = $9; + if (parser_state->pseudo_header != NULL) { + parser_state->pseudo_header->type = $1; + parser_state->pseudo_header->call_num[0] = '\0'; + parser_state->pseudo_header->chunk = 0; + parser_state->pseudo_header->task = $6; } } ; @@ -267,17 +283,17 @@ ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decn /* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */ /* 1 2 3 4 5 6 7 8 9 10 11 */ wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen = $9; - caplen = $9; - secs = $7; - usecs = $8; - if (pseudo_header != NULL) { - /* pseudo_header->user is set in ascend_scanner.l */ - pseudo_header->type = $1; - pseudo_header->sess = $3; - pseudo_header->call_num[0] = '\0'; - pseudo_header->chunk = 0; - pseudo_header->task = $5; + parser_state->wirelen = $9; + parser_state->caplen = $9; + parser_state->secs = $7; + parser_state->usecs = $8; + if (parser_state->pseudo_header != NULL) { + /* parser_state->pseudo_header->user is set in ascend_scanner.l */ + parser_state->pseudo_header->type = $1; + parser_state->pseudo_header->sess = $3; + parser_state->pseudo_header->call_num[0] = '\0'; + parser_state->pseudo_header->chunk = 0; + parser_state->pseudo_header->task = $5; } } ; @@ -285,17 +301,17 @@ wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KE /* RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198 */ /* 1 2 3 4 5 6 7 8 9 10 11 12 13 */ wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen = $11; - caplen = $11; - secs = $9; - usecs = $10; - if (pseudo_header != NULL) { - /* pseudo_header->user is set in ascend_scanner.l */ - pseudo_header->type = $1; - pseudo_header->sess = $3; - pseudo_header->call_num[0] = '\0'; - pseudo_header->chunk = 0; - pseudo_header->task = $7; + parser_state->wirelen = $11; + parser_state->caplen = $11; + parser_state->secs = $9; + parser_state->usecs = $10; + if (parser_state->pseudo_header != NULL) { + /* parser_state->pseudo_header->user is set in ascend_scanner.l */ + parser_state->pseudo_header->type = $1; + parser_state->pseudo_header->sess = $3; + parser_state->pseudo_header->call_num[0] = '\0'; + parser_state->pseudo_header->chunk = 0; + parser_state->pseudo_header->task = $7; } } ; @@ -303,17 +319,17 @@ wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum /* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */ /* 1 2 3 4 5 6 7 8 9 10 */ wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen = $8; - caplen = $8; - secs = $6; - usecs = $7; - if (pseudo_header != NULL) { - /* pseudo_header->user is set in ascend_scanner.l */ - pseudo_header->type = $1; - pseudo_header->sess = $2; - pseudo_header->call_num[0] = '\0'; - pseudo_header->chunk = 0; - pseudo_header->task = $4; + parser_state->wirelen = $8; + parser_state->caplen = $8; + parser_state->secs = $6; + parser_state->usecs = $7; + if (parser_state->pseudo_header != NULL) { + /* parser_state->pseudo_header->user is set in ascend_scanner.l */ + parser_state->pseudo_header->type = $1; + parser_state->pseudo_header->sess = $2; + parser_state->pseudo_header->call_num[0] = '\0'; + parser_state->pseudo_header->chunk = 0; + parser_state->pseudo_header->task = $4; } } ; @@ -321,17 +337,17 @@ wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD /* XMIT-44: (task "freedm_task" at 0xe051fd10, time: 6258.66) 29 octets @ 0x606d1f00 */ /* 1 2 3 4 5 6 7 8 9 10 11 12 */ wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen = $10; - caplen = $10; - secs = $8; - usecs = $9; - if (pseudo_header != NULL) { - /* pseudo_header->user is set in ascend_scanner.l */ - pseudo_header->type = $1; - pseudo_header->sess = $2; - pseudo_header->call_num[0] = '\0'; - pseudo_header->chunk = 0; - pseudo_header->task = $6; + parser_state->wirelen = $10; + parser_state->caplen = $10; + parser_state->secs = $8; + parser_state->usecs = $9; + if (parser_state->pseudo_header != NULL) { + /* parser_state->pseudo_header->user is set in ascend_scanner.l */ + parser_state->pseudo_header->type = $1; + parser_state->pseudo_header->sess = $2; + parser_state->pseudo_header->call_num[0] = '\0'; + parser_state->pseudo_header->chunk = 0; + parser_state->pseudo_header->task = $6; } } ; @@ -356,7 +372,8 @@ wdd_date: WDD_DATE decnum decnum decnum KEYWORD decnum decnum decnum KEYWORD str wddt.tm_year = ($4 > 1970) ? $4 - 1900 : 70; wddt.tm_isdst = -1; - start_time = (guint32) mktime(&wddt); + parser_state->timestamp = (guint32) mktime(&wddt); + parser_state->saw_timestamp = TRUE; } ; @@ -366,17 +383,17 @@ WD_DIALOUT_DISP: chunk 2515EE type IP. */ /* 1 2 3 4 5 6 7 8 9 10 11*/ wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { - wirelen = $9; - caplen = $9; - secs = $7; - usecs = $8; - if (pseudo_header != NULL) { - /* pseudo_header->call_num is set in ascend_scanner.l */ - pseudo_header->type = ASCEND_PFX_WDD; - pseudo_header->user[0] = '\0'; - pseudo_header->sess = 0; - pseudo_header->chunk = $2; - pseudo_header->task = $5; + parser_state->wirelen = $9; + parser_state->caplen = $9; + parser_state->secs = $7; + parser_state->usecs = $8; + if (parser_state->pseudo_header != NULL) { + /* parser_state->pseudo_header->call_num is set in ascend_scanner.l */ + parser_state->pseudo_header->type = ASCEND_PFX_WDD; + parser_state->pseudo_header->user[0] = '\0'; + parser_state->pseudo_header->sess = 0; + parser_state->pseudo_header->chunk = $2; + parser_state->pseudo_header->task = $5; } } ; @@ -384,16 +401,16 @@ wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KE byte: HEXBYTE { /* remember the position of the data group in the trace, to tip off ascend_seek() as to where to look for the next header. */ - if (first_hexbyte == 0) - first_hexbyte = file_tell(fh); + if (parser_state->first_hexbyte == 0) + parser_state->first_hexbyte = file_tell(fh); - if (bcur < caplen) { - pkt_data[bcur] = $1; - bcur++; + if (parser_state->bcur < parser_state->caplen) { + parser_state->pkt_data[parser_state->bcur] = $1; + parser_state->bcur++; } /* arbitrary safety maximum... */ - if (bcur >= ASCEND_MAX_PKT_LEN) + if (parser_state->bcur >= ASCEND_MAX_PKT_LEN) YYACCEPT; } ; @@ -431,27 +448,42 @@ datagroup: dataln %% -void -init_parse_ascend(void) -{ - start_time = 0; /* we haven't see a date/time yet */ -} - /* Run the parser. */ -static int -run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd) +int +run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd, + ascend_state_t *parser_state, int *err, gchar **err_info) { - /* yydebug = 1; */ + yyscan_t scanner = NULL; int retval; - ascend_init_lexer(fh); - pseudo_header = &phdr->pseudo_header.ascend; - pkt_data = pd; + if (ascendlex_init(&scanner) != 0) { + /* errno is set if this fails */ + *err = errno; + *err_info = NULL; + return 1; + } + /* Associate the parser state with the lexical analyzer state */ + ascendset_extra(parser_state, scanner); + parser_state->fh = fh; + parser_state->ascend_parse_error = NULL; + parser_state->err = err; + parser_state->err_info = err_info; + parser_state->pseudo_header = &phdr->pseudo_header.ascend; + parser_state->pkt_data = pd; + + /* + * We haven't seen a time stamp yet. + */ + parser_state->saw_timestamp = FALSE; + parser_state->timestamp = 0; - bcur = 0; - first_hexbyte = 0; - wirelen = 0; - caplen = 0; + parser_state->bcur = 0; + parser_state->first_hexbyte = 0; + parser_state->wirelen = 0; + parser_state->caplen = 0; + + parser_state->secs = 0; + parser_state->usecs = 0; /* * Not all packets in a "wdd" dump necessarily have a "Cause an @@ -464,125 +496,16 @@ run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd) * phone number from the last call, and remember that for use * when doing random access. */ - pseudo_header->call_num[0] = '\0'; - - retval = yyparse(fh); - - caplen = bcur; + parser_state->pseudo_header->call_num[0] = '\0'; + retval = yyparse(scanner, parser_state, fh); + if (retval == 0) + parser_state->caplen = parser_state->bcur; return retval; } -/* Parse the capture file. - Returns: - TRUE if we got a packet - FALSE otherwise. */ -gboolean -check_ascend(FILE_T fh, struct wtap_pkthdr *phdr) -{ - guint8 buf[ASCEND_MAX_PKT_LEN]; - - run_ascend_parser(fh, phdr, buf); - - /* if we got at least some data, return success even if the parser - reported an error. This is because the debug header gives the number - of bytes on the wire, not actually how many bytes are in the trace. - We won't know where the data ends until we run into the next packet. */ - return (caplen != 0); -} - -/* Parse the capture file. - Returns: - PARSED_RECORD if we got a packet - PARSED_NONRECORD if the parser succeeded but didn't see a packet - PARSE_FAILED if the parser failed. */ -parse_t -parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, - guint length) -{ - int retval; - - ws_buffer_assure_space(buf, length); - retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf)); - - /* did we see any data (hex bytes)? if so, tip off ascend_seek() - as to where to look for the next packet, if any. If we didn't, - maybe this record was broken. Advance so we don't get into - an infinite loop reading a broken trace. */ - if (first_hexbyte) { - ascend->next_packet_seek_start = first_hexbyte; - } else { - /* Sometimes, a header will be printed but the data will be omitted, or - worse -- two headers will be printed, followed by the data for each. - Because of this, we need to be fairly tolerant of what we accept - here. If we didn't find any hex bytes, skip over what we've read so - far so we can try reading a new packet. */ - ascend->next_packet_seek_start = file_tell(fh); - retval = 0; - } - - /* if we got at least some data, return success even if the parser - reported an error. This is because the debug header gives the number - of bytes on the wire, not actually how many bytes are in the trace. - We won't know where the data ends until we run into the next packet. */ - if (caplen) { - if (! ascend->adjusted) { - ascend->adjusted = TRUE; - if (start_time != 0) { - /* - * Capture file contained a date and time. - * We do this only if this is the very first packet we've seen - - * i.e., if "ascend->adjusted" is false - because - * if we get a date and time after the first packet, we can't - * go back and adjust the time stamps of the packets we've already - * processed, and basing the time stamps of this and following - * packets on the time stamp from the file text rather than the - * ctime of the capture file means times before this and after - * this can't be compared. - */ - ascend->inittime = start_time; - } - if (ascend->inittime > secs) - ascend->inittime -= secs; - } - phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; - phdr->ts.secs = secs + ascend->inittime; - phdr->ts.nsecs = usecs * 1000; - phdr->caplen = caplen; - phdr->len = wirelen; - - /* - * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND, - * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN - * or WTAP_ENCAP_ETHERNET). - */ - switch(phdr->pseudo_header.ascend.type) { - case ASCEND_PFX_ISDN_X: - phdr->pseudo_header.isdn.uton = TRUE; - phdr->pseudo_header.isdn.channel = 0; - break; - - case ASCEND_PFX_ISDN_R: - phdr->pseudo_header.isdn.uton = FALSE; - phdr->pseudo_header.isdn.channel = 0; - break; - - case ASCEND_PFX_ETHER: - phdr->pseudo_header.eth.fcs_len = 0; - break; - } - return PARSED_RECORD; - } - - /* Didn't see any data. Still, perhaps the parser was happy. */ - if (retval) - return PARSE_FAILED; - else - return PARSED_NONRECORD; -} - void -yyerror (FILE_T fh _U_, const char *s) +yyerror (void *yyscanner, ascend_state_t *state _U_, FILE_T fh _U_, const char *s) { - ascend_parse_error = s; + ascendget_extra(yyscanner)->ascend_parse_error = s; } diff --git a/wiretap/ascend_scanner.l b/wiretap/ascend_scanner.l index 950df9fd3d..24b539e512 100644 --- a/wiretap/ascend_scanner.l +++ b/wiretap/ascend_scanner.l @@ -1,4 +1,15 @@ /* + * We want a reentrant scanner. + */ +%option reentrant + +/* + * We want to generate code that can be used by a reentrant parser + * generated by Bison or Berkeley YACC. + */ +%option bison-bridge + +/* * We don't read interactively from the terminal. */ %option never-interactive @@ -14,6 +25,19 @@ */ %option prefix="ascend" +/* + * 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 + %{ /* ascend_scanner.l * @@ -42,14 +66,24 @@ #include "wtap-int.h" #include "ascendtext.h" -#include "ascend.h" #include "ascend-int.h" +#include "ascend.h" #include "file_wrappers.h" -#include "ascend_scanner_lex.h" -FILE_T yy_fh; -#define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh); \ -result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); } +#define YY_INPUT(buf,result,max_size) { \ + ascend_state_t *parser_state = ascendget_extra(yyscanner); \ + int c = file_getc(parser_state->fh); \ + if (c == EOF) { \ + *(parser_state->err) = file_error(parser_state->fh, \ + parser_state->err_info); \ + if (*(parser_state->err) == 0) \ + *(parser_state->err) = WTAP_ERR_SHORT_READ; \ + result = YY_NULL; \ + } else { \ + buf[0] = c; \ + result = 1; \ + } \ +} #define NO_USER "<none>" @@ -57,6 +91,17 @@ result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); } #define YY_NO_UNISTD_H #endif +/* + * 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 ascendtext_alloc(size, yyscanner) (void *)malloc(size) +#define ascendtext_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size)) +#define ascendtext_free(ptr, yyscanner) free((char *)ptr) %} @@ -110,43 +155,43 @@ WDD_TYPE "type "[^\n\r\t ]+ <INITIAL,sc_gen_byte>{ETHER_PFX} { BEGIN(sc_ether_direction); - ascendlval.d = ASCEND_PFX_ETHER; + yylval->d = ASCEND_PFX_ETHER; return ETHER_PREFIX; } <INITIAL,sc_gen_byte>{ISDN_XPFX} { BEGIN(sc_isdn_call); - ascendlval.d = ASCEND_PFX_ISDN_X; + yylval->d = ASCEND_PFX_ISDN_X; return ISDN_PREFIX; } <INITIAL,sc_gen_byte>{ISDN_RPFX} { BEGIN(sc_isdn_call); - ascendlval.d = ASCEND_PFX_ISDN_R; + yylval->d = ASCEND_PFX_ISDN_R; return ISDN_PREFIX; } <INITIAL,sc_gen_byte>{WAN_XPFX} { BEGIN(sc_wds_user); - ascendlval.d = ASCEND_PFX_WDS_X; + yylval->d = ASCEND_PFX_WDS_X; return WDS_PREFIX; } <INITIAL,sc_gen_byte>{WAN_RPFX} { BEGIN(sc_wds_user); - ascendlval.d = ASCEND_PFX_WDS_R; + yylval->d = ASCEND_PFX_WDS_R; return WDS_PREFIX; } <INITIAL,sc_gen_byte>{PPP_XPFX} { BEGIN(sc_wds_user); - ascendlval.d = ASCEND_PFX_WDS_X; + yylval->d = ASCEND_PFX_WDS_X; return WDS_PREFIX; } <INITIAL,sc_gen_byte>{PPP_RPFX} { BEGIN(sc_wds_user); - ascendlval.d = ASCEND_PFX_WDS_R; + yylval->d = ASCEND_PFX_WDS_R; return WDS_PREFIX; } @@ -161,26 +206,26 @@ WDD_TYPE "type "[^\n\r\t ]+ } <sc_wds_user>[^:]{2,20} { - char *atcopy = g_strdup(ascendtext); - char colon = input(); - char after = input(); + char *atcopy = g_strdup(yytext); + char colon = input(yyscanner); + char after = input(yyscanner); int retval = STRING; unput(after); unput(colon); if (after != '(' && after != ' ') { BEGIN(sc_wds_sess); - if (pseudo_header != NULL) { - g_strlcpy(pseudo_header->user, atcopy, ASCEND_MAX_STR_LEN); + if (yyextra->pseudo_header != NULL) { + g_strlcpy(yyextra->pseudo_header->user, atcopy, ASCEND_MAX_STR_LEN); } } else { /* We have a version 7 file */ BEGIN(sc_gen_task); - if (pseudo_header != NULL) { - g_strlcpy(pseudo_header->user, NO_USER, ASCEND_MAX_STR_LEN); + if (yyextra->pseudo_header != NULL) { + g_strlcpy(yyextra->pseudo_header->user, NO_USER, ASCEND_MAX_STR_LEN); } /* Are valid values ever > 2^32? If so we need to adjust YYSTYPE and a lot of */ /* upstream code accordingly. */ - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); retval = DECNUM; } g_free (atcopy); @@ -189,13 +234,13 @@ WDD_TYPE "type "[^\n\r\t ]+ <sc_wds_sess>{D}* { BEGIN(sc_gen_task); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } <sc_gen_task>(0x|0X)?{H}{2,8} { BEGIN(sc_gen_time_s); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 16); + yylval->d = (guint32) strtoul(yytext, NULL, 16); return HEXNUM; } @@ -205,24 +250,24 @@ WDD_TYPE "type "[^\n\r\t ]+ <sc_gen_time_s>{D}{1,10} { BEGIN(sc_gen_time_u); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } <sc_gen_time_u>{D}{1,6} { - char *atcopy = g_strdup(ascendtext); + char *atcopy = g_strdup(yytext); BEGIN(sc_gen_octets); /* only want the most significant 2 digits. convert to usecs */ if (strlen(atcopy) > 2) atcopy[2] = '\0'; - ascendlval.d = (guint32) strtoul(atcopy, NULL, 10) * 10000; + yylval->d = (guint32) strtoul(atcopy, NULL, 10) * 10000; g_free(atcopy); return DECNUM; } <sc_gen_octets>{D}{1,10} { BEGIN(sc_gen_counter); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } @@ -232,7 +277,7 @@ WDD_TYPE "type "[^\n\r\t ]+ } <sc_gen_byte>{H}{2} { - ascendlval.b = (guint8)(guint32) strtoul(ascendtext, NULL, 16); + yylval->b = (guint8)(guint32) strtoul(yytext, NULL, 16); return HEXBYTE; } @@ -251,19 +296,19 @@ WDD_TYPE "type "[^\n\r\t ]+ <sc_wdd_date_d>{D}{2} { BEGIN(sc_wdd_date_m); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } <sc_wdd_date_m>{D}{2} { BEGIN(sc_wdd_date_y); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } <sc_wdd_date_y>{D}{4} { BEGIN(sc_wdd_time); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } @@ -274,19 +319,19 @@ WDD_TYPE "type "[^\n\r\t ]+ <sc_wdd_time_h>{D}{2} { BEGIN(sc_wdd_time_m); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } <sc_wdd_time_m>{D}{2} { BEGIN(sc_wdd_time_s); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } <sc_wdd_time_s>{D}{2} { BEGIN(sc_wdd_cause); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10); + yylval->d = (guint32) strtoul(yytext, NULL, 10); return DECNUM; } @@ -297,8 +342,8 @@ WDD_TYPE "type "[^\n\r\t ]+ <sc_wdd_callnum>{WDD_CALLNUM} { BEGIN(sc_wdd_chunk); - if (pseudo_header != NULL) { - g_strlcpy(pseudo_header->call_num, ascendtext, ASCEND_MAX_STR_LEN); + if (yyextra->pseudo_header != NULL) { + g_strlcpy(yyextra->pseudo_header->call_num, yytext, ASCEND_MAX_STR_LEN); } return STRING; } @@ -310,7 +355,7 @@ WDD_TYPE "type "[^\n\r\t ]+ <sc_wdd_chunknum>{H}{1,8} { BEGIN(sc_wdd_type); - ascendlval.d = (guint32) strtoul(ascendtext, NULL, 16); + yylval->d = (guint32) strtoul(yytext, NULL, 16); return HEXNUM; } @@ -330,12 +375,3 @@ task:|task|at|time:|octets { return KEYWORD; } <<EOF>> { yyterminate(); } (.|\n) ; - -%% - -void ascend_init_lexer(FILE_T fh) -{ - yyrestart(0); - yy_fh = fh; - BEGIN(INITIAL); -} diff --git a/wiretap/ascendtext.c b/wiretap/ascendtext.c index 7697c45e40..7259fa94bf 100644 --- a/wiretap/ascendtext.c +++ b/wiretap/ascendtext.c @@ -220,6 +220,8 @@ found: wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info) { gint64 offset; + guint8 buf[ASCEND_MAX_PKT_LEN]; + ascend_state_t parser_state; ws_statb64 statbuf; ascend_t *ascend; @@ -236,8 +238,19 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info) } /* Do a trial parse of the first packet just found to see if we might really have an Ascend file */ - init_parse_ascend(); - if (!check_ascend(wth->fh, &wth->phdr)) { + if (run_ascend_parser(wth->fh, &wth->phdr, buf, &parser_state, err, err_info) != 0) { + if (*err != 0) { + /* An I/O error. */ + return WTAP_OPEN_ERROR; + } + } + + /* if we got at least some data, and didn't get an I/O error, return + success even if the parser reported an error. This is because the + debug header gives the number of bytes on the wire, not actually + how many bytes are in the trace. We won't know where the data ends + until we run into the next packet. */ + if (parser_state.caplen == 0) { return WTAP_OPEN_NOT_MINE; } @@ -280,11 +293,113 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info) ascend->adjusted = FALSE; wth->file_tsprec = WTAP_TSPREC_USEC; - init_parse_ascend(); - return WTAP_OPEN_MINE; } +typedef enum { + PARSED_RECORD, + PARSED_NONRECORD, + PARSE_FAILED +} parse_t; + +/* Parse the capture file. + Returns: + PARSED_RECORD if we got a packet + PARSED_NONRECORD if the parser succeeded but didn't see a packet + PARSE_FAILED if the parser failed. */ +static parse_t +parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, + guint length, int *err, gchar **err_info) +{ + ascend_state_t parser_state; + int retval; + + ws_buffer_assure_space(buf, length); + retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf), &parser_state, + err, err_info); + + /* did we see any data (hex bytes)? if so, tip off ascend_seek() + as to where to look for the next packet, if any. If we didn't, + maybe this record was broken. Advance so we don't get into + an infinite loop reading a broken trace. */ + if (parser_state.first_hexbyte) { + ascend->next_packet_seek_start = parser_state.first_hexbyte; + } else { + /* Sometimes, a header will be printed but the data will be omitted, or + worse -- two headers will be printed, followed by the data for each. + Because of this, we need to be fairly tolerant of what we accept + here. If we didn't find any hex bytes, skip over what we've read so + far so we can try reading a new packet. */ + ascend->next_packet_seek_start = file_tell(fh); + retval = 0; + } + + /* if we got at least some data, return success even if the parser + reported an error. This is because the debug header gives the number + of bytes on the wire, not actually how many bytes are in the trace. + We won't know where the data ends until we run into the next packet. */ + if (parser_state.caplen) { + if (! ascend->adjusted) { + ascend->adjusted = TRUE; + if (parser_state.saw_timestamp) { + /* + * Capture file contained a date and time. + * We do this only if this is the very first packet we've seen - + * i.e., if "ascend->adjusted" is false - because + * if we get a date and time after the first packet, we can't + * go back and adjust the time stamps of the packets we've already + * processed, and basing the time stamps of this and following + * packets on the time stamp from the file text rather than the + * ctime of the capture file means times before this and after + * this can't be compared. + */ + ascend->inittime = parser_state.timestamp; + } + if (ascend->inittime > parser_state.secs) + ascend->inittime -= parser_state.secs; + } + phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; + phdr->ts.secs = parser_state.secs + ascend->inittime; + phdr->ts.nsecs = parser_state.usecs * 1000; + phdr->caplen = parser_state.caplen; + phdr->len = parser_state.wirelen; + + /* + * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND, + * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN + * or WTAP_ENCAP_ETHERNET). + */ + switch(phdr->pseudo_header.ascend.type) { + case ASCEND_PFX_ISDN_X: + phdr->pseudo_header.isdn.uton = TRUE; + phdr->pseudo_header.isdn.channel = 0; + break; + + case ASCEND_PFX_ISDN_R: + phdr->pseudo_header.isdn.uton = FALSE; + phdr->pseudo_header.isdn.channel = 0; + break; + + case ASCEND_PFX_ETHER: + phdr->pseudo_header.eth.fcs_len = 0; + break; + } + return PARSED_RECORD; + } + + /* Didn't see any data. Still, perhaps the parser was happy. */ + if (retval) { + if (*err == 0) { + /* Not a bad record, so a parse error. Return WTAP_ERR_BAD_FILE, + with the parse error as the error string. */ + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup((parser_state.ascend_parse_error != NULL) ? parser_state.ascend_parse_error : "parse error"); + } + return PARSE_FAILED; + } else + return PARSED_NONRECORD; +} + /* Read the next packet; called from wtap_read(). */ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) @@ -304,11 +419,8 @@ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, if (offset == -1) return FALSE; if (parse_ascend(ascend, wth->fh, &wth->phdr, wth->frame_buffer, - wth->snapshot_length) != PARSED_RECORD) { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error"); + wth->snapshot_length, err, err_info) != PARSED_RECORD) return FALSE; - } *data_offset = offset; return TRUE; @@ -323,11 +435,8 @@ static gboolean ascend_seek_read(wtap *wth, gint64 seek_off, if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) return FALSE; if (parse_ascend(ascend, wth->random_fh, phdr, buf, - wth->snapshot_length) != PARSED_RECORD) { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error"); + wth->snapshot_length, err, err_info) != PARSED_RECORD) return FALSE; - } return TRUE; } diff --git a/wiretap/k12text.l b/wiretap/k12text.l index 3ff7ca8610..4cdea9c951 100644 --- a/wiretap/k12text.l +++ b/wiretap/k12text.l @@ -1,4 +1,9 @@ /* + * We want a reentrant scanner. + */ +%option reentrant + +/* * We don't use input, so don't generate code for it. */ %option noinput @@ -19,10 +24,15 @@ %option noyywrap /* - * Prefix scanner routines with "K12Text_" rather than "yy", so this scanner + * The type for the state we keep for a scanner. + */ +%option extra-type="k12text_state_t *" + +/* + * Prefix scanner routines with "k12text_" rather than "yy", so this scanner * can coexist with other scanners. */ -%option prefix="K12Text_" +%option prefix="k12text_" %option outfile="k12text.c" @@ -45,6 +55,19 @@ /* %option noline */ /* %option debug */ +/* + * 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 + %{ /* k12text.l * @@ -82,41 +105,64 @@ #include "file_wrappers.h" #include <wsutil/buffer.h> #include "k12.h" -#include "k12text_lex.h" #ifndef HAVE_UNISTD_H #define YY_NO_UNISTD_H #endif -static guint g_h; -static guint g_m; -static guint g_s; -static guint g_ms; -static guint g_ns; -static gint g_encap; -static guint8 bb[WTAP_MAX_PACKET_SIZE]; -static guint ii; -static gboolean is_k12text; -static gboolean at_eof; -static guint junk_chars; -static void finalize_frame(void); -static gchar* error_str; -static guint64 file_bytes_read; -static gboolean ok_frame; -static FILE_T yy_fh; - -#define KERROR(text) do { error_str = g_strdup(text); yyterminate(); } while(0) -#define SET_HOURS(text) g_h = (guint) strtoul(text,NULL,10) -#define SET_MINUTES(text) g_m = (guint) strtoul(text,NULL,10) -#define SET_SECONDS(text) g_s = (guint) strtoul(text,NULL,10) -#define SET_MS(text) g_ms = (guint) strtoul(text,NULL,10) -#define SET_NS(text) g_ns = (guint) strtoul(text,NULL,10) -#define ADD_BYTE(text) do {if (ii >= WTAP_MAX_PACKET_SIZE) {KERROR("frame too large");} bb[ii++] = (guint8)strtoul(text,NULL,16); } while(0) -#define FINALIZE_FRAME() finalize_frame() +/* + * State kept by the scanner. + */ +typedef struct { + FILE_T fh; + int *err; + gchar **err_info; + int start_state; + + guint g_h; + guint g_m; + guint g_s; + guint g_ms; + guint g_ns; + gint g_encap; + guint8 bb[WTAP_MAX_PACKET_SIZE]; + guint ii; + gboolean is_k12text; + gboolean at_eof; + guint junk_chars; + gchar* error_str; + guint64 file_bytes_read; + gboolean ok_frame; +} k12text_state_t; + +#define KERROR(text) do { yyextra->error_str = g_strdup(text); yyterminate(); } while(0) +#define SET_HOURS(text) yyextra->g_h = (guint) strtoul(text,NULL,10) +#define SET_MINUTES(text) yyextra->g_m = (guint) strtoul(text,NULL,10) +#define SET_SECONDS(text) yyextra->g_s = (guint) strtoul(text,NULL,10) +#define SET_MS(text) yyextra->g_ms = (guint) strtoul(text,NULL,10) +#define SET_NS(text) yyextra->g_ns = (guint) strtoul(text,NULL,10) +#define ADD_BYTE(text) do {if (yyextra->ii >= WTAP_MAX_PACKET_SIZE) {KERROR("frame too large");} yyextra->bb[yyextra->ii++] = (guint8)strtoul(text,NULL,16); } while(0) +#define FINALIZE_FRAME() do { yyextra->ok_frame = TRUE; } while (0) /*~ #define ECHO*/ -#define YY_USER_ACTION file_bytes_read += yyleng; -#define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh); result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); } - +#define YY_USER_ACTION yyextra->file_bytes_read += yyleng; +#define YY_USER_INIT { \ + k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \ + BEGIN(scanner_state->start_state); \ +} +#define YY_INPUT(buf,result,max_size) { \ + k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \ + int c = file_getc(scanner_state->fh); \ + if (c == EOF) { \ + *(scanner_state->err) = file_error(scanner_state->fh, \ + scanner_state->err_info); \ + if (*(scanner_state->err) == 0) \ + *(scanner_state->err) = WTAP_ERR_SHORT_READ; \ + result = YY_NULL; \ + } else { \ + buf[0] = c; \ + result = 1; \ + } \ +} #define MAX_JUNK 400000 #define ECHO @@ -134,6 +180,19 @@ typedef struct { */ gint64 next_frame_offset; } k12text_t; + +/* + * 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 k12text_alloc(size, yyscanner) (void *)malloc(size) +#define k12text_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size)) +#define k12text_free(ptr, yyscanner) free((char *)ptr) + %} start_timestamp \053[\055]{9}\053[\055]{15,100}\053[\055]{10,100}\053 oneormoredigits [0-9]+: @@ -153,9 +212,9 @@ hdlc HDLC %START MAGIC NEXT_FRAME HOURS MINUTES M2S SECONDS S2M MS M2N NS ENCAP STARTBYTES BYTE %% -<MAGIC>{start_timestamp} { is_k12text = TRUE; yyterminate(); } +<MAGIC>{start_timestamp} { yyextra->is_k12text = TRUE; yyterminate(); } -<MAGIC>. { if (++ junk_chars > MAX_JUNK) { is_k12text = FALSE; yyterminate(); } } +<MAGIC>. { if (++ yyextra->junk_chars > MAX_JUNK) { yyextra->is_k12text = FALSE; yyterminate(); } } <NEXT_FRAME>{start_timestamp} {BEGIN(HOURS); } <HOURS>{oneormoredigits} { SET_HOURS(yytext); BEGIN(MINUTES); } @@ -166,42 +225,39 @@ hdlc HDLC <MS>{threedigits} { SET_MS(yytext); BEGIN(M2N); } <M2N>{comma} { BEGIN(NS); } <NS>{threedigits} { SET_NS(yytext); BEGIN(ENCAP);} -<ENCAP>{eth} {g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); } -<ENCAP>{mtp2} {g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); } -<ENCAP>{sscop} {g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); } -<ENCAP>{sscfnni} {g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); } -<ENCAP>{hdlc} {g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); } +<ENCAP>{eth} {yyextra->g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); } +<ENCAP>{mtp2} {yyextra->g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); } +<ENCAP>{sscop} {yyextra->g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); } +<ENCAP>{sscfnni} {yyextra->g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); } +<ENCAP>{hdlc} {yyextra->g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); } <ENCAP,STARTBYTES>{start_bytes} { BEGIN(BYTE); } <BYTE>{byte} { ADD_BYTE(yytext); } <BYTE>{bytes_junk} ; <BYTE>{end_bytes} { FINALIZE_FRAME(); yyterminate(); } -. { if (++junk_chars > MAX_JUNK) { KERROR("too much junk"); } } -<<EOF>> { at_eof = TRUE; yyterminate(); } +. { if (++yyextra->junk_chars > MAX_JUNK) { KERROR("too much junk"); } } +<<EOF>> { yyextra->at_eof = TRUE; yyterminate(); } %% -static void finalize_frame(void) { - ok_frame = TRUE; -} - /* Fill in pkthdr */ static gboolean -k12text_set_headers(struct wtap_pkthdr *phdr, int *err, gchar **err_info) +k12text_set_headers(struct wtap_pkthdr *phdr, k12text_state_t *state, + int *err, gchar **err_info) { phdr->rec_type = REC_TYPE_PACKET; phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; - phdr->ts.secs = 946681200 + (3600*g_h) + (60*g_m) + g_s; - phdr->ts.nsecs = 1000000*g_ms + 1000*g_ns; + phdr->ts.secs = 946681200 + (3600*state->g_h) + (60*state->g_m) + state->g_s; + phdr->ts.nsecs = 1000000*state->g_ms + 1000*state->g_ns; - phdr->caplen = phdr->len = ii; + phdr->caplen = phdr->len = state->ii; - phdr->pkt_encap = g_encap; + phdr->pkt_encap = state->g_encap; /* The file-encap is WTAP_ENCAP_PER_PACKET */ - switch(g_encap) { + switch(state->g_encap) { case WTAP_ENCAP_ETHERNET: phdr->pseudo_header.eth.fcs_len = 0; break; @@ -236,30 +292,54 @@ k12text_set_headers(struct wtap_pkthdr *phdr, int *err, gchar **err_info) /* used even when multiple files are open simultaneously (as for */ /* a file merge). */ -static void -k12text_reset(FILE_T fh) +static gboolean +k12text_run_scanner(k12text_state_t *state, FILE_T fh, int start_state, + int *err, gchar **err_info) { - yy_fh = fh; - yyrestart(0); - g_encap = WTAP_ENCAP_UNKNOWN; - ok_frame = FALSE; - is_k12text = FALSE; - at_eof = FALSE; - junk_chars = 0; - error_str = NULL; - file_bytes_read=0; - g_h=0; - g_m=0; - g_s=0; - g_ns=0; - g_ms=0; - ii=0; + yyscan_t scanner = NULL; + + if (yylex_init(&scanner) != 0) { + /* errno is set if this fails */ + *err = errno; + *err_info = NULL; + return FALSE; + } + state->fh = fh; + state->err = err; + state->err_info = err_info; + state->start_state = start_state; + + state->g_encap = WTAP_ENCAP_UNKNOWN; + state->ok_frame = FALSE; + state->is_k12text = FALSE; + state->at_eof = FALSE; + state->junk_chars = 0; + state->error_str = NULL; + state->file_bytes_read=0; + state->g_h=0; + state->g_m=0; + state->g_s=0; + state->g_ns=0; + state->g_ms=0; + state->ii=0; + + /* Associate the state with the scanner */ + k12text_set_extra(state, scanner); + + yylex(scanner); + yylex_destroy(scanner); + if (*err != 0 && *err != WTAP_ERR_SHORT_READ) { + /* I/O error. */ + return FALSE; + } + return TRUE; } static gboolean k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset) { k12text_t *k12text = (k12text_t *)wth->priv; + k12text_state_t state; /* * We seek to the file position after the end of the previous frame @@ -273,30 +353,29 @@ k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset) if ( file_seek(wth->fh, k12text->next_frame_offset, SEEK_SET, err) == -1) { return FALSE; } - k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */ - - BEGIN(NEXT_FRAME); - yylex(); + if (!k12text_run_scanner(&state, wth->fh, NEXT_FRAME, err, err_info)) { + return FALSE; + } - if (ok_frame == FALSE) { - if (at_eof) { + if (state.ok_frame == FALSE) { + if (state.at_eof) { *err = 0; *err_info = NULL; } else { *err = WTAP_ERR_BAD_FILE; - *err_info = error_str; + *err_info = state.error_str; } return FALSE; } - *data_offset = k12text->next_frame_offset; /* file position for beginning of this frame */ - k12text->next_frame_offset += file_bytes_read; /* file position after end of this frame */ + *data_offset = k12text->next_frame_offset; /* file position for beginning of this frame */ + k12text->next_frame_offset += state.file_bytes_read; /* file position after end of this frame */ - if (!k12text_set_headers(&wth->phdr, err, err_info)) + if (!k12text_set_headers(&wth->phdr, &state, err, err_info)) return FALSE; ws_buffer_assure_space(wth->frame_buffer, wth->phdr.caplen); - memcpy(ws_buffer_start_ptr(wth->frame_buffer), bb, wth->phdr.caplen); + memcpy(ws_buffer_start_ptr(wth->frame_buffer), state.bb, wth->phdr.caplen); return TRUE; } @@ -304,30 +383,31 @@ k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset) static gboolean k12text_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, char **err_info) { + k12text_state_t state; + if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) { return FALSE; } - k12text_reset(wth->random_fh); /* init lexer buffer and vars set by lexer */ - - BEGIN(NEXT_FRAME); - yylex(); + if (!k12text_run_scanner(&state, wth->random_fh, NEXT_FRAME, err, err_info)) { + return FALSE; + } - if (ok_frame == FALSE) { + if (state.ok_frame == FALSE) { *err = WTAP_ERR_BAD_FILE; - if (at_eof) { + if (state.at_eof) { /* What happened ? The desired frame was previously read without a problem */ *err_info = g_strdup("Unexpected EOF (program error ?)"); } else { - *err_info = error_str; + *err_info = state.error_str; } return FALSE; } - if (!k12text_set_headers(phdr, err, err_info)) + if (!k12text_set_headers(phdr, &state, err, err_info)) return FALSE; ws_buffer_assure_space(buf, phdr->caplen); - memcpy(ws_buffer_start_ptr(buf), bb, phdr->caplen); + memcpy(ws_buffer_start_ptr(buf), state.bb, phdr->caplen); return TRUE; } @@ -336,13 +416,17 @@ wtap_open_return_val k12text_open(wtap *wth, int *err, gchar **err_info _U_) { k12text_t *k12text; + k12text_state_t state; - k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */ - - BEGIN(MAGIC); - yylex(); + if (!k12text_run_scanner(&state, wth->fh, MAGIC, err, err_info)) { + return WTAP_OPEN_ERROR; + } - if (! is_k12text) return WTAP_OPEN_NOT_MINE; + if (!state.is_k12text) { + /* *err might have been set to WTAP_ERR_SHORT_READ */ + *err = 0; + return WTAP_OPEN_NOT_MINE; + } if ( file_seek(wth->fh, 0, SEEK_SET, err) == -1) { return WTAP_OPEN_ERROR; |