diff options
author | Gerald Combs <gerald@wireshark.org> | 2005-02-05 17:39:12 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2005-02-05 17:39:12 +0000 |
commit | 9e93bf474710d9ef0eb4ba33bde284b6685fd360 (patch) | |
tree | 59d8d2204fb8fef65bf8a637ed5c4284558230fc | |
parent | 17608107ff86cd057a7a46983616a01b4ff25cd8 (diff) |
From Josh Bailey:
Attached is an update to Lucent/Ascend trace parsing: fix a few bugs,
add support for ISDN and Ethernet captures - diffs to 0.10.9.
svn path=/trunk/; revision=13311
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | wiretap/ascend-grammar.y | 228 | ||||
-rw-r--r-- | wiretap/ascend-int.h | 2 | ||||
-rw-r--r-- | wiretap/ascend-scanner.l | 75 | ||||
-rw-r--r-- | wiretap/ascend.c | 288 | ||||
-rw-r--r-- | wiretap/wtap.h | 3 |
6 files changed, 364 insertions, 233 deletions
@@ -2117,6 +2117,7 @@ Brian Wheeler <Brian.Wheeler [AT] arrisi.com> { Josh Bailey <joshbailey [AT] lucent.com> { IPDC support + Lucent/Ascend trace parsing updates } Jelmer Vernooij <jelmer [AT] samba.org> { diff --git a/wiretap/ascend-grammar.y b/wiretap/ascend-grammar.y index 323b5c497d..50dc36d6cf 100644 --- a/wiretap/ascend-grammar.y +++ b/wiretap/ascend-grammar.y @@ -23,7 +23,32 @@ */ /* - Example 'wandsess' output data: + Example 'pridisp' output data - one paragraph/frame: + +PRI-XMIT-27: (task "l1Task" at 0x10216fe0, time: 560194.01) 4 octets @ 0x1027c5b0 + [0000]: 00 01 01 a9 .... +PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00 + [0000]: 00 01 01 dd + + Example 'pridisp' output data - two paragraphs/frame for XMIT case only: + +PRI-XMIT-19/1: (task "l1Task" at 0x10216840, time: 274759.98) 4 octets @ 0x1027f230 + [0000]: 00 01 30 d8 ..0. +PRI-XMIT-19/2 (task "l1Task" at 0x10216840, time: 274759.98) 11 octets @ 0x1027f234 + [0000]: 08 02 8c bf 02 18 04 e9 82 83 8f ........ ... + + Example 'ether-disp' output data: + +ETHER3ND RECV: (task "_sarTask" at 0x802c6eb0, time: 259848.03) 775 octets @ 0xa8fb2020 + [0000]: 00 d0 52 04 e7 1e 08 00 20 ae 51 b5 08 00 45 00 ..R..... .Q...E. + [0010]: 02 f9 05 e6 40 00 3f 11 6e 39 87 fe c4 95 3c 3c ....@.?. n9....<< + [0020]: 3c 05 13 c4 13 c4 02 e5 ef ed 49 4e 56 49 54 45 <....... ..INVITE + [0030]: 20 73 69 70 3a 35 32 30 37 33 40 36 30 2e 36 30 sip:520 73@60.60 + [0040]: 2e 36 30 2e 35 20 53 49 50 2f 32 2e 30 0d 0a 56 .60.5 SI P/2.0..V + [0050]: 69 61 3a 20 53 49 50 2f 32 2e 30 2f 55 44 50 20 ia: SIP/ 2.0/UDP + [0060]: 31 33 35 2e 135. + + Example 'wandsess' output data: RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 [0000]: FF 03 00 3D C0 06 CA 22 2F 45 00 00 28 6A 3B 40 @@ -109,11 +134,13 @@ XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octet #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "wtap-int.h" #include "buffer.h" #include "ascend.h" #include "ascend-int.h" +#include "file_wrappers.h" #define NO_USER "<none>" @@ -122,11 +149,13 @@ void yyerror(char *); gchar *ascend_parse_error; -static unsigned int bcur = 0, bcount; +static unsigned int bcur; static guint32 start_time, secs, usecs, caplen, wirelen; static ascend_pkthdr *header; struct ascend_phdr *pseudo_header; static guint8 *pkt_data; +static long first_hexbyte; +static FILE_T *fh_ptr; %} @@ -136,17 +165,20 @@ guint32 d; guint8 b; } -%token <s> STRING KEYWORD WDD_DATE WDD_CHUNK COUNTER -%token <d> WDS_PREFIX DECNUM HEXNUM +%token <s> STRING KEYWORD WDD_DATE WDD_CHUNK COUNTER SLASH_SUFFIX +%token <d> WDS_PREFIX ISDN_PREFIX ETHER_PREFIX DECNUM HEXNUM %token <b> HEXBYTE -%type <s> string dataln datagroup -%type <d> wds_prefix decnum hexnum +%type <s> string dataln datagroup +%type <d> wds_prefix isdn_prefix ether_prefix decnum hexnum %type <b> byte bytegroup %% data_packet: + | ether_hdr datagroup + | deferred_isdn_hdr datagroup deferred_isdn_hdr datagroup + | isdn_hdr datagroup | wds_hdr datagroup | wds8_hdr datagroup | wdp7_hdr datagroup @@ -155,6 +187,10 @@ data_packet: | wdd_hdr datagroup ; +isdn_prefix: ISDN_PREFIX; + +ether_prefix: ETHER_PREFIX; + wds_prefix: WDS_PREFIX; string: STRING; @@ -163,16 +199,80 @@ decnum: DECNUM; hexnum: HEXNUM; +/* + pridisp special case - I-frame header printed separately from contents, + one frame across two messages. + +PRI-XMIT-0/1: (task "l1Task" at 0x80152b20, time: 283529.65) 4 octets @ +0x80128220 + [0000]: 00 01 ae b2 .... +PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @ +0x80128224 + [0000]: 08 02 d7 e3 02 18 03 a9 83 8a ........ + +*/ +deferred_isdn_hdr: isdn_prefix decnum SLASH_SUFFIX KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { + wirelen += $11; + caplen += $11; + secs = $9; + usecs = $10; + if (pseudo_header != NULL) { + pseudo_header->type = $1; + pseudo_header->sess = $2; + pseudo_header->call_num[0] = '\0'; + pseudo_header->chunk = 0; + pseudo_header->task = $7; + } + /* because we have two data groups */ + first_hexbyte = 0; +} +; + +/* +PRI-XMIT-19: (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1c0 + ... or ... +PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00 +*/ +isdn_hdr: isdn_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { + wirelen = $10; + caplen = $10; + secs = $8; + usecs = $9; + if (pseudo_header != NULL) { + pseudo_header->type = $1; + pseudo_header->sess = $2; + pseudo_header->call_num[0] = '\0'; + pseudo_header->chunk = 0; + pseudo_header->task = $6; + } + first_hexbyte = 0; +} +; + +/* +ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa +885f80e +*/ +ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decnum + decnum KEYWORD HEXNUM { + wirelen = $10; + caplen = $10; + secs = $8; + usecs = $9; + if (pseudo_header != NULL) { + pseudo_header->type = $1; + pseudo_header->call_num[0] = '\0'; + pseudo_header->chunk = 0; + pseudo_header->task = $6; + } +} +; + /* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */ /* 1 2 3 4 5 6 7 8 9 10 11 */ wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { wirelen = $9; - caplen = ($9 < ASCEND_MAX_PKT_LEN) ? $9 : ASCEND_MAX_PKT_LEN; - /* If we don't have as many bytes of data as the octet count in - the header, make the capture length the number of bytes we - actually have. */ - if (bcount > 0 && bcount <= caplen) - caplen = bcount; + caplen = $9; secs = $7; usecs = $8; if (pseudo_header != NULL) { @@ -183,8 +283,6 @@ wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KE pseudo_header->chunk = 0; pseudo_header->task = $5; } - - bcur = 0; } ; @@ -192,12 +290,7 @@ wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KE /* 1 2 3 4 5 6 7 8 9 10 11 12 13 */ wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { wirelen = $11; - caplen = ($11 < ASCEND_MAX_PKT_LEN) ? $11 : ASCEND_MAX_PKT_LEN; - /* If we don't have as many bytes of data as the octet count in - the header, make the capture length the number of bytes we - actually have. */ - if (bcount > 0 && bcount <= caplen) - caplen = bcount; + caplen = $11; secs = $9; usecs = $10; if (pseudo_header != NULL) { @@ -208,8 +301,6 @@ wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum pseudo_header->chunk = 0; pseudo_header->task = $7; } - - bcur = 0; } ; @@ -217,12 +308,7 @@ wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum /* 1 2 3 4 5 6 7 8 9 10 */ wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { wirelen = $8; - caplen = ($8 < ASCEND_MAX_PKT_LEN) ? $8 : ASCEND_MAX_PKT_LEN; - /* If we don't have as many bytes of data as the octet count in - the header, make the capture length the number of bytes we - actually have. */ - if (bcount > 0 && bcount <= caplen) - caplen = bcount; + caplen = $8; secs = $6; usecs = $7; if (pseudo_header != NULL) { @@ -233,8 +319,6 @@ wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD pseudo_header->chunk = 0; pseudo_header->task = $4; } - - bcur = 0; } ; @@ -242,12 +326,7 @@ wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD /* 1 2 3 4 5 6 7 8 9 10 11 12 */ wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { wirelen = $10; - caplen = ($10 < ASCEND_MAX_PKT_LEN) ? $10 : ASCEND_MAX_PKT_LEN; - /* If we don't have as many bytes of data as the octet count in - the header, make the capture length the number of bytes we - actually have. */ - if (bcount > 0 && bcount <= caplen) - caplen = bcount; + caplen = $10; secs = $8; usecs = $9; if (pseudo_header != NULL) { @@ -258,8 +337,6 @@ wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum pseudo_header->chunk = 0; pseudo_header->task = $6; } - - bcur = 0; } ; @@ -286,7 +363,7 @@ wdd_date: WDD_DATE decnum decnum decnum KEYWORD decnum decnum decnum KEYWORD str start_time = mktime(&wddt); } ; - + /* WD_DIALOUT_DISP: chunk 2515EE type IP. (task: 251790, time: 994953.28) 44 octets @ 2782B8 @@ -294,12 +371,7 @@ WD_DIALOUT_DISP: chunk 2515EE type IP. /* 1 2 3 4 5 6 7 8 9 10 11*/ wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM { wirelen = $9; - caplen = ($9 < ASCEND_MAX_PKT_LEN) ? $9 : ASCEND_MAX_PKT_LEN; - /* If we don't have as many bytes of data as the octet count in - the header, make the capture length the number of bytes we - actually have. */ - if (bcount > 0 && bcount <= caplen) - caplen = bcount; + caplen = $9; secs = $7; usecs = $8; if (pseudo_header != NULL) { @@ -310,27 +382,23 @@ wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KE pseudo_header->chunk = $2; pseudo_header->task = $5; } - - bcur = 0; } ; byte: HEXBYTE { + /* remember the position of the data group in the trace, to tip + off ascend_seek() as to where to look for the next header. */ + if (first_hexbyte == 0) + first_hexbyte = file_tell(*fh_ptr); + if (bcur < caplen) { pkt_data[bcur] = $1; bcur++; } - if (bcur >= caplen) { - if (header != NULL) { - header->start_time = start_time; - header->secs = secs; - header->usecs = usecs; - header->caplen = caplen; - header->len = wirelen; - } + /* arbitrary safety maximum... */ + if (bcur >= ASCEND_MAX_PKT_LEN) YYACCEPT; - } } ; @@ -370,7 +438,6 @@ datagroup: dataln void init_parse_ascend() { - bcur = 0; at_eof = 0; start_time = 0; /* we haven't see a date/time yet */ } @@ -379,16 +446,21 @@ init_parse_ascend() if there is none. */ int parse_ascend(FILE_T fh, guint8 *pd, struct ascend_phdr *phdr, - ascend_pkthdr *hdr, int len) + ascend_pkthdr *hdr, long *start_of_data) { /* yydebug = 1; */ - + int retval; ascend_init_lexer(fh); pkt_data = pd; pseudo_header = phdr; header = hdr; - bcount = len; - + fh_ptr = &fh; + + bcur = 0; + first_hexbyte = 0; + wirelen = 0; + caplen = 0; + /* * Not all packets in a "wdd" dump necessarily have a "Cause an * attempt to place call to" header (I presume this can happen if @@ -402,9 +474,39 @@ parse_ascend(FILE_T fh, guint8 *pd, struct ascend_phdr *phdr, */ pseudo_header->call_num[0] = '\0'; - if (yyparse()) - return 0; + retval = yyparse(); + + caplen = bcur; + + /* did we see any data (hex bytes)? if so, tip off ascend_seek() + as to where to look for the next packet, if any. If we didn't, + maybe this record was broken. Advance so we don't get into + an infinite loop reading a broken trace. */ + if (first_hexbyte) + *start_of_data = first_hexbyte; else + *start_of_data++; + + /* if we got at least some data, return success even if the parser + reported an error. This is because the debug header gives the number + of bytes on the wire, not actually how many bytes are in the trace. + We won't know where the data ends until we run into the next packet. */ + if (caplen) { + if (header) { + header->start_time = start_time; + header->secs = secs; + header->usecs = usecs; + header->caplen = caplen; + header->len = wirelen; + } + + return 1; + } + + /* Didn't see any data. Still, perhaps the parser was happy. */ + if (retval) + return 0; + else return 1; } diff --git a/wiretap/ascend-int.h b/wiretap/ascend-int.h index 137984cf5f..f46825db7d 100644 --- a/wiretap/ascend-int.h +++ b/wiretap/ascend-int.h @@ -49,6 +49,6 @@ int ascendlex(void); void init_parse_ascend(void); void ascend_init_lexer(FILE_T fh); int parse_ascend(FILE_T fh, guint8 *pd, struct ascend_phdr *phdr, - ascend_pkthdr *hdr, int len); + ascend_pkthdr *hdr, long *start_of_data); #endif /* ! __ASCEND_INT_H__ */ diff --git a/wiretap/ascend-scanner.l b/wiretap/ascend-scanner.l index 0f3658f6b8..655db6254e 100644 --- a/wiretap/ascend-scanner.l +++ b/wiretap/ascend-scanner.l @@ -56,17 +56,22 @@ int mul, scratch; #define YY_NO_UNISTD_H #endif + %} -/* %option debug */ %option nostdinit %option noyywrap D [0-9] H [A-Fa-f0-9] -XPFX XMIT- -RPFX RECV- +PPP_XPFX PPP-IN +PPP_RPFX PPP-OUT +ISDN_XPFX PRI-XMIT- +ISDN_RPFX PRI-RCV- +WAN_XPFX XMIT[\-:]* +WAN_RPFX RECV[\-:]* +ETHER_PFX ETHER WDD_DATE "Date:" WDD_TIME "Time:" @@ -100,20 +105,63 @@ WDD_TYPE "type "[^\n\r\t ]+ %s sc_chardisp +%s sc_isdn_call +%s sc_ether_direction + %% -<INITIAL,sc_gen_byte>{XPFX} { +<INITIAL,sc_gen_byte>{ETHER_PFX} { + BEGIN(sc_ether_direction); + ascendlval.d = ASCEND_PFX_ETHER; + return ETHER_PREFIX; +} + +<INITIAL,sc_gen_byte>{ISDN_XPFX} { + BEGIN(sc_isdn_call); + ascendlval.d = ASCEND_PFX_ISDN_X; + return ISDN_PREFIX; +} + +<INITIAL,sc_gen_byte>{ISDN_RPFX} { + BEGIN(sc_isdn_call); + ascendlval.d = ASCEND_PFX_ISDN_R; + return ISDN_PREFIX; +} + +<INITIAL,sc_gen_byte>{WAN_XPFX} { BEGIN(sc_wds_user); ascendlval.d = ASCEND_PFX_WDS_X; return WDS_PREFIX; } -<INITIAL,sc_gen_byte>{RPFX} { +<INITIAL,sc_gen_byte>{WAN_RPFX} { BEGIN(sc_wds_user); ascendlval.d = ASCEND_PFX_WDS_R; return WDS_PREFIX; } +<INITIAL,sc_gen_byte>{PPP_XPFX} { + BEGIN(sc_wds_user); + ascendlval.d = ASCEND_PFX_WDS_X; + return WDS_PREFIX; +} + +<INITIAL,sc_gen_byte>{PPP_RPFX} { + BEGIN(sc_wds_user); + ascendlval.d = ASCEND_PFX_WDS_R; + return WDS_PREFIX; +} + +<sc_ether_direction>[^\(]+ { + BEGIN(sc_gen_task); + return STRING; +} + +<sc_isdn_call>[^\/\(:]+ { + BEGIN(sc_gen_task); + return DECNUM; +} + <sc_wds_user>[^:]+ { char *atcopy = strdup(ascendtext); char colon = input(); @@ -163,14 +211,13 @@ WDD_TYPE "type "[^\n\r\t ]+ } <sc_gen_time_u>{D}+ { + char *atcopy = strdup(ascendtext); BEGIN(sc_gen_octets); - /* We have the fractional portion of the time. We want it converted - to microseconds. */ - mul = 1000000; - ascendlval.d = strtol(ascendtext, NULL, 10); - for (scratch = ascendlval.d; scratch > 0; scratch /= 10) - mul /= 10; - ascendlval.d *= mul; + /* only want the most significant 2 digits. convert to usecs */ + if (strlen(atcopy) > 2) + atcopy[2] = '\0'; + ascendlval.d = strtol(atcopy, NULL, 10) * 10000; + free(atcopy); return DECNUM; } @@ -274,6 +321,10 @@ WDD_TYPE "type "[^\n\r\t ]+ return KEYWORD; } +<sc_gen_task>\/{D}+ { + return SLASH_SUFFIX; +} + (0x|0X)?{H}+ { return HEXNUM; } task:|task|at|time:|octets { return KEYWORD; } diff --git a/wiretap/ascend.c b/wiretap/ascend.c index b145afb6e4..95ad5cd3c9 100644 --- a/wiretap/ascend.c +++ b/wiretap/ascend.c @@ -42,64 +42,47 @@ #include <ctype.h> #include <string.h> -/* This module reads the output of the 'wandsession', 'wannext', - 'wandisplay', and similar commands available on Lucent/Ascend access - equipment. The output is text, with a header line followed by the - packet data. Usage instructions for the commands can be found by - searching http://aos.ascend.com . Ascend likes to move their pages - around quite a bit, otherwise I'd put a more specific URL here. - - Example 'wandsess' output data: - -RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 - [0000]: FF 03 00 3D C0 06 CA 22 2F 45 00 00 28 6A 3B 40 - [0010]: 00 3F 03 D7 37 CE 41 62 12 CF 00 FB 08 20 27 00 - [0020]: 50 E4 08 DD D7 7C 4C 71 92 50 10 7D 78 67 C8 00 - [0030]: 00 -XMIT-iguana:241:(task: B04E12C0, time: 1975432.85) 53 octets @ 8009EB16 - [0000]: FF 03 00 3D C0 09 1E 31 21 45 00 00 2C 2D BD 40 - [0010]: 00 7A 06 D8 B1 CF 00 FB 08 CE 41 62 12 00 50 20 - [0020]: 29 7C 4C 71 9C 9A 6A 93 A4 60 12 22 38 3F 10 00 - [0030]: 00 02 04 05 B4 - - Example 'wdd' output data: - -Date: 01/12/1990. Time: 12:22:33 -Cause an attempt to place call to 14082750382 -WD_DIALOUT_DISP: chunk 2515EE type IP. -(task: 251790, time: 994953.28) 44 octets @ 2782B8 - [0000]: 00 C0 7B 71 45 6C 00 60 08 16 AA 51 08 00 45 00 - [0010]: 00 2C 66 1C 40 00 80 06 53 F6 AC 14 00 18 CC 47 - [0020]: C8 45 0A 31 00 50 3B D9 5B 75 00 00 - - (note that the capture whence this came dates back to January - *1999*; I presume that either the person who sent it to me - hadn't bothered keeping its internal clock set, or that its - internal clock or the date it displays in those messages - is only loosely connected to reality) - - Note that a maximum of eight rows will be displayed (for a maximum of - 128 bytes), no matter what the octet count is. - - When reading a packet, the module prepends an ascend_pkt_hdr to the - data. +/* Last updated: Feb 03 2005: Josh Bailey (joshbailey@lucent.com). - */ + This module reads the text hex dump output of various TAOS + (Lucent/Ascend Max, Max TNT, APX, etc) debug commands, including: + + * pridisplay traces primary rate ISDN + * ether-display traces Ethernet packets (dangerous! CPU intensive) + * wanopening, wandisplay, wannext, wandsess + traces PPP or other WAN connections + + Please see ascend-grammar.y for examples. + + Detailed documentation on TAOS products is at http://support.lucent.com. + + Support for other commands will be added on an ongoing basis. */ /* How far into the file we should look for packet headers */ #define ASCEND_MAX_SEEK 100000 -/* XXX Should we replace this with a more generalized array? */ -/* Magic numbers for Ascend wandsession/wanopening/ether-display data */ -static const char ascend_xmagic[] = { 'X', 'M', 'I', 'T', '-' }; -static const char ascend_rmagic[] = { 'R', 'E', 'C', 'V', '-' }; -static const char ascend_w1magic[] = { 'D', 'a', 't', 'e', ':', }; -static const char ascend_w2magic[] = { 'W', 'D', '_', 'D', 'I', 'A', 'L', 'O', 'U', 'T', '_', 'D', 'I', 'S', 'P', ':' }; - -#define ASCEND_X_SIZE (sizeof ascend_xmagic / sizeof ascend_xmagic[0]) -#define ASCEND_R_SIZE (sizeof ascend_rmagic / sizeof ascend_rmagic[0]) -#define ASCEND_W1_SIZE (sizeof ascend_w1magic / sizeof ascend_w1magic[0]) -#define ASCEND_W2_SIZE (sizeof ascend_w2magic / sizeof ascend_w2magic[0]) +typedef struct _ascend_magic_string { + guint type; + gchar *strptr; +} ascend_magic_string; + +#define ASCEND_MAGIC_STRINGS 11 +#define ASCEND_DATE "Date:" + +/* these magic strings signify the headers of a supported debug commands */ +static const ascend_magic_string ascend_magic[] = { + { ASCEND_PFX_ISDN_X, "PRI-XMIT-" }, + { ASCEND_PFX_ISDN_R, "PRI-RCV-" }, + { ASCEND_PFX_WDS_X, "XMIT-" }, + { ASCEND_PFX_WDS_R, "RECV-" }, + { ASCEND_PFX_WDS_X, "XMIT:" }, + { ASCEND_PFX_WDS_R, "RECV:" }, + { ASCEND_PFX_WDS_X, "PPP-OUT" }, + { ASCEND_PFX_WDS_R, "PPP-IN" }, + { ASCEND_PFX_WDD, ASCEND_DATE }, + { ASCEND_PFX_WDD, "WD_DIALOUT_DISP:" }, + { ASCEND_PFX_ETHER, "ETHER" }, +}; static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, long *data_offset); @@ -109,102 +92,58 @@ static gboolean ascend_seek_read(wtap *wth, long seek_off, static void ascend_close(wtap *wth); /* Seeks to the beginning of the next packet, and returns the - byte offset at which the heade for that packet begins. - Returns -1 on failure. - - If it finds a packet, then, if "wth->capture.ascend" is non-null, - it sets "wth->capture.ascend->next_packet_seek_start" to the point - at which the seek pointer should be set before this routine is called - to find the packet *after* the packet it finds. */ + byte offset at which the header for that packet begins. + Returns -1 on failure. */ static long ascend_seek(wtap *wth, int max_seek, int *err) { int byte, bytes_read = 0; long date_off = -1, cur_off, packet_off; - unsigned int r_level = 0, x_level = 0, w1_level = 0, w2_level = 0; + guint string_level[ASCEND_MAGIC_STRINGS]; + guint string_i = 0, type = 0; - while (((byte = file_getc(wth->fh)) != EOF) && bytes_read < max_seek) { - if (byte == ascend_xmagic[x_level]) { - x_level++; - if (x_level >= ASCEND_X_SIZE) { - /* At what offset are we now? */ - cur_off = file_tell(wth->fh); - if (cur_off == -1) { - /* Error. */ - *err = file_error(wth->fh); - return -1; - } + memset(&string_level, 0, sizeof(string_level)); - /* Back up over the header we just read; that's where a read - of this packet should start. */ - packet_off = cur_off - ASCEND_X_SIZE; - goto found; - } - } else { - x_level = 0; - } - if (byte == ascend_rmagic[r_level]) { - r_level++; - if (r_level >= ASCEND_R_SIZE) { - /* At what offset are we now? */ - cur_off = file_tell(wth->fh); - if (cur_off == -1) { - /* Error. */ - *err = file_error(wth->fh); - return -1; - } - - /* Back up over the header we just read; that's where a read - of this packet should start. */ - packet_off = cur_off - ASCEND_R_SIZE; - goto found; - } - } else { - r_level = 0; - } - if (byte == ascend_w1magic[w1_level]) { - w1_level++; - if (w1_level >= ASCEND_W1_SIZE) { - /* Get the offset at which the "Date:" header started. */ - cur_off = file_tell(wth->fh); - if (cur_off == -1) { - /* Error. */ - *err = file_error(wth->fh); - return -1; - } - - date_off = cur_off - ASCEND_W1_SIZE; - } - } else { - w1_level = 0; - } - if (byte == ascend_w2magic[w2_level]) { - w2_level++; - if (w2_level >= ASCEND_W2_SIZE) { - /* At what offset are we now? */ - cur_off = file_tell(wth->fh); - if (cur_off == -1) { - /* Error. */ - *err = file_error(wth->fh); - return -1; - } + while (((byte = file_getc(wth->fh)) != EOF) && bytes_read < max_seek) { - if (date_off != -1) { - /* This packet has a date/time header; a read of it should - start at the beginning of *that* header. */ - packet_off = date_off; - } else { - /* This packet has only a per-packet header. - Back up over that header, which we just read; that's where - a read of this packet should start. */ - packet_off = cur_off - ASCEND_W2_SIZE; + for (string_i = 0; string_i < ASCEND_MAGIC_STRINGS; string_i++) { + gchar *strptr = ascend_magic[string_i].strptr; + guint len = strlen(strptr); + + if (byte == *(strptr + string_level[string_i])) { + string_level[string_i]++; + if (string_level[string_i] >= len) { + cur_off = file_tell(wth->fh); + if (cur_off == -1) { + /* Error. */ + *err = file_error(wth->fh); + return -1; + } + + /* Date: header is a special case. Remember the offset, + but keep looking for other headers. */ + if (strcmp(strptr, ASCEND_DATE) == 0) { + date_off = cur_off - len; + } else { + if (date_off == -1) { + /* Back up over the header we just read; that's where a read + of this packet should start. */ + packet_off = cur_off - len; + } else { + /* This packet has a date/time header; a read of it should + start at the beginning of *that* header. */ + packet_off = date_off; + } + + type = ascend_magic[string_i].type; + goto found; + } } - goto found; + } else { + string_level[string_i] = 0; } - } else { - w2_level = 0; } - bytes_read++; } + if (byte != EOF || file_eof(wth->fh)) { /* Either we didn't find the offset, or we got an EOF. */ *err = 0; @@ -217,20 +156,14 @@ static long ascend_seek(wtap *wth, int max_seek, int *err) found: /* - * The search for the packet after this one should start right - * after the header for this packet. (Ideally, it should - * start after the *data* for this one, but we haven't - * read that yet.) - */ - if (wth->capture.ascend != NULL) - wth->capture.ascend->next_packet_seek_start = cur_off + 1; - - /* * Move to where the read for this packet should start, and return * that seek offset. */ if (file_seek(wth->fh, packet_off, SEEK_SET, err) == -1) return -1; + + wth->pseudo_header.ascend.type = type; + return packet_off; } @@ -253,8 +186,22 @@ int ascend_open(wtap *wth, int *err, gchar **err_info _U_) } wth->data_offset = offset; - wth->file_encap = WTAP_ENCAP_ASCEND; wth->file_type = WTAP_FILE_ASCEND; + + switch(wth->pseudo_header.ascend.type) { + case ASCEND_PFX_ISDN_X: + case ASCEND_PFX_ISDN_R: + wth->file_encap = WTAP_ENCAP_ISDN; + break; + + case ASCEND_PFX_ETHER: + wth->file_encap = WTAP_ENCAP_ETHERNET; + break; + + default: + wth->file_encap = WTAP_ENCAP_ASCEND; + } + wth->snapshot_length = ASCEND_MAX_PKT_LEN; wth->subtype_read = ascend_read; wth->subtype_seek_read = ascend_seek_read; @@ -284,6 +231,25 @@ int ascend_open(wtap *wth, int *err, gchar **err_info _U_) return 1; } +static void config_pseudo_header(union wtap_pseudo_header *pseudo_head) +{ + switch(pseudo_head->ascend.type) { + case ASCEND_PFX_ISDN_X: + pseudo_head->isdn.uton = TRUE; + pseudo_head->isdn.channel = 0; + break; + + case ASCEND_PFX_ISDN_R: + pseudo_head->isdn.uton = FALSE; + pseudo_head->isdn.channel = 0; + break; + + case ASCEND_PFX_ETHER: + pseudo_head->eth.fcs_len = 0; + break; + } +} + /* Read the next packet; called from wtap_loop(). */ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, long *data_offset) @@ -292,17 +258,18 @@ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, guint8 *buf = buffer_start_ptr(wth->frame_buffer); ascend_pkthdr header; - /* (f)lex reads large chunks of the file into memory, so file_tell() doesn't - give us the correct location of the packet. Instead, we seek to the - offset after the header of the previous packet and try to find the next - packet. */ + /* parse_ascend() will advance the point at which to look for the next + packet's header, to just after the last packet's header (ie. at the + start of the last packet's data). We have to get past the last + packet's header because we might mistake part of it for a new header. */ if (file_seek(wth->fh, wth->capture.ascend->next_packet_seek_start, SEEK_SET, err) == -1) return FALSE; - offset = ascend_seek(wth, ASCEND_MAX_SEEK, err); - if (offset == -1) - return FALSE; - if (! parse_ascend(wth->fh, buf, &wth->pseudo_header.ascend, &header, 0)) { + + offset = ascend_seek(wth, ASCEND_MAX_SEEK, err); + if (offset == -1) + return FALSE; + if (! parse_ascend(wth->fh, buf, &wth->pseudo_header.ascend, &header, &(wth->capture.ascend->next_packet_seek_start))) { *err = WTAP_ERR_BAD_RECORD; *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error"); return FALSE; @@ -310,6 +277,8 @@ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, buffer_assure_space(wth->frame_buffer, wth->snapshot_length); + config_pseudo_header(&wth->pseudo_header); + if (! wth->capture.ascend->adjusted) { wth->capture.ascend->adjusted = 1; if (header.start_time != 0) { @@ -343,13 +312,18 @@ static gboolean ascend_seek_read(wtap *wth, long seek_off, union wtap_pseudo_header *pseudo_head, guint8 *pd, int len, int *err, gchar **err_info) { + /* don't care for length. */ + (void) len; + if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) return FALSE; - if (! parse_ascend(wth->random_fh, pd, &pseudo_head->ascend, NULL, len)) { + if (! parse_ascend(wth->random_fh, pd, &pseudo_head->ascend, NULL, &(wth->capture.ascend->next_packet_seek_start))) { *err = WTAP_ERR_BAD_RECORD; *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error"); return FALSE; } + + config_pseudo_header(pseudo_head); return TRUE; } diff --git a/wiretap/wtap.h b/wiretap/wtap.h index bda40aa2ea..05b4a36ed7 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -342,6 +342,9 @@ struct atm_phdr { #define ASCEND_PFX_WDS_X 1 #define ASCEND_PFX_WDS_R 2 #define ASCEND_PFX_WDD 3 +#define ASCEND_PFX_ISDN_X 4 +#define ASCEND_PFX_ISDN_R 5 +#define ASCEND_PFX_ETHER 6 struct ascend_phdr { guint16 type; /* ASCEND_PFX_*, as defined above */ |