Bugfixes of ASTERIX I034
[metze/wireshark/wip.git] / wiretap / ascend.y
1 /*
2  * We want a reentrant parser.
3  */
4 %pure-parser
5
6 /*
7  * We also want a reentrant scanner, so we have to pass the
8  * handle for the reentrant scanner to the parser, and the
9  * parser has to pass it to the lexical analyzer.
10  *
11  * We use void * rather than yyscan_t because, at least with some
12  * versions of Flex and Bison, if you use yyscan_t in %parse-param and
13  * %lex-param, you have to include the ascend_lex_scanner.h before
14  * ascend.h to get yyscan_t declared, and you have to include ascend.h
15  * before ascend_lex_scanner.h to get YYSTYPE declared.  Using void *
16  * breaks the cycle; the Flex documentation says yyscan_t is just a void *.
17  */
18 %parse-param {void *yyscanner}
19 %lex-param {void *yyscanner}
20
21 /*
22  * And we need to pass the parser/scanner state to the parser.
23  */
24 %parse-param {ascend_state_t *parser_state}
25
26 %{
27 /* ascend.y
28  *
29  * Wiretap Library
30  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
31  *
32  * SPDX-License-Identifier: GPL-2.0-or-later
33  */
34
35 /*
36     Example 'pridisp' output data - one paragraph/frame:
37
38 PRI-XMIT-27: (task "l1Task" at 0x10216fe0, time: 560194.01) 4 octets @ 0x1027c5b0
39   [0000]: 00 01 01 a9                                         ....
40 PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
41   [0000]: 00 01 01 dd
42
43     Example 'pridisp' output data - two paragraphs/frame for XMIT case only:
44
45 PRI-XMIT-19/1:  (task "l1Task" at 0x10216840, time: 274759.98) 4 octets @ 0x1027f230
46   [0000]: 00 01 30 d8                                         ..0.
47 PRI-XMIT-19/2 (task "l1Task" at 0x10216840, time: 274759.98) 11 octets @ 0x1027f234
48   [0000]: 08 02 8c bf 02 18 04 e9  82 83 8f                   ........ ...
49
50     Example 'ether-disp' output data:
51
52 ETHER3ND RECV: (task "_sarTask" at 0x802c6eb0, time: 259848.03) 775 octets @ 0xa8fb2020
53   [0000]: 00 d0 52 04 e7 1e 08 00  20 ae 51 b5 08 00 45 00    ..R..... .Q...E.
54   [0010]: 02 f9 05 e6 40 00 3f 11  6e 39 87 fe c4 95 3c 3c    ....@.?.  n9....<<
55   [0020]: 3c 05 13 c4 13 c4 02 e5  ef ed 49 4e 56 49 54 45    <.......  ..INVITE
56   [0030]: 20 73 69 70 3a 35 32 30  37 33 40 36 30 2e 36 30     sip:520 73@60.60
57   [0040]: 2e 36 30 2e 35 20 53 49  50 2f 32 2e 30 0d 0a 56    .60.5 SI P/2.0..V
58   [0050]: 69 61 3a 20 53 49 50 2f  32 2e 30 2f 55 44 50 20    ia: SIP/ 2.0/UDP
59   [0060]: 31 33 35 2e                                         135.
60
61     Example 'wandsess' output data:
62
63 RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94
64   [0000]: FF 03 00 3D C0 06 CA 22 2F 45 00 00 28 6A 3B 40
65   [0010]: 00 3F 03 D7 37 CE 41 62 12 CF 00 FB 08 20 27 00
66   [0020]: 50 E4 08 DD D7 7C 4C 71 92 50 10 7D 78 67 C8 00
67   [0030]: 00
68 XMIT-iguana:241:(task: B04E12C0, time: 1975432.85) 53 octets @ 8009EB16
69   [0000]: FF 03 00 3D C0 09 1E 31 21 45 00 00 2C 2D BD 40
70   [0010]: 00 7A 06 D8 B1 CF 00 FB 08 CE 41 62 12 00 50 20
71   [0020]: 29 7C 4C 71 9C 9A 6A 93 A4 60 12 22 38 3F 10 00
72   [0030]: 00 02 04 05 B4
73
74     Example 'wdd' output data:
75
76 Date: 01/12/1990.  Time: 12:22:33
77 Cause an attempt to place call to 14082750382
78 WD_DIALOUT_DISP: chunk 2515EE type IP.
79 (task: 251790, time: 994953.28) 44 octets @ 2782B8
80   [0000]: 00 C0 7B 71 45 6C 00 60 08 16 AA 51 08 00 45 00
81   [0010]: 00 2C 66 1C 40 00 80 06 53 F6 AC 14 00 18 CC 47
82   [0020]: C8 45 0A 31 00 50 3B D9 5B 75 00 00
83
84     The following output comes from a MAX with Software 7.2.3:
85
86 RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0
87   [0000]: FF 03 00 21 45 00 00 60 E3 49 00 00 7F 11 FD 7B
88   [0010]: C0 A8 F7 05 8A C8 18 51 00 89 00 89 00 4C C7 C1
89   [0020]: CC 8E 40 00 00 01 00 00 00 00 00 01 20 45 4A 45
90   [0030]: 42 45 43 45 48 43 4E 46 43 46 41 43 41 43 41 43
91   [0040]: 41 43 41 43 41 43 41 43 41 43 41 42 4E 00 00 20
92   [0050]: 00 01 C0 0C 00 20 00 01 00 04 93 E0 00 06 60 00
93   [0060]: C0 A8 F7 05
94 XMIT-187:(task: B0292CA0, time: 18042248.04) 60 octets @ 800AD576
95   [0000]: FF 03 00 21 45 00 00 38 D7 EE 00 00 0F 01 11 2B
96   [0010]: 0A FF FF FE C0 A8 F7 05 03 0D 33 D3 00 00 00 00
97   [0020]: 45 00 00 60 E3 49 00 00 7E 11 FE 7B C0 A8 F7 05
98   [0030]: 8A C8 18 51 00 89 00 89 00 4C C7 C1
99 RECV-187:(task: B0292CA0, time: 18042251.92) 16 octets @ 800018E8
100   [0000]: FF 03 C0 21 09 01 00 0C DE 61 96 4B 00 30 94 92
101
102   In TAOS 8.0, Lucent slightly changed the format as follows:
103
104     Example 'wandisp' output data (TAOS 8.0.3): (same format is used
105     for 'wanopen' and 'wannext' command)
106
107 RECV-14: (task "idle task" at 0xb05e6e00, time: 1279.01) 29 octets @ 0x8000e0fc
108   [0000]: ff 03 c0 21 01 01 00 19  01 04 05 f4 11 04 05 f4    ...!.... ........
109   [0010]: 13 09 03 00 c0 7b 9a 9f  2d 17 04 10 00             .....{.. -....
110 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 38 octets @ 0x8007fd56
111   [0000]: ff 03 c0 21 01 01 00 22  00 04 00 00 01 04 05 f4    ...!..." ........
112   [0010]: 03 05 c2 23 05 11 04 05  f4 13 09 03 00 c0 7b 80    ...#.... ......{.
113   [0020]: 7c ef 17 04 0e 00                                   |.....
114 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 29 octets @ 0x8007fa36
115   [0000]: ff 03 c0 21 02 01 00 19  01 04 05 f4 11 04 05 f4    ...!.... ........
116   [0010]: 13 09 03 00 c0 7b 9a 9f  2d 17 04 10 00             .....{.. -....
117
118     Example 'wandsess' output data (TAOS 8.0.3):
119
120 RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198
121   [0000]: ff 03 00 3d c0 00 00 04  80 fd 02 01 00 0a 11 06    ...=.... ........
122   [0010]: 00 01 01 03                                         ....
123 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 26 octets @ 0x800806b6
124   [0000]: ff 03 00 3d c0 00 00 00  80 21 01 01 00 10 02 06    ...=.... .!......
125   [0010]: 00 2d 0f 01 03 06 89 64  03 08                      .-.....d ..
126 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octets @ 0x8007f716
127   [0000]: ff 03 00 3d c0 00 00 01  80 fd 01 01 00 0a 11 06    ...=.... ........
128   [0010]: 00 01 01 03                                         ....
129
130   The changes since TAOS 7.X are:
131
132     1) White space is added before "(task".
133     2) Task has a name, indicated by a subsequent string surrounded by a
134        double-quote.
135     3) Address expressed in hex number has a preceeding "0x".
136     4) Hex numbers are in lower case.
137     5) There is a character display corresponding to hex data in each line.
138
139  */
140
141 #include "config.h"
142
143 #include <stdlib.h>
144 #include <string.h>
145
146 #include "wtap-int.h"
147 #include <wsutil/buffer.h>
148 #include "ascendtext.h"
149 #include "ascend-int.h"
150 DIAG_OFF_BYACC
151 #include "ascend.h"
152 #include "ascend_scanner_lex.h"
153 DIAG_ON_BYACC
154 #include "file_wrappers.h"
155
156 #define NO_USER "<none>"
157
158 extern void yyerror (void *yyscanner, ascend_state_t *state, FILE_T fh _U_, const char *s);
159
160 DIAG_OFF_BYACC
161 %}
162
163 %union {
164 gchar  *s;
165 guint32 d;
166 guint8  b;
167 }
168
169 %token <s> STRING KEYWORD WDD_DATE WDD_CHUNK COUNTER SLASH_SUFFIX
170 %token <d> WDS_PREFIX ISDN_PREFIX ETHER_PREFIX DECNUM HEXNUM
171 %token <b> HEXBYTE
172
173 %type <s> string dataln datagroup
174 %type <d> wds_prefix isdn_prefix ether_prefix decnum hexnum
175 %type <b> byte bytegroup
176
177 %parse-param { FILE_T fh }
178
179 %%
180
181 data_packet:
182   | ether_hdr datagroup
183   | deferred_isdn_hdr datagroup deferred_isdn_hdr datagroup
184   | isdn_hdr datagroup
185   | wds_hdr datagroup
186   | wds8_hdr datagroup
187   | wdp7_hdr datagroup
188   | wdp8_hdr datagroup
189   | wdd_date wdd_hdr datagroup
190   | wdd_hdr datagroup
191 ;
192
193 isdn_prefix: ISDN_PREFIX;
194
195 ether_prefix: ETHER_PREFIX;
196
197 wds_prefix: WDS_PREFIX;
198
199 string: STRING;
200
201 decnum: DECNUM;
202
203 hexnum: HEXNUM;
204
205 /*
206   pridisp special case - I-frame header printed separately from contents,
207   one frame across two messages.
208
209 PRI-XMIT-0/1:  (task "l1Task" at 0x80152b20, time: 283529.65) 4 octets @
210 0x80128220
211   [0000]: 00 01 ae b2                                         ....
212 PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @
213 0x80128224
214   [0000]: 08 02 d7 e3 02 18 03 a9  83 8a                      ........
215
216 */
217 deferred_isdn_hdr: isdn_prefix decnum SLASH_SUFFIX KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
218   parser_state->wirelen += $11;
219   parser_state->secs = $9;
220   parser_state->usecs = $10;
221   if (parser_state->pseudo_header != NULL) {
222     parser_state->pseudo_header->type = $1;
223     parser_state->pseudo_header->sess = $2;
224     parser_state->pseudo_header->call_num[0] = '\0';
225     parser_state->pseudo_header->chunk = 0;
226     parser_state->pseudo_header->task = $7;
227   }
228   /* because we have two data groups */
229   parser_state->first_hexbyte = 0;
230 }
231 ;
232
233 /*
234 PRI-XMIT-19:  (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1c0
235  ... or ...
236 PRI-RCV-27:  (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
237 */
238 isdn_hdr: isdn_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
239   parser_state->wirelen = $10;
240   parser_state->secs = $8;
241   parser_state->usecs = $9;
242   if (parser_state->pseudo_header != NULL) {
243     parser_state->pseudo_header->type = $1;
244     parser_state->pseudo_header->sess = $2;
245     parser_state->pseudo_header->call_num[0] = '\0';
246     parser_state->pseudo_header->chunk = 0;
247     parser_state->pseudo_header->task = $6;
248   }
249   parser_state->first_hexbyte = 0;
250 }
251 ;
252
253 /*
254 ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa
255 885f80e
256 */
257 ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decnum
258  decnum KEYWORD HEXNUM {
259   parser_state->wirelen = $10;
260   parser_state->secs = $8;
261   parser_state->usecs = $9;
262   if (parser_state->pseudo_header != NULL) {
263     parser_state->pseudo_header->type = $1;
264     parser_state->pseudo_header->call_num[0] = '\0';
265     parser_state->pseudo_header->chunk = 0;
266     parser_state->pseudo_header->task = $6;
267   }
268 }
269 ;
270
271 /* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */
272 /*            1        2      3      4       5      6       7      8      9      10     11 */
273 wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
274   parser_state->wirelen = $9;
275   parser_state->secs = $7;
276   parser_state->usecs = $8;
277   if (parser_state->pseudo_header != NULL) {
278     /* parser_state->pseudo_header->user is set in ascend_scanner.l */
279     parser_state->pseudo_header->type = $1;
280     parser_state->pseudo_header->sess = $3;
281     parser_state->pseudo_header->call_num[0] = '\0';
282     parser_state->pseudo_header->chunk = 0;
283     parser_state->pseudo_header->task = $5;
284   }
285 }
286 ;
287
288 /* RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198 */
289 /*                1       2       3     4       5       6      7       8      9      10     11     12      13 */
290 wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
291   parser_state->wirelen = $11;
292   parser_state->secs = $9;
293   parser_state->usecs = $10;
294   if (parser_state->pseudo_header != NULL) {
295     /* parser_state->pseudo_header->user is set in ascend_scanner.l */
296     parser_state->pseudo_header->type = $1;
297     parser_state->pseudo_header->sess = $3;
298     parser_state->pseudo_header->call_num[0] = '\0';
299     parser_state->pseudo_header->chunk = 0;
300     parser_state->pseudo_header->task = $7;
301   }
302 }
303 ;
304
305 /* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */
306 /*            1        2       3      4       5       6      7      8      9      10    */
307 wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
308   parser_state->wirelen = $8;
309   parser_state->secs = $6;
310   parser_state->usecs = $7;
311   if (parser_state->pseudo_header != NULL) {
312     /* parser_state->pseudo_header->user is set in ascend_scanner.l */
313     parser_state->pseudo_header->type = $1;
314     parser_state->pseudo_header->sess = $2;
315     parser_state->pseudo_header->call_num[0] = '\0';
316     parser_state->pseudo_header->chunk = 0;
317     parser_state->pseudo_header->task = $4;
318   }
319 }
320 ;
321
322 /* XMIT-44: (task "freedm_task" at 0xe051fd10, time: 6258.66) 29 octets @ 0x606d1f00 */
323 /*              1        2       3      4       5      6      7       8      9      10     11      12 */
324 wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
325   parser_state->wirelen = $10;
326   parser_state->secs = $8;
327   parser_state->usecs = $9;
328   if (parser_state->pseudo_header != NULL) {
329     /* parser_state->pseudo_header->user is set in ascend_scanner.l */
330     parser_state->pseudo_header->type = $1;
331     parser_state->pseudo_header->sess = $2;
332     parser_state->pseudo_header->call_num[0] = '\0';
333     parser_state->pseudo_header->chunk = 0;
334     parser_state->pseudo_header->task = $6;
335   }
336 }
337 ;
338
339 /*
340 Date: 01/12/1990.  Time: 12:22:33
341 Cause an attempt to place call to 14082750382
342 */
343 /*           1        2      3      4      5       6      7      8      9      10*/
344 wdd_date: WDD_DATE decnum decnum decnum KEYWORD decnum decnum decnum KEYWORD string {
345   /*
346    * Supply the date/time value to the code above us; it will use the
347    * first date/time value supplied as the capture start date/time.
348    */
349   struct tm wddt;
350
351   wddt.tm_sec  = $8;
352   wddt.tm_min  = $7;
353   wddt.tm_hour = $6;
354   wddt.tm_mday = $3;
355   wddt.tm_mon  = $2 - 1;
356   wddt.tm_year = ($4 > 1970) ? $4 - 1900 : 70;
357   wddt.tm_isdst = -1;
358
359   parser_state->timestamp = (guint32) mktime(&wddt);
360   parser_state->saw_timestamp = TRUE;
361 }
362 ;
363
364 /*
365 WD_DIALOUT_DISP: chunk 2515EE type IP.
366 (task: 251790, time: 994953.28) 44 octets @ 2782B8
367 */
368 /*           1        2      3       4       5      6       7      8      9      10     11*/
369 wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
370   parser_state->wirelen = $9;
371   parser_state->secs = $7;
372   parser_state->usecs = $8;
373   if (parser_state->pseudo_header != NULL) {
374     /* parser_state->pseudo_header->call_num is set in ascend_scanner.l */
375     parser_state->pseudo_header->type = ASCEND_PFX_WDD;
376     parser_state->pseudo_header->user[0] = '\0';
377     parser_state->pseudo_header->sess = 0;
378     parser_state->pseudo_header->chunk = $2;
379     parser_state->pseudo_header->task = $5;
380   }
381 }
382 ;
383
384 byte: HEXBYTE {
385   /* remember the position of the data group in the trace, to tip off
386      ascend_find_next_packet() as to where to look for the next header. */
387   if (parser_state->first_hexbyte == 0)
388     parser_state->first_hexbyte = file_tell(fh);
389
390   /* XXX - if this test fails, it means that we parsed more bytes than
391      the header claimed there were. */
392   if (parser_state->caplen < parser_state->wirelen) {
393     parser_state->pkt_data[parser_state->caplen] = $1;
394     parser_state->caplen++;
395   }
396
397   /* arbitrary safety maximum... */
398   if (parser_state->caplen >= ASCEND_MAX_PKT_LEN)
399     YYACCEPT;
400 }
401 ;
402
403 /* XXX  There must be a better way to do this... */
404 bytegroup: byte
405   | byte byte
406   | byte byte byte
407   | byte byte byte byte
408   | byte byte byte byte byte
409   | byte byte byte byte byte byte
410   | byte byte byte byte byte byte byte
411   | byte byte byte byte byte byte byte byte
412   | byte byte byte byte byte byte byte byte byte
413   | byte byte byte byte byte byte byte byte byte byte
414   | byte byte byte byte byte byte byte byte byte byte byte
415   | byte byte byte byte byte byte byte byte byte byte byte byte
416   | byte byte byte byte byte byte byte byte byte byte byte byte byte
417   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte
418   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte
419   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte
420 ;
421
422 dataln: COUNTER bytegroup;
423
424 datagroup: dataln
425   | dataln dataln
426   | dataln dataln dataln
427   | dataln dataln dataln dataln
428   | dataln dataln dataln dataln dataln
429   | dataln dataln dataln dataln dataln dataln
430   | dataln dataln dataln dataln dataln dataln dataln
431   | dataln dataln dataln dataln dataln dataln dataln dataln
432 ;
433
434 %%
435
436 DIAG_ON_BYACC
437
438 /* Run the parser. */
439 int
440 run_ascend_parser(FILE_T fh, wtap_rec *rec, guint8 *pd,
441                   ascend_state_t *parser_state, int *err, gchar **err_info)
442 {
443   yyscan_t scanner = NULL;
444   int status;
445
446   if (ascendlex_init(&scanner) != 0) {
447     /* errno is set if this fails */
448     *err = errno;
449     *err_info = NULL;
450     return 1;
451   }
452   /* Associate the parser state with the lexical analyzer state */
453   ascendset_extra(parser_state, scanner);
454   parser_state->fh = fh;
455   parser_state->ascend_parse_error = NULL;
456   parser_state->err = 0;
457   parser_state->err_info = NULL;
458   parser_state->pseudo_header = &rec->rec_header.packet_header.pseudo_header.ascend;
459   parser_state->pkt_data = pd;
460
461   /*
462    * We haven't seen a time stamp yet.
463    */
464   parser_state->saw_timestamp = FALSE;
465   parser_state->timestamp = 0;
466
467   parser_state->first_hexbyte = 0;
468   parser_state->caplen = 0;
469   parser_state->wirelen = 0;
470
471   parser_state->secs = 0;
472   parser_state->usecs = 0;
473
474   /*
475    * Not all packets in a "wdd" dump necessarily have a "Cause an
476    * attempt to place call to" header (I presume this can happen if
477    * there was a call in progress when the packet was sent or
478    * received), so we won't necessarily have the phone number for
479    * the packet.
480    *
481    * XXX - we could assume, in the sequential pass, that it's the
482    * phone number from the last call, and remember that for use
483    * when doing random access.
484    */
485   parser_state->pseudo_header->call_num[0] = '\0';
486
487   status = yyparse(scanner, parser_state, fh);
488   *err = parser_state->err;
489   *err_info = parser_state->err_info;
490   return status;
491 }
492
493 void
494 yyerror (void *yyscanner, ascend_state_t *state _U_, FILE_T fh _U_, const char *s)
495 {
496   ascendget_extra(yyscanner)->ascend_parse_error = s;
497 }
498
499 DIAG_OFF_BYACC