Put ERF pseudo-header reading and writing into single routines.

Have pcap_read_erf_pseudoheader() do all the work of reading an ERF
pseudo-header.

Add pcap_write_erf_pseudoheader() as a routine to do all the work of
writing an ERF pseudo-header.

Change-Id: If53ae50fcee35a45113ca0f0c64f69848e044cbd
Reviewed-on: https://code.wireshark.org/review/29847
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Guy Harris 2018-09-26 00:45:31 -07:00
parent bb4badac59
commit 6b904030f6
1 changed files with 174 additions and 154 deletions

View File

@ -1805,8 +1805,10 @@ pcap_read_erf_pseudoheader(FILE_T fh, wtap_rec *rec,
int *err, gchar **err_info)
{
guint8 erf_hdr[sizeof(struct erf_phdr)];
guint8 erf_subhdr[sizeof(union erf_subhdr)];
int phdr_len;
if (packet_size < sizeof(struct erf_phdr) ) {
if (packet_size < sizeof(struct erf_phdr)) {
/*
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
@ -1818,8 +1820,9 @@ pcap_read_erf_pseudoheader(FILE_T fh, wtap_rec *rec,
}
if (!wtap_read_bytes(fh, erf_hdr, sizeof(struct erf_phdr), err, err_info))
return -1;
phdr_len = (int)sizeof(struct erf_phdr);
pseudo_header->erf.phdr.ts = pletoh64(&erf_hdr[0]); /* timestamp */
pseudo_header->erf.phdr.type = erf_hdr[8];
pseudo_header->erf.phdr.type = erf_hdr[8];
pseudo_header->erf.phdr.flags = erf_hdr[9];
pseudo_header->erf.phdr.rlen = pntoh16(&erf_hdr[10]);
pseudo_header->erf.phdr.lctr = pntoh16(&erf_hdr[12]);
@ -1834,54 +1837,51 @@ pcap_read_erf_pseudoheader(FILE_T fh, wtap_rec *rec,
ts = ((ts & 0xffffffff) * 1000 * 1000 * 1000);
ts += (ts & 0x80000000) << 1; /* rounding */
rec->ts.nsecs = ((guint32) (ts >> 32));
if ( rec->ts.nsecs >= 1000000000) {
if (rec->ts.nsecs >= 1000000000) {
rec->ts.nsecs -= 1000000000;
rec->ts.secs += 1;
}
}
return (int)sizeof(struct erf_phdr);
}
/*
* If the type of record given in the pseudo header indicate the presence of an extension
* header then, read all the extension headers
*/
static gboolean
pcap_read_erf_exheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
int *err, gchar **err_info, guint * psize)
{
guint8 erf_exhdr[8];
guint64 erf_exhdr_sw;
int i = 0, max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
guint8 type;
*psize = 0;
if (pseudo_header->erf.phdr.type & 0x80){
do{
/*
* If the type of record given in the pseudo header indicates
* the presence of an extension header then, read all the
* extension headers.
*/
if (pseudo_header->erf.phdr.type & 0x80) {
int i = 0, max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
guint8 erf_exhdr[8];
guint8 type;
do {
if (phdr_len > INT_MAX - 8) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a packet larger than %d bytes",
INT_MAX);
return -1;
}
if (packet_size < (guint)phdr_len + 8) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a %u-byte packet, too small to include the extension headers",
packet_size);
return -1;
}
if (!wtap_read_bytes(fh, erf_exhdr, 8, err, err_info))
return FALSE;
return -1;
type = erf_exhdr[0];
erf_exhdr_sw = pntoh64(erf_exhdr);
if (i < max)
if (i < max) {
guint64 erf_exhdr_sw;
erf_exhdr_sw = pntoh64(erf_exhdr);
memcpy(&pseudo_header->erf.ehdr_list[i].ehdr, &erf_exhdr_sw, sizeof(erf_exhdr_sw));
*psize += 8;
}
phdr_len += 8;
i++;
} while (type & 0x80);
}
return TRUE;
}
/*
* If the type of record given in the pseudo header indicate the precense of a subheader
* then, read this optional subheader
*/
static gboolean
pcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
int *err, gchar **err_info, guint * psize)
{
guint8 erf_subhdr[sizeof(union erf_subhdr)];
*psize=0;
switch(pseudo_header->erf.phdr.type & 0x7F) {
/* check the optional subheader */
switch (pseudo_header->erf.phdr.type & 0x7F) {
case ERF_TYPE_MC_HDLC:
case ERF_TYPE_MC_RAW:
case ERF_TYPE_MC_ATM:
@ -1890,32 +1890,161 @@ pcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
case ERF_TYPE_MC_AAL2:
case ERF_TYPE_COLOR_MC_HDLC_POS:
/* Extract the Multi Channel header to include it in the pseudo header part */
if (phdr_len > INT_MAX - (int)sizeof(erf_mc_header_t)) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a packet larger than %d bytes",
INT_MAX);
return -1;
}
if (packet_size < (guint)(phdr_len + (int)sizeof(erf_mc_header_t))) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a %u-byte packet, too small to include the Multi Channel header",
packet_size);
return -1;
}
if (!wtap_read_bytes(fh, erf_subhdr, sizeof(erf_mc_header_t), err, err_info))
return FALSE;
return -1;
pseudo_header->erf.subhdr.mc_hdr = pntoh32(&erf_subhdr[0]);
*psize = sizeof(erf_mc_header_t);
phdr_len += sizeof(erf_mc_header_t);
break;
case ERF_TYPE_AAL2:
/* Extract the AAL2 header to include it in the pseudo header part */
if (phdr_len > INT_MAX - (int)sizeof(erf_aal2_header_t)) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a packet larger than %d bytes",
INT_MAX);
return -1;
}
if (packet_size < (guint)(phdr_len + (int)sizeof(erf_aal2_header_t))) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a %u-byte packet, too small to include the AAL2 headerr",
packet_size);
return -1;
}
if (!wtap_read_bytes(fh, erf_subhdr, sizeof(erf_aal2_header_t), err, err_info))
return FALSE;
return -1;
pseudo_header->erf.subhdr.aal2_hdr = pntoh32(&erf_subhdr[0]);
*psize = sizeof(erf_aal2_header_t);
phdr_len += sizeof(erf_aal2_header_t);
break;
case ERF_TYPE_ETH:
case ERF_TYPE_COLOR_ETH:
case ERF_TYPE_DSM_COLOR_ETH:
case ERF_TYPE_COLOR_HASH_ETH:
/* Extract the Ethernet additional header to include it in the pseudo header part */
if (phdr_len > INT_MAX - (int)sizeof(erf_eth_header_t)) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a packet larger than %d bytes",
INT_MAX);
return -1;
}
if (packet_size < (guint)(phdr_len + (int)sizeof(erf_eth_header_t))) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a %u-byte packet, too small to include the Ethernet additional header",
packet_size);
return -1;
}
if (!wtap_read_bytes(fh, erf_subhdr, sizeof(erf_eth_header_t), err, err_info))
return FALSE;
return -1;
memcpy(&pseudo_header->erf.subhdr.eth_hdr, erf_subhdr, sizeof pseudo_header->erf.subhdr.eth_hdr);
*psize = sizeof(erf_eth_header_t);
phdr_len += sizeof(erf_eth_header_t);
break;
default:
/* No optional pseudo header for this ERF type */
break;
}
return phdr_len;
}
static gboolean
pcap_write_erf_pseudoheader(wtap_dumper *wdh,
const union wtap_pseudo_header *pseudo_header, int *err)
{
guint8 erf_hdr[sizeof(struct erf_phdr)];
guint8 erf_subhdr[sizeof(union erf_subhdr)];
/*
* Write the ERF header.
*/
memset(&erf_hdr, 0, sizeof(erf_hdr));
phtolell(&erf_hdr[0], pseudo_header->erf.phdr.ts);
erf_hdr[8] = pseudo_header->erf.phdr.type;
erf_hdr[9] = pseudo_header->erf.phdr.flags;
/*
* Recalculate rlen as padding (and maybe extension headers)
* have been stripped from caplen.
*
* XXX: Since we don't have rec->rec_header.packet_header.caplen
* here, assume caplen was calculated correctly and
* recalculate from wlen.
*/
phtons(&erf_hdr[10],
MIN(pseudo_header->erf.phdr.rlen, pseudo_header->erf.phdr.wlen + pcap_get_phdr_size(WTAP_ENCAP_ERF, pseudo_header)));
phtons(&erf_hdr[12], pseudo_header->erf.phdr.lctr);
phtons(&erf_hdr[14], pseudo_header->erf.phdr.wlen);
if (!wtap_dump_file_write(wdh, erf_hdr, sizeof(struct erf_phdr), err))
return FALSE;
wdh->bytes_dumped += sizeof(struct erf_phdr);
/*
* Now write out the extension headers.
*/
if (pseudo_header->erf.phdr.type & 0x80) {
int i = 0, max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
guint8 erf_exhdr[8];
guint8 type;
do {
phtonll(erf_exhdr, pseudo_header->erf.ehdr_list[i].ehdr);
type = erf_exhdr[0];
/* Clear more extension headers bit if > 8 */
if(i == max-1)
erf_exhdr[0] = erf_exhdr[0] & 0x7F;
if (!wtap_dump_file_write(wdh, erf_exhdr, 8, err))
return FALSE;
wdh->bytes_dumped += 8;
i++;
} while (type & 0x80 && i < max);
}
/*
* Now write out the subheader, if any
*/
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);
if (!wtap_dump_file_write(wdh, erf_subhdr,
sizeof(struct erf_mc_hdr), err))
return FALSE;
wdh->bytes_dumped += sizeof(struct erf_mc_hdr);;
break;
case ERF_TYPE_AAL2:
phtonl(&erf_subhdr[0], pseudo_header->erf.subhdr.aal2_hdr);
if (!wtap_dump_file_write(wdh, erf_subhdr,
sizeof(struct erf_aal2_hdr), err))
return FALSE;
wdh->bytes_dumped += sizeof(struct erf_aal2_hdr);;
break;
case ERF_TYPE_ETH:
case ERF_TYPE_COLOR_ETH:
case ERF_TYPE_DSM_COLOR_ETH:
case ERF_TYPE_COLOR_HASH_ETH:
memcpy(&erf_subhdr[0], &pseudo_header->erf.subhdr.eth_hdr, sizeof pseudo_header->erf.subhdr.eth_hdr);
if (!wtap_dump_file_write(wdh, erf_subhdr,
sizeof(struct erf_eth_hdr), err))
return FALSE;
wdh->bytes_dumped += sizeof(struct erf_eth_hdr);
break;
default:
break;
}
return TRUE;
}
@ -1977,7 +2106,6 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
guint packet_size, wtap_rec *rec, int *err, gchar **err_info)
{
int phdr_len = 0;
guint size;
switch (wtap_encap) {
@ -2112,31 +2240,6 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
packet_size, err, err_info);
if (phdr_len == -1)
return -1; /* Read error */
/* check the optional Extension header */
if (!pcap_read_erf_exheader(fh, &rec->rec_header.packet_header.pseudo_header, err, err_info,
&size))
return -1; /* Read error */
phdr_len += size;
/* check the optional Multi Channel header */
if (!pcap_read_erf_subheader(fh, &rec->rec_header.packet_header.pseudo_header, err, err_info,
&size))
return -1; /* Read error */
phdr_len += size;
if (packet_size < (guint)phdr_len) {
/*
* Uh-oh, the packet isn't big enough for the pseudo-
* header.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap/pcapng: ERF file has a %u-byte packet, too small for a pseudo-header with ex- and sub-headers (%d)",
packet_size, phdr_len);
return -1;
}
break;
case WTAP_ENCAP_I2C:
@ -2327,11 +2430,6 @@ gboolean
pcap_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(union erf_subhdr)];
size_t size;
size_t subhdr_size = 0;
switch (encap) {
case WTAP_ENCAP_ATM_PDUS:
@ -2380,86 +2478,8 @@ pcap_write_phdr(wtap_dumper *wdh, int encap, const union wtap_pseudo_header *pse
break;
case WTAP_ENCAP_ERF:
/*
* Write the ERF header.
*/
memset(&erf_hdr, 0, sizeof(erf_hdr));
phtolell(&erf_hdr[0], pseudo_header->erf.phdr.ts);
erf_hdr[8] = pseudo_header->erf.phdr.type;
erf_hdr[9] = pseudo_header->erf.phdr.flags;
/*
* Recalculate rlen as padding (and maybe extension headers)
* have been stripped from caplen.
*
* XXX: Since we don't have rec->rec_header.packet_header.caplen
* here, assume caplen was calculated correctly and
* recalculate from wlen.
*/
phtons(&erf_hdr[10],
MIN(pseudo_header->erf.phdr.rlen, pseudo_header->erf.phdr.wlen + pcap_get_phdr_size(WTAP_ENCAP_ERF, pseudo_header)));
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_AAL2:
phtonl(&erf_subhdr[0], pseudo_header->erf.subhdr.aal2_hdr);
subhdr_size += (int)sizeof(struct erf_aal2_hdr);
break;
case ERF_TYPE_ETH:
case ERF_TYPE_COLOR_ETH:
case ERF_TYPE_DSM_COLOR_ETH:
case ERF_TYPE_COLOR_HASH_ETH:
memcpy(&erf_subhdr[0], &pseudo_header->erf.subhdr.eth_hdr, sizeof pseudo_header->erf.subhdr.eth_hdr);
subhdr_size += (int)sizeof(struct erf_eth_hdr);
break;
default:
break;
}
if (!wtap_dump_file_write(wdh, erf_hdr, size, err))
if (!pcap_write_erf_pseudoheader(wdh, pseudo_header, err))
return FALSE;
wdh->bytes_dumped += size;
/*
* Now write out the extension headers.
*/
if (pseudo_header->erf.phdr.type & 0x80) {
int i = 0, max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
guint8 erf_exhdr[8];
guint8 type;
do {
phtonll(erf_exhdr, pseudo_header->erf.ehdr_list[i].ehdr);
type = erf_exhdr[0];
/* Clear more extension headers bit if > 8 */
if(i == max-1)
erf_exhdr[0] = erf_exhdr[0] & 0x7F;
if (!wtap_dump_file_write(wdh, erf_exhdr, 8, err))
return FALSE;
wdh->bytes_dumped += 8;
i++;
} while (type & 0x80 && i < max);
}
/*
* Now write out the subheader.
*/
if(!wtap_dump_file_write(wdh, erf_subhdr, subhdr_size, err))
return FALSE;
wdh->bytes_dumped += subhdr_size;
break;
case WTAP_ENCAP_I2C: