summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wiretap/erf.c212
-rw-r--r--wiretap/erf.h2
-rw-r--r--wiretap/file_access.c2
-rw-r--r--wiretap/wtap.h5
4 files changed, 218 insertions, 3 deletions
diff --git a/wiretap/erf.c b/wiretap/erf.c
index 5d406af476..562bf65b28 100644
--- a/wiretap/erf.c
+++ b/wiretap/erf.c
@@ -50,13 +50,14 @@
#include <stdlib.h>
#include <string.h>
+#include <wsutil/crc32.c>
+
#include "wtap-int.h"
#include "file_wrappers.h"
#include "buffer.h"
#include "atm.h"
#include "erf.h"
-
static int erf_read_header(FILE_T fh,
struct wtap_pkthdr *phdr,
union wtap_pseudo_header *pseudo_header,
@@ -71,6 +72,22 @@ 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);
+static const struct {
+ int erf_encap_value;
+ int wtap_encap_value;
+} erf_to_wtap_map[] = {
+ { ERF_TYPE_HDLC_POS, WTAP_ENCAP_CHDLC },
+ { ERF_TYPE_HDLC_POS, WTAP_ENCAP_HHDLC },
+ { ERF_TYPE_HDLC_POS, WTAP_ENCAP_CHDLC_WITH_PHDR },
+ { ERF_TYPE_HDLC_POS, WTAP_ENCAP_PPP },
+ { ERF_TYPE_HDLC_POS, WTAP_ENCAP_FRELAY },
+ { ERF_TYPE_HDLC_POS, WTAP_ENCAP_MTP2 },
+ { ERF_TYPE_ETH, WTAP_ENCAP_ETHERNET },
+ { 99, WTAP_ENCAP_ERF }, /*this type added so WTAP_ENCAP_ERF will work and then be treated at ERF->ERF*/
+};
+
+#define NUM_ERF_ENCAPS (sizeof erf_to_wtap_map / sizeof erf_to_wtap_map[0])
+
extern int erf_open(wtap *wth, int *err, gchar **err_info)
{
int i, n, records_for_erf_check = RECORDS_FOR_ERF_CHECK;
@@ -454,3 +471,196 @@ static int erf_read_header(FILE_T fh,
}
return TRUE;
}
+
+static int wtap_wtap_encap_to_erf_encap(int encap)
+{
+ unsigned int i;
+ for(i = 0; i < NUM_ERF_ENCAPS; i++){
+ if(erf_to_wtap_map[i].wtap_encap_value == encap)
+ return erf_to_wtap_map[i].erf_encap_value;
+ }
+ return -1;
+}
+
+static gboolean erf_write_phdr(wtap_dumper *wdh, int encap, const union wtap_pseudo_header *pseudo_header, int * err)
+{
+ guint8 erf_hdr[sizeof(struct erf_mc_phdr)];
+ guint8 erf_subhdr[((sizeof(struct erf_mc_hdr) > sizeof(struct erf_eth_hdr))?
+ sizeof(struct erf_mc_hdr) : sizeof(struct erf_eth_hdr))];
+ guint8 ehdr[8*MAX_ERF_EHDR];
+ size_t size = 0;
+ size_t subhdr_size = 0;
+ int i = 0;
+
+ switch(encap){
+ case WTAP_ENCAP_ERF:
+ memset(&erf_hdr, 0, sizeof(erf_hdr));
+ pletonll(&erf_hdr[0], pseudo_header->erf.phdr.ts);
+ erf_hdr[8] = pseudo_header->erf.phdr.type;
+ erf_hdr[9] = pseudo_header->erf.phdr.flags;
+ phtons(&erf_hdr[10], pseudo_header->erf.phdr.rlen);
+ phtons(&erf_hdr[12], pseudo_header->erf.phdr.lctr);
+ phtons(&erf_hdr[14], pseudo_header->erf.phdr.wlen);
+ size = sizeof(struct erf_phdr);
+
+ switch(pseudo_header->erf.phdr.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:
+ phtonl(&erf_subhdr[0], pseudo_header->erf.subhdr.mc_hdr);
+ subhdr_size += (int)sizeof(struct erf_mc_hdr);
+ break;
+ case ERF_TYPE_ETH:
+ case ERF_TYPE_COLOR_ETH:
+ case ERF_TYPE_DSM_COLOR_ETH:
+ phtons(&erf_subhdr[0], pseudo_header->erf.subhdr.eth_hdr);
+ subhdr_size += (int)sizeof(struct erf_eth_hdr);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ return FALSE;
+
+ }
+ if (!wtap_dump_file_write(wdh, erf_hdr, size, err))
+ return FALSE;
+ wdh->bytes_dumped += size;
+
+ /*write out up to MAX_ERF_EHDR extension headers*/
+ if((pseudo_header->erf.phdr.type & 0x80) != 0){ /*we have extension headers*/
+ do{
+ phtonll(ehdr+(i*8), pseudo_header->erf.ehdr_list[i].ehdr);
+ if(i == MAX_ERF_EHDR-1) ehdr[i*8] = ehdr[i*8] & 0x7F;
+ i++;
+ }while((ehdr[0] & 0x80) != 0 && i < MAX_ERF_EHDR);
+ wtap_dump_file_write(wdh, ehdr, MAX_ERF_EHDR*i, err);
+ wdh->bytes_dumped += MAX_ERF_EHDR*i;
+ }
+
+ if(!wtap_dump_file_write(wdh, erf_subhdr, subhdr_size, err))
+ return FALSE;
+ wdh->bytes_dumped += subhdr_size;
+
+ return TRUE;
+}
+
+static gboolean erf_dump(
+ wtap_dumper *wdh,
+ const struct wtap_pkthdr *phdr,
+ const union wtap_pseudo_header *pseudo_header,
+ const guchar *pd,
+ int *err)
+{
+ union wtap_pseudo_header other_phdr;
+ int newencap = -1;
+ int encap;
+ int alignbytes = 0;
+ int i;
+ guint32 crc32 = 0x00000000;
+
+ if(wdh->encap == WTAP_ENCAP_PER_PACKET){
+ encap = phdr->pkt_encap;
+ }else{
+ encap = wdh->encap;
+ }
+
+ switch(encap){
+ case WTAP_ENCAP_ERF:
+ alignbytes = wdh->bytes_dumped + pseudo_header->erf.phdr.rlen;
+
+ if(!erf_write_phdr(wdh, encap, pseudo_header, err)) return FALSE;
+
+ if(!wtap_dump_file_write(wdh, pd, phdr->caplen, err)) return FALSE;
+ wdh->bytes_dumped += phdr->caplen;
+
+ while(wdh->bytes_dumped < alignbytes){
+ if(!wtap_dump_file_write(wdh, "", 1, err)) return FALSE;
+ wdh->bytes_dumped++;
+ }
+ break;
+ default: /*deal with generic wtap format*/
+ /*generate a fake header in other_phdr using data that we know*/
+ /*covert time erf timestamp format*/
+ other_phdr.erf.phdr.ts = ((guint64) phdr->ts.secs << 32) + (((guint64) phdr->ts.nsecs <<32) / 1000 / 1000 / 1000);
+ newencap = other_phdr.erf.phdr.type = wtap_wtap_encap_to_erf_encap(encap);
+ other_phdr.erf.phdr.flags = 0x4; /*vlen flag set because we're creating variable length records*/
+ other_phdr.erf.phdr.lctr = 0;
+ /*now we work out rlen, accounting for all the different headers and missing fcs(eth)*/
+ other_phdr.erf.phdr.rlen = phdr->caplen+16;
+ other_phdr.erf.phdr.wlen = phdr->caplen;
+ switch(other_phdr.erf.phdr.type){
+ case ERF_TYPE_ETH:
+ crc32 = crc32_ccitt_seed(pd, phdr->caplen, 0xFFFFFFFF);
+ other_phdr.erf.phdr.rlen += 2; /*2 bytes for erf eth_type*/
+ other_phdr.erf.phdr.rlen += 4; /*4 bytes for added checksum*/
+ other_phdr.erf.phdr.wlen += 4;
+ break;
+ case ERF_TYPE_HDLC_POS:
+ /*we assume that it's missing a FCS checksum, make one up*/
+ crc32 = crc32_ccitt_seed(pd, phdr->caplen, 0xFFFFFFFF);
+ other_phdr.erf.phdr.rlen += 4; /*4 bytes for added checksum*/
+ other_phdr.erf.phdr.wlen += 4;
+ break;
+ default:
+ break;
+ }
+
+ alignbytes = (8 - (other_phdr.erf.phdr.rlen % 8)) % 8; /*calculate how much padding will be required */
+ other_phdr.erf.phdr.rlen += alignbytes;
+
+ if(!erf_write_phdr(wdh, WTAP_ENCAP_ERF, &other_phdr, err)) return FALSE;
+ if(!wtap_dump_file_write(wdh, pd, phdr->caplen, err)) return FALSE;
+ wdh->bytes_dumped += phdr->caplen;
+
+ /*add the 4 byte checksum if type eth*/
+ if(newencap == ERF_TYPE_ETH || newencap == ERF_TYPE_HDLC_POS){
+ if(!wtap_dump_file_write(wdh, &crc32, 4, err)) return FALSE;
+ wdh->bytes_dumped += 4;
+ }
+ /*records should be 8byte aligned, so we add padding*/
+ for(i = alignbytes; i > 0; i--){
+ if(!wtap_dump_file_write(wdh, "", 1, err)) return FALSE;
+ wdh->bytes_dumped++;
+ }
+
+ break;
+ }
+
+ return TRUE;
+}
+
+int erf_dump_can_write_encap(int encap)
+{
+
+ if(encap == WTAP_ENCAP_PER_PACKET)
+ return 0;
+
+ if (wtap_wtap_encap_to_erf_encap(encap) == -1)
+ return WTAP_ERR_UNSUPPORTED_ENCAP;
+
+ return 0;
+}
+
+int erf_dump_open(wtap_dumper *wdh, int *err)
+{
+ wdh->subtype_write = erf_dump;
+ wdh->subtype_close = NULL;
+
+ switch(wdh->file_type){
+ case WTAP_FILE_ERF:
+ wdh->tsprecision = WTAP_FILE_TSPREC_NSEC;
+ break;
+ default:
+ *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/wiretap/erf.h b/wiretap/erf.h
index 4b31e2a65f..fde72e102a 100644
--- a/wiretap/erf.h
+++ b/wiretap/erf.h
@@ -105,5 +105,7 @@ union erf_subhdr {
#define FCS_BITS 32
int erf_open(wtap *wth, int *err, gchar **err_info);
+int erf_dump_can_write_encap(int encap);
+int erf_dump_open(wtap_dumper *wdh, int *err);
#endif /* __W_ERF_H__ */
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index 0f56d4481a..e5f9090bb0 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.c
@@ -486,7 +486,7 @@ static const struct file_type_info dump_open_table_base[] = {
/* WTAP_FILE_ERF */
{ "Endace ERF capture", "erf", "*.erf", ".erf", FALSE, FALSE,
- NULL, NULL },
+ erf_dump_can_write_encap, erf_dump_open },
/* WTAP_FILE_EYESDN */
{ "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.trc", ".trc", FALSE, FALSE,
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index a233644062..73f10e8321 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -665,9 +665,12 @@ struct erf_ehdr {
* ERF pseudo header with optional subheader
* (Multichannel or Ethernet)
*/
+
+#define MAX_ERF_EHDR 8
+
struct erf_mc_phdr {
struct erf_phdr phdr;
- struct erf_ehdr ehdr_list[8];
+ struct erf_ehdr ehdr_list[MAX_ERF_EHDR];
union
{
guint16 eth_hdr;