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:
parent
17608107ff
commit
9e93bf4747
1
AUTHORS
1
AUTHORS
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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; }
|
||||
|
|
274
wiretap/ascend.c
274
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.
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue