pcapng: clean up pcapng_block_read().

Instead of pcapng_open() calling pcap_block_read() to do all the work of
reading the initial SHB, have it do the read of the initial SHB itself,
by calling the same routines that pcap_block_read() calls.

That way, pcap_block_read() doesn't have to be prepared to be called to
read that block, so it can treat all issues with an SHB that it reads as
errors, rather than possibly reporting them as "not a pcapng file", and
it doesn't have to support being called without a pointer to the
pcapng_t for the file being read, as it no longer ever is.  It can now
just return a gboolean success/failure indication.

That makes pcapng_open() a little more complicated but it makes
pcap_block_read() less complicated.

Fix some use of : as ' in comments while we're at it.
This commit is contained in:
Guy Harris 2021-03-11 02:11:02 -08:00
parent fa9d8fbc85
commit aab0bd12a5
1 changed files with 124 additions and 97 deletions

View File

@ -691,19 +691,13 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
/* read fixed-length part of the block */ /* read fixed-length part of the block */
if (!wtap_read_bytes(fh, &shb, sizeof shb, err, err_info)) { if (!wtap_read_bytes(fh, &shb, sizeof shb, err, err_info)) {
if (*err == WTAP_ERR_SHORT_READ) { /*
/* * Even if this is just a short read, report it as an error.
* This block is too short to be an SHB. * It *is* a read error except when we're doing an open, in
* * which case it's a "this isn't a pcapng file" indication.
* If we're reading this as part of an open, * The open code will call us directly, and treat a short
* the file is too short to be a pcapng file. * read error as such an indication.
* */
* If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
* PCAPNG_BLOCK_ERROR the same, so we can just return
* PCAPNG_BLOCK_NOT_SHB in both cases.
*/
return PCAPNG_BLOCK_NOT_SHB;
}
return PCAPNG_BLOCK_ERROR; return PCAPNG_BLOCK_ERROR;
} }
@ -2530,8 +2524,33 @@ pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh,
return TRUE; return TRUE;
} }
static gboolean
pcapng_read_and_check_block_trailer(FILE_T fh, pcapng_block_header_t *bh,
section_info_t *section_info,
int *err, gchar **err_info)
{
guint32 block_total_length;
static block_return_val /* sanity check: first and second block lengths must match */
if (!wtap_read_bytes(fh, &block_total_length, sizeof block_total_length,
err, err_info)) {
pcapng_debug("pcapng_read_and_check_block_trailer: couldn't read second block length");
return FALSE;
}
if (section_info->byte_swapped)
block_total_length = GUINT32_SWAP_LE_BE(block_total_length);
if (block_total_length != bh->block_total_length) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcapng_read_and_check_block_trailer: total block lengths (first %u and second %u) don't match",
bh->block_total_length, block_total_length);
return FALSE;
}
return TRUE;
}
static gboolean
pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn, pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn,
section_info_t *section_info, section_info_t *section_info,
section_info_t *new_section_info, section_info_t *new_section_info,
@ -2540,27 +2559,13 @@ pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn,
{ {
block_return_val ret; block_return_val ret;
pcapng_block_header_t bh; pcapng_block_header_t bh;
guint32 block_total_length;
wblock->block = NULL; wblock->block = NULL;
/* Try to read the (next) block header */ /* Try to read the (next) block header */
if (!wtap_read_bytes_or_eof(fh, &bh, sizeof bh, err, err_info)) { if (!wtap_read_bytes_or_eof(fh, &bh, sizeof bh, err, err_info)) {
pcapng_debug("pcapng_read_block: wtap_read_bytes_or_eof() failed, err = %d.", *err); pcapng_debug("pcapng_read_block: wtap_read_bytes_or_eof() failed, err = %d.", *err);
if (*err == 0 || *err == WTAP_ERR_SHORT_READ) { return FALSE;
/*
* Short read or EOF.
*
* If we're reading this as part of an open,
* the file is too short to be a pcapng file.
*
* If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
* PCAPNG_BLOCK_ERROR the same, so we can just return
* PCAPNG_BLOCK_NOT_SHB in both cases.
*/
return PCAPNG_BLOCK_NOT_SHB;
}
return PCAPNG_BLOCK_ERROR;
} }
/* /*
@ -2596,7 +2601,7 @@ pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn,
ret = pcapng_read_section_header_block(fh, &bh, new_section_info, ret = pcapng_read_section_header_block(fh, &bh, new_section_info,
wblock, err, err_info); wblock, err, err_info);
if (ret != PCAPNG_BLOCK_OK) { if (ret != PCAPNG_BLOCK_OK) {
return ret; return FALSE;
} }
/* /*
@ -2608,21 +2613,7 @@ pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn,
} else { } else {
/* /*
* Not an SHB. * Not an SHB.
*
* If pn is null, it means we're calling this from pcapng_open()
* to see whether the file begins with an SHB.
* It doesn't, which means that it is not a pcapng file.
*/ */
if (pn == NULL) {
*err = 0;
*err_info = NULL;
return PCAPNG_BLOCK_NOT_SHB;
}
/*
* pn is not null; section_info must not be null, either.
*/
g_assert(section_info != NULL);
if (section_info->byte_swapped) { if (section_info->byte_swapped) {
bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type); bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length); bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
@ -2641,72 +2632,63 @@ pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn,
*err = WTAP_ERR_BAD_FILE; *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcapng_read_block: total block length %u is too large (> %u)", *err_info = g_strdup_printf("pcapng_read_block: total block length %u is too large (> %u)",
bh.block_total_length, MAX_BLOCK_SIZE); bh.block_total_length, MAX_BLOCK_SIZE);
return PCAPNG_BLOCK_ERROR; return FALSE;
} }
switch (bh.block_type) { switch (bh.block_type) {
case(BLOCK_TYPE_IDB): case(BLOCK_TYPE_IDB):
if (!pcapng_read_if_descr_block(wth, fh, &bh, section_info, wblock, err, err_info)) if (!pcapng_read_if_descr_block(wth, fh, &bh, section_info, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_PB): case(BLOCK_TYPE_PB):
if (!pcapng_read_packet_block(fh, &bh, section_info, wblock, err, err_info, FALSE)) if (!pcapng_read_packet_block(fh, &bh, section_info, wblock, err, err_info, FALSE))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_SPB): case(BLOCK_TYPE_SPB):
if (!pcapng_read_simple_packet_block(fh, &bh, section_info, wblock, err, err_info)) if (!pcapng_read_simple_packet_block(fh, &bh, section_info, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_EPB): case(BLOCK_TYPE_EPB):
if (!pcapng_read_packet_block(fh, &bh, section_info, wblock, err, err_info, TRUE)) if (!pcapng_read_packet_block(fh, &bh, section_info, wblock, err, err_info, TRUE))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_NRB): case(BLOCK_TYPE_NRB):
if (!pcapng_read_name_resolution_block(fh, &bh, pn, section_info, wblock, err, err_info)) if (!pcapng_read_name_resolution_block(fh, &bh, pn, section_info, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_ISB): case(BLOCK_TYPE_ISB):
if (!pcapng_read_interface_statistics_block(fh, &bh, section_info, wblock, err, err_info)) if (!pcapng_read_interface_statistics_block(fh, &bh, section_info, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_DSB): case(BLOCK_TYPE_DSB):
if (!pcapng_read_decryption_secrets_block(fh, &bh, section_info, wblock, err, err_info)) if (!pcapng_read_decryption_secrets_block(fh, &bh, section_info, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_SYSDIG_EVENT): case(BLOCK_TYPE_SYSDIG_EVENT):
/* case(BLOCK_TYPE_SYSDIG_EVF): */ /* case(BLOCK_TYPE_SYSDIG_EVF): */
if (!pcapng_read_sysdig_event_block(fh, &bh, section_info, wblock, err, err_info)) if (!pcapng_read_sysdig_event_block(fh, &bh, section_info, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
case(BLOCK_TYPE_SYSTEMD_JOURNAL): case(BLOCK_TYPE_SYSTEMD_JOURNAL):
if (!pcapng_read_systemd_journal_export_block(wth, fh, &bh, pn, wblock, err, err_info)) if (!pcapng_read_systemd_journal_export_block(wth, fh, &bh, pn, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
default: default:
pcapng_debug("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length); pcapng_debug("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
if (!pcapng_read_unknown_block(fh, &bh, section_info, wblock, err, err_info)) if (!pcapng_read_unknown_block(fh, &bh, section_info, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR; return FALSE;
break; break;
} }
} }
/* sanity check: first and second block lengths must match */ /*
if (!wtap_read_bytes(fh, &block_total_length, sizeof block_total_length, * Read and check the block trailer.
err, err_info)) { */
pcapng_debug("pcapng_check_block_trailer: couldn't read second block length"); if (!pcapng_read_and_check_block_trailer(fh, &bh, section_info, err, err_info)) {
return PCAPNG_BLOCK_ERROR; /* Not readable or not valid. */
return FALSE;
} }
return TRUE;
if (section_info->byte_swapped)
block_total_length = GUINT32_SWAP_LE_BE(block_total_length);
if (block_total_length != bh.block_total_length) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcapng_check_block_trailer: total block lengths (first %u and second %u) don't match",
bh.block_total_length, block_total_length);
return PCAPNG_BLOCK_ERROR;
}
return PCAPNG_BLOCK_OK;
} }
/* Process an IDB that we've just read. The contents of wblock are copied as needed. */ /* Process an IDB that we've just read. The contents of wblock are copied as needed. */
@ -2777,12 +2759,51 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
/* /*
* Read first block. * Read first block.
* *
* There is no current section_info yet, so don't pass any. * First, try to read the block header.
* Pass a pointer to first_section to fill in.
*/ */
switch (pcapng_read_block(wth, wth->fh, NULL, NULL, &first_section, &wblock, if (!wtap_read_bytes_or_eof(wth->fh, &bh, sizeof bh, err, err_info)) {
err, err_info)) { pcapng_debug("pcapng_open: wtap_read_bytes_or_eof() failed, err = %d.", *err);
if (*err == 0 || *err == WTAP_ERR_SHORT_READ) {
/*
* Short read or EOF.
*
* We're reading this as part of an open, so
* the file is too short to be a pcapng file.
*/
*err = 0;
g_free(*err_info);
*err_info = NULL;
return WTAP_OPEN_NOT_MINE;
}
return WTAP_OPEN_ERROR;
}
/*
* If this is a pcapng file, the first block must be a
* Section Header Block.
*/
if (bh.block_type != BLOCK_TYPE_SHB) {
/*
* Not an SHB, so this isn't a pcapng file.
*
* XXX - check for damage from transferring a file
* between Windows and UN*X as text rather than
* binary data?
*/
pcapng_debug("pcapng_open: first block type %u not SHB", wblock.type);
return WTAP_OPEN_NOT_MINE;
}
pcapng_debug("pcapng_open: got an SHB");
/*
* Now try to read the block body, filling in the section_info_t
* for the first section.
*/
wblock.type = bh.block_type;
wblock.block = NULL;
switch (pcapng_read_section_header_block(wth->fh, &bh, &first_section,
&wblock, err, err_info)) {
case PCAPNG_BLOCK_OK: case PCAPNG_BLOCK_OK:
/* No problem */ /* No problem */
break; break;
@ -2796,21 +2817,30 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
return WTAP_OPEN_NOT_MINE; return WTAP_OPEN_NOT_MINE;
case PCAPNG_BLOCK_ERROR: case PCAPNG_BLOCK_ERROR:
/* An I/O error, or this probably *is* a pcapng file but not a valid one. */
wtap_block_free(wblock.block); wtap_block_free(wblock.block);
if (*err == WTAP_ERR_SHORT_READ) {
/*
* Short read.
*
* We're reading this as part of an open, so
* the file is too short to be a pcapng file.
*/
*err = 0;
g_free(*err_info);
*err_info = NULL;
return WTAP_OPEN_NOT_MINE;
}
/* An I/O error. */
return WTAP_OPEN_ERROR; return WTAP_OPEN_ERROR;
} }
/* first block must be a "Section Header Block" */ /*
if (wblock.type != BLOCK_TYPE_SHB) { * Read and check the block trailer.
/* */
* XXX - check for damage from transferring a file if (!pcapng_read_and_check_block_trailer(wth->fh, &bh, &first_section, err, err_info)) {
* between Windows and UN*X as text rather than /* Not readable or not valid. */
* binary data?
*/
pcapng_debug("pcapng_open: first block type %u not SHB", wblock.type);
wtap_block_free(wblock.block); wtap_block_free(wblock.block);
return WTAP_OPEN_NOT_MINE; return WTAP_OPEN_ERROR;
} }
/* /*
@ -2862,7 +2892,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
* wtap_dumper can refer to it right after opening the capture file. */ * wtap_dumper can refer to it right after opening the capture file. */
wth->dsbs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t)); wth->dsbs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
/* Loop over all IDB:s that appear before any packets */ /* Loop over all IDBs that appear before any packets */
while (1) { while (1) {
/* peek at next block */ /* peek at next block */
/* Try to read the (next) block header */ /* Try to read the (next) block header */
@ -2893,12 +2923,11 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
pcapng_debug("pcapng_open: Check for more IDBs, block_type 0x%x", bh.block_type); pcapng_debug("pcapng_open: Check for more IDBs, block_type 0x%x", bh.block_type);
if (bh.block_type != BLOCK_TYPE_IDB) { if (bh.block_type != BLOCK_TYPE_IDB) {
break; /* No more IDB:s */ break; /* No more IDBs */
} }
if (pcapng_read_block(wth, wth->fh, pcapng, current_section, if (!pcapng_read_block(wth, wth->fh, pcapng, current_section,
&new_section, &wblock, &new_section, &wblock, err, err_info)) {
err, err_info) != PCAPNG_BLOCK_OK) {
wtap_block_free(wblock.block); wtap_block_free(wblock.block);
if (*err == 0) { if (*err == 0) {
pcapng_debug("No more IDBs available..."); pcapng_debug("No more IDBs available...");
@ -2950,9 +2979,8 @@ pcapng_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err,
/* /*
* Read the next block. * Read the next block.
*/ */
if (pcapng_read_block(wth, wth->fh, pcapng, current_section, if (!pcapng_read_block(wth, wth->fh, pcapng, current_section,
&new_section, &wblock, &new_section, &wblock, err, err_info)) {
err, err_info) != PCAPNG_BLOCK_OK) {
pcapng_debug("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset); pcapng_debug("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
pcapng_debug("pcapng_read: couldn't read packet block"); pcapng_debug("pcapng_read: couldn't read packet block");
wtap_block_free(wblock.block); wtap_block_free(wblock.block);
@ -3124,9 +3152,8 @@ pcapng_seek_read(wtap *wth, gint64 seek_off,
wblock.rec = rec; wblock.rec = rec;
/* read the block */ /* read the block */
if (pcapng_read_block(wth, wth->random_fh, pcapng, section_info, if (!pcapng_read_block(wth, wth->random_fh, pcapng, section_info,
&new_section, &wblock, &new_section, &wblock, err, err_info)) {
err, err_info) != PCAPNG_BLOCK_OK) {
pcapng_debug("pcapng_seek_read: couldn't read packet block (err=%d).", pcapng_debug("pcapng_seek_read: couldn't read packet block (err=%d).",
*err); *err);
wtap_block_free(wblock.block); wtap_block_free(wblock.block);
@ -4925,7 +4952,7 @@ pcapng_dump_open(wtap_dumper *wdh, int *err, gchar **err_info _U_)
pcapng_debug("pcapng_dump_open: wrote section header block."); pcapng_debug("pcapng_dump_open: wrote section header block.");
/* Write the Interface description blocks */ /* Write the Interface description blocks */
pcapng_debug("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", pcapng_debug("pcapng_dump_open: Number of IDBs to write (number of interfaces) %u",
wdh->interface_data->len); wdh->interface_data->len);
for (i = 0; i < wdh->interface_data->len; i++) { for (i = 0; i < wdh->interface_data->len; i++) {