3 * Daemon variant of Wireshark
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include <epan/exceptions.h>
36 #include <epan/epan-int.h>
37 #include <epan/epan.h>
39 #include <wsutil/clopts_common.h>
40 #include <wsutil/cmdarg_err.h>
41 #include <wsutil/crash_info.h>
42 #include <wsutil/filesystem.h>
43 #include <wsutil/file_util.h>
44 #include <wsutil/privileges.h>
45 #include <wsutil/report_message.h>
46 #include <ws_version_info.h>
47 #include <wiretap/wtap_opttypes.h>
48 #include <wiretap/pcapng.h>
50 #include <epan/decode_as.h>
51 #include <epan/timestamp.h>
52 #include <epan/packet.h>
53 #include "frame_tvbuff.h"
54 #include <epan/disabled_protos.h>
55 #include <epan/prefs.h>
56 #include <epan/column.h>
57 #include <epan/print.h>
58 #include <epan/addr_resolv.h>
60 #include "ui/ui_util.h"
61 #include "ui/decode_as_utils.h"
62 #include "ui/filter_files.h"
63 #include "ui/tap_export_pdu.h"
64 #include "ui/failure_message.h"
66 #include <epan/epan_dissect.h>
69 #include <codecs/codecs.h>
73 #include <wsutil/str_util.h>
74 #include <wsutil/utf8_entities.h>
77 #include <wsutil/plugins.h>
83 #define EPAN_INIT_FAIL 2
85 static guint32 cum_bytes;
86 static const frame_data *ref;
87 static frame_data ref_frame;
88 static frame_data *prev_dis;
89 static frame_data *prev_cap;
91 static void failure_warning_message(const char *msg_format, va_list ap);
92 static void open_failure_message(const char *filename, int err,
93 gboolean for_writing);
94 static void read_failure_message(const char *filename, int err);
95 static void write_failure_message(const char *filename, int err);
96 static void failure_message_cont(const char *msg_format, va_list ap);
101 print_current_user(void) {
102 gchar *cur_user, *cur_group;
104 if (started_with_special_privs()) {
105 cur_user = get_cur_username();
106 cur_group = get_cur_groupname();
107 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
108 cur_user, cur_group);
111 if (running_with_special_privs()) {
112 fprintf(stderr, " This could be dangerous.");
114 fprintf(stderr, "\n");
119 main(int argc, char *argv[])
121 GString *comp_info_str;
122 GString *runtime_info_str;
123 char *init_progfile_dir_error;
125 char *err_msg = NULL;
127 int ret = EXIT_SUCCESS;
129 cmdarg_err_init(failure_warning_message, failure_message_cont);
132 * Get credential information for later use, and drop privileges
133 * before doing anything else.
134 * Let the user know if anything happened.
136 init_process_policies();
137 relinquish_special_privs_perm();
138 print_current_user();
141 * Attempt to get the pathname of the executable file.
143 init_progfile_dir_error = init_progfile_dir(argv[0], main);
144 if (init_progfile_dir_error != NULL) {
145 fprintf(stderr, "sharkd: Can't get pathname of sharkd program: %s.\n",
146 init_progfile_dir_error);
149 /* Get the compile-time version information string */
150 comp_info_str = get_compiled_version_info(NULL, epan_get_compiled_version_info);
152 /* Get the run-time version information string */
153 runtime_info_str = get_runtime_version_info(epan_get_runtime_version_info);
155 /* Add it to the information to be reported on a crash. */
156 ws_add_crash_info("Sharkd (Wireshark) %s\n"
161 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
162 g_string_free(comp_info_str, TRUE);
163 g_string_free(runtime_info_str, TRUE);
165 if (sharkd_init(argc, argv) < 0)
167 printf("cannot initialize sharkd\n");
172 init_report_message(failure_warning_message, failure_warning_message,
173 open_failure_message, read_failure_message,
174 write_failure_message);
176 timestamp_set_type(TS_RELATIVE);
177 timestamp_set_precision(TS_PREC_AUTO);
178 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
183 /* Register all the plugin types we have. */
184 epan_register_plugin_types(); /* Types known to libwireshark */
186 /* Scan for plugins. This does *not* call their registration routines;
187 that's done later. */
188 scan_plugins(REPORT_LOAD_FAILURE);
190 /* Register all libwiretap plugin modules. */
191 register_all_wiretap_modules();
194 register_all_codecs();
196 /* Register all dissectors; we must do this before checking for the
197 "-G" flag, as the "-G" flag dumps information registered by the
198 dissectors, and we must do it before we read the preferences, in
199 case any dissectors register preferences. */
200 if (!epan_init(register_all_protocols, register_all_protocol_handoffs, NULL,
202 ret = EPAN_INIT_FAIL;
206 /* Load libwireshark settings from the current profile. */
207 prefs_p = epan_load_settings();
209 read_filter_list(CFILTER_LIST);
211 if (!color_filters_init(&err_msg, NULL)) {
212 fprintf(stderr, "%s\n", err_msg);
216 cap_file_init(&cfile);
218 /* Notify all registered modules that have had any of their preferences
219 changed either from one of the preferences file or from the command
220 line that their preferences have changed. */
223 /* Build the column format array */
224 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
228 col_cleanup(&cfile.cinfo);
238 static const nstime_t *
239 sharkd_get_frame_ts(void *data, guint32 frame_num)
241 capture_file *cf = (capture_file *) data;
243 if (ref && ref->num == frame_num)
246 if (prev_dis && prev_dis->num == frame_num)
247 return &prev_dis->abs_ts;
249 if (prev_cap && prev_cap->num == frame_num)
250 return &prev_cap->abs_ts;
253 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
255 return (fd) ? &fd->abs_ts : NULL;
262 sharkd_epan_new(capture_file *cf)
264 epan_t *epan = epan_new();
267 epan->get_frame_ts = sharkd_get_frame_ts;
268 epan->get_interface_name = cap_file_get_interface_name;
269 epan->get_interface_description = cap_file_get_interface_description;
270 epan->get_user_comment = NULL;
276 process_packet(capture_file *cf, epan_dissect_t *edt,
277 gint64 offset, struct wtap_pkthdr *whdr,
284 /* The frame number of this packet is one more than the count of
285 frames in this packet. */
286 framenum = cf->count + 1;
288 /* If we're not running a display filter and we're not printing any
289 packet information, we don't need to do a dissection. This means
290 that all packets can be marked as 'passed'. */
293 frame_data_init(&fdlocal, framenum, whdr, offset, cum_bytes);
295 /* If we're going to print packet information, or we're going to
296 run a read filter, or display filter, or we're going to process taps, set up to
297 do a dissection and do so. */
299 if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
300 gbl_resolv_flags.transport_name)
301 /* Grab any resolved addresses */
302 host_name_lookup_process();
304 /* If we're running a read filter, prime the epan_dissect_t with that
307 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
310 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
312 /* This is the first and only pass, so prime the epan_dissect_t
313 with the hfids postdissectors want on the first pass. */
314 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
316 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
318 if (ref == &fdlocal) {
323 epan_dissect_run(edt, cf->cd_t, whdr, frame_tvbuff_new(&fdlocal, pd), &fdlocal, NULL);
325 /* Run the read filter if we have one. */
327 passed = dfilter_apply_edt(cf->rfcode, edt);
331 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
332 prev_cap = prev_dis = frame_data_sequence_add(cf->frames, &fdlocal);
334 /* If we're not doing dissection then there won't be any dependent frames.
335 * More importantly, edt.pi.dependent_frames won't be initialized because
336 * epan hasn't been initialized.
337 * if we *are* doing dissection, then mark the dependent frames, but only
338 * if a display filter was given and it matches this packet.
340 if (edt && cf->dfcode) {
341 if (dfilter_apply_edt(cf->dfcode, edt)) {
342 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
348 /* if we don't add it to the frame_data_sequence, clean it up right now
350 frame_data_destroy(&fdlocal);
354 epan_dissect_reset(edt);
361 load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
364 gchar *err_info = NULL;
366 epan_dissect_t *edt = NULL;
369 /* Allocate a frame_data_sequence for all the frames. */
370 cf->frames = new_frame_data_sequence();
373 gboolean create_proto_tree;
376 * Determine whether we need to create a protocol tree.
379 * we're going to apply a read filter;
381 * we're going to apply a display filter;
383 * a postdissector wants field values or protocols
387 (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids());
389 /* We're not going to display the protocol tree on this pass,
390 so it's not going to be "visible". */
391 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
394 while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
395 if (process_packet(cf, edt, data_offset, wtap_phdr(cf->wth),
396 wtap_buf_ptr(cf->wth))) {
397 /* Stop reading if we have the maximum number of packets;
398 * When the -c option has not been used, max_packet_count
399 * starts at 0, which practically means, never stop reading.
400 * (unless we roll over max_packet_count ?)
402 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
403 err = 0; /* This is not an error */
410 epan_dissect_free(edt);
414 /* Close the sequential I/O side, to free up memory it requires. */
415 wtap_sequential_close(cf->wth);
417 /* Allow the protocol dissectors to free up memory that they
418 * don't need after the sequential run-through of the packets. */
419 postseq_cleanup_all_protocols();
426 cfile_read_failure_message("sharkd", cf->filename, err, err_info);
433 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
438 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
442 /* The open succeeded. Fill in the information for this file. */
444 /* Create new epan session for dissection. */
446 cf->epan = sharkd_epan_new(cf);
449 cf->f_datalen = 0; /* not used, but set it anyway */
451 /* Set the file name because we need it to set the follow stream filter.
452 XXX - is that still true? We need it for other reasons, though,
454 cf->filename = g_strdup(fname);
456 /* Indicate whether it's a permanent or temporary file. */
457 cf->is_tempfile = is_tempfile;
459 /* No user changes yet. */
460 cf->unsaved_changes = FALSE;
462 cf->cd_t = wtap_file_type_subtype(cf->wth);
463 cf->open_type = type;
465 cf->drops_known = FALSE;
467 cf->snap = wtap_snapshot_length(cf->wth);
468 nstime_set_zero(&cf->elapsed_time);
473 cf->state = FILE_READ_IN_PROGRESS;
475 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
476 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
481 cfile_open_failure_message("sharkd", fname, *err, err_info);
486 * General errors and warnings are reported with an console message
490 failure_warning_message(const char *msg_format, va_list ap)
492 fprintf(stderr, "sharkd: ");
493 vfprintf(stderr, msg_format, ap);
494 fprintf(stderr, "\n");
498 * Open/create errors are reported with an console message in sharkd.
501 open_failure_message(const char *filename, int err, gboolean for_writing)
503 fprintf(stderr, "sharkd: ");
504 fprintf(stderr, file_open_error_message(err, for_writing), filename);
505 fprintf(stderr, "\n");
509 * Read errors are reported with an console message in sharkd.
512 read_failure_message(const char *filename, int err)
514 cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
515 filename, g_strerror(err));
519 * Write errors are reported with an console message in sharkd.
522 write_failure_message(const char *filename, int err)
524 cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
525 filename, g_strerror(err));
529 * Report additional information for an error in command-line arguments.
532 failure_message_cont(const char *msg_format, va_list ap)
534 vfprintf(stderr, msg_format, ap);
535 fprintf(stderr, "\n");
539 sharkd_cf_open(const char *fname, unsigned int type, gboolean is_tempfile, int *err)
541 return cf_open(&cfile, fname, type, is_tempfile, err);
545 sharkd_load_cap_file(void)
547 return load_cap_file(&cfile, 0, 0);
551 sharkd_dissect_request(unsigned int framenum, void (*cb)(packet_info *, proto_tree *, struct epan_column_info *, const GSList *, void *), int dissect_bytes, int dissect_columns, int dissect_tree, void *data)
554 column_info *cinfo = (dissect_columns) ? &cfile.cinfo : NULL;
556 gboolean create_proto_tree;
557 struct wtap_pkthdr phdr; /* Packet header */
558 Buffer buf; /* Packet data */
561 char *err_info = NULL;
563 fdata = frame_data_sequence_find(cfile.frames, framenum);
567 wtap_phdr_init(&phdr);
568 ws_buffer_init(&buf, 1500);
570 if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info)) {
571 ws_buffer_free(&buf);
572 return -1; /* error reading the record */
575 create_proto_tree = (dissect_tree) || (cinfo && have_custom_cols(cinfo));
576 epan_dissect_init(&edt, cfile.epan, create_proto_tree, dissect_tree);
579 col_custom_prime_edt(&edt, cinfo);
582 * XXX - need to catch an OutOfMemoryError exception and
583 * attempt to recover from it.
585 epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, cinfo);
588 /* "Stringify" non frame_data vals */
589 epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
592 cb(&edt.pi, dissect_tree ? edt.tree : NULL, cinfo, dissect_bytes ? edt.pi.data_src : NULL, data);
594 epan_dissect_cleanup(&edt);
595 wtap_phdr_cleanup(&phdr);
596 ws_buffer_free(&buf);
600 /* based on packet_list_dissect_and_cache_record */
602 sharkd_dissect_columns(int framenum, column_info *cinfo, gboolean dissect_color)
606 gboolean create_proto_tree;
607 struct wtap_pkthdr phdr; /* Packet header */
608 Buffer buf; /* Packet data */
611 char *err_info = NULL;
613 fdata = frame_data_sequence_find(cfile.frames, framenum);
615 col_fill_in_error(cinfo, fdata, FALSE, TRUE/* fill_fd_columns */);
616 return -1; /* error reading the record */
619 wtap_phdr_init(&phdr);
620 ws_buffer_init(&buf, 1500);
622 if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info)) {
623 col_fill_in_error(cinfo, fdata, FALSE, FALSE /* fill_fd_columns */);
624 ws_buffer_free(&buf);
625 return -1; /* error reading the record */
628 create_proto_tree = (dissect_color && color_filters_used()) || (cinfo && have_custom_cols(cinfo));
630 epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE /* proto_tree_visible */);
633 color_filters_prime_edt(&edt);
634 fdata->flags.need_colorize = 1;
638 col_custom_prime_edt(&edt, cinfo);
641 * XXX - need to catch an OutOfMemoryError exception and
642 * attempt to recover from it.
644 epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, cinfo);
647 /* "Stringify" non frame_data vals */
648 epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
651 epan_dissect_cleanup(&edt);
652 wtap_phdr_cleanup(&phdr);
653 ws_buffer_free(&buf);
663 struct wtap_pkthdr phdr;
665 char *err_info = NULL;
668 gboolean create_proto_tree;
672 /* Get the union of the flags for all tap listeners. */
673 tap_flags = union_of_tap_listener_flags();
675 /* If any tap listeners require the columns, construct them. */
676 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cfile.cinfo : NULL;
679 * Determine whether we need to create a protocol tree.
682 * one of the tap listeners is going to apply a filter;
684 * one of the tap listeners requires a protocol tree.
687 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
689 wtap_phdr_init(&phdr);
690 ws_buffer_init(&buf, 1500);
691 epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE);
693 reset_tap_listeners();
695 for (framenum = 1; framenum <= cfile.count; framenum++) {
696 fdata = frame_data_sequence_find(cfile.frames, framenum);
698 if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info))
701 epan_dissect_run_with_taps(&edt, cfile.cd_t, &phdr, frame_tvbuff_new(fdata, ws_buffer_start_ptr(&buf)), fdata, cinfo);
702 epan_dissect_reset(&edt);
705 wtap_phdr_cleanup(&phdr);
706 ws_buffer_free(&buf);
707 epan_dissect_cleanup(&edt);
709 draw_tap_listeners(TRUE);
715 sharkd_filter(const char *dftext, guint8 **result)
717 dfilter_t *dfcode = NULL;
720 guint32 frames_count;
722 struct wtap_pkthdr phdr;
724 char *err_info = NULL;
731 if (!dfilter_compile(dftext, &dfcode, &err_info)) {
736 frames_count = cfile.count;
738 wtap_phdr_init(&phdr);
739 ws_buffer_init(&buf, 1500);
740 epan_dissect_init(&edt, cfile.epan, TRUE, FALSE);
743 result_bits = (guint8 *) g_malloc(2 + (frames_count / 8));
745 for (framenum = 1; framenum <= frames_count; framenum++) {
746 frame_data *fdata = frame_data_sequence_find(cfile.frames, framenum);
748 if ((framenum & 7) == 0) {
749 result_bits[(framenum / 8) - 1] = passed_bits;
753 if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info))
756 /* frame_data_set_before_dissect */
757 epan_dissect_prime_with_dfilter(&edt, dfcode);
759 epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, NULL);
761 if (dfilter_apply_edt(dfcode, &edt))
762 passed_bits |= (1 << (framenum % 8));
764 /* if passed or ref -> frame_data_set_after_dissect */
766 epan_dissect_reset(&edt);
769 if ((framenum & 7) == 0)
771 result_bits[framenum / 8] = passed_bits;
773 wtap_phdr_cleanup(&phdr);
774 ws_buffer_free(&buf);
775 epan_dissect_cleanup(&edt);
777 dfilter_free(dfcode);
779 *result = result_bits;
785 const char *sharkd_version(void)
787 /* based on get_ws_vcs_version_info(), but shorter */
796 * Editor modelines - https://www.wireshark.org/tools/modelines.html
801 * indent-tabs-mode: nil
804 * vi: set shiftwidth=2 tabstop=8 expandtab:
805 * :indentSize=2:tabSize=8:noTabs=true: