5 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 Example 'pridisp' output data - one paragraph/frame:
26 PRI-XMIT-27: (task "l1Task" at 0x10216fe0, time: 560194.01) 4 octets @ 0x1027c5b0
27 [0000]: 00 01 01 a9 ....
28 PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
31 Example 'pridisp' output data - two paragraphs/frame for XMIT case only:
33 PRI-XMIT-19/1: (task "l1Task" at 0x10216840, time: 274759.98) 4 octets @ 0x1027f230
34 [0000]: 00 01 30 d8 ..0.
35 PRI-XMIT-19/2 (task "l1Task" at 0x10216840, time: 274759.98) 11 octets @ 0x1027f234
36 [0000]: 08 02 8c bf 02 18 04 e9 82 83 8f ........ ...
38 Example 'ether-disp' output data:
40 ETHER3ND RECV: (task "_sarTask" at 0x802c6eb0, time: 259848.03) 775 octets @ 0xa8fb2020
41 [0000]: 00 d0 52 04 e7 1e 08 00 20 ae 51 b5 08 00 45 00 ..R..... .Q...E.
42 [0010]: 02 f9 05 e6 40 00 3f 11 6e 39 87 fe c4 95 3c 3c ....@.?. n9....<<
43 [0020]: 3c 05 13 c4 13 c4 02 e5 ef ed 49 4e 56 49 54 45 <....... ..INVITE
44 [0030]: 20 73 69 70 3a 35 32 30 37 33 40 36 30 2e 36 30 sip:520 73@60.60
45 [0040]: 2e 36 30 2e 35 20 53 49 50 2f 32 2e 30 0d 0a 56 .60.5 SI P/2.0..V
46 [0050]: 69 61 3a 20 53 49 50 2f 32 2e 30 2f 55 44 50 20 ia: SIP/ 2.0/UDP
47 [0060]: 31 33 35 2e 135.
49 Example 'wandsess' output data:
51 RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94
52 [0000]: FF 03 00 3D C0 06 CA 22 2F 45 00 00 28 6A 3B 40
53 [0010]: 00 3F 03 D7 37 CE 41 62 12 CF 00 FB 08 20 27 00
54 [0020]: 50 E4 08 DD D7 7C 4C 71 92 50 10 7D 78 67 C8 00
56 XMIT-iguana:241:(task: B04E12C0, time: 1975432.85) 53 octets @ 8009EB16
57 [0000]: FF 03 00 3D C0 09 1E 31 21 45 00 00 2C 2D BD 40
58 [0010]: 00 7A 06 D8 B1 CF 00 FB 08 CE 41 62 12 00 50 20
59 [0020]: 29 7C 4C 71 9C 9A 6A 93 A4 60 12 22 38 3F 10 00
60 [0030]: 00 02 04 05 B4
62 Example 'wdd' output data:
64 Date: 01/12/1990. Time: 12:22:33
65 Cause an attempt to place call to 14082750382
66 WD_DIALOUT_DISP: chunk 2515EE type IP.
67 (task: 251790, time: 994953.28) 44 octets @ 2782B8
68 [0000]: 00 C0 7B 71 45 6C 00 60 08 16 AA 51 08 00 45 00
69 [0010]: 00 2C 66 1C 40 00 80 06 53 F6 AC 14 00 18 CC 47
70 [0020]: C8 45 0A 31 00 50 3B D9 5B 75 00 00
72 The following output comes from a MAX with Software 7.2.3:
74 RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0
75 [0000]: FF 03 00 21 45 00 00 60 E3 49 00 00 7F 11 FD 7B
76 [0010]: C0 A8 F7 05 8A C8 18 51 00 89 00 89 00 4C C7 C1
77 [0020]: CC 8E 40 00 00 01 00 00 00 00 00 01 20 45 4A 45
78 [0030]: 42 45 43 45 48 43 4E 46 43 46 41 43 41 43 41 43
79 [0040]: 41 43 41 43 41 43 41 43 41 43 41 42 4E 00 00 20
80 [0050]: 00 01 C0 0C 00 20 00 01 00 04 93 E0 00 06 60 00
82 XMIT-187:(task: B0292CA0, time: 18042248.04) 60 octets @ 800AD576
83 [0000]: FF 03 00 21 45 00 00 38 D7 EE 00 00 0F 01 11 2B
84 [0010]: 0A FF FF FE C0 A8 F7 05 03 0D 33 D3 00 00 00 00
85 [0020]: 45 00 00 60 E3 49 00 00 7E 11 FE 7B C0 A8 F7 05
86 [0030]: 8A C8 18 51 00 89 00 89 00 4C C7 C1
87 RECV-187:(task: B0292CA0, time: 18042251.92) 16 octets @ 800018E8
88 [0000]: FF 03 C0 21 09 01 00 0C DE 61 96 4B 00 30 94 92
90 In TAOS 8.0, Lucent slightly changed the format as follows:
92 Example 'wandisp' output data (TAOS 8.0.3): (same format is used
93 for 'wanopen' and 'wannext' command)
95 RECV-14: (task "idle task" at 0xb05e6e00, time: 1279.01) 29 octets @ 0x8000e0fc
96 [0000]: ff 03 c0 21 01 01 00 19 01 04 05 f4 11 04 05 f4 ...!.... ........
97 [0010]: 13 09 03 00 c0 7b 9a 9f 2d 17 04 10 00 .....{.. -....
98 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 38 octets @ 0x8007fd56
99 [0000]: ff 03 c0 21 01 01 00 22 00 04 00 00 01 04 05 f4 ...!..." ........
100 [0010]: 03 05 c2 23 05 11 04 05 f4 13 09 03 00 c0 7b 80 ...#.... ......{.
101 [0020]: 7c ef 17 04 0e 00 |.....
102 XMIT-14: (task "idle task" at 0xb05e6e00, time: 1279.02) 29 octets @ 0x8007fa36
103 [0000]: ff 03 c0 21 02 01 00 19 01 04 05 f4 11 04 05 f4 ...!.... ........
104 [0010]: 13 09 03 00 c0 7b 9a 9f 2d 17 04 10 00 .....{.. -....
106 Example 'wandsess' output data (TAOS 8.0.3):
108 RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198
109 [0000]: ff 03 00 3d c0 00 00 04 80 fd 02 01 00 0a 11 06 ...=.... ........
110 [0010]: 00 01 01 03 ....
111 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 26 octets @ 0x800806b6
112 [0000]: ff 03 00 3d c0 00 00 00 80 21 01 01 00 10 02 06 ...=.... .!......
113 [0010]: 00 2d 0f 01 03 06 89 64 03 08 .-.....d ..
114 XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octets @ 0x8007f716
115 [0000]: ff 03 00 3d c0 00 00 01 80 fd 01 01 00 0a 11 06 ...=.... ........
116 [0010]: 00 01 01 03 ....
118 The changes since TAOS 7.X are:
120 1) White space is added before "(task".
121 2) Task has a name, indicated by a subsequent string surrounded by a
123 3) Address expressed in hex number has a preceeding "0x".
124 4) Hex numbers are in lower case.
125 5) There is a character display corresponding to hex data in each line.
134 #include "wtap-int.h"
135 #include <wsutil/buffer.h>
136 #include "ascendtext.h"
137 #include "ascend-int.h"
138 #include "file_wrappers.h"
140 #define NO_USER "<none>"
142 int yyparse(FILE_T fh);
143 void yyerror(FILE_T fh _U_, const char *);
145 const gchar *ascend_parse_error;
147 static unsigned int bcur;
148 static guint32 start_time, usecs, caplen, wirelen;
150 struct ascend_phdr *pseudo_header;
151 static guint8 *pkt_data;
152 static gint64 first_hexbyte;
162 %token <s> STRING KEYWORD WDD_DATE WDD_CHUNK COUNTER SLASH_SUFFIX
163 %token <d> WDS_PREFIX ISDN_PREFIX ETHER_PREFIX DECNUM HEXNUM
166 %type <s> string dataln datagroup
167 %type <d> wds_prefix isdn_prefix ether_prefix decnum hexnum
168 %type <b> byte bytegroup
170 %parse-param { FILE_T fh }
175 | ether_hdr datagroup
176 | deferred_isdn_hdr datagroup deferred_isdn_hdr datagroup
182 | wdd_date wdd_hdr datagroup
186 isdn_prefix: ISDN_PREFIX;
188 ether_prefix: ETHER_PREFIX;
190 wds_prefix: WDS_PREFIX;
199 pridisp special case - I-frame header printed separately from contents,
200 one frame across two messages.
202 PRI-XMIT-0/1: (task "l1Task" at 0x80152b20, time: 283529.65) 4 octets @
204 [0000]: 00 01 ae b2 ....
205 PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @
207 [0000]: 08 02 d7 e3 02 18 03 a9 83 8a ........
210 deferred_isdn_hdr: isdn_prefix decnum SLASH_SUFFIX KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
215 if (pseudo_header != NULL) {
216 pseudo_header->type = $1;
217 pseudo_header->sess = $2;
218 pseudo_header->call_num[0] = '\0';
219 pseudo_header->chunk = 0;
220 pseudo_header->task = $7;
222 /* because we have two data groups */
228 PRI-XMIT-19: (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1c0
230 PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
232 isdn_hdr: isdn_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
237 if (pseudo_header != NULL) {
238 pseudo_header->type = $1;
239 pseudo_header->sess = $2;
240 pseudo_header->call_num[0] = '\0';
241 pseudo_header->chunk = 0;
242 pseudo_header->task = $6;
249 ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa
252 ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decnum
253 decnum KEYWORD HEXNUM {
258 if (pseudo_header != NULL) {
259 pseudo_header->type = $1;
260 pseudo_header->call_num[0] = '\0';
261 pseudo_header->chunk = 0;
262 pseudo_header->task = $6;
267 /* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */
268 /* 1 2 3 4 5 6 7 8 9 10 11 */
269 wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
274 if (pseudo_header != NULL) {
275 /* pseudo_header->user is set in ascend_scanner.l */
276 pseudo_header->type = $1;
277 pseudo_header->sess = $3;
278 pseudo_header->call_num[0] = '\0';
279 pseudo_header->chunk = 0;
280 pseudo_header->task = $5;
285 /* RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198 */
286 /* 1 2 3 4 5 6 7 8 9 10 11 12 13 */
287 wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
292 if (pseudo_header != NULL) {
293 /* pseudo_header->user is set in ascend_scanner.l */
294 pseudo_header->type = $1;
295 pseudo_header->sess = $3;
296 pseudo_header->call_num[0] = '\0';
297 pseudo_header->chunk = 0;
298 pseudo_header->task = $7;
303 /* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */
304 /* 1 2 3 4 5 6 7 8 9 10 */
305 wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
310 if (pseudo_header != NULL) {
311 /* pseudo_header->user is set in ascend_scanner.l */
312 pseudo_header->type = $1;
313 pseudo_header->sess = $2;
314 pseudo_header->call_num[0] = '\0';
315 pseudo_header->chunk = 0;
316 pseudo_header->task = $4;
321 /* XMIT-44: (task "freedm_task" at 0xe051fd10, time: 6258.66) 29 octets @ 0x606d1f00 */
322 /* 1 2 3 4 5 6 7 8 9 10 11 12 */
323 wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
328 if (pseudo_header != NULL) {
329 /* pseudo_header->user is set in ascend_scanner.l */
330 pseudo_header->type = $1;
331 pseudo_header->sess = $2;
332 pseudo_header->call_num[0] = '\0';
333 pseudo_header->chunk = 0;
334 pseudo_header->task = $6;
340 Date: 01/12/1990. Time: 12:22:33
341 Cause an attempt to place call to 14082750382
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 {
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.
355 wddt.tm_mon = $2 - 1;
356 wddt.tm_year = ($4 > 1970) ? $4 - 1900 : 70;
359 start_time = (guint32) mktime(&wddt);
364 WD_DIALOUT_DISP: chunk 2515EE type IP.
365 (task: 251790, time: 994953.28) 44 octets @ 2782B8
367 /* 1 2 3 4 5 6 7 8 9 10 11*/
368 wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
373 if (pseudo_header != NULL) {
374 /* pseudo_header->call_num is set in ascend_scanner.l */
375 pseudo_header->type = ASCEND_PFX_WDD;
376 pseudo_header->user[0] = '\0';
377 pseudo_header->sess = 0;
378 pseudo_header->chunk = $2;
379 pseudo_header->task = $5;
385 /* remember the position of the data group in the trace, to tip
386 off ascend_seek() as to where to look for the next header. */
387 if (first_hexbyte == 0)
388 first_hexbyte = file_tell(fh);
395 /* arbitrary safety maximum... */
396 if (bcur >= ASCEND_MAX_PKT_LEN)
401 /* XXX There must be a better way to do this... */
405 | byte byte byte byte
406 | byte byte byte byte byte
407 | byte byte byte byte byte byte
408 | byte byte byte byte byte byte byte
409 | byte byte byte byte byte byte byte byte
410 | byte byte byte byte byte byte byte byte byte
411 | byte byte byte byte byte byte byte byte byte byte
412 | byte byte byte byte byte byte byte byte byte byte byte
413 | byte byte byte byte byte byte byte byte byte byte byte byte
414 | byte byte byte byte byte byte byte byte byte byte byte byte byte
415 | byte byte 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 byte byte
417 | byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte byte
420 dataln: COUNTER bytegroup;
424 | dataln dataln dataln
425 | dataln dataln dataln dataln
426 | dataln dataln dataln dataln dataln
427 | dataln dataln dataln dataln dataln dataln
428 | dataln dataln dataln dataln dataln dataln dataln
429 | dataln dataln dataln dataln dataln dataln dataln dataln
435 init_parse_ascend(void)
437 start_time = 0; /* we haven't see a date/time yet */
440 /* Run the parser. */
442 run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd)
447 ascend_init_lexer(fh);
448 pseudo_header = &phdr->pseudo_header.ascend;
457 * Not all packets in a "wdd" dump necessarily have a "Cause an
458 * attempt to place call to" header (I presume this can happen if
459 * there was a call in progress when the packet was sent or
460 * received), so we won't necessarily have the phone number for
463 * XXX - we could assume, in the sequential pass, that it's the
464 * phone number from the last call, and remember that for use
465 * when doing random access.
467 pseudo_header->call_num[0] = '\0';
469 retval = yyparse(fh);
476 /* Parse the capture file.
478 TRUE if we got a packet
481 check_ascend(FILE_T fh, struct wtap_pkthdr *phdr)
483 guint8 buf[ASCEND_MAX_PKT_LEN];
485 run_ascend_parser(fh, phdr, buf);
487 /* if we got at least some data, return success even if the parser
488 reported an error. This is because the debug header gives the number
489 of bytes on the wire, not actually how many bytes are in the trace.
490 We won't know where the data ends until we run into the next packet. */
491 return (caplen != 0);
494 /* Parse the capture file.
496 PARSED_RECORD if we got a packet
497 PARSED_NONRECORD if the parser succeeded but didn't see a packet
498 PARSE_FAILED if the parser failed. */
500 parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
505 ws_buffer_assure_space(buf, length);
506 retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf));
508 /* did we see any data (hex bytes)? if so, tip off ascend_seek()
509 as to where to look for the next packet, if any. If we didn't,
510 maybe this record was broken. Advance so we don't get into
511 an infinite loop reading a broken trace. */
513 ascend->next_packet_seek_start = first_hexbyte;
515 /* Sometimes, a header will be printed but the data will be omitted, or
516 worse -- two headers will be printed, followed by the data for each.
517 Because of this, we need to be fairly tolerant of what we accept
518 here. If we didn't find any hex bytes, skip over what we've read so
519 far so we can try reading a new packet. */
520 ascend->next_packet_seek_start = file_tell(fh);
524 /* if we got at least some data, return success even if the parser
525 reported an error. This is because the debug header gives the number
526 of bytes on the wire, not actually how many bytes are in the trace.
527 We won't know where the data ends until we run into the next packet. */
529 if (! ascend->adjusted) {
530 ascend->adjusted = TRUE;
531 if (start_time != 0) {
533 * Capture file contained a date and time.
534 * We do this only if this is the very first packet we've seen -
535 * i.e., if "ascend->adjusted" is false - because
536 * if we get a date and time after the first packet, we can't
537 * go back and adjust the time stamps of the packets we've already
538 * processed, and basing the time stamps of this and following
539 * packets on the time stamp from the file text rather than the
540 * ctime of the capture file means times before this and after
541 * this can't be compared.
543 ascend->inittime = start_time;
545 if (ascend->inittime > secs)
546 ascend->inittime -= secs;
548 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
549 phdr->ts.secs = secs + ascend->inittime;
550 phdr->ts.nsecs = usecs * 1000;
551 phdr->caplen = caplen;
555 * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND,
556 * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN
557 * or WTAP_ENCAP_ETHERNET).
559 switch(phdr->pseudo_header.ascend.type) {
560 case ASCEND_PFX_ISDN_X:
561 phdr->pseudo_header.isdn.uton = TRUE;
562 phdr->pseudo_header.isdn.channel = 0;
565 case ASCEND_PFX_ISDN_R:
566 phdr->pseudo_header.isdn.uton = FALSE;
567 phdr->pseudo_header.isdn.channel = 0;
570 case ASCEND_PFX_ETHER:
571 phdr->pseudo_header.eth.fcs_len = 0;
574 return PARSED_RECORD;
577 /* Didn't see any data. Still, perhaps the parser was happy. */
581 return PARSED_NONRECORD;
585 yyerror (FILE_T fh _U_, const char *s)
587 ascend_parse_error = s;