SMB2: dissect new signing capability negotiate context
[wireshark-sm.git] / sharkd.c
blob467e3c330a7a02d5abad83042832db3463ed41ca
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>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <limits.h>
18 #include <errno.h>
19 #include <signal.h>
21 #include <glib.h>
23 #include <epan/exceptions.h>
24 #include <epan/epan.h>
26 #include <ui/clopts_common.h>
27 #include <ui/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 <version_info.h>
33 #include <wiretap/wtap_opttypes.h>
34 #include <wiretap/pcapng.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 "ui/filter_files.h"
49 #include "ui/tap_export_pdu.h"
50 #include "ui/failure_message.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 "log.h"
60 #include <wsutil/str_util.h>
61 #include <wsutil/utf8_entities.h>
63 #ifdef HAVE_PLUGINS
64 #include <wsutil/plugins.h>
65 #endif
67 #include "sharkd.h"
69 #define INIT_FAILED 1
70 #define EPAN_INIT_FAIL 2
72 capture_file cfile;
74 static guint32 cum_bytes;
75 static frame_data ref_frame;
77 static void failure_warning_message(const char *msg_format, va_list ap);
78 static void open_failure_message(const char *filename, int err,
79 gboolean for_writing);
80 static void read_failure_message(const char *filename, int err);
81 static void write_failure_message(const char *filename, int err);
82 static void failure_message_cont(const char *msg_format, va_list ap);
84 static void
85 print_current_user(void) {
86 gchar *cur_user, *cur_group;
88 if (started_with_special_privs()) {
89 cur_user = get_cur_username();
90 cur_group = get_cur_groupname();
91 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
92 cur_user, cur_group);
93 g_free(cur_user);
94 g_free(cur_group);
95 if (running_with_special_privs()) {
96 fprintf(stderr, " This could be dangerous.");
98 fprintf(stderr, "\n");
103 main(int argc, char *argv[])
105 char *init_progfile_dir_error;
107 char *err_msg = NULL;
108 e_prefs *prefs_p;
109 int ret = EXIT_SUCCESS;
111 cmdarg_err_init(failure_warning_message, failure_message_cont);
114 * Get credential information for later use, and drop privileges
115 * before doing anything else.
116 * Let the user know if anything happened.
118 init_process_policies();
119 relinquish_special_privs_perm();
120 print_current_user();
123 * Attempt to get the pathname of the executable file.
125 init_progfile_dir_error = init_progfile_dir(argv[0]);
126 if (init_progfile_dir_error != NULL) {
127 fprintf(stderr, "sharkd: Can't get pathname of sharkd program: %s.\n",
128 init_progfile_dir_error);
131 /* Initialize the version information. */
132 ws_init_version_info("Sharkd (Wireshark)", NULL,
133 epan_get_compiled_version_info,
134 epan_get_runtime_version_info);
136 if (sharkd_init(argc, argv) < 0)
138 printf("cannot initialize sharkd\n");
139 ret = INIT_FAILED;
140 goto clean_exit;
143 init_report_message(failure_warning_message, failure_warning_message,
144 open_failure_message, read_failure_message,
145 write_failure_message);
147 timestamp_set_type(TS_RELATIVE);
148 timestamp_set_precision(TS_PREC_AUTO);
149 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
151 wtap_init(TRUE);
153 /* Register all dissectors; we must do this before checking for the
154 "-G" flag, as the "-G" flag dumps information registered by the
155 dissectors, and we must do it before we read the preferences, in
156 case any dissectors register preferences. */
157 if (!epan_init(NULL, NULL, TRUE)) {
158 ret = EPAN_INIT_FAIL;
159 goto clean_exit;
162 codecs_init();
164 /* Load libwireshark settings from the current profile. */
165 prefs_p = epan_load_settings();
167 read_filter_list(CFILTER_LIST);
169 if (!color_filters_init(&err_msg, NULL)) {
170 fprintf(stderr, "%s\n", err_msg);
171 g_free(err_msg);
174 cap_file_init(&cfile);
176 /* Notify all registered modules that have had any of their preferences
177 changed either from one of the preferences file or from the command
178 line that their preferences have changed. */
179 prefs_apply_all();
181 /* Build the column format array */
182 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
184 #ifdef HAVE_MAXMINDDB
185 /* 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.
186 * Need to stop it, otherwise all sharkd will have same mmdbresolve process, including pipe descriptors to read and write. */
187 uat_clear(uat_get_table_by_name("MaxMind Database Paths"));
188 #endif
190 ret = sharkd_loop();
191 clean_exit:
192 col_cleanup(&cfile.cinfo);
193 free_filter_lists();
194 codecs_cleanup();
195 wtap_cleanup();
196 free_progdirs();
197 return ret;
200 static const nstime_t *
201 sharkd_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
203 if (prov->ref && prov->ref->num == frame_num)
204 return &prov->ref->abs_ts;
206 if (prov->prev_dis && prov->prev_dis->num == frame_num)
207 return &prov->prev_dis->abs_ts;
209 if (prov->prev_cap && prov->prev_cap->num == frame_num)
210 return &prov->prev_cap->abs_ts;
212 if (prov->frames) {
213 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
215 return (fd) ? &fd->abs_ts : NULL;
218 return NULL;
221 static epan_t *
222 sharkd_epan_new(capture_file *cf)
224 static const struct packet_provider_funcs funcs = {
225 sharkd_get_frame_ts,
226 cap_file_provider_get_interface_name,
227 cap_file_provider_get_interface_description,
228 cap_file_provider_get_user_comment
231 return epan_new(&cf->provider, &funcs);
234 static gboolean
235 process_packet(capture_file *cf, epan_dissect_t *edt,
236 gint64 offset, wtap_rec *rec, Buffer *buf)
238 frame_data fdlocal;
239 gboolean passed;
241 /* If we're not running a display filter and we're not printing any
242 packet information, we don't need to do a dissection. This means
243 that all packets can be marked as 'passed'. */
244 passed = TRUE;
246 /* The frame number of this packet, if we add it to the set of frames,
247 would be one more than the count of frames in the file so far. */
248 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cum_bytes);
250 /* If we're going to print packet information, or we're going to
251 run a read filter, or display filter, or we're going to process taps, set up to
252 do a dissection and do so. */
253 if (edt) {
254 if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
255 gbl_resolv_flags.transport_name)
256 /* Grab any resolved addresses */
257 host_name_lookup_process();
259 /* If we're running a read filter, prime the epan_dissect_t with that
260 filter. */
261 if (cf->rfcode)
262 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
264 if (cf->dfcode)
265 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
267 /* This is the first and only pass, so prime the epan_dissect_t
268 with the hfids postdissectors want on the first pass. */
269 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
271 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
272 &cf->provider.ref, cf->provider.prev_dis);
273 if (cf->provider.ref == &fdlocal) {
274 ref_frame = fdlocal;
275 cf->provider.ref = &ref_frame;
278 epan_dissect_run(edt, cf->cd_t, rec,
279 frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf),
280 &fdlocal, NULL);
282 /* Run the read filter if we have one. */
283 if (cf->rfcode)
284 passed = dfilter_apply_edt(cf->rfcode, edt);
287 if (passed) {
288 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
289 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
291 /* If we're not doing dissection then there won't be any dependent frames.
292 * More importantly, edt.pi.dependent_frames won't be initialized because
293 * epan hasn't been initialized.
294 * if we *are* doing dissection, then mark the dependent frames, but only
295 * if a display filter was given and it matches this packet.
297 if (edt && cf->dfcode) {
298 if (dfilter_apply_edt(cf->dfcode, edt)) {
299 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
303 cf->count++;
304 } else {
305 /* if we don't add it to the frame_data_sequence, clean it up right now
306 * to avoid leaks */
307 frame_data_destroy(&fdlocal);
310 if (edt)
311 epan_dissect_reset(edt);
313 return passed;
317 static int
318 load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
320 int err;
321 gchar *err_info = NULL;
322 gint64 data_offset;
323 wtap_rec rec;
324 Buffer buf;
325 epan_dissect_t *edt = NULL;
328 /* Allocate a frame_data_sequence for all the frames. */
329 cf->provider.frames = new_frame_data_sequence();
332 gboolean create_proto_tree;
335 * Determine whether we need to create a protocol tree.
336 * We do if:
338 * we're going to apply a read filter;
340 * we're going to apply a display filter;
342 * a postdissector wants field values or protocols
343 * on the first pass.
345 create_proto_tree =
346 (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids());
348 /* We're not going to display the protocol tree on this pass,
349 so it's not going to be "visible". */
350 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
353 wtap_rec_init(&rec);
354 ws_buffer_init(&buf, 1514);
356 while (wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, &data_offset)) {
357 if (process_packet(cf, edt, data_offset, &rec, &buf)) {
358 /* Stop reading if we have the maximum number of packets;
359 * When the -c option has not been used, max_packet_count
360 * starts at 0, which practically means, never stop reading.
361 * (unless we roll over max_packet_count ?)
363 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
364 err = 0; /* This is not an error */
365 break;
370 if (edt) {
371 epan_dissect_free(edt);
372 edt = NULL;
375 wtap_rec_cleanup(&rec);
376 ws_buffer_free(&buf);
378 /* Close the sequential I/O side, to free up memory it requires. */
379 wtap_sequential_close(cf->provider.wth);
381 /* Allow the protocol dissectors to free up memory that they
382 * don't need after the sequential run-through of the packets. */
383 postseq_cleanup_all_protocols();
385 cf->provider.prev_dis = NULL;
386 cf->provider.prev_cap = NULL;
389 if (err != 0) {
390 cfile_read_failure_message("sharkd", cf->filename, err, err_info);
393 return err;
396 cf_status_t
397 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
399 wtap *wth;
400 gchar *err_info;
402 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
403 if (wth == NULL)
404 goto fail;
406 /* The open succeeded. Fill in the information for this file. */
408 cf->provider.wth = wth;
409 cf->f_datalen = 0; /* not used, but set it anyway */
411 /* Set the file name because we need it to set the follow stream filter.
412 XXX - is that still true? We need it for other reasons, though,
413 in any case. */
414 cf->filename = g_strdup(fname);
416 /* Indicate whether it's a permanent or temporary file. */
417 cf->is_tempfile = is_tempfile;
419 /* No user changes yet. */
420 cf->unsaved_changes = FALSE;
422 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
423 cf->open_type = type;
424 cf->count = 0;
425 cf->drops_known = FALSE;
426 cf->drops = 0;
427 cf->snap = wtap_snapshot_length(cf->provider.wth);
428 nstime_set_zero(&cf->elapsed_time);
429 cf->provider.ref = NULL;
430 cf->provider.prev_dis = NULL;
431 cf->provider.prev_cap = NULL;
433 /* Create new epan session for dissection. */
434 epan_free(cf->epan);
435 cf->epan = sharkd_epan_new(cf);
437 cf->state = FILE_READ_IN_PROGRESS;
439 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
440 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
441 wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback);
443 return CF_OK;
445 fail:
446 cfile_open_failure_message("sharkd", fname, *err, err_info);
447 return CF_ERROR;
451 * General errors and warnings are reported with an console message
452 * in sharkd.
454 static void
455 failure_warning_message(const char *msg_format, va_list ap)
457 fprintf(stderr, "sharkd: ");
458 vfprintf(stderr, msg_format, ap);
459 fprintf(stderr, "\n");
463 * Open/create errors are reported with an console message in sharkd.
465 static void
466 open_failure_message(const char *filename, int err, gboolean for_writing)
468 fprintf(stderr, "sharkd: ");
469 fprintf(stderr, file_open_error_message(err, for_writing), filename);
470 fprintf(stderr, "\n");
474 * Read errors are reported with an console message in sharkd.
476 static void
477 read_failure_message(const char *filename, int err)
479 cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
480 filename, g_strerror(err));
484 * Write errors are reported with an console message in sharkd.
486 static void
487 write_failure_message(const char *filename, int err)
489 cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
490 filename, g_strerror(err));
494 * Report additional information for an error in command-line arguments.
496 static void
497 failure_message_cont(const char *msg_format, va_list ap)
499 vfprintf(stderr, msg_format, ap);
500 fprintf(stderr, "\n");
503 cf_status_t
504 sharkd_cf_open(const char *fname, unsigned int type, gboolean is_tempfile, int *err)
506 return cf_open(&cfile, fname, type, is_tempfile, err);
510 sharkd_load_cap_file(void)
512 return load_cap_file(&cfile, 0, 0);
515 frame_data *
516 sharkd_get_frame(guint32 framenum)
518 return frame_data_sequence_find(cfile.provider.frames, framenum);
522 sharkd_dissect_request(guint32 framenum, guint32 frame_ref_num, guint32 prev_dis_num, sharkd_dissect_func_t cb, guint32 dissect_flags, void *data)
524 frame_data *fdata;
525 column_info *cinfo = (dissect_flags & SHARKD_DISSECT_FLAG_COLUMNS) ? &cfile.cinfo : NULL;
526 epan_dissect_t edt;
527 gboolean create_proto_tree;
528 wtap_rec rec; /* Record metadata */
529 Buffer buf; /* Record data */
531 int err;
532 char *err_info = NULL;
534 fdata = sharkd_get_frame(framenum);
535 if (fdata == NULL)
536 return -1;
538 wtap_rec_init(&rec);
539 ws_buffer_init(&buf, 1514);
541 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info)) {
542 wtap_rec_cleanup(&rec);
543 ws_buffer_free(&buf);
544 return -1; /* error reading the record */
547 create_proto_tree = ((dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ||
548 ((dissect_flags & SHARKD_DISSECT_FLAG_COLOR) && color_filters_used()) ||
549 (cinfo && have_custom_cols(cinfo)));
550 epan_dissect_init(&edt, cfile.epan, create_proto_tree, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE));
552 if (dissect_flags & SHARKD_DISSECT_FLAG_COLOR) {
553 color_filters_prime_edt(&edt);
554 fdata->need_colorize = 1;
557 if (cinfo)
558 col_custom_prime_edt(&edt, cinfo);
561 * XXX - need to catch an OutOfMemoryError exception and
562 * attempt to recover from it.
564 fdata->ref_time = (framenum == frame_ref_num);
565 fdata->frame_ref_num = frame_ref_num;
566 fdata->prev_dis_num = prev_dis_num;
567 epan_dissect_run(&edt, cfile.cd_t, &rec,
568 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
569 fdata, cinfo);
571 if (cinfo) {
572 /* "Stringify" non frame_data vals */
573 epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
576 cb(&edt, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ? edt.tree : NULL,
577 cinfo, (dissect_flags & SHARKD_DISSECT_FLAG_BYTES) ? edt.pi.data_src : NULL,
578 data);
580 epan_dissect_cleanup(&edt);
581 wtap_rec_cleanup(&rec);
582 ws_buffer_free(&buf);
583 return 0;
586 /* based on packet_list_dissect_and_cache_record */
588 sharkd_dissect_columns(frame_data *fdata, guint32 frame_ref_num, guint32 prev_dis_num, column_info *cinfo, gboolean dissect_color)
590 epan_dissect_t edt;
591 gboolean create_proto_tree;
592 wtap_rec rec; /* Record metadata */
593 Buffer buf; /* Record data */
595 int err;
596 char *err_info = NULL;
598 wtap_rec_init(&rec);
599 ws_buffer_init(&buf, 1514);
601 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info)) {
602 col_fill_in_error(cinfo, fdata, FALSE, FALSE /* fill_fd_columns */);
603 wtap_rec_cleanup(&rec);
604 ws_buffer_free(&buf);
605 return -1; /* error reading the record */
608 create_proto_tree = (dissect_color && color_filters_used()) || (cinfo && have_custom_cols(cinfo));
610 epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE /* proto_tree_visible */);
612 if (dissect_color) {
613 color_filters_prime_edt(&edt);
614 fdata->need_colorize = 1;
617 if (cinfo)
618 col_custom_prime_edt(&edt, cinfo);
621 * XXX - need to catch an OutOfMemoryError exception and
622 * attempt to recover from it.
624 fdata->ref_time = (fdata->num == frame_ref_num);
625 fdata->frame_ref_num = frame_ref_num;
626 fdata->prev_dis_num = prev_dis_num;
627 epan_dissect_run(&edt, cfile.cd_t, &rec,
628 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
629 fdata, cinfo);
631 if (cinfo) {
632 /* "Stringify" non frame_data vals */
633 epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
636 epan_dissect_cleanup(&edt);
637 wtap_rec_cleanup(&rec);
638 ws_buffer_free(&buf);
639 return 0;
643 sharkd_retap(void)
645 guint32 framenum;
646 frame_data *fdata;
647 Buffer buf;
648 wtap_rec rec;
649 int err;
650 char *err_info = NULL;
652 guint tap_flags;
653 gboolean create_proto_tree;
654 epan_dissect_t edt;
655 column_info *cinfo;
657 /* Get the union of the flags for all tap listeners. */
658 tap_flags = union_of_tap_listener_flags();
660 /* If any tap listeners require the columns, construct them. */
661 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cfile.cinfo : NULL;
664 * Determine whether we need to create a protocol tree.
665 * We do if:
667 * one of the tap listeners is going to apply a filter;
669 * one of the tap listeners requires a protocol tree.
671 create_proto_tree =
672 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
674 wtap_rec_init(&rec);
675 ws_buffer_init(&buf, 1514);
676 epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE);
678 reset_tap_listeners();
680 for (framenum = 1; framenum <= cfile.count; framenum++) {
681 fdata = sharkd_get_frame(framenum);
683 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info))
684 break;
686 fdata->ref_time = FALSE;
687 fdata->frame_ref_num = (framenum != 1) ? 1 : 0;
688 fdata->prev_dis_num = framenum - 1;
689 epan_dissect_run_with_taps(&edt, cfile.cd_t, &rec,
690 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
691 fdata, cinfo);
692 epan_dissect_reset(&edt);
695 wtap_rec_cleanup(&rec);
696 ws_buffer_free(&buf);
697 epan_dissect_cleanup(&edt);
699 draw_tap_listeners(TRUE);
701 return 0;
705 sharkd_filter(const char *dftext, guint8 **result)
707 dfilter_t *dfcode = NULL;
709 guint32 framenum, prev_dis_num = 0;
710 guint32 frames_count;
711 Buffer buf;
712 wtap_rec rec;
713 int err;
714 char *err_info = NULL;
716 guint8 *result_bits;
717 guint8 passed_bits;
719 epan_dissect_t edt;
721 if (!dfilter_compile(dftext, &dfcode, &err_info)) {
722 g_free(err_info);
723 return -1;
726 /* if dfilter_compile() success, but (dfcode == NULL) all frames are matching */
727 if (dfcode == NULL) {
728 *result = NULL;
729 return 0;
732 frames_count = cfile.count;
734 wtap_rec_init(&rec);
735 ws_buffer_init(&buf, 1514);
736 epan_dissect_init(&edt, cfile.epan, TRUE, FALSE);
738 passed_bits = 0;
739 result_bits = (guint8 *) g_malloc(2 + (frames_count / 8));
741 for (framenum = 1; framenum <= frames_count; framenum++) {
742 frame_data *fdata = sharkd_get_frame(framenum);
744 if ((framenum & 7) == 0) {
745 result_bits[(framenum / 8) - 1] = passed_bits;
746 passed_bits = 0;
749 if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info))
750 break;
752 /* frame_data_set_before_dissect */
753 epan_dissect_prime_with_dfilter(&edt, dfcode);
755 fdata->ref_time = FALSE;
756 fdata->frame_ref_num = (framenum != 1) ? 1 : 0;
757 fdata->prev_dis_num = prev_dis_num;
758 epan_dissect_run(&edt, cfile.cd_t, &rec,
759 frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf),
760 fdata, NULL);
762 if (dfilter_apply_edt(dfcode, &edt)) {
763 passed_bits |= (1 << (framenum % 8));
764 prev_dis_num = framenum;
767 /* if passed or ref -> frame_data_set_after_dissect */
769 epan_dissect_reset(&edt);
772 if ((framenum & 7) == 0)
773 framenum--;
774 result_bits[framenum / 8] = passed_bits;
776 wtap_rec_cleanup(&rec);
777 ws_buffer_free(&buf);
778 epan_dissect_cleanup(&edt);
780 dfilter_free(dfcode);
782 *result = result_bits;
784 return framenum;
787 const char *
788 sharkd_get_user_comment(const frame_data *fd)
790 return cap_file_provider_get_user_comment(&cfile.provider, fd);
794 sharkd_set_user_comment(frame_data *fd, const gchar *new_comment)
796 cap_file_provider_set_user_comment(&cfile.provider, fd, new_comment);
797 return 0;
800 #include "version.h"
801 const char *sharkd_version(void)
803 /* based on get_ws_vcs_version_info(), but shorter */
804 #ifdef VCSVERSION
805 return VCSVERSION;
806 #else
807 return VERSION;
808 #endif
812 * Editor modelines - https://www.wireshark.org/tools/modelines.html
814 * Local variables:
815 * c-basic-offset: 2
816 * tab-width: 8
817 * indent-tabs-mode: nil
818 * End:
820 * vi: set shiftwidth=2 tabstop=8 expandtab:
821 * :indentSize=2:tabSize=8:noTabs=true: