From Joerg Mayer:
[obnox/wireshark/wip.git] / wiretap / ascend-grammar.y
1 %{
2 /* ascend-grammar.y
3  *
4  * $Id: ascend-grammar.y,v 1.19 2001/07/13 00:55:57 guy Exp $
5  *
6  * Wiretap Library
7  * Copyright (c) 1998 by Gilbert Ramirez <gram@xiexie.org>
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 'wandsess' output data:
27    
28 RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94
29   [0000]: FF 03 00 3D C0 06 CA 22 2F 45 00 00 28 6A 3B 40 
30   [0010]: 00 3F 03 D7 37 CE 41 62 12 CF 00 FB 08 20 27 00 
31   [0020]: 50 E4 08 DD D7 7C 4C 71 92 50 10 7D 78 67 C8 00 
32   [0030]: 00 
33 XMIT-iguana:241:(task: B04E12C0, time: 1975432.85) 53 octets @ 8009EB16
34   [0000]: FF 03 00 3D C0 09 1E 31 21 45 00 00 2C 2D BD 40 
35   [0010]: 00 7A 06 D8 B1 CF 00 FB 08 CE 41 62 12 00 50 20 
36   [0020]: 29 7C 4C 71 9C 9A 6A 93 A4 60 12 22 38 3F 10 00 
37   [0030]: 00 02 04 05 B4 
38
39     Example 'wdd' output data:
40
41 Date: 01/12/1990.  Time: 12:22:33
42 Cause an attempt to place call to 14082750382
43 WD_DIALOUT_DISP: chunk 2515EE type IP.
44 (task: 251790, time: 994953.28) 44 octets @ 2782B8
45   [0000]: 00 C0 7B 71 45 6C 00 60 08 16 AA 51 08 00 45 00
46   [0010]: 00 2C 66 1C 40 00 80 06 53 F6 AC 14 00 18 CC 47
47   [0020]: C8 45 0A 31 00 50 3B D9 5B 75 00 00
48
49     The following output comes from a MAX with Software 7.2.3:
50
51 RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0
52   [0000]: FF 03 00 21 45 00 00 60 E3 49 00 00 7F 11 FD 7B
53   [0010]: C0 A8 F7 05 8A C8 18 51 00 89 00 89 00 4C C7 C1
54   [0020]: CC 8E 40 00 00 01 00 00 00 00 00 01 20 45 4A 45
55   [0030]: 42 45 43 45 48 43 4E 46 43 46 41 43 41 43 41 43
56   [0040]: 41 43 41 43 41 43 41 43 41 43 41 42 4E 00 00 20
57   [0050]: 00 01 C0 0C 00 20 00 01 00 04 93 E0 00 06 60 00
58   [0060]: C0 A8 F7 05
59 XMIT-187:(task: B0292CA0, time: 18042248.04) 60 octets @ 800AD576
60   [0000]: FF 03 00 21 45 00 00 38 D7 EE 00 00 0F 01 11 2B
61   [0010]: 0A FF FF FE C0 A8 F7 05 03 0D 33 D3 00 00 00 00
62   [0020]: 45 00 00 60 E3 49 00 00 7E 11 FE 7B C0 A8 F7 05
63   [0030]: 8A C8 18 51 00 89 00 89 00 4C C7 C1
64 RECV-187:(task: B0292CA0, time: 18042251.92) 16 octets @ 800018E8
65   [0000]: FF 03 C0 21 09 01 00 0C DE 61 96 4B 00 30 94 92
66
67
68  */
69
70 #include <stdio.h>
71 #include <stdlib.h>
72
73 #ifdef HAVE_CONFIG_H
74 #include "config.h"
75 #endif
76 #include "wtap-int.h"
77 #include "buffer.h"
78 #include "ascend.h"
79 #include "ascend-int.h"
80
81 #define NFH_PATH "/dev/null"
82 #define NO_USER "<none>"
83
84 extern int at_eof;
85
86 int yyparse(void);
87 void yyerror(char *);
88
89 unsigned int bcur = 0, bcount;
90 guint32 start_time, secs, usecs, caplen, wirelen;
91 ascend_pkthdr *header;
92 struct ascend_phdr *pseudo_header;
93 char *pkt_data;
94 FILE *nfh = NULL;
95
96 %}
97  
98 %union {
99 gchar  *s;
100 guint32 d;
101 char    b;
102 }
103
104 %token <s> STRING KEYWORD WDD_DATE WDD_CHUNK COUNTER
105 %token <d> WDS_PREFIX DECNUM HEXNUM
106 %token <b> HEXBYTE
107
108 %type <s> string dataln datagroup
109 %type <d> wds_prefix decnum hexnum
110 %type <b> byte bytegroup
111
112 %%
113
114 data_packet:
115   | wds_hdr datagroup
116   | wds7_hdr datagroup
117   | wdd_date wdd_hdr datagroup
118   | wdd_hdr datagroup
119 ;
120
121 wds_prefix: WDS_PREFIX;
122
123 string: STRING;
124
125 decnum: DECNUM;
126
127 hexnum: HEXNUM;
128
129 /* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */
130 /*            1        2      3      4       5      6       7      8      9      10     11 */
131 wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
132   wirelen = $9;
133   caplen = ($9 < ASCEND_MAX_PKT_LEN) ? $9 : ASCEND_MAX_PKT_LEN;
134   /* If we don't have as many bytes of data as the octet count in
135      the header, make the capture length the number of bytes we
136      actually have. */
137   if (bcount > 0 && bcount <= caplen)
138     caplen = bcount;
139   secs = $7;
140   usecs = $8;
141   if (pseudo_header != NULL) {
142     /* pseudo_header->user is set in ascend-scanner.l */
143     pseudo_header->type = $1;
144     pseudo_header->sess = $3;
145     pseudo_header->call_num[0] = '\0';
146     pseudo_header->chunk = 0;
147     pseudo_header->task = $5;
148   }
149   
150   bcur = 0;
151 }
152 ;
153
154
155 /* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */
156 /*            1        2       3      4       5       6      7      8      9      10    */
157 wds7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
158   wirelen = $8;
159   caplen = ($8 < ASCEND_MAX_PKT_LEN) ? $8 : ASCEND_MAX_PKT_LEN;
160   /* If we don't have as many bytes of data as the octet count in
161      the header, make the capture length the number of bytes we
162      actually have. */
163   if (bcount > 0 && bcount <= caplen)
164     caplen = bcount;
165   secs = $6;
166   usecs = $7;
167   if (pseudo_header != NULL) {
168     /* pseudo_header->user is set in ascend-scanner.l */
169     pseudo_header->type = $1;
170     pseudo_header->sess = $2;
171     pseudo_header->call_num[0] = '\0';
172     pseudo_header->chunk = 0;
173     pseudo_header->task = $4;
174   }
175   
176   bcur = 0;
177 }
178 ;
179
180 /*
181 Date: 01/12/1990.  Time: 12:22:33
182 Cause an attempt to place call to 14082750382
183 */
184 /*           1        2      3      4      5       6      7      8      9      10*/
185 wdd_date: WDD_DATE decnum decnum decnum KEYWORD decnum decnum decnum KEYWORD string {
186   /*
187    * Supply the date/time value to the code above us; it will use the
188    * first date/time value supplied as the capture start date/time.
189    */
190   struct tm wddt;
191
192   wddt.tm_sec  = $8;
193   wddt.tm_min  = $7;
194   wddt.tm_hour = $6;
195   wddt.tm_mday = $3;
196   wddt.tm_mon  = $2 - 1;
197   wddt.tm_year = ($4 > 1970) ? $4 - 1900 : 70;
198   wddt.tm_isdst = -1;
199   
200   start_time = mktime(&wddt);
201 }
202 ;
203  
204 /*
205 WD_DIALOUT_DISP: chunk 2515EE type IP.
206 (task: 251790, time: 994953.28) 44 octets @ 2782B8
207 */
208 /*           1        2      3       4       5      6       7      8      9      10     11*/
209 wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
210   wirelen = $9;
211   caplen = ($9 < ASCEND_MAX_PKT_LEN) ? $9 : ASCEND_MAX_PKT_LEN;
212   /* If we don't have as many bytes of data as the octet count in
213      the header, make the capture length the number of bytes we
214      actually have. */
215   if (bcount > 0 && bcount <= caplen)
216     caplen = bcount;
217   secs = $7;
218   usecs = $8;
219   if (pseudo_header != NULL) {
220     /* pseudo_header->call_num is set in ascend-scanner.l */
221     pseudo_header->type = ASCEND_PFX_WDD;
222     pseudo_header->user[0] = '\0';
223     pseudo_header->sess = 0;
224     pseudo_header->chunk = $2;
225     pseudo_header->task = $5;
226   }
227   
228   bcur = 0;
229 }
230 ;
231  
232 byte: HEXBYTE {
233   if (bcur < caplen) {
234     pkt_data[bcur] = $1;
235     bcur++;
236   }
237
238   if (bcur >= caplen) {
239     if (header != NULL) {
240       header->start_time = start_time;
241       header->secs = secs;
242       header->usecs = usecs;
243       header->caplen = caplen;
244       header->len = wirelen;
245     }
246     YYACCEPT;
247   }
248
249 ;
250
251 /* XXX  There must be a better way to do this... */
252 bytegroup: byte
253   | byte byte
254   | byte byte byte
255   | byte byte byte byte
256   | byte byte byte byte byte
257   | byte byte byte byte byte byte
258   | byte byte byte byte byte byte byte
259   | byte byte byte byte byte byte byte byte
260   | byte byte byte byte byte byte byte byte byte
261   | byte byte byte byte byte byte byte byte byte byte
262   | byte byte byte byte byte byte byte byte byte byte byte
263   | byte byte byte byte byte byte byte byte byte byte byte byte
264   | byte byte byte byte byte byte byte byte byte byte byte byte byte
265   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte
266   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte
267   | byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte
268 ;
269
270 dataln: COUNTER bytegroup;
271
272 datagroup: dataln
273   | dataln dataln
274   | dataln dataln dataln
275   | dataln dataln dataln dataln
276   | dataln dataln dataln dataln dataln
277   | dataln dataln dataln dataln dataln dataln
278   | dataln dataln dataln dataln dataln dataln dataln
279   | dataln dataln dataln dataln dataln dataln dataln dataln
280 ;
281
282 %%
283
284 void
285 init_parse_ascend()
286 {
287   bcur = 0;
288   at_eof = 0;
289   start_time = 0;       /* we haven't see a date/time yet */
290   
291   /* In order to keep flex from printing a lot of newlines while reading
292      the capture data, we open up /dev/null and point yyout at the null
293      file handle. */
294   if (! nfh) {
295     nfh = fopen(NFH_PATH, "r");
296   }
297 }
298
299 /* Parse the capture file.  Return the offset of the next packet, or zero
300    if there is none. */
301 int
302 parse_ascend(FILE_T fh, void *pd, struct ascend_phdr *phdr,
303                 ascend_pkthdr *hdr, int len)
304 {
305   /* yydebug = 1; */
306  
307   ascend_init_lexer(fh, nfh);
308   pkt_data = pd;
309   pseudo_header = phdr;
310   header = hdr;
311   bcount = len;
312   
313   /*
314    * Not all packets in a "wdd" dump necessarily have a "Cause an
315    * attempt to place call to" header (I presume this can happen if
316    * there was a call in progress when the packet was sent or
317    * received), so we won't necessarily have the phone number for
318    * the packet.
319    *
320    * XXX - we could assume, in the sequential pass, that it's the
321    * phone number from the last call, and remember that for use
322    * when doing random access.
323    */
324   pseudo_header->call_num[0] = '\0';
325
326   if (yyparse())
327     return 0;
328   else
329     return 1;
330 }
331
332 void
333 yyerror (char *s)
334 {
335   /* fprintf (stderr, "%s\n", s); */
336 }