diff --git a/capture_opts.c b/capture_opts.c index ae94e8dd3e..177ffe3701 100644 --- a/capture_opts.c +++ b/capture_opts.c @@ -106,6 +106,7 @@ capture_opts_init(capture_options *capture_opts, void *cf) capture_opts->linktype = -1; /* the default linktype */ capture_opts->saving_to_file = FALSE; capture_opts->save_file = NULL; + capture_opts->use_pcapng = FALSE; /* the default is pcap */ capture_opts->real_time_mode = TRUE; capture_opts->show_info = TRUE; capture_opts->quit_after_cap = FALSE; @@ -179,6 +180,7 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio g_log(log_domain, log_level, "LinkType : %d", capture_opts->linktype); g_log(log_domain, log_level, "SavingToFile : %u", capture_opts->saving_to_file); g_log(log_domain, log_level, "SaveFile : %s", (capture_opts->save_file) ? capture_opts->save_file : ""); + g_log(log_domain, log_level, "Fileformat : %s", (capture_opts->use_pcapng) ? "PCAPNG" : "PCAP"); g_log(log_domain, log_level, "RealTimeMode : %u", capture_opts->real_time_mode); g_log(log_domain, log_level, "ShowInfo : %u", capture_opts->show_info); g_log(log_domain, log_level, "QuitAfterCap : %u", capture_opts->quit_after_cap); @@ -500,6 +502,9 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, } break; #endif + case 'n': /* Use pcapng format */ + capture_opts->use_pcapng = TRUE; + break; case 'p': /* Don't capture in promiscuous mode */ capture_opts->promisc_mode = FALSE; break; diff --git a/capture_opts.h b/capture_opts.h index 0ce50a2f88..7b7fb67d86 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -116,6 +116,7 @@ typedef struct capture_options_tag { "use default" */ gboolean saving_to_file; /**< TRUE if capture is writing to a file */ gchar *save_file; /**< the capture file name */ + gboolean use_pcapng; /**< TRUE if file format is pcapng */ /* GUI related */ gboolean real_time_mode; /**< Update list of packets in real time */ diff --git a/doc/dumpcap.pod b/doc/dumpcap.pod index 6b9723950a..597fe43a79 100644 --- a/doc/dumpcap.pod +++ b/doc/dumpcap.pod @@ -15,6 +15,7 @@ S<[ B<-f> Ecapture filterE ]> S<[ B<-h> ]> S<[ B<-i> Ecapture interfaceE|- ]> S<[ B<-L> ]> +S<[ B<-n> ]> S<[ B<-M> ]> S<[ B<-p> ]> S<[ B<-s> Ecapture snaplenE ]> @@ -28,6 +29,8 @@ B is a network traffic dump tool. It lets you capture packet data from a live network and write the packets to a file. B's native capture file format is B format, which is also the format used by B, B and various other tools. +When the B<-n> option is specified, the output file is written in the +new B format. Without any options set it will use the pcap library to capture traffic from the first available network @@ -165,6 +168,10 @@ link types can be used for the B<-y> option. When used with B<-D> and B<-L>, print verbose, machine-readable output. +=item -n + +Write the output file in the pcapng format instead of the default pcap format. + =item -p I put the interface into promiscuous mode. Note that the diff --git a/dumpcap.c b/dumpcap.c index 3ee06b8cf8..ca5a2a09f1 100644 --- a/dumpcap.c +++ b/dumpcap.c @@ -322,6 +322,7 @@ print_usage(gboolean print_ver) { fprintf(output, " -b ... duration:NUM - switch to next file after NUM secs\n"); fprintf(output, " filesize:NUM - switch to next file after NUM KB\n"); fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n"); + fprintf(output, " -n use pcapng format instead of pcap\n"); /*fprintf(output, "\n");*/ fprintf(output, "Miscellaneous:\n"); fprintf(output, " -v print version information and exit\n"); @@ -1475,9 +1476,20 @@ capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_d ld->pdh = libpcap_fdopen(save_file_fd, &err); } if (ld->pdh) { + gboolean successful; + ld->bytes_written = 0; - if (!libpcap_write_file_header(ld->pdh, ld->linktype, ld->file_snaplen, - &ld->bytes_written, &err)) { + if (capture_opts->use_pcapng) { + char appname[100]; + + g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion); + successful = libpcap_write_session_header_block(ld->pdh, appname, &ld->bytes_written, &err) && + libpcap_write_interface_description_block(ld->pdh, capture_opts->iface, capture_opts->cfilter, ld->linktype, ld->file_snaplen, &ld->bytes_written, &err); + } else { + successful = libpcap_write_file_header(ld->pdh, ld->linktype, ld->file_snaplen, + &ld->bytes_written, &err); + } + if (!successful) { fclose(ld->pdh); ld->pdh = NULL; } @@ -1527,6 +1539,9 @@ capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err if (capture_opts->multi_files_on) { return ringbuf_libpcap_dump_close(&capture_opts->save_file, err_close); } else { + if (capture_opts->use_pcapng) { + libpcap_write_interface_statistics_block(ld->pdh, 0, ld->pcap_h, &ld->bytes_written, err_close); + } return libpcap_dump_close(ld->pdh, err_close); } } @@ -1987,10 +2002,21 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct /* Switch to the next ringbuffer file */ if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file, &save_file_fd, &global_ld.err)) { + gboolean successful; + /* File switch succeeded: reset the conditions */ global_ld.bytes_written = 0; - if (!libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen, - &global_ld.bytes_written, &global_ld.err)) { + if (capture_opts->use_pcapng) { + char appname[100]; + + g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion); + successful = libpcap_write_session_header_block(global_ld.pdh, appname, &global_ld.bytes_written, &global_ld.err) && + libpcap_write_interface_description_block(global_ld.pdh, capture_opts->iface, capture_opts->cfilter, global_ld.linktype, global_ld.file_snaplen, &global_ld.bytes_written, &global_ld.err); + } else { + successful = libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen, + &global_ld.bytes_written, &global_ld.err); + } + if (!successful) { fclose(global_ld.pdh); global_ld.pdh = NULL; global_ld.go = FALSE; @@ -2068,10 +2094,21 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct /* Switch to the next ringbuffer file */ if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file, &save_file_fd, &global_ld.err)) { + gboolean successful; + /* file switch succeeded: reset the conditions */ global_ld.bytes_written = 0; - if (!libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen, - &global_ld.bytes_written, &global_ld.err)) { + if (capture_opts->use_pcapng) { + char appname[100]; + + g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion); + successful = libpcap_write_session_header_block(global_ld.pdh, appname, &global_ld.bytes_written, &global_ld.err) && + libpcap_write_interface_description_block(global_ld.pdh, capture_opts->iface, capture_opts->cfilter, global_ld.linktype, global_ld.file_snaplen, &global_ld.bytes_written, &global_ld.err); + } else { + successful = libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen, + &global_ld.bytes_written, &global_ld.err); + } + if (!successful) { fclose(global_ld.pdh); global_ld.pdh = NULL; global_ld.go = FALSE; @@ -2325,10 +2362,16 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr, return; if (ld->pdh) { + gboolean successful; /* We're supposed to write the packet to a file; do so. If this fails, set "ld->go" to FALSE, to stop the capture, and set "ld->err" to the error. */ - if (!libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err)) { + if (global_capture_opts.use_pcapng) { + successful = libpcap_write_enhanced_packet_block(ld->pdh, phdr, 0, pd, &ld->bytes_written, &err); + } else { + successful = libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err); + } + if (!successful) { ld->go = FALSE; ld->err = err; } else { @@ -2369,9 +2412,9 @@ main(int argc, char *argv[]) gint i; #ifdef HAVE_PCAP_REMOTE -#define OPTSTRING_INIT "a:A:b:c:Df:hi:Lm:MprSs:uvw:y:Z:" +#define OPTSTRING_INIT "a:A:b:c:Df:hi:Lm:MnprSs:uvw:y:Z:" #else -#define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z:" +#define OPTSTRING_INIT "a:b:c:Df:hi:LMnpSs:vw:y:Z:" #endif #ifdef _WIN32 @@ -2594,6 +2637,7 @@ main(int argc, char *argv[]) case 'c': /* Capture x packets */ case 'f': /* capture filter */ case 'i': /* Use interface x */ + case 'n': /* Use pcapng format */ case 'p': /* Don't capture in promiscuous mode */ case 's': /* Set the snapshot (capture) length */ case 'w': /* Write to capture file x */