diff options
Diffstat (limited to 'wiretap/ascendtext.c')
-rw-r--r-- | wiretap/ascendtext.c | 133 |
1 files changed, 121 insertions, 12 deletions
diff --git a/wiretap/ascendtext.c b/wiretap/ascendtext.c index 7697c45e40..7259fa94bf 100644 --- a/wiretap/ascendtext.c +++ b/wiretap/ascendtext.c @@ -220,6 +220,8 @@ found: wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info) { gint64 offset; + guint8 buf[ASCEND_MAX_PKT_LEN]; + ascend_state_t parser_state; ws_statb64 statbuf; ascend_t *ascend; @@ -236,8 +238,19 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info) } /* Do a trial parse of the first packet just found to see if we might really have an Ascend file */ - init_parse_ascend(); - if (!check_ascend(wth->fh, &wth->phdr)) { + if (run_ascend_parser(wth->fh, &wth->phdr, buf, &parser_state, err, err_info) != 0) { + if (*err != 0) { + /* An I/O error. */ + return WTAP_OPEN_ERROR; + } + } + + /* if we got at least some data, and didn't get an I/O error, 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 (parser_state.caplen == 0) { return WTAP_OPEN_NOT_MINE; } @@ -280,11 +293,113 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info) ascend->adjusted = FALSE; wth->file_tsprec = WTAP_TSPREC_USEC; - init_parse_ascend(); - return WTAP_OPEN_MINE; } +typedef enum { + PARSED_RECORD, + PARSED_NONRECORD, + PARSE_FAILED +} parse_t; + +/* Parse the capture file. + Returns: + PARSED_RECORD if we got a packet + PARSED_NONRECORD if the parser succeeded but didn't see a packet + PARSE_FAILED if the parser failed. */ +static parse_t +parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, + guint length, int *err, gchar **err_info) +{ + ascend_state_t parser_state; + int retval; + + ws_buffer_assure_space(buf, length); + retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf), &parser_state, + err, err_info); + + /* 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 (parser_state.first_hexbyte) { + ascend->next_packet_seek_start = parser_state.first_hexbyte; + } else { + /* Sometimes, a header will be printed but the data will be omitted, or + worse -- two headers will be printed, followed by the data for each. + Because of this, we need to be fairly tolerant of what we accept + here. If we didn't find any hex bytes, skip over what we've read so + far so we can try reading a new packet. */ + ascend->next_packet_seek_start = file_tell(fh); + retval = 0; + } + + /* 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 (parser_state.caplen) { + if (! ascend->adjusted) { + ascend->adjusted = TRUE; + if (parser_state.saw_timestamp) { + /* + * Capture file contained a date and time. + * We do this only if this is the very first packet we've seen - + * i.e., if "ascend->adjusted" is false - because + * if we get a date and time after the first packet, we can't + * go back and adjust the time stamps of the packets we've already + * processed, and basing the time stamps of this and following + * packets on the time stamp from the file text rather than the + * ctime of the capture file means times before this and after + * this can't be compared. + */ + ascend->inittime = parser_state.timestamp; + } + if (ascend->inittime > parser_state.secs) + ascend->inittime -= parser_state.secs; + } + phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; + phdr->ts.secs = parser_state.secs + ascend->inittime; + phdr->ts.nsecs = parser_state.usecs * 1000; + phdr->caplen = parser_state.caplen; + phdr->len = parser_state.wirelen; + + /* + * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND, + * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN + * or WTAP_ENCAP_ETHERNET). + */ + switch(phdr->pseudo_header.ascend.type) { + case ASCEND_PFX_ISDN_X: + phdr->pseudo_header.isdn.uton = TRUE; + phdr->pseudo_header.isdn.channel = 0; + break; + + case ASCEND_PFX_ISDN_R: + phdr->pseudo_header.isdn.uton = FALSE; + phdr->pseudo_header.isdn.channel = 0; + break; + + case ASCEND_PFX_ETHER: + phdr->pseudo_header.eth.fcs_len = 0; + break; + } + return PARSED_RECORD; + } + + /* Didn't see any data. Still, perhaps the parser was happy. */ + if (retval) { + if (*err == 0) { + /* Not a bad record, so a parse error. Return WTAP_ERR_BAD_FILE, + with the parse error as the error string. */ + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup((parser_state.ascend_parse_error != NULL) ? parser_state.ascend_parse_error : "parse error"); + } + return PARSE_FAILED; + } else + return PARSED_NONRECORD; +} + /* Read the next packet; called from wtap_read(). */ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) @@ -304,11 +419,8 @@ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info, if (offset == -1) return FALSE; if (parse_ascend(ascend, wth->fh, &wth->phdr, wth->frame_buffer, - wth->snapshot_length) != PARSED_RECORD) { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error"); + wth->snapshot_length, err, err_info) != PARSED_RECORD) return FALSE; - } *data_offset = offset; return TRUE; @@ -323,11 +435,8 @@ static gboolean ascend_seek_read(wtap *wth, gint64 seek_off, if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) return FALSE; if (parse_ascend(ascend, wth->random_fh, phdr, buf, - wth->snapshot_length) != PARSED_RECORD) { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error"); + wth->snapshot_length, err, err_info) != PARSED_RECORD) return FALSE; - } return TRUE; } |