static void write_pcap_ng_shb(HANDLE_OR_FILEPTR file) { PCap_NG_shb shb; u32 btl; PCap_NG_option userappl = {4, 0}; // 4 = user application name PCap_NG_option end_of_options = {0, 0}; userappl.length = strlen(hw_description); btl = sizeof(PCap_NG_shb) + sizeof(userappl) + round_up_32_bit(userappl.length) + sizeof(end_of_options) + sizeof(shb.block_total_length); shb.type = 0x0A0D0D0A; shb.block_total_length = btl; shb.byte_order_magic = 0x1A2B3C4D; shb.major_version = 1; shb.minor_version = 0; shb.section_length = 0xffffffffFFFFFFFFULL; // "unknown" checked_fwrite((void*)&shb, sizeof shb, file); checked_fwrite((void*)&userappl, sizeof userappl, file); checked_fwrite((void*)hw_description, round_up_32_bit(userappl.length), file); checked_fwrite((void*)&end_of_options, sizeof end_of_options, file); checked_fwrite((void*)&btl, sizeof(btl), file); return; }
// Having both if_description and if_name causes Wireshark 1.10.3 to // display only if_description. So we only have if_name. static void write_pcap_idbs(HANDLE_OR_FILEPTR file, Channel_t *c, int n) { int x; PCap_NG_option end_of_options = { 0, 0 }; for (x = 0; x < n; x++) { PCap_NG_idb idb; PCap_NG_option if_name; char idb_if_name[MAX_IF_NAME]; PCap_NG_option if_tsresol; /* TIMESTAMP PRECISION NOTICE: Precision is set to MILLIseconds (10^-3 seconds) */ char tsresol[4] = { 3, 0, 0, 0 }; // 10^-3 resolution, three padding bytes u32 block_total_length; if_name.code = 2; // if_name if_name.length = snprintf(idb_if_name, MAX_IF_NAME, "%s:%d", c[x].span, c[x].timeslots[0]); if (if_name.length < 0 || if_name.length >= MAX_IF_NAME) die("interface name is too long"); block_total_length = sizeof(idb) + sizeof(PCap_NG_option) + round_up_32_bit(if_name.length) + sizeof(PCap_NG_option) + sizeof(tsresol) + sizeof(PCap_NG_option) + sizeof(block_total_length); idb.type = 1; idb.block_total_length = block_total_length; idb.link_type = LINK_TYPE_MTP2; idb.reserved = 0; idb.snaplen = 279; if_tsresol.code = 9; // tsresol if_tsresol.length = 1; checked_fwrite((void*)&idb, sizeof(idb), file); checked_fwrite((void*)&if_name, sizeof(if_name), file); checked_fwrite((void*)&idb_if_name, round_up_32_bit(if_name.length), file); checked_fwrite((void*)&if_tsresol, sizeof(if_tsresol), file); checked_fwrite((void*)&tsresol, sizeof(tsresol), file); checked_fwrite((void*)&end_of_options, sizeof(end_of_options), file); checked_fwrite((void*)&block_total_length, sizeof block_total_length, file); } }
static inline void write_packet(HANDLE_OR_FILEPTR file, u32 timestamp_hi, u32 timestamp_lo, u16 tag, void *payload, int length, int format) { u32 total_length; switch (format) { case PCAP_CLASSIC: write_classic_packet_header(file, timestamp_hi, timestamp_lo, length); checked_fwrite(payload, length, file); break; case PCAP_NG: total_length = write_ng_packet_header(file, timestamp_hi, timestamp_lo, tag, length); checked_fwrite(payload, round_up_32_bit(length), file); checked_fwrite(&total_length, sizeof total_length, file); break; default: die("internal error"); } }
static u32 write_ng_packet_header(HANDLE_OR_FILEPTR file, u32 timestamp_hi, u32 timestamp_lo, u16 tag, int length) { PCap_NG_epb epb; epb.type = 6; epb.block_total_length = sizeof(epb) + round_up_32_bit(length) + sizeof(epb.block_total_length); epb.interface_id = tag; epb.timestamp_hi = timestamp_hi; epb.timestamp_lo = timestamp_lo; epb.captured_len = length; epb.packet_len = length; checked_fwrite(&epb, sizeof epb, file); return epb.block_total_length; }