Have parse_ascend() return:
[metze/wireshark/wip.git] / wiretap / ascend.y
1 %{
2 /* ascend.y
3  *
4  * $Id$
5  *
6  * Wiretap Library
7  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8  * 
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  */
24
25 /*
26     Example 'pridisp' output data - one paragraph/frame:
27
28 PRI-XMIT-27: (task "l1Task" at 0x10216fe0, time: 560194.01) 4 octets @ 0x1027c5b0
29   [0000]: 00 01 01 a9                                         ....
30 PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
31   [0000]: 00 01 01 dd
32
33     Example 'pridisp' output data - two paragraphs/frame for XMIT case only:
34
35 PRI-XMIT-19/1:  (task "l1Task" at 0x10216840, time: 274759.98) 4 octets @ 0x1027f230
36   [0000]: 00 01 30 d8                                         ..0.
37 PRI-XMIT-19/2 (task "l1Task" at 0x10216840, time: 274759.98) 11 octets @ 0x1027f234
38   [0000]: 08 02 8c bf 02 18 04 e9  82 83 8f                   ........ ...
39
40     Example 'ether-disp' output data:
41
42 ETHER3ND RECV: (task "_sarTask" at 0x802c6eb0, time: 259848.03) 775 octets @ 0xa8fb2020
43   [0000]: 00 d0 52 04 e7 1e 08 00  20 ae 51 b5 08 00 45 00    ..R..... .Q...E.
44   [0010]: 02 f9 05 e6 40 00 3f 11  6e 39 87 fe c4 95 3c 3c    ....@.?.  n9....<<
45   [0020]: 3c 05 13 c4 13 c4 02 e5  ef ed 49 4e 56 49 54 45    <.......  ..INVITE
46   [0030]: 20 73 69 70 3a 35 32 30  37 33 40 36 30 2e 36 30     sip:520 73@60.60
47   [0040]: 2e 36 30 2e 35 20 53 49  50 2f 32 2e 30 0d 0a 56    .60.5 SI P/2.0..V
48   [0050]: 69 61 3a 20 53 49 50 2f  32 2e 30 2f 55 44 50 20    ia: SIP/ 2.0/UDP
49   [0060]: 31 33 35 2e                                         135.
50
51     Example 'wandsess' output data:
52    
53 RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94
54   [0000]: FF 03 00 3D C0 06 CA 22 2F 45 00 00 28 6A 3B 40 
55   [0010]: 00 3F 03 D7 37 CE 41 62 12 CF 00 FB 08 20 27 00 
56   [0020]: 50 E4 08 DD D7 7C 4C 71 92 50 10 7D 78 67 C8 00 
57   [0030]: 00 
58 XMIT-iguana:241:(task: B04E12C0, time: 1975432.85) 53 octets @ 8009EB16
59   [0000]: FF 03 00 3D C0 09 1E 31 21 45 00 00 2C 2D BD 40 
60   [0010]: 00 7A 06 D8 B1 CF 00 FB 08 CE 41 62 12 00 50 20 
61   [0020]: 29 7C 4C 71 9C 9A 6A 93 A4 60 12 22 38 3F 10 00 
62   [0030]: 00 02 04 05 B4 
63
64     Example 'wdd' output data:
65
66 Date: 01/12/1990.  Time: 12:22:33
67 Cause an attempt to place call to 14082750382
68 WD_DIALOUT_DISP: chunk 2515EE type IP.
69 (task: 251790, time: 994953.28) 44 octets @ 2782B8
70   [0000]: 00 C0 7B 71 45 6C 00 60 08 16 AA 51 08 00 45 00
71   [0010]: 00 2C 66 1C 40 00 80 06 53 F6 AC 14 00 18 CC 47
72   [0020]: C8 45 0A 31 00 50 3B D9 5B 75 00 00
73
74     The following output comes from a MAX with Software 7.2.3:
75
76 RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0
77   [0000]: FF 03 00 21 45 00 00 60 E3 49 00 00 7F 11 FD 7B
78   [0010]: C0 A8 F7 05 8A C8 18 51 00 89 00 89 00 4C C7 C1
79   [0020]: CC 8E 40 00 00 01 00 00 00 00 00 01 20 45 4A 45
80   [0030]: 42 45 43 45 48 43 4E 46 43 46 41 43 41 43 41 43
81   [0040]: 41 43 41 43 41 43 41 43 41 43 41 42 4E 00 00 20
82   [0050]: 00 01 C0 0C 00 20 00 01 00 04 93 E0 00 06 60 00
83   [0060]: C0 A8 F7 05
84 XMIT-187:(task: B0292CA0, time: 18042248.04) 60 octets @ 800AD576
85   [0000]: FF 03 00 21 45 00 00 38 D7 EE 00 00 0F 01 11 2B
86   [0010]: 0A FF FF FE C0 A8 F7 05 03 0D 33 D3 00 00 00 00
87   [0020]: 45 00 00 60 E3 49 00 00 7E 11 FE 7B C0 A8 F7 05
88   [0030]: 8A C8 18 51 00 89 00 89 00 4C C7 C1
89 RECV-187:(task: B0292CA0, time: 18042251.92) 16 octets @ 800018E8
90   [0000]: FF 03 C0 21 09 01 00 0C DE 61 96 4B 00 30 94 92
91
92   In TAOS 8.0, Lucent slightly changed the format as follows:
93
94     Example 'wandisp' output data (TAOS 8.0.3): (same format is used 
95     for 'wanopen' and 'wannext' command)
96
97 RECV-14: (task "idle task" at 0xb05e6e00, time: 1279.01) 29 octets @ 0x8000e0fc
98   [0000]: ff 03 c0 21 01 01 00 19  01 04 05 f4 11 04 05 f4    ...!.... ........
99   [0010]: 13 09 03 00 c0 7b 9a 9f  2d 17 04 10 00             .....{.. -....
100 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 38 octets @ 0x8007fd56
101   [0000]: ff 03 c0 21 01 01 00 22  00 04 00 00 01 04 05 f4    ...!..." ........
102   [0010]: 03 05 c2 23 05 11 04 05  f4 13 09 03 00 c0 7b 80    ...#.... ......{.
103   [0020]: 7c ef 17 04 0e 00                                   |.....
104 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 29 octets @ 0x8007fa36
105   [0000]: ff 03 c0 21 02 01 00 19  01 04 05 f4 11 04 05 f4    ...!.... ........
106   [0010]: 13 09 03 00 c0 7b 9a 9f  2d 17 04 10 00             .....{.. -....
107
108     Example 'wandsess' output data (TAOS 8.0.3): 
109
110 RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198
111   [0000]: ff 03 00 3d c0 00 00 04  80 fd 02 01 00 0a 11 06    ...=.... ........
112   [0010]: 00 01 01 03                                         ....
113 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 26 octets @ 0x800806b6
114   [0000]: ff 03 00 3d c0 00 00 00  80 21 01 01 00 10 02 06    ...=.... .!......
115   [0010]: 00 2d 0f 01 03 06 89 64  03 08                      .-.....d ..
116 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octets @ 0x8007f716
117   [0000]: ff 03 00 3d c0 00 00 01  80 fd 01 01 00 0a 11 06    ...=.... ........
118   [0010]: 00 01 01 03                                         ....
119
120   The changes since TAOS 7.X are:
121
122     1) White space is added before "(task".
123     2) Task has a name, indicated by a subsequent string surrounded by a
124        double-quote.
125     3) Address expressed in hex number has a preceeding "0x".
126     4) Hex numbers are in lower case.
127     5) There is a character display corresponding to hex data in each line.
128
129  */
130
131 #ifdef HAVE_CONFIG_H
132 #include "config.h"
133 #endif
134
135 #include <stdio.h>
136 #include <stdlib.h>
137 #include <string.h>
138
139 #include "wtap-int.h"
140 #include "buffer.h"
141 #include "ascendtext.h"
142 #include "ascend-int.h"
143 #include "file_wrappers.h"
144
145 #define NO_USER "<none>"
146
147 int yyparse(void);
148 void yyerror(const char *);
149
150 const gchar *ascend_parse_error;
151
152 static unsigned int bcur;
153 static guint32 start_time, secs, usecs, caplen, wirelen;
154 static ascend_pkthdr *header;
155 struct ascend_phdr *pseudo_header;
156 static guint8 *pkt_data;
157 static gint64 first_hexbyte;
158 static FILE_T *fh_ptr;
159
160 %}
161  
162 %union {
163 gchar  *s;
164 guint32 d;
165 guint8  b;
166 }
167
168 %token <s> STRING KEYWORD WDD_DATE WDD_CHUNK COUNTER SLASH_SUFFIX
169 %token <d> WDS_PREFIX ISDN_PREFIX ETHER_PREFIX DECNUM HEXNUM 
170 %token <b> HEXBYTE
171
172 %type <s> string dataln datagroup 
173 %type <d> wds_prefix isdn_prefix ether_prefix decnum hexnum
174 %type <b> byte bytegroup
175
176 %%
177
178 data_packet:
179   | ether_hdr datagroup
180   | deferred_isdn_hdr datagroup deferred_isdn_hdr datagroup
181   | isdn_hdr datagroup
182   | wds_hdr datagroup
183   | wds8_hdr datagroup
184   | wdp7_hdr datagroup
185   | wdp8_hdr datagroup
186   | wdd_date wdd_hdr datagroup
187   | wdd_hdr datagroup
188 ;
189
190 isdn_prefix: ISDN_PREFIX;
191
192 ether_prefix: ETHER_PREFIX;
193
194 wds_prefix: WDS_PREFIX;
195
196 string: STRING;
197
198 decnum: DECNUM;
199
200 hexnum: HEXNUM;
201
202 /*
203   pridisp special case - I-frame header printed separately from contents,
204   one frame across two messages.
205
206 PRI-XMIT-0/1:  (task "l1Task" at 0x80152b20, time: 283529.65) 4 octets @
207 0x80128220
208   [0000]: 00 01 ae b2                                         ....
209 PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @
210 0x80128224
211   [0000]: 08 02 d7 e3 02 18 03 a9  83 8a                      ........
212
213 */
214 deferred_isdn_hdr: isdn_prefix decnum SLASH_SUFFIX KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
215   wirelen += $11;
216   caplen += $11;
217   secs = $9;
218   usecs = $10;
219   if (pseudo_header != NULL) {
220     pseudo_header->type = $1;
221     pseudo_header->sess = $2;
222     pseudo_header->call_num[0] = '\0';
223     pseudo_header->chunk = 0;
224     pseudo_header->task = $7;
225   }
226   /* because we have two data groups */
227   first_hexbyte = 0;
228 }
229 ;
230
231 /*
232 PRI-XMIT-19:  (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1c0 
233  ... or ...
234 PRI-RCV-27:  (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
235 */
236 isdn_hdr: isdn_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
237   wirelen = $10;
238   caplen = $10;
239   secs = $8;
240   usecs = $9;
241   if (pseudo_header != NULL) {
242     pseudo_header->type = $1;
243     pseudo_header->sess = $2;
244     pseudo_header->call_num[0] = '\0';
245     pseudo_header->chunk = 0;
246     pseudo_header->task = $6;
247   }
248   first_hexbyte = 0;
249 }
250 ;
251
252 /*
253 ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa
254 885f80e
255 */
256 ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decnum
257  decnum KEYWORD HEXNUM {
258   wirelen = $10;
259   caplen = $10;
260   secs = $8;
261   usecs = $9;
262   if (pseudo_header != NULL) {
263     pseudo_header->type = $1;
264     pseudo_header->call_num[0] = '\0';
265     pseudo_header->chunk = 0;
266     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   wirelen = $9;
275   caplen = $9;
276   secs = $7;
277   usecs = $8;
278   if (pseudo_header != NULL) {
279     /* pseudo_header->user is set in ascend_scanner.l */
280     pseudo_header->type = $1;
281     pseudo_header->sess = $3;
282     pseudo_header->call_num[0] = '\0';
283     pseudo_header->chunk = 0;
284     pseudo_header->task = $5;
285   }
286 }
287 ;
288
289 /* RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198 */
290 /*                1       2       3     4       5       6      7       8      9      10     11     12      13 */
291 wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
292   wirelen = $11;
293   caplen = $11;
294   secs = $9;
295   usecs = $10;
296   if (pseudo_header != NULL) {
297     /* pseudo_header->user is set in ascend_scanner.l */
298     pseudo_header->type = $1;
299     pseudo_header->sess = $3;
300     pseudo_header->call_num[0] = '\0';
301     pseudo_header->chunk = 0;
302     pseudo_header->task = $7;
303   }
304 }
305 ;
306
307 /* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */
308 /*            1        2       3      4       5       6      7      8      9      10    */
309 wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
310   wirelen = $8;
311   caplen = $8;
312   secs = $6;
313   usecs = $7;
314   if (pseudo_header != NULL) {
315     /* pseudo_header->user is set in ascend_scanner.l */
316     pseudo_header->type = $1;
317     pseudo_header->sess = $2;
318     pseudo_header->call_num[0] = '\0';
319     pseudo_header->chunk = 0;
320     pseudo_header->task = $4;
321   }
322 }
323 ;
324
325 /* XMIT-44: (task "freedm_task" at 0xe051fd10, time: 6258.66) 29 octets @ 0x606d1f00 */
326 /*              1        2       3      4       5      6      7       8      9      10     11      12 */
327 wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
328   wirelen = $10;
329   caplen = $10;
330   secs = $8;
331   usecs = $9;
332   if (pseudo_header != NULL) {
333     /* pseudo_header->user is set in ascend_scanner.l */
334     pseudo_header->type = $1;
335     pseudo_header->sess = $2;
336     pseudo_header->call_num[0] = '\0';
337     pseudo_header->chunk = 0;
338     pseudo_header->task = $6;
339   }
340 }
341 ;
342
343 /*
344 Date: 01/12/1990.  Time: 12:22:33
345 Cause an attempt to place call to 14082750382
346 */
347 /*           1        2      3      4      5       6      7      8      9      10*/
348 wdd_date: WDD_DATE decnum decnum decnum KEYWORD decnum decnum decnum KEYWORD string {
349   /*
350    * Supply the date/time value to the code above us; it will use the
351    * first date/time value supplied as the capture start date/time.
352    */
353   struct tm wddt;
354
355   wddt.tm_sec  = $8;
356   wddt.tm_min  = $7;
357   wddt.tm_hour = $6;
358   wddt.tm_mday = $3;
359   wddt.tm_mon  = $2 - 1;
360   wddt.tm_year = ($4 > 1970) ? $4 - 1900 : 70;
361   wddt.tm_isdst = -1;
362   
363   start_time = (guint32) mktime(&wddt);
364 }
365 ;
366
367 /*
368 WD_DIALOUT_DISP: chunk 2515EE type IP.
369 (task: 251790, time: 994953.28) 44 octets @ 2782B8
370 */
371 /*           1        2      3       4       5      6       7      8      9      10     11*/
372 wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
373   wirelen = $9;
374   caplen = $9;
375   secs = $7;
376   usecs = $8;
377   if (pseudo_header != NULL) {
378     /* pseudo_header->call_num is set in ascend_scanner.l */
379     pseudo_header->type = ASCEND_PFX_WDD;
380     pseudo_header->user[0] = '\0';
381     pseudo_header->sess = 0;
382     pseudo_header->chunk = $2;
383     pseudo_header->task = $5;
384   }
385 }
386 ;
387  
388 byte: HEXBYTE {
389   /* remember the position of the data group in the trace, to tip
390      off ascend_seek() as to where to look for the next header. */
391   if (first_hexbyte == 0)
392     first_hexbyte = file_tell(*fh_ptr);
393
394   if (bcur < caplen) {
395     pkt_data[bcur] = $1;
396     bcur++;
397   }
398
399   /* arbitrary safety maximum... */
400   if (bcur >= ASCEND_MAX_PKT_LEN)
401     YYACCEPT;
402
403 ;
404
405 /* XXX  There must be a better way to do this... */
406 bytegroup: byte
407   | byte byte
408   | byte byte byte
409   | byte byte byte byte
410   | byte byte byte byte byte
411   | byte byte byte byte byte byte
412   | byte byte byte byte byte byte byte
413   | byte byte byte byte byte byte byte byte
414   | byte byte byte byte byte byte byte byte byte
415   | byte byte byte byte byte byte byte byte byte byte
416   | byte byte byte byte byte byte byte byte byte byte byte
417   | 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
419   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte
420   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte
421   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte
422 ;
423
424 dataln: COUNTER bytegroup;
425
426 datagroup: dataln
427   | dataln dataln
428   | dataln dataln dataln
429   | dataln dataln dataln dataln
430   | dataln dataln dataln dataln dataln
431   | dataln dataln dataln dataln dataln dataln
432   | dataln dataln dataln dataln dataln dataln dataln
433   | dataln dataln dataln dataln dataln dataln dataln dataln
434 ;
435
436 %%
437
438 void
439 init_parse_ascend()
440 {
441   at_eof = 0;
442   start_time = 0;       /* we haven't see a date/time yet */
443 }
444
445 /* Parse the capture file.
446    Returns:
447      PARSED_RECORD if we got a packet
448      PARSED_NONRECORD if the parser succeeded but didn't see a packet
449      PARSE_FAILED if the parser failed. */
450 parse_t
451 parse_ascend(FILE_T fh, guint8 *pd, struct ascend_phdr *phdr,
452                 ascend_pkthdr *hdr, gint64 *start_of_data)
453 {
454   /* yydebug = 1; */
455   int retval;
456   ascend_init_lexer(fh);
457   pkt_data = pd;
458   pseudo_header = phdr;
459   header = hdr;
460   fh_ptr = &fh;
461
462   bcur = 0;
463   first_hexbyte = 0;
464   wirelen = 0;
465   caplen = 0;
466
467   /*
468    * Not all packets in a "wdd" dump necessarily have a "Cause an
469    * attempt to place call to" header (I presume this can happen if
470    * there was a call in progress when the packet was sent or
471    * received), so we won't necessarily have the phone number for
472    * the packet.
473    *
474    * XXX - we could assume, in the sequential pass, that it's the
475    * phone number from the last call, and remember that for use
476    * when doing random access.
477    */
478   pseudo_header->call_num[0] = '\0';
479
480   retval = yyparse();
481
482   caplen = bcur;
483
484   /* did we see any data (hex bytes)? if so, tip off ascend_seek()
485      as to where to look for the next packet, if any. If we didn't,
486      maybe this record was broken. Advance so we don't get into
487      an infinite loop reading a broken trace. */
488   if (first_hexbyte) {
489     *start_of_data = first_hexbyte;
490   } else {
491     /* Sometimes, a header will be printed but the data will be omitted, or
492        worse -- two headers will be printed, followed by the data for each. 
493        Because of this, we need to be fairly tolerant of what we accept
494        here.  If we didn't find any hex bytes, skip over what we've read so
495        far so we can try reading a new packet. */
496     *start_of_data = file_tell(*fh_ptr);
497     retval = 0;
498   }
499
500   /* if we got at least some data, return success even if the parser
501      reported an error. This is because the debug header gives the number
502      of bytes on the wire, not actually how many bytes are in the trace.
503      We won't know where the data ends until we run into the next packet. */
504   if (caplen) {
505     if (header) {
506       header->start_time = start_time;
507       header->secs = secs;
508       header->usecs = usecs;
509       header->caplen = caplen;
510       header->len = wirelen;
511     }
512
513     return PARSED_RECORD;
514   }
515
516   /* Didn't see any data. Still, perhaps the parser was happy.  */
517   if (retval)
518     return PARSE_FAILED;
519   else 
520     return PARSED_NONRECORD;
521 }
522
523 void
524 yyerror (const char *s)
525 {
526   ascend_parse_error = s;
527 }