X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=wiretap%2Ferf.c;h=6d9a549cd21a94674ad5237123e6f9b6fb5cc440;hb=fae5a6096a7321126ad660acb2e4ec1b5b87f765;hp=ae5fcc237cf911f442ea8612e78df78bb2b6658e;hpb=61860a9b8cc4d40f74ca15749f5a7b8700c8f755;p=obnox%2Fwireshark%2Fwip.git diff --git a/wiretap/erf.c b/wiretap/erf.c index ae5fcc237c..6d9a549cd2 100644 --- a/wiretap/erf.c +++ b/wiretap/erf.c @@ -1,41 +1,41 @@ /* -* -* Copyright (c) 2003 Endace Technology Ltd, Hamilton, New Zealand. -* All rights reserved. -* -* This software and documentation has been developed by Endace Technology Ltd. -* along with the DAG PCI network capture cards. For further information please -* visit http://www.endace.com/. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* -* 3. The name of Endace Technology Ltd may not be used to endorse or promote -* products derived from this software without specific prior written -* permission. -* -* THIS SOFTWARE IS PROVIDED BY ENDACE TECHNOLOGY LTD ``AS IS'' AND ANY EXPRESS -* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -* EVENT SHALL ENDACE TECHNOLOGY LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -* $Id$ -*/ - -/* + * + * Copyright (c) 2003 Endace Technology Ltd, Hamilton, New Zealand. + * All rights reserved. + * + * This software and documentation has been developed by Endace Technology Ltd. + * along with the DAG PCI network capture cards. For further information please + * visit http://www.endace.com/. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of Endace Technology Ltd may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ENDACE TECHNOLOGY LTD ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ENDACE TECHNOLOGY LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + */ + +/* * erf - Endace ERF (Extensible Record Format) * * See @@ -56,397 +56,393 @@ #include "atm.h" #include "erf.h" -typedef guint32 atm_hdr_t; - -static int erf_read_header( - FILE_T fh, - struct wtap_pkthdr *phdr, - union wtap_pseudo_header *pseudo_header, - erf_header_t *erf_header, - erf_t *erf, - int *err, - gchar **err_info, - guint32 *bytes_read, - guint32 *packet_size); -static gboolean erf_read(wtap *wth, int *err, gchar **err_info, - long *data_offset); -static gboolean erf_seek_read(wtap *wth, long seek_off, - union wtap_pseudo_header *pseudo_header, guchar *pd, - int length, int *err, gchar **err_info); -static void erf_close(wtap *wth); -static int erf_encap_to_wtap_encap(erf_t *erf, guint8 erf_encap); -static void erf_set_pseudo_header( - guint8 type, - erf_t *erf, - guchar *pd, - int length, - union wtap_pseudo_header *pseudo_header); - -int erf_open(wtap *wth, int *err, gchar **err_info _U_) -{ - guint32 i, n; - char *s; - guint32 records_for_erf_check = RECORDS_FOR_ERF_CHECK; - guint32 atm_encap = WTAP_ENCAP_ATM_PDUS; - gboolean is_rawatm = FALSE; - gboolean is_ppp = FALSE; - int common_type = 0; - erf_timestamp_t prevts; - - memset(&prevts, 0, sizeof(prevts)); - - if ((s = getenv("ERF_ATM_ENCAP")) != NULL) { - if (!strcmp(s, "sunatm")) { - atm_encap = WTAP_ENCAP_ATM_PDUS; - } else - if (!strcmp(s, "sunraw")) { - atm_encap = WTAP_ENCAP_ATM_PDUS; - is_rawatm = TRUE; - } else - if (!strcmp(s, "rfc1483")) { - atm_encap = WTAP_ENCAP_ATM_RFC1483; - } - } - - /* number of records to scan before deciding if this really is ERF (dflt=3) */ - if ((s = getenv("ERF_RECORDS_TO_CHECK")) != NULL) { - if ((n = atoi(s)) > 0 && n < 101) { - records_for_erf_check = n; - } - } - - /* ERF is a little hard because there's no magic number */ - - for (i = 0; i < records_for_erf_check; i++) { - - erf_header_t header; - guint32 packet_size; - erf_timestamp_t ts; - - if (file_read(&header,1,sizeof(header),wth->fh) != sizeof(header)) { - if ((*err = file_error(wth->fh)) != 0) - return -1; - else - return 0; - } - - packet_size = g_ntohs(header.rlen) - sizeof(header); - - /* fail on invalid record type, decreasing timestamps or non-zero pad-bits */ - if (header.type == 0 || header.type > TYPE_AAL5 || - (header.flags & 0xc0) != 0) { - return 0; - } - - if ((ts = pletohll(&header.ts)) < prevts) { - /* reassembled AAL5 records may not be in time order, so allow 1 sec fudge */ - if (header.type != TYPE_AAL5 || ((prevts-ts)>>32) > 1) { - return 0; - } - } - memcpy(&prevts, &ts, sizeof(prevts)); - - if (common_type == 0) { - common_type = header.type; - } else - if (common_type > 0 && common_type != header.type) { - common_type = -1; - } - - if (header.type == TYPE_HDLC_POS && !is_ppp) { - guint16 chdlc_hdr; - if (file_read(&chdlc_hdr,1,sizeof(chdlc_hdr),wth->fh) != sizeof(chdlc_hdr)) { - *err = file_error(wth->fh); - } - packet_size -= sizeof(chdlc_hdr); - if (g_ntohs(chdlc_hdr) == 0xff03) { - is_ppp = TRUE; - } - } - - if (file_seek(wth->fh, packet_size, SEEK_CUR, err) == -1) { - return -1; - } - } - - if (file_seek(wth->fh, 0L, SEEK_SET, err) == -1) { /* rewind */ - return -1; - } +#ifndef min +#define min(a, b) ((a) > (b) ? (b) : (a)) +#endif - wth->data_offset = 0; +static int erf_read_header(FILE_T fh, + struct wtap_pkthdr *phdr, + union wtap_pseudo_header *pseudo_header, + erf_header_t *erf_header, + int *err, + gchar **err_info, + guint32 *bytes_read, + guint32 *packet_size); +static gboolean erf_read(wtap *wth, int *err, gchar **err_info, + gint64 *data_offset); +static gboolean erf_seek_read(wtap *wth, gint64 seek_off, + union wtap_pseudo_header *pseudo_header, guchar *pd, + int length, int *err, gchar **err_info); - /* This is an ERF file */ - wth->file_type = WTAP_FILE_ERF; - wth->snapshot_length = 0; /* not available in header, only in frame */ - wth->capture.erf = g_malloc(sizeof(erf_t)); - wth->capture.erf->is_ppp = is_ppp; - if (common_type == TYPE_AAL5) { - wth->capture.erf->atm_encap = WTAP_ENCAP_ATM_PDUS_UNTRUNCATED; - wth->capture.erf->is_rawatm = FALSE; +extern int erf_open(wtap *wth, int *err, gchar **err_info _U_) +{ + int i, n, records_for_erf_check = RECORDS_FOR_ERF_CHECK; + char *s; + erf_timestamp_t prevts,ts; + erf_header_t header; + guint32 mc_hdr; + guint16 eth_hdr; + guint32 packet_size; + guint16 rlen,wlen; + guint64 erf_ext_header; + guint8 type; + size_t r; + gchar * buffer; + + memset(&prevts, 0, sizeof(prevts)); + + /* number of records to scan before deciding if this really is ERF */ + if ((s = getenv("ERF_RECORDS_TO_CHECK")) != NULL) { + if ((n = atoi(s)) > 0 && n < 101) { + records_for_erf_check = n; + } + } + + /* + * ERF is a little hard because there's no magic number; we look at + * the first few records and see if they look enough like ERF + * records. + */ + + for (i = 0; i < records_for_erf_check; i++) { /* records_for_erf_check */ + + r = file_read(&header,1,sizeof(header),wth->fh); + + if (r == 0 ) break; + if (r != sizeof(header)) { + if ((*err = file_error(wth->fh)) != 0) { + return -1; + } else { + /* ERF header too short accept the file, + only if the very first records have been successfully checked */ + if (i < MIN_RECORDS_FOR_ERF_CHECK) { + return 0; } else { - wth->capture.erf->atm_encap = atm_encap; - wth->capture.erf->is_rawatm = is_rawatm; + /* BREAK, the last record is too short, and will be ignored */ + break; } - - /* - * Really want WTAP_ENCAP_PER_PACKET here but that severely limits - * the number of output formats we can write to. If all the records - * tested in the loop above were the same encap then use that one, - * otherwise use WTAP_ENCAP_PER_PACKET. - */ - wth->file_encap = - (common_type < 0 - ? WTAP_ENCAP_PER_PACKET - : erf_encap_to_wtap_encap(wth->capture.erf, (guint8) common_type)); - - wth->subtype_read = erf_read; - wth->subtype_seek_read = erf_seek_read; - wth->subtype_close = erf_close; - wth->tsprecision = WTAP_FILE_TSPREC_NSEC; - - return 1; + } + } + + rlen=g_ntohs(header.rlen); + wlen=g_ntohs(header.wlen); + + /* fail on invalid record type, invalid rlen, timestamps decreasing, or incrementing too far */ + + /* Test valid rlen >= 16 */ + if (rlen < 16) { + return 0; + } + + packet_size = rlen - (guint32)sizeof(header); + if (packet_size > WTAP_MAX_PACKET_SIZE) { + /* + * Probably a corrupt capture file or a file that's not an ERF file + * but that passed earlier tests; don't blow up trying + * to allocate space for an immensely-large packet. + */ + return 0; + } + + /* Skip PAD records, timestamps may not be set */ + if ((header.type & 0x7F) == ERF_TYPE_PAD) { + if (file_seek(wth->fh, packet_size, SEEK_CUR, err) == -1) { + return -1; + } + continue; + } + + /* fail on invalid record type, decreasing timestamps or non-zero pad-bits */ + /* Not all types within this range are decoded, but it is a first filter */ + if ((header.type & 0x7F) == 0 || (header.type & 0x7F) > ERF_TYPE_MAX ) { + return 0; + } + + /* The ERF_TYPE_MAX is the PAD record, but the last used type is ERF_TYPE_RAW_LINK */ + if ((header.type & 0x7F) > ERF_TYPE_RAW_LINK) { + return 0; + } + + if ((ts = pletohll(&header.ts)) < prevts) { + /* reassembled AALx records may not be in time order, also records are not in strict time order between physical interfaces, so allow 1 sec fudge */ + if ( ((prevts-ts)>>32) > 1 ) { + return 0; + } + } + + /* Check to see if timestamp increment is > 1 week */ + if ( (i) && (ts > prevts) && (((ts-prevts)>>32) > 3600*24*7) ) { + return 0; + } + + memcpy(&prevts, &ts, sizeof(prevts)); + + /* Read over the extension headers */ + type = header.type; + while (type & 0x80){ + if (file_read(&erf_ext_header, 1, sizeof(erf_ext_header),wth->fh) != sizeof(erf_ext_header)) { + *err = file_error(wth->fh); + return -1; + } + packet_size -= (guint32)sizeof(erf_ext_header); + memcpy(&type, &erf_ext_header, sizeof(type)); + } + + + /* Read over MC or ETH subheader */ + switch(header.type & 0x7F) { + case ERF_TYPE_MC_HDLC: + case ERF_TYPE_MC_RAW: + case ERF_TYPE_MC_ATM: + case ERF_TYPE_MC_RAW_CHANNEL: + case ERF_TYPE_MC_AAL5: + case ERF_TYPE_MC_AAL2: + case ERF_TYPE_COLOR_MC_HDLC_POS: + if (file_read(&mc_hdr,1,sizeof(mc_hdr),wth->fh) != sizeof(mc_hdr)) { + *err = file_error(wth->fh); + return -1; + } + packet_size -= (guint32)sizeof(mc_hdr); + break; + case ERF_TYPE_ETH: + case ERF_TYPE_COLOR_ETH: + case ERF_TYPE_DSM_COLOR_ETH: + if (file_read(ð_hdr,1,sizeof(eth_hdr),wth->fh) != sizeof(eth_hdr)) { + *err = file_error(wth->fh); + return -1; + } + packet_size -= (guint32)sizeof(eth_hdr); + break; + default: + break; + } + + /* The file_seek function do not return an error if the end of file + is reached whereas the record is truncated */ + if (packet_size > WTAP_MAX_PACKET_SIZE) { + /* + * Probably a corrupt capture file; don't blow up trying + * to allocate space for an immensely-large packet. + */ + return 0; + } + buffer=g_malloc(packet_size); + r = file_read(buffer, 1, packet_size, wth->fh); + g_free(buffer); + + if (r != packet_size) { + /* ERF record too short, accept the file, + only if the very first records have been successfully checked */ + if (i < MIN_RECORDS_FOR_ERF_CHECK) { + return 0; + } + + } + } /* records_for_erf_check */ + + if (file_seek(wth->fh, 0L, SEEK_SET, err) == -1) { /* rewind */ + return -1; + } + + wth->data_offset = 0; + + /* This is an ERF file */ + wth->file_type = WTAP_FILE_ERF; + wth->snapshot_length = 0; /* not available in header, only in frame */ + + /* + * Use the encapsulation for ERF records. + */ + wth->file_encap = WTAP_ENCAP_ERF; + + wth->subtype_read = erf_read; + wth->subtype_seek_read = erf_seek_read; + wth->tsprecision = WTAP_FILE_TSPREC_NSEC; + + return 1; } /* Read the next packet */ static gboolean erf_read(wtap *wth, int *err, gchar **err_info, - long *data_offset) -{ - erf_header_t erf_header; - guint32 packet_size, bytes_read; - gint32 offset = 0; - - *data_offset = wth->data_offset; - - if (!erf_read_header( - wth->fh, - &wth->phdr, &wth->pseudo_header, &erf_header, wth->capture.erf, - err, err_info, &bytes_read, &packet_size)) { - return FALSE; - } - wth->data_offset += bytes_read; - - buffer_assure_space(wth->frame_buffer, packet_size+(wth->capture.erf->is_rawatm?(sizeof(atm_hdr_t)+1):0)); - - if (wth->capture.erf->is_rawatm) { - wtap_file_read_expected_bytes( - buffer_start_ptr(wth->frame_buffer), (gint32)sizeof(atm_hdr_t), wth->fh, err - ); - wth->data_offset += sizeof(atm_hdr_t); - packet_size -= sizeof(atm_hdr_t); - offset += sizeof(atm_hdr_t)+1; - } - - wtap_file_read_expected_bytes( - buffer_start_ptr(wth->frame_buffer)+offset, (gint32)packet_size, wth->fh, err - ); - wth->data_offset += packet_size; - - erf_set_pseudo_header( - erf_header.type, wth->capture.erf, - buffer_start_ptr(wth->frame_buffer), packet_size, &wth->pseudo_header - ); - - return TRUE; -} - -static gboolean erf_seek_read(wtap *wth, long seek_off, - union wtap_pseudo_header *pseudo_header, guchar *pd, - int length, int *err, gchar **err_info) + gint64 *data_offset) { - erf_header_t erf_header; - guint32 packet_size; - int offset = 0; - - if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) - return FALSE; + erf_header_t erf_header; + guint32 packet_size, bytes_read; - if (!erf_read_header(wth->random_fh, NULL, pseudo_header, &erf_header, - wth->capture.erf, err, err_info, NULL, &packet_size)) - return FALSE; + *data_offset = wth->data_offset; - if (wth->capture.erf->is_rawatm) { - wtap_file_read_expected_bytes(pd, (int)sizeof(atm_hdr_t), wth->random_fh, err); - packet_size -= sizeof(atm_hdr_t); - offset += sizeof(atm_hdr_t)+1; - } + do { + if (!erf_read_header(wth->fh, + &wth->phdr, &wth->pseudo_header, &erf_header, + err, err_info, &bytes_read, &packet_size)) { + return FALSE; + } + wth->data_offset += bytes_read; + } while ( erf_header.type == ERF_TYPE_PAD ); - wtap_file_read_expected_bytes(pd+offset, (int)packet_size, wth->random_fh, err); + buffer_assure_space(wth->frame_buffer, packet_size); - erf_set_pseudo_header(erf_header.type, wth->capture.erf, pd, length, pseudo_header); + wtap_file_read_expected_bytes(buffer_start_ptr(wth->frame_buffer), + (gint32)(packet_size), wth->fh, err ); + wth->data_offset += packet_size; - return TRUE; + return TRUE; } -static void erf_close(wtap *wth) +static gboolean erf_seek_read(wtap *wth, gint64 seek_off, + union wtap_pseudo_header *pseudo_header, guchar *pd, + int length _U_, int *err, gchar **err_info) { - g_free(wth->capture.erf); -} - -static int erf_read_header( - FILE_T fh, - struct wtap_pkthdr *phdr, - union wtap_pseudo_header *pseudo_header, - erf_header_t *erf_header, - erf_t *erf, - int *err, - gchar **err_info, - guint32 *bytes_read, - guint32 *packet_size) -{ - guint32 rec_size, skip; - - wtap_file_read_expected_bytes(erf_header, sizeof(*erf_header), fh, err); - if (bytes_read != NULL) { - *bytes_read = sizeof(*erf_header); - } - - rec_size = g_ntohs(erf_header->rlen); - *packet_size = rec_size - sizeof(*erf_header); - skip = 0; /* # bytes of payload to ignore */ - - if (*packet_size > WTAP_MAX_PACKET_SIZE) { - /* - * Probably a corrupt capture file; don't blow up trying - * to allocate space for an immensely-large packet. - */ - *err = WTAP_ERR_BAD_RECORD; - *err_info = g_strdup_printf("erf: File has %u-byte packet, bigger than maximum of %u", - *packet_size, WTAP_MAX_PACKET_SIZE); - return FALSE; - } - - if (phdr != NULL) { - guint64 ts = pletohll(&erf_header->ts); - - phdr->ts.secs = (long) (ts >> 32); - ts = ((ts & 0xffffffff) * 1000 * 1000); - ts += (ts & 0x80000000) << 1; /* rounding */ - phdr->ts.nsecs = ((long) (ts >> 32)) * 1000; - if (phdr->ts.nsecs >= 1000000000) { - phdr->ts.nsecs -= 1000000000; - phdr->ts.secs += 1; - } - } - - switch (erf_header->type) { - - case TYPE_ATM: - case TYPE_AAL5: - if (phdr != NULL) { - if (erf_header->type == TYPE_AAL5) { - phdr->caplen = phdr->len = *packet_size - sizeof(atm_hdr_t); - } else { - phdr->caplen = ATM_SLEN(erf_header, NULL); - phdr->len = ATM_WLEN(erf_header, NULL); - } - } - - if (erf->atm_encap == WTAP_ENCAP_ATM_PDUS || erf->atm_encap == WTAP_ENCAP_ATM_PDUS_UNTRUNCATED) { - memset(&pseudo_header->atm, 0, sizeof(pseudo_header->atm)); - if (erf->is_rawatm) { - pseudo_header->atm.flags = ATM_RAW_CELL; - if (phdr != NULL) { - phdr->caplen += sizeof(atm_hdr_t)+1; - phdr->len += sizeof(atm_hdr_t)+1; - } - } else { - atm_hdr_t atm_hdr; - - wtap_file_read_expected_bytes(&atm_hdr, sizeof(atm_hdr), fh, err); - if (bytes_read != NULL) { - *bytes_read += sizeof(atm_hdr); - } - *packet_size -= sizeof(atm_hdr); - - atm_hdr = g_ntohl(atm_hdr); - - pseudo_header->atm.vpi = ((atm_hdr & 0x0ff00000) >> 20); - pseudo_header->atm.vci = ((atm_hdr & 0x000ffff0) >> 4); - pseudo_header->atm.channel = (erf_header->flags & 0x03); - } - } else { - skip = 4; - } - break; - case TYPE_ETH: - if (phdr != NULL) { - phdr->caplen = ETHERNET_SLEN(erf_header, erf); - phdr->len = ETHERNET_WLEN(erf_header, erf); - } - skip = 2; - break; - case TYPE_HDLC_POS: - if (phdr != NULL) { - phdr->caplen = HDLC_SLEN(erf_header, erf); - phdr->len = HDLC_WLEN(erf_header, erf); - } - memset(&pseudo_header->p2p, 0, sizeof(pseudo_header->p2p)); - pseudo_header->p2p.sent = ((erf_header->flags & 0x01) ? TRUE : FALSE); - break; - default: - *err = WTAP_ERR_UNSUPPORTED_ENCAP; - *err_info = g_strdup_printf("erf: unknown record encapsulation %u", - erf_header->type); - return FALSE; - } + erf_header_t erf_header; + guint32 packet_size; - if (phdr != NULL) { - phdr->pkt_encap = erf_encap_to_wtap_encap(erf, erf_header->type); - } + if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) + return FALSE; - if (skip > 0) { - if (file_seek(fh, skip, SEEK_CUR, err) == -1) { - return FALSE; - } - if (bytes_read != NULL) { - *bytes_read += skip; - } - *packet_size -= skip; - } + do { + if (!erf_read_header(wth->random_fh, NULL, pseudo_header, &erf_header, + err, err_info, NULL, &packet_size)) + return FALSE; + } while ( erf_header.type == ERF_TYPE_PAD ); - return TRUE; -} + wtap_file_read_expected_bytes(pd, (int)packet_size, wth->random_fh, err); -static int erf_encap_to_wtap_encap(erf_t *erf, guint8 erf_encap) -{ - int wtap_encap = WTAP_ENCAP_UNKNOWN; - - switch (erf_encap) { - case TYPE_ATM: - case TYPE_AAL5: - wtap_encap = erf->atm_encap; - break; - case TYPE_ETH: - wtap_encap = WTAP_ENCAP_ETHERNET; - break; - case TYPE_HDLC_POS: - wtap_encap = (erf->is_ppp ? WTAP_ENCAP_PPP : WTAP_ENCAP_CHDLC); - break; - default: - break; - } - - return wtap_encap; + return TRUE; } -static void erf_set_pseudo_header( - guint8 type, erf_t *erf, guchar *pd, int length, union wtap_pseudo_header *pseudo_header) +static int erf_read_header(FILE_T fh, + struct wtap_pkthdr *phdr, + union wtap_pseudo_header *pseudo_header, + erf_header_t *erf_header, + int *err, + gchar **err_info, + guint32 *bytes_read, + guint32 *packet_size) { - if (type == TYPE_ETH) { - /* - * We don't know whether there's an FCS in this frame or not. - */ - pseudo_header->eth.fcs_len = -1; - } else - if (!erf->is_rawatm && - (type == TYPE_ATM || type == TYPE_AAL5) && - (erf->atm_encap == WTAP_ENCAP_ATM_PDUS || - erf->atm_encap == WTAP_ENCAP_ATM_PDUS_UNTRUNCATED)) { - atm_guess_traffic_type(pd, length, pseudo_header); - } else - if (type == TYPE_AAL5) { - pseudo_header->atm.aal = AAL_5; - pseudo_header->atm.type = TRAF_UNKNOWN; - pseudo_header->atm.subtype = TRAF_ST_UNKNOWN; - } + guint32 mc_hdr; + guint8 erf_exhdr[8]; + guint64 erf_exhdr_sw; + guint8 type = 0; + guint16 eth_hdr; + guint32 skiplen=0; + int i = 0 , max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr); + + wtap_file_read_expected_bytes(erf_header, sizeof(*erf_header), fh, err); + if (bytes_read != NULL) { + *bytes_read = sizeof(*erf_header); + } + + *packet_size = g_ntohs(erf_header->rlen) - (guint32)sizeof(*erf_header); + + if (*packet_size > WTAP_MAX_PACKET_SIZE) { + /* + * Probably a corrupt capture file; don't blow up trying + * to allocate space for an immensely-large packet. + */ + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("erf: File has %u-byte packet, bigger than maximum of %u", + *packet_size, WTAP_MAX_PACKET_SIZE); + return FALSE; + } + + if (phdr != NULL) { + guint64 ts = pletohll(&erf_header->ts); + + phdr->ts.secs = (long) (ts >> 32); + ts = ((ts & 0xffffffff) * 1000 * 1000 * 1000); + ts += (ts & 0x80000000) << 1; /* rounding */ + phdr->ts.nsecs = ((int) (ts >> 32)); + if (phdr->ts.nsecs >= 1000000000) { + phdr->ts.nsecs -= 1000000000; + phdr->ts.secs += 1; + } + } + + /* Copy the ERF pseudo header */ + pseudo_header->erf.phdr.ts = pletohll(&erf_header->ts); + pseudo_header->erf.phdr.type = erf_header->type; + pseudo_header->erf.phdr.flags = erf_header->flags; + pseudo_header->erf.phdr.rlen = g_ntohs(erf_header->rlen); + pseudo_header->erf.phdr.lctr = g_ntohs(erf_header->lctr); + pseudo_header->erf.phdr.wlen = g_ntohs(erf_header->wlen); + + /* Copy the ERF extension header into the pseudo header */ + type = erf_header->type; + while (type & 0x80){ + wtap_file_read_expected_bytes(&erf_exhdr, sizeof(erf_exhdr), fh, err); + if (bytes_read != NULL) + *bytes_read += (guint32)sizeof(erf_exhdr); + *packet_size -= (guint32)sizeof(erf_exhdr); + skiplen += (guint32)sizeof(erf_exhdr); + erf_exhdr_sw = pntohll((guint64*) &(erf_exhdr[0])); + if (i < max) + memcpy(&pseudo_header->erf.ehdr_list[i].ehdr, &erf_exhdr_sw, sizeof(erf_exhdr_sw)); + type = erf_exhdr[0]; + i++; + } + + switch (erf_header->type & 0x7F) { + case ERF_TYPE_IPV4: + case ERF_TYPE_IPV6: + case ERF_TYPE_RAW_LINK: + case ERF_TYPE_INFINIBAND: + /*** + if (phdr != NULL) { + phdr->len = g_htons(erf_header->wlen); + phdr->caplen = g_htons(erf_header->wlen); + } + return TRUE; + ***/ + break; + case ERF_TYPE_PAD: + case ERF_TYPE_HDLC_POS: + case ERF_TYPE_COLOR_HDLC_POS: + case ERF_TYPE_DSM_COLOR_HDLC_POS: + case ERF_TYPE_ATM: + case ERF_TYPE_AAL5: + case ERF_TYPE_AAL2: + break; + + case ERF_TYPE_ETH: + case ERF_TYPE_COLOR_ETH: + case ERF_TYPE_DSM_COLOR_ETH: + wtap_file_read_expected_bytes(ð_hdr, sizeof(eth_hdr), fh, err); + if (bytes_read != NULL) + *bytes_read += (guint32)sizeof(eth_hdr); + *packet_size -= (guint32)sizeof(eth_hdr); + skiplen += (guint32)sizeof(eth_hdr); + pseudo_header->erf.subhdr.eth_hdr = g_htons(eth_hdr); + break; + + case ERF_TYPE_MC_HDLC: + case ERF_TYPE_MC_RAW: + case ERF_TYPE_MC_ATM: + case ERF_TYPE_MC_RAW_CHANNEL: + case ERF_TYPE_MC_AAL5: + case ERF_TYPE_MC_AAL2: + case ERF_TYPE_COLOR_MC_HDLC_POS: + wtap_file_read_expected_bytes(&mc_hdr, sizeof(mc_hdr), fh, err); + if (bytes_read != NULL) + *bytes_read += (guint32)sizeof(mc_hdr); + *packet_size -= (guint32)sizeof(mc_hdr); + skiplen += (guint32)sizeof(mc_hdr); + pseudo_header->erf.subhdr.mc_hdr = g_htonl(mc_hdr); + break; + + case ERF_TYPE_IP_COUNTER: + case ERF_TYPE_TCP_FLOW_COUNTER: + /* unsupported, continue with default: */ + default: + *err = WTAP_ERR_UNSUPPORTED_ENCAP; + *err_info = g_strdup_printf("erf: unknown record encapsulation %u", + erf_header->type); + return FALSE; + } + + if (phdr != NULL) { + phdr->len = g_htons(erf_header->wlen); + phdr->caplen = min( g_htons(erf_header->wlen), + g_htons(erf_header->rlen) - (guint32)sizeof(*erf_header) - skiplen ); + } + return TRUE; }