pidl:dcerpc-*: regenerate dissectors after {NT,WERR,HRES}_errors_ext pidl changes
[wireshark-sm.git] / sharkd.c
blobcde63071095642f097fc6318405fc34c033901bf
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/report_message.h>
32 #include <wsutil/wslog.h>
33 #include <wsutil/version_info.h>
34 #include <wiretap/wtap_opttypes.h>
36 #include <epan/decode_as.h>
37 #include <epan/timestamp.h>
38 #include <epan/packet.h>
39 #include "frame_tvbuff.h"
40 #include <epan/disabled_protos.h>
41 #include <epan/prefs.h>
42 #include <epan/column.h>
43 #include <epan/print.h>
44 #include <epan/addr_resolv.h>
45 #include "ui/util.h"
46 #include "ui/ws_ui_util.h"
47 #include "ui/decode_as_utils.h"
48 #include "wsutil/filter_files.h"
49 #include "ui/tap_export_pdu.h"
50 #include "ui/failure_message.h"
51 #include "wtap.h"
52 #include <epan/epan_dissect.h>
53 #include <epan/tap.h>
54 #include <epan/uat-int.h>
55 #include <epan/secrets.h>
57 #include <wsutil/codecs.h>
59 #include <wsutil/str_util.h>
60 #include <wsutil/utf8_entities.h>
62 #ifdef HAVE_PLUGINS
63 #include <wsutil/plugins.h>
64 #endif
66 #include "sharkd.h"
68 #define SHARKD_INIT_FAILED 1
69 #define SHARKD_EPAN_INIT_FAIL 2
71 capture_file cfile;
73 static uint32_t cum_bytes;
74 static frame_data ref_frame;
76 static void sharkd_cmdarg_err(const char *msg_format, va_list ap);
77 static void sharkd_cmdarg_err_cont(const char *msg_format, va_list ap);
79 static void
80 print_current_user(void)
82 char *cur_user, *cur_group;
84 if (started_with_special_privs()) {
85 cur_user = get_cur_username();
86 cur_group = get_cur_groupname();
87 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
88 cur_user, cur_group);
89 g_free(cur_user);
90 g_free(cur_group);
91 if (running_with_special_privs()) {
92 fprintf(stderr, " This could be dangerous.");
94 fprintf(stderr, "\n");
98 int
99 main(int argc, char *argv[])
101 char *configuration_init_error;
103 char *err_msg = NULL;
104 e_prefs *prefs_p;
105 int ret = EXIT_SUCCESS;
106 static const struct report_message_routines sharkd_report_routines = {
107 failure_message,
108 failure_message,
109 open_failure_message,
110 read_failure_message,
111 write_failure_message,
112 cfile_open_failure_message,
113 cfile_dump_open_failure_message,
114 cfile_read_failure_message,
115 cfile_write_failure_message,
116 cfile_close_failure_message
119 cmdarg_err_init(sharkd_cmdarg_err, sharkd_cmdarg_err_cont);
121 /* Initialize log handler early so we can have proper logging during startup. */
122 ws_log_init("sharkd", vcmdarg_err);
124 /* Early logging command-line initialization. */
125 ws_log_parse_args(&argc, argv, vcmdarg_err, SHARKD_INIT_FAILED);
127 ws_noisy("Finished log init and parsing command line log arguments");
130 * Get credential information for later use, and drop privileges
131 * before doing anything else.
132 * Let the user know if anything happened.
134 init_process_policies();
135 relinquish_special_privs_perm();
136 print_current_user();
139 * Attempt to get the pathname of the executable file.
141 configuration_init_error = configuration_init(argv[0], NULL);
142 if (configuration_init_error != NULL) {
143 fprintf(stderr, "sharkd: Can't get pathname of sharkd program: %s.\n",
144 configuration_init_error);
147 /* Initialize the version information. */
148 ws_init_version_info("Sharkd",
149 epan_gather_compile_info,
150 epan_gather_runtime_info);
152 if (sharkd_init(argc, argv) < 0)
154 printf("cannot initialize sharkd\n");
155 ret = SHARKD_INIT_FAILED;
156 goto clean_exit;
159 init_report_message("sharkd", &sharkd_report_routines);
161 timestamp_set_type(TS_RELATIVE);
162 timestamp_set_precision(TS_PREC_AUTO);
163 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
166 * Libwiretap must be initialized before libwireshark is, so that
167 * dissection-time handlers for file-type-dependent blocks can
168 * register using the file type/subtype value for the file type.
170 wtap_init(true);
172 /* Register all dissectors; we must do this before checking for the
173 "-G" flag, as the "-G" flag dumps information registered by the
174 dissectors, and we must do it before we read the preferences, in
175 case any dissectors register preferences. */
176 if (!epan_init(NULL, NULL, true)) {
177 ret = SHARKD_EPAN_INIT_FAIL;
178 goto clean_exit;
181 codecs_init();
183 /* Load libwireshark settings from the current profile. */
184 prefs_p = epan_load_settings();
186 if (!color_filters_init(&err_msg, NULL)) {
187 fprintf(stderr, "%s\n", err_msg);
188 g_free(err_msg);
191 cap_file_init(&cfile);
193 /* Notify all registered modules that have had any of their preferences
194 changed either from one of the preferences file or from the command
195 line that their preferences have changed. */
196 prefs_apply_all();
198 /* Build the column format array */
199 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, true);
201 #ifdef HAVE_MAXMINDDB
202 /* 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.
203 * Need to stop it, otherwise all sharkd will have same mmdbresolve process, including pipe descriptors to read and write. */
204 uat_get_table_by_name("MaxMind Database Paths")->reset_cb();
205 #endif
207 ret = sharkd_loop(argc, argv);
208 clean_exit:
209 col_cleanup(&cfile.cinfo);
210 codecs_cleanup();
211 wtap_cleanup();
212 free_progdirs();
213 return ret;
216 static epan_t *
217 sharkd_epan_new(capture_file *cf)
219 static const struct packet_provider_funcs funcs = {
220 cap_file_provider_get_frame_ts,
221 cap_file_provider_get_interface_name,
222 cap_file_provider_get_interface_description,
223 cap_file_provider_get_modified_block
226 return epan_new(&cf->provider, &funcs);
229 static bool
230 process_packet(capture_file *cf, epan_dissect_t *edt,
231 int64_t offset, wtap_rec *rec, Buffer *buf)
233 frame_data fdlocal;
234 bool passed;
236 /* If we're not running a display filter and we're not printing any
237 packet information, we don't need to do a dissection. This means
238 that all packets can be marked as 'passed'. */
239 passed = true;
241 /* The frame number of this packet, if we add it to the set of frames,
242 would be one more than the count of frames in the file so far. */
243 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cum_bytes);
245 /* If we're going to print packet information, or we're going to
246 run a read filter, or display filter, or we're going to process taps, set up to
247 do a dissection and do so. */
248 if (edt) {
249 if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
250 gbl_resolv_flags.transport_name)
251 /* Grab any resolved addresses */
252 host_name_lookup_process();
254 /* If we're running a read filter, prime the epan_dissect_t with that
255 filter. */
256 if (cf->rfcode)
257 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
259 if (cf->dfcode)
260 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
262 /* This is the first and only pass, so prime the epan_dissect_t
263 with the hfids postdissectors want on the first pass. */
264 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
266 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
267 &cf->provider.ref, cf->provider.prev_dis);
268 if (cf->provider.ref == &fdlocal) {
269 ref_frame = fdlocal;
270 cf->provider.ref = &ref_frame;
273 epan_dissect_run(edt, cf->cd_t, rec,
274 frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf),
275 &fdlocal, NULL);
277 /* Run the read filter if we have one. */
278 if (cf->rfcode)
279 passed = dfilter_apply_edt(cf->rfcode, edt);
282 if (passed) {
283 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
284 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
286 /* If we're not doing dissection then there won't be any dependent frames.
287 * More importantly, edt.pi.fd.dependent_frames won't be initialized because
288 * epan hasn't been initialized.
289 * if we *are* doing dissection, then mark the dependent frames, but only
290 * if a display filter was given and it matches this packet.
292 if (edt && cf->dfcode) {
293 if (dfilter_apply_edt(cf->dfcode, edt) && edt->pi.fd->dependent_frames) {
294 g_hash_table_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
298 cf->count++;
299 } else {
300 /* if we don't add it to the frame_data_sequence, clean it up right now
301 * to avoid leaks */
302 frame_data_destroy(&fdlocal);
305 if (edt)
306 epan_dissect_reset(edt);
308 return passed;
312 static int
313 load_cap_file(capture_file *cf, int max_packet_count, int64_t max_byte_count)
315 int err;
316 char *err_info = NULL;
317 int64_t data_offset;
318 wtap_rec rec;
319 Buffer buf;
320 epan_dissect_t *edt = NULL;
323 /* Allocate a frame_data_sequence for all the frames. */
324 cf->provider.frames = new_frame_data_sequence();
327 bool create_proto_tree;
330 * Determine whether we need to create a protocol tree.
331 * We do if:
333 * we're going to apply a read filter;
335 * we're going to apply a display filter;
337 * a postdissector wants field values or protocols
338 * on the first pass.
340 create_proto_tree =
341 (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids());
343 /* We're not going to display the protocol tree on this pass,
344 so it's not going to be "visible". */
345 edt = epan_dissect_new(cf->epan, create_proto_tree, false);
348 wtap_rec_init(&rec);
349 ws_buffer_init(&buf, 1514);
351 while (wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, &data_offset)) {
352 if (process_packet(cf, edt, data_offset, &rec, &buf)) {
353 wtap_rec_reset(&rec);
354 /* Stop reading if we have the maximum number of packets;
355 * When the -c option has not been used, max_packet_count
356 * starts at 0, which practically means, never stop reading.
357 * (unless we roll over max_packet_count ?)
359 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
360 err = 0; /* This is not an error */
361 break;
366 if (edt) {
367 epan_dissect_free(edt);
368 edt = NULL;
371 wtap_rec_cleanup(&rec);
372 ws_buffer_free(&buf);
374 /* Close the sequential I/O side, to free up memory it requires. */
375 wtap_sequential_close(cf->provider.wth);
377 /* Allow the protocol dissectors to free up memory that they
378 * don't need after the sequential run-through of the packets. */
379 postseq_cleanup_all_protocols();
381 cf->provider.prev_dis = NULL;
382 cf->provider.prev_cap = NULL;
385 if (err != 0) {
386 cfile_read_failure_message(cf->filename, err, err_info);
389 return err;
392 cf_status_t
393 cf_open(capture_file *cf, const char *fname, unsigned int type, bool is_tempfile, int *err)
395 wtap *wth;
396 char *err_info;
398 wth = wtap_open_offline(fname, type, err, &err_info, true);
399 if (wth == NULL)
400 goto fail;
402 /* The open succeeded. Fill in the information for this file. */
404 cf->provider.wth = wth;
405 cf->f_datalen = 0; /* not used, but set it anyway */
407 /* Set the file name because we need it to set the follow stream filter.
408 XXX - is that still true? We need it for other reasons, though,
409 in any case. */
410 cf->filename = g_strdup(fname);
412 /* Indicate whether it's a permanent or temporary file. */
413 cf->is_tempfile = is_tempfile;
415 /* No user changes yet. */
416 cf->unsaved_changes = false;
418 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
419 cf->open_type = type;
420 cf->count = 0;
421 cf->drops_known = false;
422 cf->drops = 0;
423 cf->snap = wtap_snapshot_length(cf->provider.wth);
424 nstime_set_zero(&cf->elapsed_time);
425 cf->provider.ref = NULL;
426 cf->provider.prev_dis = NULL;
427 cf->provider.prev_cap = NULL;
429 /* Create new epan session for dissection. */
430 epan_free(cf->epan);
431 cf->epan = sharkd_epan_new(cf);
433 cf->state = FILE_READ_IN_PROGRESS;
435 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
436 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
437 wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback);
439 return CF_OK;
441 fail:
442 cfile_open_failure_message(fname, *err, err_info);
443 return CF_ERROR;
447 * Report an error in command-line arguments.
449 static void
450 sharkd_cmdarg_err(const char *msg_format, va_list ap)
452 fprintf(stderr, "sharkd: ");
453 vfprintf(stderr, msg_format, ap);
454 fprintf(stderr, "\n");
458 * Report additional information for an error in command-line arguments.
460 static void
461 sharkd_cmdarg_err_cont(const char *msg_format, va_list ap)
463 vfprintf(stderr, msg_format, ap);
464 fprintf(stderr, "\n");
467 cf_status_t
468 sharkd_cf_open(const char *fname, unsigned int type, bool is_tempfile, int *err)
470 return cf_open(&cfile, fname, type, is_tempfile, err);
474 sharkd_load_cap_file(void)
476 return load_cap_file(&cfile, 0, 0);
479 frame_data *
480 sharkd_get_frame(uint32_t framenum)
482 return frame_data_sequence_find(cfile.provider.frames, framenum);
485 enum dissect_request_status
486 sharkd_dissect_request(uint32_t framenum, uint32_t frame_ref_num,
487 uint32_t prev_dis_num, wtap_rec *rec, Buffer *buf,
488 column_info *cinfo, uint32_t dissect_flags,
489 sharkd_dissect_func_t cb, void *data,
490 int *err, char **err_info)
492 frame_data *fdata;
493 epan_dissect_t edt;
494 bool create_proto_tree;
496 fdata = sharkd_get_frame(framenum);
497 if (fdata == NULL)
498 return DISSECT_REQUEST_NO_SUCH_FRAME;
500 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, rec, buf, err, err_info)) {
501 if (cinfo != NULL)
502 col_fill_in_error(cinfo, fdata, false, false /* fill_fd_columns */);
503 return DISSECT_REQUEST_READ_ERROR; /* error reading the record */
506 create_proto_tree = ((dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ||
507 ((dissect_flags & SHARKD_DISSECT_FLAG_COLOR) && color_filters_used()) ||
508 (cinfo && have_custom_cols(cinfo)));
509 epan_dissect_init(&edt, cfile.epan, create_proto_tree, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE));
511 if (dissect_flags & SHARKD_DISSECT_FLAG_COLOR) {
512 color_filters_prime_edt(&edt);
513 fdata->need_colorize = 1;
516 if (cinfo)
517 col_custom_prime_edt(&edt, cinfo);
520 * XXX - need to catch an OutOfMemoryError exception and
521 * attempt to recover from it.
523 fdata->ref_time = (framenum == frame_ref_num);
524 fdata->frame_ref_num = frame_ref_num;
525 fdata->prev_dis_num = prev_dis_num;
526 epan_dissect_run(&edt, cfile.cd_t, rec,
527 frame_tvbuff_new_buffer(&cfile.provider, fdata, buf),
528 fdata, cinfo);
530 if (cinfo) {
531 /* "Stringify" non frame_data vals */
532 epan_dissect_fill_in_columns(&edt, false, true/* fill_fd_columns */);
535 cb(&edt, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ? edt.tree : NULL,
536 cinfo, (dissect_flags & SHARKD_DISSECT_FLAG_BYTES) ? edt.pi.data_src : NULL,
537 data);
539 wtap_rec_reset(rec);
540 epan_dissect_cleanup(&edt);
541 return DISSECT_REQUEST_SUCCESS;
545 sharkd_retap(void)
547 uint32_t framenum;
548 frame_data *fdata;
549 Buffer buf;
550 wtap_rec rec;
551 int err;
552 char *err_info = NULL;
554 unsigned tap_flags;
555 bool create_proto_tree;
556 epan_dissect_t edt;
557 column_info *cinfo;
559 /* Get the union of the flags for all tap listeners. */
560 tap_flags = union_of_tap_listener_flags();
562 /* If any tap listeners require the columns, construct them. */
563 cinfo = (tap_listeners_require_columns()) ? &cfile.cinfo : NULL;
566 * Determine whether we need to create a protocol tree.
567 * We do if:
569 * one of the tap listeners is going to apply a filter;
571 * one of the tap listeners requires a protocol tree.
573 create_proto_tree =
574 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
576 wtap_rec_init(&rec);
577 ws_buffer_init(&buf, 1514);
578 epan_dissect_init(&edt, cfile.epan, create_proto_tree, false);
580 reset_tap_listeners();
582 for (framenum = 1; framenum <= cfile.count; framenum++) {
583 fdata = sharkd_get_frame(framenum);
585 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info))
586 break;
588 fdata->ref_time = false;
589 fdata->frame_ref_num = (framenum != 1) ? 1 : 0;
590 fdata->prev_dis_num = framenum - 1;
591 epan_dissect_run_with_taps(&edt, cfile.cd_t, &rec,
592 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
593 fdata, cinfo);
594 wtap_rec_reset(&rec);
595 epan_dissect_reset(&edt);
598 wtap_rec_cleanup(&rec);
599 ws_buffer_free(&buf);
600 epan_dissect_cleanup(&edt);
602 draw_tap_listeners(true);
604 return 0;
608 sharkd_filter(const char *dftext, uint8_t **result)
610 dfilter_t *dfcode = NULL;
612 uint32_t framenum, prev_dis_num = 0;
613 uint32_t frames_count;
614 Buffer buf;
615 wtap_rec rec;
616 int err;
617 char *err_info = NULL;
619 uint8_t *result_bits;
620 uint8_t passed_bits;
622 epan_dissect_t edt;
624 if (!dfilter_compile(dftext, &dfcode, NULL)) {
625 return -1;
628 /* if dfilter_compile() success, but (dfcode == NULL) all frames are matching */
629 if (dfcode == NULL) {
630 *result = NULL;
631 return 0;
634 frames_count = cfile.count;
636 wtap_rec_init(&rec);
637 ws_buffer_init(&buf, 1514);
638 epan_dissect_init(&edt, cfile.epan, true, false);
640 passed_bits = 0;
641 result_bits = (uint8_t *) g_malloc(2 + (frames_count / 8));
643 for (framenum = 1; framenum <= frames_count; framenum++) {
644 frame_data *fdata = sharkd_get_frame(framenum);
646 if ((framenum & 7) == 0) {
647 result_bits[(framenum / 8) - 1] = passed_bits;
648 passed_bits = 0;
651 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info))
652 break;
654 /* frame_data_set_before_dissect */
655 epan_dissect_prime_with_dfilter(&edt, dfcode);
657 fdata->ref_time = false;
658 fdata->frame_ref_num = (framenum != 1) ? 1 : 0;
659 fdata->prev_dis_num = prev_dis_num;
660 epan_dissect_run(&edt, cfile.cd_t, &rec,
661 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
662 fdata, NULL);
664 if (dfilter_apply_edt(dfcode, &edt)) {
665 passed_bits |= (1 << (framenum % 8));
666 prev_dis_num = framenum;
669 /* if passed or ref -> frame_data_set_after_dissect */
671 wtap_rec_reset(&rec);
672 epan_dissect_reset(&edt);
675 if ((framenum & 7) == 0)
676 framenum--;
677 result_bits[framenum / 8] = passed_bits;
679 wtap_rec_cleanup(&rec);
680 ws_buffer_free(&buf);
681 epan_dissect_cleanup(&edt);
683 dfilter_free(dfcode);
685 *result = result_bits;
687 return framenum;
691 * Get the modified block if available, nothing otherwise.
692 * Must be cloned if changes desired.
694 wtap_block_t
695 sharkd_get_modified_block(const frame_data *fd)
697 return cap_file_provider_get_modified_block(&cfile.provider, fd);
701 * Gets the modified block if available, otherwise the packet's default block,
702 * or a new packet block.
703 * User must wtap_block_unref() it when done.
705 wtap_block_t
706 sharkd_get_packet_block(const frame_data *fd)
708 if (fd->has_modified_block)
709 return wtap_block_ref(cap_file_provider_get_modified_block(&cfile.provider, fd));
710 else
712 wtap_rec rec; /* Record metadata */
713 Buffer buf; /* Record data */
714 wtap_block_t block;
715 int err;
716 char *err_info;
718 wtap_rec_init(&rec);
719 ws_buffer_init(&buf, 1514);
721 if (!wtap_seek_read(cfile.provider.wth, fd->file_off, &rec, &buf, &err, &err_info))
722 { /* XXX, what we can do here? */ }
724 /* rec.block is owned by the record, steal it before it is gone. */
725 block = wtap_block_ref(rec.block);
727 wtap_rec_cleanup(&rec);
728 ws_buffer_free(&buf);
729 return block;
734 sharkd_set_modified_block(frame_data *fd, wtap_block_t new_block)
736 cap_file_provider_set_modified_block(&cfile.provider, fd, new_block);
737 return 0;