Revert "UNUSED enc_key_id_{equal,hash}"
[wireshark-sm.git] / wiretap / k12text.l
blobfc61251de7c72e538f28c7ba0b17367a9c0297de
1 %top {
2 /* Include this before everything else, for various large-file definitions */
3 #include "config.h"
4 #include <wireshark.h>
7 /*
8  * We want a reentrant scanner.
9  */
10 %option reentrant
13  * We don't use input, so don't generate code for it.
14  */
15 %option noinput
18  * We don't use unput, so don't generate code for it.
19  */
20 %option nounput
23  * We don't read interactively from the terminal.
24  */
25 %option never-interactive
28  * We want to stop processing when we get to the end of the input.
29  */
30 %option noyywrap
33  * The type for the state we keep for a scanner.
34  */
35 %option extra-type="k12text_state_t *"
38  * Prefix scanner routines with "k12text_" rather than "yy", so this scanner
39  * can coexist with other scanners.
40  */
41 %option prefix="k12text_"
43 %option outfile="k12text.c"
45 /* Options useful for debugging                         */
46 /* noline:  Prevent generation of #line directives      */
47 /*          Seems to be required when using the         */
48 /*          Windows VS debugger so as to be able        */
49 /*          to properly step through the code and       */
50 /*          set breakpoints & etc using the             */
51 /*          k12text.c file rather than the              */
52 /*          k12text.l file                              */
53 /*      XXX: %option noline gives an error message:     */
54 /*          "unrecognized %option: line"                */
55 /*          with flex 2.5.35; the --noline              */
56 /*          command-line option works OK.               */
57 /*                                                      */
58 /* debug:   Do output of "rule acceptance" info         */
59 /*          during parse                                */
60 /*                                                      */
61 /* %option noline  */
62 /* %option debug   */
65  * We have to override the memory allocators so that we don't get
66  * "unused argument" warnings from the yyscanner argument (which
67  * we don't use, as we have a global memory allocator).
68  *
69  * We provide, as macros, our own versions of the routines generated by Flex,
70  * which just call malloc()/realloc()/free() (as the Flex versions do),
71  * discarding the extra argument.
72  */
73 %option noyyalloc
74 %option noyyrealloc
75 %option noyyfree
78 /* k12text.l
79  *
80  * Wiretap Library
81  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
82  *
83  * SPDX-License-Identifier: GPL-2.0-or-later
84  */
86  /*
87   * TODO:
88   *   - fix timestamps after midnight
89   *   - verify encapsulations
90   */
92 #include <stdlib.h>
93 #include <string.h>
94 #include <errno.h>
95 #include <time.h>
96 #include "wtap-int.h"
97 #include "wtap.h"
98 #include "file_wrappers.h"
99 #include <wsutil/buffer.h>
100 #include "k12.h"
102 #ifndef HAVE_UNISTD_H
103 #define YY_NO_UNISTD_H
104 #endif
107  * Disable diagnostics in the code generated by Flex.
108  */
109 DIAG_OFF_FLEX()
112  * State kept by the scanner.
113  */
114 typedef struct {
115         FILE_T fh;
116         int err;
117         char *err_info;
118         int start_state;
120         unsigned g_h;
121         unsigned g_m;
122         unsigned g_s;
123         unsigned g_ms;
124         unsigned g_ns;
125         int g_encap;
126         uint8_t *bb;
127         unsigned ii;
128         bool is_k12text;
129         bool at_eof;
130         unsigned junk_chars;
131         char* error_str;
132         uint64_t file_bytes_read;
133         bool ok_frame;
134 } k12text_state_t;
136 #define KERROR(text) do { yyextra->error_str = g_strdup(text); yyterminate(); } while(0)
137 #define SET_HOURS(text) yyextra->g_h = (unsigned) strtoul(text,NULL,10)
138 #define SET_MINUTES(text) yyextra->g_m = (unsigned) strtoul(text,NULL,10)
139 #define SET_SECONDS(text) yyextra->g_s = (unsigned) strtoul(text,NULL,10)
140 #define SET_MS(text) yyextra->g_ms = (unsigned) strtoul(text,NULL,10)
141 #define SET_NS(text) yyextra->g_ns = (unsigned) strtoul(text,NULL,10)
142 #define ADD_BYTE(text) do {if (yyextra->ii >= WTAP_MAX_PACKET_SIZE_STANDARD) {KERROR("frame too large");} yyextra->bb[yyextra->ii++] = (uint8_t)strtoul(text,NULL,16); } while(0)
143 #define FINALIZE_FRAME() do { yyextra->ok_frame = true; } while (0)
144 /*~ #define ECHO*/
145 #define YY_USER_ACTION yyextra->file_bytes_read += yyleng;
146 #define YY_USER_INIT { \
147         k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \
148         BEGIN(scanner_state->start_state); \
150 #define YY_INPUT(buf,result,max_size) { \
151         k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \
152         int c = file_getc(scanner_state->fh); \
153         if (c == EOF) { \
154                 scanner_state->err = file_error(scanner_state->fh, \
155                     &scanner_state->err_info); \
156                 if (scanner_state->err == 0) \
157                         scanner_state->err = WTAP_ERR_SHORT_READ; \
158                 result = YY_NULL; \
159         } else { \
160                 buf[0] = c; \
161                 result = 1; \
162         } \
164 #define MAX_JUNK 400000
165 #define ECHO
168  * Private per-file data.
169  */
170 typedef struct {
171         /*
172          * The file position after the end of the previous frame processed by
173          * k12text_read.
174          *
175          * We need to keep this around, and seek to it at the beginning of
176          * each call to k12text_read(), since the lexer undoubtedly did some
177          * amount of look-ahead when processing the previous frame.
178          */
179         int64_t next_frame_offset;
180 } k12text_t;
183  * Sleazy hack to suppress compiler warnings in yy_fatal_error().
184  */
185 #define YY_EXIT_FAILURE ((void)yyscanner, 2)
188  * Macros for the allocators, to discard the extra argument.
189  */
190 #define k12text_alloc(size, yyscanner)          (void *)malloc(size)
191 #define k12text_realloc(ptr, size, yyscanner)   (void *)realloc((char *)(ptr), (size))
192 #define k12text_free(ptr, yyscanner)            free((char *)ptr)
194 static int k12text_file_type_subtype = -1;
196 void register_k12text(void);
199 start_timestamp \053[\055]{9}\053[\055]{15,100}\053[\055]{10,100}\053
200 oneormoredigits [0-9]+:
201 twodigits [0-9][0-9]
202 colon :
203 comma ,
204 threedigits [0-9][0-9][0-9]
205 start_bytes \174\060\040\040\040\174
206 bytes_junk \174[A-F0-9][A-F0-9\040][A-F0-9\040][A-F0-9\040]\174
207 byte [a-f0-9][a-f0-9]\174
208 end_bytes \015?\012\015?\012
209 eth ETHER
210 mtp2 MTP-L2
211 sscop SSCOP
212 sscfnni SSCF
213 hdlc HDLC
215 %START MAGIC NEXT_FRAME HOURS MINUTES M2S SECONDS S2M MS M2N NS ENCAP STARTBYTES BYTE
217 <MAGIC>{start_timestamp}  { yyextra->is_k12text = true; yyterminate(); }
219 <MAGIC>. { if (++ yyextra->junk_chars > MAX_JUNK) { yyextra->is_k12text = false;  yyterminate(); } }
221 <NEXT_FRAME>{start_timestamp} {BEGIN(HOURS); }
222 <HOURS>{oneormoredigits} { SET_HOURS(yytext); BEGIN(MINUTES); }
223 <MINUTES>{twodigits} { SET_MINUTES(yytext); BEGIN(M2S);}
224 <M2S>{colon} { BEGIN(SECONDS);}
225 <SECONDS>{twodigits} { SET_SECONDS(yytext); BEGIN(S2M); }
226 <S2M>{comma}  { BEGIN(MS); }
227 <MS>{threedigits} { SET_MS(yytext); BEGIN(M2N);  }
228 <M2N>{comma}  { BEGIN(NS); }
229 <NS>{threedigits} { SET_NS(yytext); BEGIN(ENCAP);}
230 <ENCAP>{eth} {yyextra->g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); }
231 <ENCAP>{mtp2} {yyextra->g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); }
232 <ENCAP>{sscop} {yyextra->g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); }
233 <ENCAP>{sscfnni} {yyextra->g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); }
234 <ENCAP>{hdlc} {yyextra->g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); }
235 <ENCAP,STARTBYTES>{start_bytes} { BEGIN(BYTE); }
236 <BYTE>{byte} { ADD_BYTE(yytext); }
237 <BYTE>{bytes_junk} ;
238 <BYTE>{end_bytes} { FINALIZE_FRAME(); yyterminate(); }
240 . {  if (++yyextra->junk_chars > MAX_JUNK) { KERROR("too much junk");  } }
241 <<EOF>> { yyextra->at_eof = true; yyterminate(); }
246  * Turn diagnostics back on, so we check the code that we've written.
247  */
248 DIAG_ON_FLEX()
250 /* Fill in pkthdr */
252 static bool
253 k12text_set_headers(wtap_rec *rec, k12text_state_t *state,
254     int *err, char **err_info)
256         rec->rec_type = REC_TYPE_PACKET;
257         rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
258         rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
260         rec->ts.secs = 946681200 + (3600*state->g_h) + (60*state->g_m) + state->g_s;
261         rec->ts.nsecs = 1000000*state->g_ms + 1000*state->g_ns;
263         rec->rec_header.packet_header.caplen = rec->rec_header.packet_header.len = state->ii;
265         rec->rec_header.packet_header.pkt_encap = state->g_encap;
267         /* The file-encap is WTAP_ENCAP_PER_PACKET */
268         switch(state->g_encap) {
269             case WTAP_ENCAP_ETHERNET:
270                     rec->rec_header.packet_header.pseudo_header.eth.fcs_len = 0;
271                     break;
272             case WTAP_ENCAP_MTP3:
273             case WTAP_ENCAP_CHDLC:
274                     /* no pseudo_header to fill in for these types */
275                     break;
276             case WTAP_ENCAP_MTP2:      /* not (yet) supported           */
277                     /* XXX: I don't know how to fill in the             */
278                     /* pseudo_header for these types.                   */
279                     *err = WTAP_ERR_UNSUPPORTED;
280                     *err_info = g_strdup("k12text: MTP2 packets not yet supported");
281                     return false;
282             case WTAP_ENCAP_ATM_PDUS:  /* not (yet) supported           */
283                     /* XXX: I don't know how to fill in the             */
284                     /* pseudo_header for these types.                   */
285                     *err = WTAP_ERR_UNSUPPORTED;
286                     *err_info = g_strdup("k12text: SSCOP packets not yet supported");
287                     return false;
288             default:
289                     *err = WTAP_ERR_UNSUPPORTED;
290                     *err_info = g_strdup("k12text: unknown encapsulation type");
291                     return false;
292         }
293         return true;
296 /* Note: k12text_reset is called each time data is to be processed from */
297 /*       a file. This ensures that no "state" from a previous read is   */
298 /*       used (such as the lexer look-ahead buffer, file_handle, file   */
299 /*       position and so on. This allows a single lexer buffer to be    */
300 /*       used even when multiple files are open simultaneously (as for  */
301 /*       a file merge).                                                 */
303 static bool
304 k12text_run_scanner(k12text_state_t *state, FILE_T fh, int start_state,
305     int *err, char **err_info)
307         yyscan_t scanner = NULL;
309         if (yylex_init(&scanner) != 0) {
310                 /* errno is set if this fails */
311                 *err = errno;
312                 *err_info = NULL;
313                 return false;
314         }
315         state->fh = fh;
316         state->err = 0;
317         state->err_info = NULL;
318         state->start_state = start_state;
320         state->g_encap = WTAP_ENCAP_UNKNOWN;
321         state->ok_frame = false;
322         state->is_k12text = false;
323         state->at_eof = false;
324         state->junk_chars = 0;
325         state->error_str = NULL;
326         state->file_bytes_read=0;
327         state->g_h=0;
328         state->g_m=0;
329         state->g_s=0;
330         state->g_ns=0;
331         state->g_ms=0;
332         state->ii=0;
334         /* Associate the state with the scanner */
335         k12text_set_extra(state, scanner);
337         yylex(scanner);
338         yylex_destroy(scanner);
339         if (state->err != 0 && state->err != WTAP_ERR_SHORT_READ) {
340                 /* I/O error. */
341                 *err = state->err;
342                 *err_info = state->err_info;
343                 return false;
344         }
345         return true;
348 static bool
349 k12text_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, char ** err_info, int64_t *data_offset)
351         k12text_t *k12text = (k12text_t *)wth->priv;
352         k12text_state_t state;
354         /*
355          * We seek to the file position after the end of the previous frame
356          * processed by k12text_read(), since the lexer undoubtedly did some
357          * amount of look-ahead when processing the previous frame.
358          *
359          * We also clear out any lexer state (eg: look-ahead buffer) and
360          * init vars set by lexer.
361          */
363         if ( file_seek(wth->fh, k12text->next_frame_offset, SEEK_SET, err) == -1) {
364                 return false;
365         }
366         state.bb = (uint8_t*)g_malloc(WTAP_MAX_PACKET_SIZE_STANDARD);
368         if (!k12text_run_scanner(&state, wth->fh, NEXT_FRAME, err, err_info)) {
369                 g_free(state.bb);
370                 return false;
371         }
373         if (state.ok_frame == false) {
374                 if (state.at_eof) {
375                         *err = 0;
376                         *err_info = NULL;
377                 } else {
378                         *err = WTAP_ERR_BAD_FILE;
379                         *err_info = state.error_str;
380                 }
381                 g_free(state.bb);
382                 return false;
383         }
385         *data_offset = k12text->next_frame_offset;           /* file position for beginning of this frame   */
386         k12text->next_frame_offset += state.file_bytes_read; /* file position after end of this frame       */
388         if (!k12text_set_headers(rec, &state, err, err_info)) {
389                 g_free(state.bb);
390                 return false;
391         }
392         ws_buffer_assure_space(buf, rec->rec_header.packet_header.caplen);
393         memcpy(ws_buffer_start_ptr(buf), state.bb, rec->rec_header.packet_header.caplen);
395         g_free(state.bb);
396         return true;
399 static bool
400 k12text_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec, Buffer *buf, int *err, char **err_info)
402         k12text_state_t state;
404         if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) {
405                 return false;
406         }
407         state.bb = (uint8_t*)g_malloc(WTAP_MAX_PACKET_SIZE_STANDARD);
409         if (!k12text_run_scanner(&state, wth->random_fh, NEXT_FRAME, err, err_info)) {
410                 g_free(state.bb);
411                 return false;
412         }
414         if (state.ok_frame == false) {
415                 *err = WTAP_ERR_BAD_FILE;
416                 if (state.at_eof) {
417                         /* What happened ? The desired frame was previously read without a problem */
418                         *err_info = g_strdup("Unexpected EOF (program error ?)");
419                 } else {
420                         *err_info = state.error_str;
421                 }
422                 g_free(state.bb);
423                 return false;
424         }
426         if (!k12text_set_headers(rec, &state, err, err_info)) {
427                 g_free(state.bb);
428                 return false;
429         }
430         ws_buffer_assure_space(buf, rec->rec_header.packet_header.caplen);
431         memcpy(ws_buffer_start_ptr(buf), state.bb, rec->rec_header.packet_header.caplen);
433         g_free(state.bb);
434         return true;
437 wtap_open_return_val
438 k12text_open(wtap *wth, int *err, char **err_info)
440         k12text_t *k12text;
441         k12text_state_t state;
443         state.bb = (uint8_t*)g_malloc(WTAP_MAX_PACKET_SIZE_STANDARD);
444         if (!k12text_run_scanner(&state, wth->fh, MAGIC, err, err_info)) {
445                 g_free(state.bb);
446                 return WTAP_OPEN_ERROR;
447         }
449         if (!state.is_k12text) {
450                 /* *err might have been set to WTAP_ERR_SHORT_READ */
451                 *err = 0;
452                 g_free(state.bb);
453                 return WTAP_OPEN_NOT_MINE;
454         }
456         if ( file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
457                 g_free(state.bb);
458                 return WTAP_OPEN_ERROR;
459         }
461         k12text = g_new(k12text_t, 1);
462         wth->priv = (void *)k12text;
463         k12text->next_frame_offset = 0;
464         wth->file_type_subtype = k12text_file_type_subtype;
465         wth->file_encap = WTAP_ENCAP_PER_PACKET;
466         wth->snapshot_length = 0;
467         wth->subtype_read = k12text_read;
468         wth->subtype_seek_read = k12text_seek_read;
469         wth->file_tsprec = WTAP_TSPREC_NSEC;
471         g_free(state.bb);
472         return WTAP_OPEN_MINE;
476 static const struct { int e; const char* s; } encaps[] = {
477         { WTAP_ENCAP_ETHERNET, "ETHER" },
478         { WTAP_ENCAP_MTP2, "MTP-L2" },
479         { WTAP_ENCAP_ATM_PDUS, "SSCOP" },
480         { WTAP_ENCAP_MTP3, "SSCF" },
481         { WTAP_ENCAP_CHDLC, "HDLC" },
482         /* ... */
483         { 0, NULL }
486 static bool
487 k12text_dump(wtap_dumper *wdh, const wtap_rec *rec,
488              const uint8_t *pd, int *err, char **err_info _U_) {
489 #define K12BUF_SIZE 196808
490         char *buf;
491         size_t left = K12BUF_SIZE;
492         size_t wl;
493         char *p;
494         const char* str_enc;
495         unsigned i;
496         unsigned ns;
497         unsigned ms;
498         bool ret;
499         struct tm *tmp;
501         /* Don't write anything bigger than we're willing to read. */
502         if (rec->rec_header.packet_header.caplen > WTAP_MAX_PACKET_SIZE_STANDARD) {
503                 *err = WTAP_ERR_PACKET_TOO_LARGE;
504                 return false;
505         }
507         str_enc = NULL;
508         for(i=0; encaps[i].s; i++) {
509                 if (rec->rec_header.packet_header.pkt_encap == encaps[i].e) {
510                         str_enc = encaps[i].s;
511                         break;
512                 }
513         }
514         if (str_enc == NULL) {
515                 /*
516                  * That encapsulation type is not supported.  Fail.
517                  */
518                 *err = WTAP_ERR_UNWRITABLE_ENCAP;
519                 return false;
520         }
522         buf = (char *)g_malloc(K12BUF_SIZE);
523         p = buf;
525         ms = rec->ts.nsecs / 1000000;
526         ns = (rec->ts.nsecs - (1000000*ms))/1000;
528         tmp = gmtime(&rec->ts.secs);
529         if (tmp == NULL)
530                 snprintf(p, 90, "+---------+---------------+----------+\r\nXX:XX:XX,");
531         else
532                 strftime(p, 90, "+---------+---------------+----------+\r\n%H:%M:%S,", tmp);
533         wl = strlen(p);
534         p += wl;
535         left -= wl;
537         wl = snprintf(p, left, "%.3d,%.3d   %s\r\n|0   |", ms, ns, str_enc);
538         p += wl;
539         left -= wl;
541         for(i = 0; i < rec->rec_header.packet_header.caplen && left > 2; i++) {
542                 wl = snprintf(p, left, "%.2x|", pd[i]);
543                 p += wl;
544                 left -= wl;
545         }
547         wl = snprintf(p, left, "\r\n\r\n");
548         left -= wl;
550         ret = wtap_dump_file_write(wdh, buf, K12BUF_SIZE - left, err);
552         g_free(buf);
553         return ret;
557 static bool
558 k12text_dump_open(wtap_dumper *wdh, int *err _U_, char **err_info _U_)
560     wdh->subtype_write = k12text_dump;
562     return true;
565 static int
566 k12text_dump_can_write_encap(int encap)
568     switch (encap) {
569         case WTAP_ENCAP_PER_PACKET:
570         case WTAP_ENCAP_ETHERNET:
571         case WTAP_ENCAP_MTP3:
572         case WTAP_ENCAP_CHDLC:
573                 return 0;
574         case WTAP_ENCAP_MTP2:
575         case WTAP_ENCAP_ATM_PDUS:
576         default:
577                 return WTAP_ERR_UNWRITABLE_ENCAP;
578     }
581 static const struct supported_block_type k12text_blocks_supported[] = {
582     /*
583      * We support packet blocks, with no comments or other options.
584      */
585     { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
588 static const struct file_type_subtype_info k12text_info = {
589     "K12 text file", "k12text", "txt", NULL,
590     false, BLOCKS_SUPPORTED(k12text_blocks_supported),
591     k12text_dump_can_write_encap, k12text_dump_open, NULL
594 void register_k12text(void)
596     k12text_file_type_subtype = wtap_register_file_type_subtype(&k12text_info);
598     /*
599      * Register name for backwards compatibility with the
600      * wtap_filetypes table in Lua.
601      */
602     wtap_register_backwards_compatibility_lua_name("K12TEXT",
603                                                    k12text_file_type_subtype);