Add a new record type REC_TYPE_SYSTEMD_JOURNAL.

Systemd journal entries aren't file-type-specific; they're found in both
systemd journal entry blocks in pcapng files and in systemd journal
export files.  Give it a record type, for use with both file types.

This fixes #16955.

It also means that you can open a systemd journal export file and save
it as a pcapng file.


(cherry picked from commit 889e0d5cb6)
This commit is contained in:
Guy Harris 2020-10-28 03:06:26 +00:00
parent 9837703a11
commit 928f32e85c
9 changed files with 78 additions and 26 deletions

View File

@ -2078,6 +2078,11 @@ invalid_time:
caplen = rec->rec_header.syscall_header.event_filelen;
do_mutation = TRUE;
break;
case REC_TYPE_SYSTEMD_JOURNAL:
caplen = rec->rec_header.systemd_journal_header.record_len;
do_mutation = TRUE;
break;
}
if (change_offset > caplen) {

View File

@ -105,6 +105,7 @@ static int frame_tap = -1;
static dissector_handle_t docsis_handle;
static dissector_handle_t sysdig_handle;
static dissector_handle_t systemd_journal_handle;
/* Preferences */
static gboolean show_file_off = FALSE;
@ -379,6 +380,10 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
pinfo->current_proto = "System Call";
break;
case REC_TYPE_SYSTEMD_JOURNAL:
pinfo->current_proto = "Systemd Journal";
break;
default:
g_assert_not_reached();
break;
@ -493,6 +498,19 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
"System Call %u: %u byte%s",
pinfo->num, frame_len, frame_plurality);
break;
case REC_TYPE_SYSTEMD_JOURNAL:
/*
* XXX - we need to rethink what's handled by
* packet-record.c, what's handled by packet-frame.c.
* and what's handled by the syscall and systemd
* journal dissectors (and maybe even the packet
* dissector).
*/
ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
"Systemd Journal Entry %u: %u byte%s",
pinfo->num, frame_len, frame_plurality);
break;
}
fh_tree = proto_item_add_subtree(ti, ett_frame);
@ -799,6 +817,14 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
(void *)pinfo->pseudo_header);
}
break;
case REC_TYPE_SYSTEMD_JOURNAL:
if (systemd_journal_handle) {
call_dissector_with_data(systemd_journal_handle,
tvb, pinfo, parent_tree,
(void *)pinfo->pseudo_header);
}
break;
}
#ifdef _MSC_VER
} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
@ -1274,6 +1300,7 @@ proto_reg_handoff_frame(void)
{
docsis_handle = find_dissector_add_dependency("docsis", proto_frame);
sysdig_handle = find_dissector_add_dependency("sysdig", proto_frame);
systemd_journal_handle = find_dissector_add_dependency("systemd_journal", proto_frame);
}
/*

View File

@ -161,6 +161,8 @@ static expert_field ei_unhandled_field_type = EI_INIT;
static expert_field ei_nonbinary_field = EI_INIT;
static expert_field ei_undecoded_field = EI_INIT;
static dissector_handle_t sje_handle = NULL;
#define MAX_DATA_SIZE 262144 // WTAP_MAX_PACKET_SIZE_STANDARD. Increase if needed.
/* Initialize the subtree pointers */
@ -877,6 +879,9 @@ proto_register_systemd_journal(void)
expert_systemd_journal = expert_register_protocol(proto_systemd_journal);
expert_register_field_array(expert_systemd_journal, ei, array_length(ei));
sje_handle = register_dissector("systemd_journal", dissect_systemd_journal_line_entry,
proto_systemd_journal);
init_jf_to_hf_map();
}
@ -884,13 +889,6 @@ proto_register_systemd_journal(void)
void
proto_reg_handoff_systemd_journal(void)
{
static dissector_handle_t sje_handle = NULL;
if (!sje_handle) {
sje_handle = create_dissector_handle(dissect_systemd_journal_line_entry,
proto_systemd_journal);
}
dissector_add_uint("wtap_fts_rec", WTAP_FILE_TYPE_SUBTYPE_SYSTEMD_JOURNAL, sje_handle);
dissector_add_uint("pcapng.block_type", BLOCK_TYPE_SYSTEMD_JOURNAL, sje_handle);
// It's possible to ship journal entries over HTTP/HTTPS using

View File

@ -192,6 +192,15 @@ frame_data_init(frame_data *fdata, guint32 num, const wtap_rec *rec,
fdata->cum_bytes = cum_bytes + rec->rec_header.syscall_header.event_len;
fdata->cap_len = rec->rec_header.syscall_header.event_filelen;
break;
case REC_TYPE_SYSTEMD_JOURNAL:
/*
* XXX - is cum_bytes supposed to count non-packet bytes?
*/
fdata->pkt_len = rec->rec_header.systemd_journal_header.record_len;
fdata->cum_bytes = cum_bytes + rec->rec_header.systemd_journal_header.record_len;
fdata->cap_len = rec->rec_header.systemd_journal_header.record_len;
break;
}
/* To save some memory, we coerce it into 4 bits */

View File

@ -501,6 +501,10 @@ dissect_record(epan_dissect_t *edt, int file_type_subtype,
record_type = "System Call";
break;
case REC_TYPE_SYSTEMD_JOURNAL:
record_type = "Systemd Journal Entry";
break;
default:
/*
* XXX - if we add record types that shouldn't be
@ -544,6 +548,10 @@ dissect_record(epan_dissect_t *edt, int file_type_subtype,
case REC_TYPE_SYSCALL:
edt->pi.pseudo_header = NULL;
break;
case REC_TYPE_SYSTEMD_JOURNAL:
edt->pi.pseudo_header = NULL;
break;
}
edt->pi.fd = fd;

View File

@ -69,6 +69,7 @@ get_stats_for_preview(wtap *wth, ws_file_preview_stats *stats,
case REC_TYPE_FT_SPECIFIC_EVENT:
case REC_TYPE_FT_SPECIFIC_REPORT:
case REC_TYPE_SYSCALL:
case REC_TYPE_SYSTEMD_JOURNAL:
data_records++;
break;
}

View File

@ -2519,9 +2519,8 @@ pcapng_read_systemd_journal_export_block(wtap *wth, FILE_T fh, pcapng_block_head
return FALSE;
}
wblock->rec->rec_type = REC_TYPE_FT_SPECIFIC_EVENT;
wblock->rec->rec_header.ft_specific_header.record_type = BLOCK_TYPE_SYSTEMD_JOURNAL;
wblock->rec->rec_header.ft_specific_header.record_len = entry_length;
wblock->rec->rec_type = REC_TYPE_SYSTEMD_JOURNAL;
wblock->rec->rec_header.systemd_journal_header.record_len = entry_length;
wblock->rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
wblock->rec->tsprec = WTAP_TSPREC_USEC;
@ -3863,23 +3862,23 @@ pcapng_write_systemd_journal_export_block(wtap_dumper *wdh, const wtap_rec *rec,
guint32 pad_len;
/* Don't write anything we're not willing to read. */
if (rec->rec_header.ft_specific_header.record_len > WTAP_MAX_PACKET_SIZE_STANDARD) {
if (rec->rec_header.systemd_journal_header.record_len > WTAP_MAX_PACKET_SIZE_STANDARD) {
*err = WTAP_ERR_PACKET_TOO_LARGE;
return FALSE;
}
if (rec->rec_header.ft_specific_header.record_len % 4) {
pad_len = 4 - (rec->rec_header.ft_specific_header.record_len % 4);
if (rec->rec_header.systemd_journal_header.record_len % 4) {
pad_len = 4 - (rec->rec_header.systemd_journal_header.record_len % 4);
} else {
pad_len = 0;
}
/* write systemd journal export block header */
bh.block_type = BLOCK_TYPE_SYSTEMD_JOURNAL;
bh.block_total_length = (guint32)sizeof(bh) + rec->rec_header.ft_specific_header.record_len + pad_len + 4;
bh.block_total_length = (guint32)sizeof(bh) + rec->rec_header.systemd_journal_header.record_len + pad_len + 4;
pcapng_debug("%s: writing %u bytes, %u padded", G_STRFUNC,
rec->rec_header.ft_specific_header.record_len,
rec->rec_header.systemd_journal_header.record_len,
bh.block_total_length);
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
@ -3887,9 +3886,9 @@ pcapng_write_systemd_journal_export_block(wtap_dumper *wdh, const wtap_rec *rec,
wdh->bytes_dumped += sizeof bh;
/* write entry data */
if (!wtap_dump_file_write(wdh, pd, rec->rec_header.ft_specific_header.record_len, err))
if (!wtap_dump_file_write(wdh, pd, rec->rec_header.systemd_journal_header.record_len, err))
return FALSE;
wdh->bytes_dumped += rec->rec_header.ft_specific_header.record_len;
wdh->bytes_dumped += rec->rec_header.systemd_journal_header.record_len;
/* write padding (if any) */
if (pad_len != 0) {
@ -4824,12 +4823,6 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
case REC_TYPE_FT_SPECIFIC_EVENT:
case REC_TYPE_FT_SPECIFIC_REPORT:
if (rec->rec_header.ft_specific_header.record_type == WTAP_FILE_TYPE_SUBTYPE_SYSTEMD_JOURNAL) {
if (!pcapng_write_systemd_journal_export_block(wdh, rec, pd, err)) {
return FALSE;
}
return TRUE;
}
#ifdef HAVE_PLUGINS
/*
* Do we have a handler for this block type?
@ -4855,6 +4848,12 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
}
break;
case REC_TYPE_SYSTEMD_JOURNAL:
if (!pcapng_write_systemd_journal_export_block(wdh, rec, pd, err)) {
return FALSE;
}
break;
default:
/* We don't support writing this record type. */
*err = WTAP_ERR_UNWRITABLE_REC_TYPE;

View File

@ -225,10 +225,9 @@ systemd_journal_read_export_entry(FILE_T fh, wtap_rec *rec, Buffer *buf, int *er
return FALSE;
}
rec->rec_type = REC_TYPE_FT_SPECIFIC_EVENT;
rec->rec_type = REC_TYPE_SYSTEMD_JOURNAL;
rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
rec->rec_header.ft_specific_header.record_type = WTAP_FILE_TYPE_SUBTYPE_SYSTEMD_JOURNAL;
rec->rec_header.ft_specific_header.record_len = (guint32) fld_end;
rec->rec_header.systemd_journal_header.record_len = (guint32) fld_end;
return TRUE;
}

View File

@ -1296,6 +1296,7 @@ union wtap_pseudo_header {
#define REC_TYPE_FT_SPECIFIC_EVENT 1 /**< file-type-specific event */
#define REC_TYPE_FT_SPECIFIC_REPORT 2 /**< file-type-specific report */
#define REC_TYPE_SYSCALL 3 /**< system call */
#define REC_TYPE_SYSTEMD_JOURNAL 4 /**< systemd journal entry */
typedef struct {
guint32 caplen; /* data length in the file */
@ -1402,6 +1403,10 @@ typedef struct {
/* ... Event ... */
} wtap_syscall_header;
typedef struct {
guint32 record_len; /* length of the record */
} wtap_systemd_journal_header;
typedef struct {
guint rec_type; /* what type of record is this? */
guint32 presence_flags; /* what stuff do we have? */
@ -1411,6 +1416,7 @@ typedef struct {
wtap_packet_header packet_header;
wtap_ft_specific_header ft_specific_header;
wtap_syscall_header syscall_header;
wtap_systemd_journal_header systemd_journal_header;
} rec_header;
/*
* XXX - this should become a full set of options.