update epan/dissectors/pidl/drsuapi/drsuapi.idl from samba
[wireshark-sm.git] / sharkd.c
blob155de57d73ec4073f2a962692e83f7d12edcb1cf
1 /* sharkd.c
3 * Daemon variant of Wireshark
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include <config.h>
13 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <signal.h>
21 #include <glib.h>
23 #include <epan/exceptions.h>
24 #include <epan/epan.h>
26 #include <wsutil/clopts_common.h>
27 #include <wsutil/cmdarg_err.h>
28 #include <wsutil/filesystem.h>
29 #include <wsutil/file_util.h>
30 #include <wsutil/privileges.h>
31 #include <wsutil/wslog.h>
32 #include <wsutil/version_info.h>
33 #include <wiretap/wtap_opttypes.h>
35 #include <epan/decode_as.h>
36 #include <epan/timestamp.h>
37 #include <epan/packet.h>
38 #include "frame_tvbuff.h"
39 #include <epan/disabled_protos.h>
40 #include <epan/prefs.h>
41 #include <epan/column.h>
42 #include <epan/print.h>
43 #include <epan/addr_resolv.h>
44 #include "ui/util.h"
45 #include "ui/ws_ui_util.h"
46 #include "ui/decode_as_utils.h"
47 #include "wsutil/filter_files.h"
48 #include "ui/tap_export_pdu.h"
49 #include "ui/failure_message.h"
50 #include <wiretap/wtap.h>
51 #include <epan/epan_dissect.h>
52 #include <epan/tap.h>
53 #include <epan/uat-int.h>
54 #include <epan/secrets.h>
56 #include <wsutil/codecs.h>
58 #include <wsutil/str_util.h>
59 #include <wsutil/utf8_entities.h>
61 #ifdef HAVE_PLUGINS
62 #include <wsutil/plugins.h>
63 #endif
65 #include "sharkd.h"
67 #define SHARKD_INIT_FAILED 1
68 #define SHARKD_EPAN_INIT_FAIL 2
70 capture_file cfile;
72 static uint32_t cum_bytes;
73 static frame_data ref_frame;
75 static void sharkd_cmdarg_err(const char *msg_format, va_list ap);
76 static void sharkd_cmdarg_err_cont(const char *msg_format, va_list ap);
78 static void
79 print_current_user(void)
81 char *cur_user, *cur_group;
83 if (started_with_special_privs()) {
84 cur_user = get_cur_username();
85 cur_group = get_cur_groupname();
86 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
87 cur_user, cur_group);
88 g_free(cur_user);
89 g_free(cur_group);
90 if (running_with_special_privs()) {
91 fprintf(stderr, " This could be dangerous.");
93 fprintf(stderr, "\n");
97 int
98 main(int argc, char *argv[])
100 char *configuration_init_error;
102 char *err_msg = NULL;
103 e_prefs *prefs_p;
104 int ret = EXIT_SUCCESS;
106 cmdarg_err_init(sharkd_cmdarg_err, sharkd_cmdarg_err_cont);
108 /* Initialize log handler early so we can have proper logging during startup. */
109 ws_log_init("sharkd", vcmdarg_err);
111 /* Early logging command-line initialization. */
112 ws_log_parse_args(&argc, argv, vcmdarg_err, SHARKD_INIT_FAILED);
114 ws_noisy("Finished log init and parsing command line log arguments");
117 * Get credential information for later use, and drop privileges
118 * before doing anything else.
119 * Let the user know if anything happened.
121 init_process_policies();
122 relinquish_special_privs_perm();
123 print_current_user();
126 * Attempt to get the pathname of the executable file.
128 configuration_init_error = configuration_init(argv[0], NULL);
129 if (configuration_init_error != NULL) {
130 fprintf(stderr, "sharkd: Can't get pathname of sharkd program: %s.\n",
131 configuration_init_error);
134 /* Initialize the version information. */
135 ws_init_version_info("Sharkd",
136 epan_gather_compile_info,
137 epan_gather_runtime_info);
139 if (sharkd_init(argc, argv) < 0)
141 printf("cannot initialize sharkd\n");
142 ret = SHARKD_INIT_FAILED;
143 goto clean_exit;
146 init_report_failure_message("sharkd");
148 timestamp_set_type(TS_RELATIVE);
149 timestamp_set_precision(TS_PREC_AUTO);
150 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
153 * Libwiretap must be initialized before libwireshark is, so that
154 * dissection-time handlers for file-type-dependent blocks can
155 * register using the file type/subtype value for the file type.
157 wtap_init(true);
159 /* Register all dissectors; we must do this before checking for the
160 "-G" flag, as the "-G" flag dumps information registered by the
161 dissectors, and we must do it before we read the preferences, in
162 case any dissectors register preferences. */
163 if (!epan_init(NULL, NULL, true)) {
164 ret = SHARKD_EPAN_INIT_FAIL;
165 goto clean_exit;
168 codecs_init();
170 /* Load libwireshark settings from the current profile. */
171 prefs_p = epan_load_settings();
173 if (!color_filters_init(&err_msg, NULL)) {
174 fprintf(stderr, "%s\n", err_msg);
175 g_free(err_msg);
178 cap_file_init(&cfile);
180 /* Notify all registered modules that have had any of their preferences
181 changed either from one of the preferences file or from the command
182 line that their preferences have changed. */
183 prefs_apply_all();
185 /* Build the column format array */
186 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, true);
188 #ifdef HAVE_MAXMINDDB
189 /* mmdbresolve is started from mmdb_resolve_start(), which is called from epan_load_settings via: read_prefs -> (...) uat_load_all -> maxmind_db_post_update_cb.
190 * Need to stop it, otherwise all sharkd will have same mmdbresolve process, including pipe descriptors to read and write. */
191 uat_get_table_by_name("MaxMind Database Paths")->reset_cb();
192 #endif
194 ret = sharkd_loop(argc, argv);
195 clean_exit:
196 col_cleanup(&cfile.cinfo);
197 codecs_cleanup();
198 wtap_cleanup();
199 free_progdirs();
200 return ret;
203 static epan_t *
204 sharkd_epan_new(capture_file *cf)
206 static const struct packet_provider_funcs funcs = {
207 cap_file_provider_get_frame_ts,
208 cap_file_provider_get_interface_name,
209 cap_file_provider_get_interface_description,
210 cap_file_provider_get_modified_block
213 return epan_new(&cf->provider, &funcs);
216 static bool
217 process_packet(capture_file *cf, epan_dissect_t *edt,
218 int64_t offset, wtap_rec *rec, Buffer *buf)
220 frame_data fdlocal;
221 bool passed;
223 /* If we're not running a display filter and we're not printing any
224 packet information, we don't need to do a dissection. This means
225 that all packets can be marked as 'passed'. */
226 passed = true;
228 /* The frame number of this packet, if we add it to the set of frames,
229 would be one more than the count of frames in the file so far. */
230 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cum_bytes);
232 /* If we're going to print packet information, or we're going to
233 run a read filter, or display filter, or we're going to process taps, set up to
234 do a dissection and do so. */
235 if (edt) {
236 if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
237 gbl_resolv_flags.transport_name)
238 /* Grab any resolved addresses */
239 host_name_lookup_process();
241 /* If we're running a read filter, prime the epan_dissect_t with that
242 filter. */
243 if (cf->rfcode)
244 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
246 if (cf->dfcode)
247 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
249 /* This is the first and only pass, so prime the epan_dissect_t
250 with the hfids postdissectors want on the first pass. */
251 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
253 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
254 &cf->provider.ref, cf->provider.prev_dis);
255 if (cf->provider.ref == &fdlocal) {
256 ref_frame = fdlocal;
257 cf->provider.ref = &ref_frame;
260 epan_dissect_run(edt, cf->cd_t, rec,
261 frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf),
262 &fdlocal, NULL);
264 /* Run the read filter if we have one. */
265 if (cf->rfcode)
266 passed = dfilter_apply_edt(cf->rfcode, edt);
269 if (passed) {
270 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
271 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
273 /* If we're not doing dissection then there won't be any dependent frames.
274 * More importantly, edt.pi.fd.dependent_frames won't be initialized because
275 * epan hasn't been initialized.
276 * if we *are* doing dissection, then mark the dependent frames, but only
277 * if a display filter was given and it matches this packet.
279 if (edt && cf->dfcode) {
280 if (dfilter_apply_edt(cf->dfcode, edt) && edt->pi.fd->dependent_frames) {
281 g_hash_table_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
285 cf->count++;
286 } else {
287 /* if we don't add it to the frame_data_sequence, clean it up right now
288 * to avoid leaks */
289 frame_data_destroy(&fdlocal);
292 if (edt)
293 epan_dissect_reset(edt);
295 return passed;
299 static int
300 load_cap_file(capture_file *cf, int max_packet_count, int64_t max_byte_count)
302 int err;
303 char *err_info = NULL;
304 int64_t data_offset;
305 wtap_rec rec;
306 Buffer buf;
307 epan_dissect_t *edt = NULL;
310 /* Allocate a frame_data_sequence for all the frames. */
311 cf->provider.frames = new_frame_data_sequence();
314 bool create_proto_tree;
317 * Determine whether we need to create a protocol tree.
318 * We do if:
320 * we're going to apply a read filter;
322 * we're going to apply a display filter;
324 * a postdissector wants field values or protocols
325 * on the first pass.
327 create_proto_tree =
328 (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids());
330 /* We're not going to display the protocol tree on this pass,
331 so it's not going to be "visible". */
332 edt = epan_dissect_new(cf->epan, create_proto_tree, false);
335 wtap_rec_init(&rec);
336 ws_buffer_init(&buf, 1514);
338 while (wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, &data_offset)) {
339 if (process_packet(cf, edt, data_offset, &rec, &buf)) {
340 wtap_rec_reset(&rec);
341 /* Stop reading if we have the maximum number of packets;
342 * When the -c option has not been used, max_packet_count
343 * starts at 0, which practically means, never stop reading.
344 * (unless we roll over max_packet_count ?)
346 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
347 err = 0; /* This is not an error */
348 break;
353 if (edt) {
354 epan_dissect_free(edt);
355 edt = NULL;
358 wtap_rec_cleanup(&rec);
359 ws_buffer_free(&buf);
361 /* Close the sequential I/O side, to free up memory it requires. */
362 wtap_sequential_close(cf->provider.wth);
364 /* Allow the protocol dissectors to free up memory that they
365 * don't need after the sequential run-through of the packets. */
366 postseq_cleanup_all_protocols();
368 cf->provider.prev_dis = NULL;
369 cf->provider.prev_cap = NULL;
372 if (err != 0) {
373 cfile_read_failure_message(cf->filename, err, err_info);
376 return err;
379 cf_status_t
380 cf_open(capture_file *cf, const char *fname, unsigned int type, bool is_tempfile, int *err)
382 wtap *wth;
383 char *err_info;
385 wth = wtap_open_offline(fname, type, err, &err_info, true);
386 if (wth == NULL)
387 goto fail;
389 /* The open succeeded. Fill in the information for this file. */
391 cf->provider.wth = wth;
392 cf->f_datalen = 0; /* not used, but set it anyway */
394 /* Set the file name because we need it to set the follow stream filter.
395 XXX - is that still true? We need it for other reasons, though,
396 in any case. */
397 cf->filename = g_strdup(fname);
399 /* Indicate whether it's a permanent or temporary file. */
400 cf->is_tempfile = is_tempfile;
402 /* No user changes yet. */
403 cf->unsaved_changes = false;
405 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
406 cf->open_type = type;
407 cf->count = 0;
408 cf->drops_known = false;
409 cf->drops = 0;
410 cf->snap = wtap_snapshot_length(cf->provider.wth);
411 nstime_set_zero(&cf->elapsed_time);
412 cf->provider.ref = NULL;
413 cf->provider.prev_dis = NULL;
414 cf->provider.prev_cap = NULL;
416 /* Create new epan session for dissection. */
417 epan_free(cf->epan);
418 cf->epan = sharkd_epan_new(cf);
420 cf->state = FILE_READ_IN_PROGRESS;
422 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
423 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
424 wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback);
426 return CF_OK;
428 fail:
429 cfile_open_failure_message(fname, *err, err_info);
430 return CF_ERROR;
434 * Report an error in command-line arguments.
436 static void
437 sharkd_cmdarg_err(const char *msg_format, va_list ap)
439 fprintf(stderr, "sharkd: ");
440 vfprintf(stderr, msg_format, ap);
441 fprintf(stderr, "\n");
445 * Report additional information for an error in command-line arguments.
447 static void
448 sharkd_cmdarg_err_cont(const char *msg_format, va_list ap)
450 vfprintf(stderr, msg_format, ap);
451 fprintf(stderr, "\n");
454 cf_status_t
455 sharkd_cf_open(const char *fname, unsigned int type, bool is_tempfile, int *err)
457 return cf_open(&cfile, fname, type, is_tempfile, err);
461 sharkd_load_cap_file(void)
463 return load_cap_file(&cfile, 0, 0);
466 frame_data *
467 sharkd_get_frame(uint32_t framenum)
469 return frame_data_sequence_find(cfile.provider.frames, framenum);
472 enum dissect_request_status
473 sharkd_dissect_request(uint32_t framenum, uint32_t frame_ref_num,
474 uint32_t prev_dis_num, wtap_rec *rec, Buffer *buf,
475 column_info *cinfo, uint32_t dissect_flags,
476 sharkd_dissect_func_t cb, void *data,
477 int *err, char **err_info)
479 frame_data *fdata;
480 epan_dissect_t edt;
481 bool create_proto_tree;
483 fdata = sharkd_get_frame(framenum);
484 if (fdata == NULL)
485 return DISSECT_REQUEST_NO_SUCH_FRAME;
487 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, rec, buf, err, err_info)) {
488 if (cinfo != NULL)
489 col_fill_in_error(cinfo, fdata, false, false /* fill_fd_columns */);
490 return DISSECT_REQUEST_READ_ERROR; /* error reading the record */
493 create_proto_tree = ((dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ||
494 ((dissect_flags & SHARKD_DISSECT_FLAG_COLOR) && color_filters_used()) ||
495 (cinfo && have_custom_cols(cinfo)));
496 epan_dissect_init(&edt, cfile.epan, create_proto_tree, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE));
498 if (dissect_flags & SHARKD_DISSECT_FLAG_COLOR) {
499 color_filters_prime_edt(&edt);
500 fdata->need_colorize = 1;
503 if (cinfo)
504 col_custom_prime_edt(&edt, cinfo);
507 * XXX - need to catch an OutOfMemoryError exception and
508 * attempt to recover from it.
510 fdata->ref_time = (framenum == frame_ref_num);
511 fdata->frame_ref_num = frame_ref_num;
512 fdata->prev_dis_num = prev_dis_num;
513 epan_dissect_run(&edt, cfile.cd_t, rec,
514 frame_tvbuff_new_buffer(&cfile.provider, fdata, buf),
515 fdata, cinfo);
517 if (cinfo) {
518 /* "Stringify" non frame_data vals */
519 epan_dissect_fill_in_columns(&edt, false, true/* fill_fd_columns */);
522 cb(&edt, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ? edt.tree : NULL,
523 cinfo, (dissect_flags & SHARKD_DISSECT_FLAG_BYTES) ? edt.pi.data_src : NULL,
524 data);
526 wtap_rec_reset(rec);
527 epan_dissect_cleanup(&edt);
528 return DISSECT_REQUEST_SUCCESS;
532 sharkd_retap(void)
534 uint32_t framenum;
535 frame_data *fdata;
536 Buffer buf;
537 wtap_rec rec;
538 int err;
539 char *err_info = NULL;
541 unsigned tap_flags;
542 bool create_proto_tree;
543 epan_dissect_t edt;
544 column_info *cinfo;
546 /* Get the union of the flags for all tap listeners. */
547 tap_flags = union_of_tap_listener_flags();
549 /* If any tap listeners require the columns, construct them. */
550 cinfo = (tap_listeners_require_columns()) ? &cfile.cinfo : NULL;
553 * Determine whether we need to create a protocol tree.
554 * We do if:
556 * one of the tap listeners is going to apply a filter;
558 * one of the tap listeners requires a protocol tree.
560 create_proto_tree =
561 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
563 wtap_rec_init(&rec);
564 ws_buffer_init(&buf, 1514);
565 epan_dissect_init(&edt, cfile.epan, create_proto_tree, false);
567 reset_tap_listeners();
569 for (framenum = 1; framenum <= cfile.count; framenum++) {
570 fdata = sharkd_get_frame(framenum);
572 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info))
573 break;
575 fdata->ref_time = false;
576 fdata->frame_ref_num = (framenum != 1) ? 1 : 0;
577 fdata->prev_dis_num = framenum - 1;
578 epan_dissect_run_with_taps(&edt, cfile.cd_t, &rec,
579 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
580 fdata, cinfo);
581 wtap_rec_reset(&rec);
582 epan_dissect_reset(&edt);
585 wtap_rec_cleanup(&rec);
586 ws_buffer_free(&buf);
587 epan_dissect_cleanup(&edt);
589 draw_tap_listeners(true);
591 return 0;
595 sharkd_filter(const char *dftext, uint8_t **result)
597 dfilter_t *dfcode = NULL;
599 uint32_t framenum, prev_dis_num = 0;
600 uint32_t frames_count;
601 Buffer buf;
602 wtap_rec rec;
603 int err;
604 char *err_info = NULL;
606 uint8_t *result_bits;
607 uint8_t passed_bits;
609 epan_dissect_t edt;
611 if (!dfilter_compile(dftext, &dfcode, NULL)) {
612 return -1;
615 /* if dfilter_compile() success, but (dfcode == NULL) all frames are matching */
616 if (dfcode == NULL) {
617 *result = NULL;
618 return 0;
621 frames_count = cfile.count;
623 wtap_rec_init(&rec);
624 ws_buffer_init(&buf, 1514);
625 epan_dissect_init(&edt, cfile.epan, true, false);
627 passed_bits = 0;
628 result_bits = (uint8_t *) g_malloc(2 + (frames_count / 8));
630 for (framenum = 1; framenum <= frames_count; framenum++) {
631 frame_data *fdata = sharkd_get_frame(framenum);
633 if ((framenum & 7) == 0) {
634 result_bits[(framenum / 8) - 1] = passed_bits;
635 passed_bits = 0;
638 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info))
639 break;
641 /* frame_data_set_before_dissect */
642 epan_dissect_prime_with_dfilter(&edt, dfcode);
644 fdata->ref_time = false;
645 fdata->frame_ref_num = (framenum != 1) ? 1 : 0;
646 fdata->prev_dis_num = prev_dis_num;
647 epan_dissect_run(&edt, cfile.cd_t, &rec,
648 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
649 fdata, NULL);
651 if (dfilter_apply_edt(dfcode, &edt)) {
652 passed_bits |= (1 << (framenum % 8));
653 prev_dis_num = framenum;
656 /* if passed or ref -> frame_data_set_after_dissect */
658 wtap_rec_reset(&rec);
659 epan_dissect_reset(&edt);
662 if ((framenum & 7) == 0)
663 framenum--;
664 result_bits[framenum / 8] = passed_bits;
666 wtap_rec_cleanup(&rec);
667 ws_buffer_free(&buf);
668 epan_dissect_cleanup(&edt);
670 dfilter_free(dfcode);
672 *result = result_bits;
674 return framenum;
678 * Get the modified block if available, nothing otherwise.
679 * Must be cloned if changes desired.
681 wtap_block_t
682 sharkd_get_modified_block(const frame_data *fd)
684 return cap_file_provider_get_modified_block(&cfile.provider, fd);
688 * Gets the modified block if available, otherwise the packet's default block,
689 * or a new packet block.
690 * User must wtap_block_unref() it when done.
692 wtap_block_t
693 sharkd_get_packet_block(const frame_data *fd)
695 if (fd->has_modified_block)
696 return wtap_block_ref(cap_file_provider_get_modified_block(&cfile.provider, fd));
697 else
699 wtap_rec rec; /* Record metadata */
700 Buffer buf; /* Record data */
701 wtap_block_t block;
702 int err;
703 char *err_info;
705 wtap_rec_init(&rec);
706 ws_buffer_init(&buf, 1514);
708 if (!wtap_seek_read(cfile.provider.wth, fd->file_off, &rec, &buf, &err, &err_info))
709 { /* XXX, what we can do here? */ }
711 /* rec.block is owned by the record, steal it before it is gone. */
712 block = wtap_block_ref(rec.block);
714 wtap_rec_cleanup(&rec);
715 ws_buffer_free(&buf);
716 return block;
721 sharkd_set_modified_block(frame_data *fd, wtap_block_t new_block)
723 cap_file_provider_set_modified_block(&cfile.provider, fd, new_block);
724 return 0;