forked from osmocom/wireshark
More Sysdig / system event support.
Add REC_TYPE_SYSCALL to wiretap and use it for Sysdig events. Call the Sysdig event dissector from the frame dissector. Create a "syscall" protocol for system calls, but add "frame" items to it for now. Add the ability to write Sysdig events. This lets us merge packet capture and syscall capture files. Change-Id: I12774ec69c89d8e329b6130c67f29aade4e3d778 Reviewed-on: https://code.wireshark.org/review/15078 Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
b26e757b31
commit
d25a60c1c1
|
@ -51,6 +51,8 @@ void proto_reg_handoff_frame(void);
|
|||
|
||||
static int proto_frame = -1;
|
||||
static int proto_pkt_comment = -1;
|
||||
static int proto_syscall = -1;
|
||||
|
||||
static int hf_frame_arrival_time = -1;
|
||||
static int hf_frame_shift_offset = -1;
|
||||
static int hf_frame_arrival_time_epoch = -1;
|
||||
|
@ -98,6 +100,7 @@ static expert_field ei_incomplete = EI_INIT;
|
|||
static int frame_tap = -1;
|
||||
|
||||
static dissector_handle_t docsis_handle;
|
||||
static dissector_handle_t sysdig_handle;
|
||||
|
||||
/* Preferences */
|
||||
static gboolean show_file_off = FALSE;
|
||||
|
@ -250,6 +253,10 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
|
|||
pinfo->current_proto = "Report";
|
||||
break;
|
||||
|
||||
case REC_TYPE_SYSCALL:
|
||||
pinfo->current_proto = "System Call";
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
|
@ -283,17 +290,37 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
|
|||
cap_plurality = plurality(cap_len, "", "s");
|
||||
frame_plurality = plurality(frame_len, "", "s");
|
||||
|
||||
ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
|
||||
"Frame %u: %u byte%s on wire",
|
||||
pinfo->num, frame_len, frame_plurality);
|
||||
if (generate_bits_field)
|
||||
proto_item_append_text(ti, " (%u bits)", frame_len * 8);
|
||||
proto_item_append_text(ti, ", %u byte%s captured",
|
||||
cap_len, cap_plurality);
|
||||
if (generate_bits_field) {
|
||||
proto_item_append_text(ti, " (%u bits)",
|
||||
cap_len * 8);
|
||||
switch (pinfo->phdr->rec_type) {
|
||||
case REC_TYPE_PACKET:
|
||||
case REC_TYPE_FT_SPECIFIC_EVENT:
|
||||
case REC_TYPE_FT_SPECIFIC_REPORT:
|
||||
ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
|
||||
"Frame %u: %u byte%s on wire",
|
||||
pinfo->num, frame_len, frame_plurality);
|
||||
if (generate_bits_field)
|
||||
proto_item_append_text(ti, " (%u bits)", frame_len * 8);
|
||||
proto_item_append_text(ti, ", %u byte%s captured",
|
||||
cap_len, cap_plurality);
|
||||
if (generate_bits_field) {
|
||||
proto_item_append_text(ti, " (%u bits)",
|
||||
cap_len * 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case REC_TYPE_SYSCALL:
|
||||
/*
|
||||
* This gives us a top-of-tree "syscall" protocol
|
||||
* with "frame" fields underneath. Should we create
|
||||
* corresponding syscall.time, .time_epoch, etc
|
||||
* fields and use them instead or would frame.*
|
||||
* be preferred?
|
||||
*/
|
||||
ti = proto_tree_add_protocol_format(tree, proto_syscall, tvb, 0, tvb_captured_length(tvb),
|
||||
"System Call %u: %u byte%s",
|
||||
pinfo->num, frame_len, frame_plurality);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) {
|
||||
proto_item_append_text(ti, " on interface %u",
|
||||
pinfo->phdr->interface_id);
|
||||
|
@ -501,6 +528,15 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REC_TYPE_SYSCALL:
|
||||
/* Sysdig is the only type we currently handle. */
|
||||
if (sysdig_handle) {
|
||||
call_dissector_with_data(sysdig_handle,
|
||||
tvb, pinfo, parent_tree,
|
||||
(void *)pinfo->pseudo_header);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
|
||||
|
@ -867,6 +903,8 @@ proto_register_frame(void)
|
|||
|
||||
proto_frame = proto_register_protocol("Frame", "Frame", "frame");
|
||||
proto_pkt_comment = proto_register_protocol("Packet comments", "Pkt_Comment", "pkt_comment");
|
||||
proto_syscall = proto_register_protocol("System Call", "Syscall", "syscall");
|
||||
|
||||
proto_register_field_array(proto_frame, hf, array_length(hf));
|
||||
proto_register_field_array(proto_frame, &hf_encap, 1);
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
@ -914,6 +952,7 @@ void
|
|||
proto_reg_handoff_frame(void)
|
||||
{
|
||||
docsis_handle = find_dissector_add_dependency("docsis", proto_frame);
|
||||
sysdig_handle = find_dissector_add_dependency("sysdig", proto_frame);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2176,6 +2176,8 @@ proto_register_sysdig_event(void)
|
|||
/* Required function calls to register the header fields and subtrees */
|
||||
proto_register_field_array(proto_sysdig_event, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
register_dissector("sysdig", dissect_sysdig_event, proto_sysdig_event);
|
||||
}
|
||||
|
||||
#define BLOCK_TYPE_SYSDIG_EVENT 0x00000204
|
||||
|
|
|
@ -474,6 +474,10 @@ dissect_record(epan_dissect_t *edt, int file_type_subtype,
|
|||
record_type = "Report";
|
||||
break;
|
||||
|
||||
case REC_TYPE_SYSCALL:
|
||||
record_type = "System Call";
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* XXX - if we add record types that shouldn't be
|
||||
|
|
|
@ -699,11 +699,14 @@ map_phdr_interface_id(struct wtap_pkthdr *phdr, const merge_in_file_t *in_file)
|
|||
|
||||
if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID) {
|
||||
current_interface_id = phdr->interface_id;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (current_interface_id >= in_file->idb_index_map->len) {
|
||||
/* this shouldn't happen, but in a malformed input file it could */
|
||||
merge_debug("merge::map_phdr_interface_id: current_interface_id >= in_file->idb_index_map->len (ERROR?)");
|
||||
merge_debug("merge::map_phdr_interface_id: current_interface_id (%u) >= in_file->idb_index_map->len (%u) (ERROR?)",
|
||||
current_interface_id, in_file->idb_index_map->len);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
126
wiretap/pcapng.c
126
wiretap/pcapng.c
|
@ -146,7 +146,8 @@ typedef struct pcapng_name_resolution_block_s {
|
|||
/*
|
||||
* Minimum Sysdig size = minimum block size + packed size of sysdig_event_phdr.
|
||||
*/
|
||||
#define MIN_SYSDIG_EVENT_SIZE ((guint32)(MIN_BLOCK_SIZE)) + ((16 + 64 + 64 + 32 + 16) / 8)
|
||||
#define SYSDIG_EVENT_HEADER_SIZE ((16 + 64 + 64 + 32 + 16)/8) /* CPU ID + TS + TID + Event len + Event type */
|
||||
#define MIN_SYSDIG_EVENT_SIZE ((guint32)(MIN_BLOCK_SIZE + SYSDIG_EVENT_HEADER_SIZE))
|
||||
|
||||
/* pcapng: common option header file encoding for every option type */
|
||||
typedef struct pcapng_option_header_s {
|
||||
|
@ -2144,7 +2145,7 @@ pcapng_read_sysdig_event_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *p
|
|||
pcapng_debug("pcapng_read_sysdig_event_block: block_total_length %u",
|
||||
bh->block_total_length);
|
||||
|
||||
wblock->packet_header->rec_type = REC_TYPE_FT_SPECIFIC_EVENT;
|
||||
wblock->packet_header->rec_type = REC_TYPE_SYSCALL;
|
||||
wblock->packet_header->pseudo_header.sysdig_event.record_type = BLOCK_TYPE_SYSDIG_EVENT;
|
||||
wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN /*|WTAP_HAS_INTERFACE_ID */;
|
||||
wblock->packet_header->pkt_tsprec = WTAP_TSPREC_NSEC;
|
||||
|
@ -2175,6 +2176,7 @@ pcapng_read_sysdig_event_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *p
|
|||
block_read -= MIN_SYSDIG_EVENT_SIZE;
|
||||
wblock->packet_header->pseudo_header.sysdig_event.byte_order = G_BYTE_ORDER;
|
||||
|
||||
/* XXX Use Gxxx_FROM_LE macros instead? */
|
||||
if (pn->byte_swapped) {
|
||||
wblock->packet_header->pseudo_header.sysdig_event.byte_order =
|
||||
G_BYTE_ORDER == G_LITTLE_ENDIAN ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
|
||||
|
@ -2202,6 +2204,8 @@ pcapng_read_sysdig_event_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *p
|
|||
block_read, err, err_info))
|
||||
return FALSE;
|
||||
|
||||
/* XXX Read comment? */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -3097,6 +3101,118 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pcapng_write_sysdig_event_block(wtap_dumper *wdh,
|
||||
const struct wtap_pkthdr *phdr,
|
||||
const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
|
||||
{
|
||||
pcapng_block_header_t bh;
|
||||
const guint32 zero_pad = 0;
|
||||
guint32 pad_len;
|
||||
guint32 phdr_len;
|
||||
#if 0
|
||||
gboolean have_options = FALSE;
|
||||
struct option option_hdr;
|
||||
guint32 comment_len = 0, comment_pad_len = 0;
|
||||
#endif
|
||||
guint32 options_total_length = 0;
|
||||
guint16 cpu_id;
|
||||
guint64 hdr_ts;
|
||||
guint64 ts;
|
||||
guint64 thread_id;
|
||||
guint32 event_len;
|
||||
guint16 event_type;
|
||||
|
||||
/* Don't write anything we're not willing to read. */
|
||||
if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
|
||||
*err = WTAP_ERR_PACKET_TOO_LARGE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
|
||||
if ((phdr_len + phdr->caplen) % 4) {
|
||||
pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
|
||||
} else {
|
||||
pad_len = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Check if we should write comment option */
|
||||
if (phdr->opt_comment) {
|
||||
have_options = TRUE;
|
||||
comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
|
||||
if ((comment_len % 4)) {
|
||||
comment_pad_len = 4 - (comment_len % 4);
|
||||
} else {
|
||||
comment_pad_len = 0;
|
||||
}
|
||||
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
|
||||
}
|
||||
if (have_options) {
|
||||
/* End-of options tag */
|
||||
options_total_length += 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* write sysdig event block header */
|
||||
bh.block_type = BLOCK_TYPE_SYSDIG_EVENT;
|
||||
bh.block_total_length = (guint32)sizeof(bh) + SYSDIG_EVENT_HEADER_SIZE + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
|
||||
|
||||
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += sizeof bh;
|
||||
|
||||
/* Sysdig is always LE? */
|
||||
cpu_id = GUINT16_TO_LE(pseudo_header->sysdig_event.cpu_id);
|
||||
hdr_ts = (((guint64)phdr->ts.secs) * 1000000000) + phdr->ts.nsecs;
|
||||
ts = GUINT64_TO_LE(hdr_ts);
|
||||
thread_id = GUINT64_TO_LE(pseudo_header->sysdig_event.thread_id);
|
||||
event_len = GUINT32_TO_LE(pseudo_header->sysdig_event.event_len);
|
||||
event_type = GUINT16_TO_LE(pseudo_header->sysdig_event.event_type);
|
||||
|
||||
if (!wtap_dump_file_write(wdh, &cpu_id, sizeof cpu_id, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += sizeof cpu_id;
|
||||
|
||||
if (!wtap_dump_file_write(wdh, &ts, sizeof ts, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += sizeof ts;
|
||||
|
||||
if (!wtap_dump_file_write(wdh, &thread_id, sizeof thread_id, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += sizeof thread_id;
|
||||
|
||||
if (!wtap_dump_file_write(wdh, &event_len, sizeof event_len, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += sizeof event_len;
|
||||
|
||||
if (!wtap_dump_file_write(wdh, &event_type, sizeof event_type, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += sizeof event_type;
|
||||
|
||||
/* write event data */
|
||||
if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += phdr->caplen;
|
||||
|
||||
/* write padding (if any) */
|
||||
if (pad_len != 0) {
|
||||
if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
|
||||
return FALSE;
|
||||
wdh->bytes_dumped += pad_len;
|
||||
}
|
||||
|
||||
/* XXX Write comment? */
|
||||
|
||||
/* write block footer */
|
||||
if (!wtap_dump_file_write(wdh, &bh.block_total_length,
|
||||
sizeof bh.block_total_length, err))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
/* Arbitrary. */
|
||||
#define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
|
||||
static gboolean
|
||||
|
@ -3842,6 +3958,12 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
|
|||
}
|
||||
break;
|
||||
|
||||
case REC_TYPE_SYSCALL:
|
||||
if (!pcapng_write_sysdig_event_block(wdh, phdr, pseudo_header, pd, err)) {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* We don't support writing this record type. */
|
||||
*err = WTAP_ERR_UNWRITABLE_REC_TYPE;
|
||||
|
|
|
@ -1203,6 +1203,7 @@ union wtap_pseudo_header {
|
|||
#define REC_TYPE_PACKET 0 /**< packet */
|
||||
#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 */
|
||||
|
||||
struct wtap_pkthdr {
|
||||
guint rec_type; /* what type of record is this? */
|
||||
|
|
Loading…
Reference in New Issue