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
This commit is contained in:
Gerald Combs 2005-02-05 17:39:12 +00:00
parent 17608107ff
commit 9e93bf4747
6 changed files with 357 additions and 226 deletions

View File

@ -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> {

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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; }

View File

@ -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.
/* Last updated: Feb 03 2005: Josh Bailey (joshbailey@lucent.com).
Example 'wandsess' output data:
This module reads the text hex dump output of various TAOS
(Lucent/Ascend Max, Max TNT, APX, etc) debug commands, including:
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
* pridisplay traces primary rate ISDN
* ether-display traces Ethernet packets (dangerous! CPU intensive)
* wanopening, wandisplay, wannext, wandsess
traces PPP or other WAN connections
Example 'wdd' output data:
Please see ascend-grammar.y for examples.
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
Detailed documentation on TAOS products is at http://support.lucent.com.
(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.
*/
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', ':' };
typedef struct _ascend_magic_string {
guint type;
gchar *strptr;
} ascend_magic_string;
#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])
#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;
memset(&string_level, 0, sizeof(string_level));
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;
}
/* 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;
}
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;
}
/* 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: 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;
}
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;
type = ascend_magic[string_i].type;
goto found;
}
}
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;
}
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;
@ -216,21 +155,15 @@ static long ascend_seek(wtap *wth, int max_seek, int *err)
return -1;
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;
}

View File

@ -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 */