Use cfile fields for some frame_data pointers.
[metze/wireshark/wip.git] / sharkd.c
1 /* sharkd.c
2  *
3  * Daemon variant of Wireshark
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0+
10  */
11
12 #include <config.h>
13
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <limits.h>
18 #include <errno.h>
19 #include <signal.h>
20
21 #include <glib.h>
22
23 #include <epan/exceptions.h>
24 #include <epan/epan-int.h>
25 #include <epan/epan.h>
26
27 #include <wsutil/clopts_common.h>
28 #include <wsutil/cmdarg_err.h>
29 #include <wsutil/crash_info.h>
30 #include <wsutil/filesystem.h>
31 #include <wsutil/file_util.h>
32 #include <wsutil/privileges.h>
33 #include <wsutil/report_message.h>
34 #include <version_info.h>
35 #include <wiretap/wtap_opttypes.h>
36 #include <wiretap/pcapng.h>
37
38 #include <epan/decode_as.h>
39 #include <epan/timestamp.h>
40 #include <epan/packet.h>
41 #include "frame_tvbuff.h"
42 #include <epan/disabled_protos.h>
43 #include <epan/prefs.h>
44 #include <epan/column.h>
45 #include <epan/print.h>
46 #include <epan/addr_resolv.h>
47 #include "ui/util.h"
48 #include "ui/ws_ui_util.h"
49 #include "ui/decode_as_utils.h"
50 #include "ui/filter_files.h"
51 #include "ui/tap_export_pdu.h"
52 #include "ui/failure_message.h"
53 #include "epan/register.h"
54 #include <epan/epan_dissect.h>
55 #include <epan/tap.h>
56
57 #include <codecs/codecs.h>
58
59 #include "log.h"
60
61 #include <wsutil/str_util.h>
62 #include <wsutil/utf8_entities.h>
63
64 #ifdef HAVE_PLUGINS
65 #include <wsutil/plugins.h>
66 #endif
67
68 #include "sharkd.h"
69
70 #define INIT_FAILED 1
71 #define EPAN_INIT_FAIL 2
72
73 capture_file cfile;
74
75 static guint32 cum_bytes;
76 static frame_data ref_frame;
77
78 static void failure_warning_message(const char *msg_format, va_list ap);
79 static void open_failure_message(const char *filename, int err,
80     gboolean for_writing);
81 static void read_failure_message(const char *filename, int err);
82 static void write_failure_message(const char *filename, int err);
83 static void failure_message_cont(const char *msg_format, va_list ap);
84
85 static void
86 print_current_user(void) {
87   gchar *cur_user, *cur_group;
88
89   if (started_with_special_privs()) {
90     cur_user = get_cur_username();
91     cur_group = get_cur_groupname();
92     fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
93       cur_user, cur_group);
94     g_free(cur_user);
95     g_free(cur_group);
96     if (running_with_special_privs()) {
97       fprintf(stderr, " This could be dangerous.");
98     }
99     fprintf(stderr, "\n");
100   }
101 }
102
103 int
104 main(int argc, char *argv[])
105 {
106   GString             *comp_info_str;
107   GString             *runtime_info_str;
108   char                *init_progfile_dir_error;
109
110   char                *err_msg = NULL;
111   e_prefs             *prefs_p;
112   int                  ret = EXIT_SUCCESS;
113
114   cmdarg_err_init(failure_warning_message, failure_message_cont);
115
116   /*
117    * Get credential information for later use, and drop privileges
118    * before doing anything else.
119    * Let the user know if anything happened.
120    */
121   init_process_policies();
122   relinquish_special_privs_perm();
123   print_current_user();
124
125   /*
126    * Attempt to get the pathname of the executable file.
127    */
128   init_progfile_dir_error = init_progfile_dir(argv[0], main);
129   if (init_progfile_dir_error != NULL) {
130     fprintf(stderr, "sharkd: Can't get pathname of sharkd program: %s.\n",
131             init_progfile_dir_error);
132   }
133
134   /* Get the compile-time version information string */
135   comp_info_str = get_compiled_version_info(NULL, epan_get_compiled_version_info);
136
137   /* Get the run-time version information string */
138   runtime_info_str = get_runtime_version_info(epan_get_runtime_version_info);
139
140   /* Add it to the information to be reported on a crash. */
141   ws_add_crash_info("Sharkd (Wireshark) %s\n"
142          "\n"
143          "%s"
144          "\n"
145          "%s",
146       get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
147   g_string_free(comp_info_str, TRUE);
148   g_string_free(runtime_info_str, TRUE);
149
150   if (sharkd_init(argc, argv) < 0)
151   {
152     printf("cannot initialize sharkd\n");
153     ret = INIT_FAILED;
154     goto clean_exit;
155   }
156
157   init_report_message(failure_warning_message, failure_warning_message,
158                       open_failure_message, read_failure_message,
159                       write_failure_message);
160
161   timestamp_set_type(TS_RELATIVE);
162   timestamp_set_precision(TS_PREC_AUTO);
163   timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
164
165   wtap_init();
166
167 #ifdef HAVE_PLUGINS
168   /* Register all the plugin types we have. */
169   epan_register_plugin_types(); /* Types known to libwireshark */
170
171   /* Scan for plugins.  This does *not* call their registration routines;
172      that's done later. */
173   scan_plugins(REPORT_LOAD_FAILURE);
174
175   /* Register all libwiretap plugin modules. */
176   register_all_wiretap_modules();
177 #endif
178
179   register_all_codecs();
180
181   /* Register all dissectors; we must do this before checking for the
182      "-G" flag, as the "-G" flag dumps information registered by the
183      dissectors, and we must do it before we read the preferences, in
184      case any dissectors register preferences. */
185   if (!epan_init(register_all_protocols, register_all_protocol_handoffs, NULL,
186                  NULL)) {
187     ret = EPAN_INIT_FAIL;
188     goto clean_exit;
189   }
190
191   /* Load libwireshark settings from the current profile. */
192   prefs_p = epan_load_settings();
193
194   read_filter_list(CFILTER_LIST);
195
196   if (!color_filters_init(&err_msg, NULL)) {
197      fprintf(stderr, "%s\n", err_msg);
198      g_free(err_msg);
199   }
200
201   cap_file_init(&cfile);
202
203   /* Notify all registered modules that have had any of their preferences
204      changed either from one of the preferences file or from the command
205      line that their preferences have changed. */
206   prefs_apply_all();
207
208   /* Build the column format array */
209   build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
210
211   ret = sharkd_loop();
212 clean_exit:
213   col_cleanup(&cfile.cinfo);
214   free_filter_lists();
215   wtap_cleanup();
216   free_progdirs();
217 #ifdef HAVE_PLUGINS
218   plugins_cleanup();
219 #endif
220   return ret;
221 }
222
223 static const nstime_t *
224 sharkd_get_frame_ts(capture_file *cf, guint32 frame_num)
225 {
226   if (cf->ref && cf->ref->num == frame_num)
227     return &cf->ref->abs_ts;
228
229   if (cf->prev_dis && cf->prev_dis->num == frame_num)
230     return &cf->prev_dis->abs_ts;
231
232   if (cf->prev_cap && cf->prev_cap->num == frame_num)
233     return &cf->prev_cap->abs_ts;
234
235   if (cf->frames) {
236      frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
237
238      return (fd) ? &fd->abs_ts : NULL;
239   }
240
241   return NULL;
242 }
243
244 static epan_t *
245 sharkd_epan_new(capture_file *cf)
246 {
247   epan_t *epan = epan_new();
248
249   epan->cf = cf;
250   epan->get_frame_ts = sharkd_get_frame_ts;
251   epan->get_interface_name = cap_file_get_interface_name;
252   epan->get_interface_description = cap_file_get_interface_description;
253   epan->get_user_comment = NULL;
254
255   return epan;
256 }
257
258 static gboolean
259 process_packet(capture_file *cf, epan_dissect_t *edt,
260                gint64 offset, struct wtap_pkthdr *whdr,
261                const guchar *pd)
262 {
263   frame_data     fdlocal;
264   guint32        framenum;
265   gboolean       passed;
266
267   /* The frame number of this packet is one more than the count of
268      frames in this packet. */
269   framenum = cf->count + 1;
270
271   /* If we're not running a display filter and we're not printing any
272      packet information, we don't need to do a dissection. This means
273      that all packets can be marked as 'passed'. */
274   passed = TRUE;
275
276   frame_data_init(&fdlocal, framenum, whdr, offset, cum_bytes);
277
278   /* If we're going to print packet information, or we're going to
279      run a read filter, or display filter, or we're going to process taps, set up to
280      do a dissection and do so. */
281   if (edt) {
282     if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
283         gbl_resolv_flags.transport_name)
284       /* Grab any resolved addresses */
285       host_name_lookup_process();
286
287     /* If we're running a read filter, prime the epan_dissect_t with that
288        filter. */
289     if (cf->rfcode)
290       epan_dissect_prime_with_dfilter(edt, cf->rfcode);
291
292     if (cf->dfcode)
293       epan_dissect_prime_with_dfilter(edt, cf->dfcode);
294
295     /* This is the first and only pass, so prime the epan_dissect_t
296        with the hfids postdissectors want on the first pass. */
297     prime_epan_dissect_with_postdissector_wanted_hfids(edt);
298
299     frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
300                                   &cf->ref, cf->prev_dis);
301     if (cf->ref == &fdlocal) {
302       ref_frame = fdlocal;
303       cf->ref = &ref_frame;
304     }
305
306     epan_dissect_run(edt, cf->cd_t, whdr, frame_tvbuff_new(&fdlocal, pd), &fdlocal, NULL);
307
308     /* Run the read filter if we have one. */
309     if (cf->rfcode)
310       passed = dfilter_apply_edt(cf->rfcode, edt);
311   }
312
313   if (passed) {
314     frame_data_set_after_dissect(&fdlocal, &cum_bytes);
315     cf->prev_cap = cf->prev_dis = frame_data_sequence_add(cf->frames, &fdlocal);
316
317     /* If we're not doing dissection then there won't be any dependent frames.
318      * More importantly, edt.pi.dependent_frames won't be initialized because
319      * epan hasn't been initialized.
320      * if we *are* doing dissection, then mark the dependent frames, but only
321      * if a display filter was given and it matches this packet.
322      */
323     if (edt && cf->dfcode) {
324       if (dfilter_apply_edt(cf->dfcode, edt)) {
325         g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
326       }
327     }
328
329     cf->count++;
330   } else {
331     /* if we don't add it to the frame_data_sequence, clean it up right now
332      * to avoid leaks */
333     frame_data_destroy(&fdlocal);
334   }
335
336   if (edt)
337     epan_dissect_reset(edt);
338
339   return passed;
340 }
341
342
343 static int
344 load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
345 {
346   int          err;
347   gchar       *err_info = NULL;
348   gint64       data_offset;
349   epan_dissect_t *edt = NULL;
350
351   {
352     /* Allocate a frame_data_sequence for all the frames. */
353     cf->frames = new_frame_data_sequence();
354
355     {
356       gboolean create_proto_tree;
357
358       /*
359        * Determine whether we need to create a protocol tree.
360        * We do if:
361        *
362        *    we're going to apply a read filter;
363        *
364        *    we're going to apply a display filter;
365        *
366        *    a postdissector wants field values or protocols
367        *    on the first pass.
368        */
369       create_proto_tree =
370         (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids());
371
372       /* We're not going to display the protocol tree on this pass,
373          so it's not going to be "visible". */
374       edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
375     }
376
377     while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
378       if (process_packet(cf, edt, data_offset, wtap_phdr(cf->wth),
379                          wtap_buf_ptr(cf->wth))) {
380         /* Stop reading if we have the maximum number of packets;
381          * When the -c option has not been used, max_packet_count
382          * starts at 0, which practically means, never stop reading.
383          * (unless we roll over max_packet_count ?)
384          */
385         if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
386           err = 0; /* This is not an error */
387           break;
388         }
389       }
390     }
391
392     if (edt) {
393       epan_dissect_free(edt);
394       edt = NULL;
395     }
396
397     /* Close the sequential I/O side, to free up memory it requires. */
398     wtap_sequential_close(cf->wth);
399
400     /* Allow the protocol dissectors to free up memory that they
401      * don't need after the sequential run-through of the packets. */
402     postseq_cleanup_all_protocols();
403
404     cf->prev_dis = NULL;
405     cf->prev_cap = NULL;
406   }
407
408   if (err != 0) {
409     cfile_read_failure_message("sharkd", cf->filename, err, err_info);
410   }
411
412   return err;
413 }
414
415 cf_status_t
416 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
417 {
418   wtap  *wth;
419   gchar *err_info;
420
421   wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
422   if (wth == NULL)
423     goto fail;
424
425   /* The open succeeded.  Fill in the information for this file. */
426
427   /* Create new epan session for dissection. */
428   epan_free(cf->epan);
429   cf->epan = sharkd_epan_new(cf);
430
431   cf->wth = wth;
432   cf->f_datalen = 0; /* not used, but set it anyway */
433
434   /* Set the file name because we need it to set the follow stream filter.
435      XXX - is that still true?  We need it for other reasons, though,
436      in any case. */
437   cf->filename = g_strdup(fname);
438
439   /* Indicate whether it's a permanent or temporary file. */
440   cf->is_tempfile = is_tempfile;
441
442   /* No user changes yet. */
443   cf->unsaved_changes = FALSE;
444
445   cf->cd_t      = wtap_file_type_subtype(cf->wth);
446   cf->open_type = type;
447   cf->count     = 0;
448   cf->drops_known = FALSE;
449   cf->drops     = 0;
450   cf->snap      = wtap_snapshot_length(cf->wth);
451   nstime_set_zero(&cf->elapsed_time);
452   cf->ref       = NULL;
453   cf->prev_dis  = NULL;
454   cf->prev_cap  = NULL;
455
456   cf->state = FILE_READ_IN_PROGRESS;
457
458   wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
459   wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
460
461   return CF_OK;
462
463 fail:
464   cfile_open_failure_message("sharkd", fname, *err, err_info);
465   return CF_ERROR;
466 }
467
468 /*
469  * General errors and warnings are reported with an console message
470  * in sharkd.
471  */
472 static void
473 failure_warning_message(const char *msg_format, va_list ap)
474 {
475   fprintf(stderr, "sharkd: ");
476   vfprintf(stderr, msg_format, ap);
477   fprintf(stderr, "\n");
478 }
479
480 /*
481  * Open/create errors are reported with an console message in sharkd.
482  */
483 static void
484 open_failure_message(const char *filename, int err, gboolean for_writing)
485 {
486   fprintf(stderr, "sharkd: ");
487   fprintf(stderr, file_open_error_message(err, for_writing), filename);
488   fprintf(stderr, "\n");
489 }
490
491 /*
492  * Read errors are reported with an console message in sharkd.
493  */
494 static void
495 read_failure_message(const char *filename, int err)
496 {
497   cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
498           filename, g_strerror(err));
499 }
500
501 /*
502  * Write errors are reported with an console message in sharkd.
503  */
504 static void
505 write_failure_message(const char *filename, int err)
506 {
507   cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
508           filename, g_strerror(err));
509 }
510
511 /*
512  * Report additional information for an error in command-line arguments.
513  */
514 static void
515 failure_message_cont(const char *msg_format, va_list ap)
516 {
517   vfprintf(stderr, msg_format, ap);
518   fprintf(stderr, "\n");
519 }
520
521 cf_status_t
522 sharkd_cf_open(const char *fname, unsigned int type, gboolean is_tempfile, int *err)
523 {
524   return cf_open(&cfile, fname, type, is_tempfile, err);
525 }
526
527 int
528 sharkd_load_cap_file(void)
529 {
530   return load_cap_file(&cfile, 0, 0);
531 }
532
533 int
534 sharkd_dissect_request(unsigned int framenum, void (*cb)(epan_dissect_t *, proto_tree *, struct epan_column_info *, const GSList *, void *), int dissect_bytes, int dissect_columns, int dissect_tree, void *data)
535 {
536   frame_data *fdata;
537   column_info *cinfo = (dissect_columns) ? &cfile.cinfo : NULL;
538   epan_dissect_t edt;
539   gboolean create_proto_tree;
540   struct wtap_pkthdr phdr; /* Packet header */
541   Buffer buf; /* Packet data */
542
543   int err;
544   char *err_info = NULL;
545
546   fdata = frame_data_sequence_find(cfile.frames, framenum);
547   if (fdata == NULL)
548     return -1;
549
550   wtap_phdr_init(&phdr);
551   ws_buffer_init(&buf, 1500);
552
553   if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info)) {
554     ws_buffer_free(&buf);
555     return -1; /* error reading the record */
556   }
557
558   create_proto_tree = (dissect_tree) || (cinfo && have_custom_cols(cinfo));
559   epan_dissect_init(&edt, cfile.epan, create_proto_tree, dissect_tree);
560
561   if (cinfo)
562     col_custom_prime_edt(&edt, cinfo);
563
564   /*
565    * XXX - need to catch an OutOfMemoryError exception and
566    * attempt to recover from it.
567    */
568   epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, cinfo);
569
570   if (cinfo) {
571     /* "Stringify" non frame_data vals */
572     epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
573   }
574
575   cb(&edt, dissect_tree ? edt.tree : NULL, cinfo, dissect_bytes ? edt.pi.data_src : NULL, data);
576
577   epan_dissect_cleanup(&edt);
578   wtap_phdr_cleanup(&phdr);
579   ws_buffer_free(&buf);
580   return 0;
581 }
582
583 /* based on packet_list_dissect_and_cache_record */
584 int
585 sharkd_dissect_columns(int framenum, column_info *cinfo, gboolean dissect_color)
586 {
587   frame_data *fdata;
588   epan_dissect_t edt;
589   gboolean create_proto_tree;
590   struct wtap_pkthdr phdr; /* Packet header */
591   Buffer buf; /* Packet data */
592
593   int err;
594   char *err_info = NULL;
595
596   fdata = frame_data_sequence_find(cfile.frames, framenum);
597   if (fdata == NULL) {
598     col_fill_in_error(cinfo, fdata, FALSE, TRUE/* fill_fd_columns */);
599     return -1; /* error reading the record */
600   }
601
602   wtap_phdr_init(&phdr);
603   ws_buffer_init(&buf, 1500);
604
605   if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info)) {
606     col_fill_in_error(cinfo, fdata, FALSE, FALSE /* fill_fd_columns */);
607     ws_buffer_free(&buf);
608     return -1; /* error reading the record */
609   }
610
611   create_proto_tree = (dissect_color && color_filters_used()) || (cinfo && have_custom_cols(cinfo));
612
613   epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE /* proto_tree_visible */);
614
615   if (dissect_color) {
616     color_filters_prime_edt(&edt);
617     fdata->flags.need_colorize = 1;
618   }
619
620   if (cinfo)
621     col_custom_prime_edt(&edt, cinfo);
622
623   /*
624    * XXX - need to catch an OutOfMemoryError exception and
625    * attempt to recover from it.
626    */
627   epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, cinfo);
628
629   if (cinfo) {
630     /* "Stringify" non frame_data vals */
631     epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
632   }
633
634   epan_dissect_cleanup(&edt);
635   wtap_phdr_cleanup(&phdr);
636   ws_buffer_free(&buf);
637   return 0;
638 }
639
640 int
641 sharkd_retap(void)
642 {
643   guint32          framenum;
644   frame_data      *fdata;
645   Buffer           buf;
646   struct wtap_pkthdr phdr;
647   int err;
648   char *err_info = NULL;
649
650   guint         tap_flags;
651   gboolean      create_proto_tree;
652   epan_dissect_t edt;
653   column_info   *cinfo;
654
655   /* Get the union of the flags for all tap listeners. */
656   tap_flags = union_of_tap_listener_flags();
657
658   /* If any tap listeners require the columns, construct them. */
659   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cfile.cinfo : NULL;
660
661   /*
662    * Determine whether we need to create a protocol tree.
663    * We do if:
664    *
665    *    one of the tap listeners is going to apply a filter;
666    *
667    *    one of the tap listeners requires a protocol tree.
668    */
669   create_proto_tree =
670     (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
671
672   wtap_phdr_init(&phdr);
673   ws_buffer_init(&buf, 1500);
674   epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE);
675
676   reset_tap_listeners();
677
678   for (framenum = 1; framenum <= cfile.count; framenum++) {
679     fdata = frame_data_sequence_find(cfile.frames, framenum);
680
681     if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info))
682       break;
683
684     epan_dissect_run_with_taps(&edt, cfile.cd_t, &phdr, frame_tvbuff_new(fdata, ws_buffer_start_ptr(&buf)), fdata, cinfo);
685     epan_dissect_reset(&edt);
686   }
687
688   wtap_phdr_cleanup(&phdr);
689   ws_buffer_free(&buf);
690   epan_dissect_cleanup(&edt);
691
692   draw_tap_listeners(TRUE);
693
694   return 0;
695 }
696
697 int
698 sharkd_filter(const char *dftext, guint8 **result)
699 {
700   dfilter_t  *dfcode = NULL;
701
702   guint32 framenum;
703   guint32 frames_count;
704   Buffer buf;
705   struct wtap_pkthdr phdr;
706   int err;
707   char *err_info = NULL;
708
709   guint8 *result_bits;
710   guint8  passed_bits;
711
712   epan_dissect_t edt;
713
714   if (!dfilter_compile(dftext, &dfcode, &err_info)) {
715     g_free(err_info);
716     return -1;
717   }
718
719   frames_count = cfile.count;
720
721   wtap_phdr_init(&phdr);
722   ws_buffer_init(&buf, 1500);
723   epan_dissect_init(&edt, cfile.epan, TRUE, FALSE);
724
725   passed_bits = 0;
726   result_bits = (guint8 *) g_malloc(2 + (frames_count / 8));
727
728   for (framenum = 1; framenum <= frames_count; framenum++) {
729     frame_data *fdata = frame_data_sequence_find(cfile.frames, framenum);
730
731     if ((framenum & 7) == 0) {
732       result_bits[(framenum / 8) - 1] = passed_bits;
733       passed_bits = 0;
734     }
735
736     if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info))
737       break;
738
739     /* frame_data_set_before_dissect */
740     epan_dissect_prime_with_dfilter(&edt, dfcode);
741
742     epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, NULL);
743
744     if (dfilter_apply_edt(dfcode, &edt))
745       passed_bits |= (1 << (framenum % 8));
746
747     /* if passed or ref -> frame_data_set_after_dissect */
748
749     epan_dissect_reset(&edt);
750   }
751
752   if ((framenum & 7) == 0)
753       framenum--;
754   result_bits[framenum / 8] = passed_bits;
755
756   wtap_phdr_cleanup(&phdr);
757   ws_buffer_free(&buf);
758   epan_dissect_cleanup(&edt);
759
760   dfilter_free(dfcode);
761
762   *result = result_bits;
763
764   return framenum;
765 }
766
767 #include "version.h"
768 const char *sharkd_version(void)
769 {
770   /* based on get_ws_vcs_version_info(), but shorter */
771 #ifdef VCSVERSION
772   return VCSVERSION;
773 #else
774   return VERSION;
775 #endif
776 }
777
778 /*
779  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
780  *
781  * Local variables:
782  * c-basic-offset: 2
783  * tab-width: 8
784  * indent-tabs-mode: nil
785  * End:
786  *
787  * vi: set shiftwidth=2 tabstop=8 expandtab:
788  * :indentSize=2:tabSize=8:noTabs=true:
789  */