epan: Fix misuse of comma operator
[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  * 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.
13  *
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.
18  *
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.
22  */
23
24 #include <config.h>
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <limits.h>
30 #include <errno.h>
31 #include <signal.h>
32
33 #include <glib.h>
34
35 #include <epan/exceptions.h>
36 #include <epan/epan-int.h>
37 #include <epan/epan.h>
38
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>
49
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>
59 #include "ui/util.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"
65 #include "register.h"
66 #include <epan/epan_dissect.h>
67 #include <epan/tap.h>
68
69 #include <codecs/codecs.h>
70
71 #include "log.h"
72
73 #include <wsutil/str_util.h>
74 #include <wsutil/utf8_entities.h>
75
76 #ifdef HAVE_PLUGINS
77 #include <wsutil/plugins.h>
78 #endif
79
80 #include "sharkd.h"
81
82 #define INIT_FAILED 1
83 #define EPAN_INIT_FAIL 2
84
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;
90
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);
97
98 capture_file cfile;
99
100 static void
101 print_current_user(void) {
102   gchar *cur_user, *cur_group;
103
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);
109     g_free(cur_user);
110     g_free(cur_group);
111     if (running_with_special_privs()) {
112       fprintf(stderr, " This could be dangerous.");
113     }
114     fprintf(stderr, "\n");
115   }
116 }
117
118 int
119 main(int argc, char *argv[])
120 {
121   GString             *comp_info_str;
122   GString             *runtime_info_str;
123   char                *init_progfile_dir_error;
124
125   char                *err_msg = NULL;
126   e_prefs             *prefs_p;
127   int                  ret = EXIT_SUCCESS;
128
129   cmdarg_err_init(failure_warning_message, failure_message_cont);
130
131   /*
132    * Get credential information for later use, and drop privileges
133    * before doing anything else.
134    * Let the user know if anything happened.
135    */
136   init_process_policies();
137   relinquish_special_privs_perm();
138   print_current_user();
139
140   /*
141    * Attempt to get the pathname of the executable file.
142    */
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);
147   }
148
149   /* Get the compile-time version information string */
150   comp_info_str = get_compiled_version_info(NULL, epan_get_compiled_version_info);
151
152   /* Get the run-time version information string */
153   runtime_info_str = get_runtime_version_info(epan_get_runtime_version_info);
154
155   /* Add it to the information to be reported on a crash. */
156   ws_add_crash_info("Sharkd (Wireshark) %s\n"
157          "\n"
158          "%s"
159          "\n"
160          "%s",
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);
164
165   if (sharkd_init(argc, argv) < 0)
166   {
167     printf("cannot initialize sharkd\n");
168     ret = INIT_FAILED;
169     goto clean_exit;
170   }
171
172   init_report_message(failure_warning_message, failure_warning_message,
173                       open_failure_message, read_failure_message,
174                       write_failure_message);
175
176   timestamp_set_type(TS_RELATIVE);
177   timestamp_set_precision(TS_PREC_AUTO);
178   timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
179
180   wtap_init();
181
182 #ifdef HAVE_PLUGINS
183   /* Register all the plugin types we have. */
184   epan_register_plugin_types(); /* Types known to libwireshark */
185
186   /* Scan for plugins.  This does *not* call their registration routines;
187      that's done later. */
188   scan_plugins(REPORT_LOAD_FAILURE);
189
190   /* Register all libwiretap plugin modules. */
191   register_all_wiretap_modules();
192 #endif
193
194   register_all_codecs();
195
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,
201                  NULL)) {
202     ret = EPAN_INIT_FAIL;
203     goto clean_exit;
204   }
205
206   /* Load libwireshark settings from the current profile. */
207   prefs_p = epan_load_settings();
208
209   read_filter_list(CFILTER_LIST);
210
211   if (!color_filters_init(&err_msg, NULL)) {
212      fprintf(stderr, "%s\n", err_msg);
213      g_free(err_msg);
214   }
215
216   cap_file_init(&cfile);
217
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. */
221   prefs_apply_all();
222
223   /* Build the column format array */
224   build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
225
226   ret = sharkd_loop();
227 clean_exit:
228   col_cleanup(&cfile.cinfo);
229   free_filter_lists();
230   wtap_cleanup();
231   free_progdirs();
232 #ifdef HAVE_PLUGINS
233   plugins_cleanup();
234 #endif
235   return ret;
236 }
237
238 static const nstime_t *
239 sharkd_get_frame_ts(void *data, guint32 frame_num)
240 {
241   capture_file *cf = (capture_file *) data;
242
243   if (ref && ref->num == frame_num)
244     return &ref->abs_ts;
245
246   if (prev_dis && prev_dis->num == frame_num)
247     return &prev_dis->abs_ts;
248
249   if (prev_cap && prev_cap->num == frame_num)
250     return &prev_cap->abs_ts;
251
252   if (cf->frames) {
253      frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
254
255      return (fd) ? &fd->abs_ts : NULL;
256   }
257
258   return NULL;
259 }
260
261 static epan_t *
262 sharkd_epan_new(capture_file *cf)
263 {
264   epan_t *epan = epan_new();
265
266   epan->data = cf;
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;
271
272   return epan;
273 }
274
275 static gboolean
276 process_packet(capture_file *cf, epan_dissect_t *edt,
277                gint64 offset, struct wtap_pkthdr *whdr,
278                const guchar *pd)
279 {
280   frame_data     fdlocal;
281   guint32        framenum;
282   gboolean       passed;
283
284   /* The frame number of this packet is one more than the count of
285      frames in this packet. */
286   framenum = cf->count + 1;
287
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'. */
291   passed = TRUE;
292
293   frame_data_init(&fdlocal, framenum, whdr, offset, cum_bytes);
294
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. */
298   if (edt) {
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();
303
304     /* If we're running a read filter, prime the epan_dissect_t with that
305        filter. */
306     if (cf->rfcode)
307       epan_dissect_prime_with_dfilter(edt, cf->rfcode);
308
309     if (cf->dfcode)
310       epan_dissect_prime_with_dfilter(edt, cf->dfcode);
311
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);
315
316     frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
317                                   &ref, prev_dis);
318     if (ref == &fdlocal) {
319       ref_frame = fdlocal;
320       ref = &ref_frame;
321     }
322
323     epan_dissect_run(edt, cf->cd_t, whdr, frame_tvbuff_new(&fdlocal, pd), &fdlocal, NULL);
324
325     /* Run the read filter if we have one. */
326     if (cf->rfcode)
327       passed = dfilter_apply_edt(cf->rfcode, edt);
328   }
329
330   if (passed) {
331     frame_data_set_after_dissect(&fdlocal, &cum_bytes);
332     prev_cap = prev_dis = frame_data_sequence_add(cf->frames, &fdlocal);
333
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.
339      */
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);
343       }
344     }
345
346     cf->count++;
347   } else {
348     /* if we don't add it to the frame_data_sequence, clean it up right now
349      * to avoid leaks */
350     frame_data_destroy(&fdlocal);
351   }
352
353   if (edt)
354     epan_dissect_reset(edt);
355
356   return passed;
357 }
358
359
360 static int
361 load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
362 {
363   int          err;
364   gchar       *err_info = NULL;
365   gint64       data_offset;
366   epan_dissect_t *edt = NULL;
367
368   {
369     /* Allocate a frame_data_sequence for all the frames. */
370     cf->frames = new_frame_data_sequence();
371
372     {
373       gboolean create_proto_tree;
374
375       /*
376        * Determine whether we need to create a protocol tree.
377        * We do if:
378        *
379        *    we're going to apply a read filter;
380        *
381        *    we're going to apply a display filter;
382        *
383        *    a postdissector wants field values or protocols
384        *    on the first pass.
385        */
386       create_proto_tree =
387         (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids());
388
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);
392     }
393
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 ?)
401          */
402         if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
403           err = 0; /* This is not an error */
404           break;
405         }
406       }
407     }
408
409     if (edt) {
410       epan_dissect_free(edt);
411       edt = NULL;
412     }
413
414     /* Close the sequential I/O side, to free up memory it requires. */
415     wtap_sequential_close(cf->wth);
416
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();
420
421     prev_dis = NULL;
422     prev_cap = NULL;
423   }
424
425   if (err != 0) {
426     cfile_read_failure_message("sharkd", cf->filename, err, err_info);
427   }
428
429   return err;
430 }
431
432 cf_status_t
433 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
434 {
435   wtap  *wth;
436   gchar *err_info;
437
438   wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
439   if (wth == NULL)
440     goto fail;
441
442   /* The open succeeded.  Fill in the information for this file. */
443
444   /* Create new epan session for dissection. */
445   epan_free(cf->epan);
446   cf->epan = sharkd_epan_new(cf);
447
448   cf->wth = wth;
449   cf->f_datalen = 0; /* not used, but set it anyway */
450
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,
453      in any case. */
454   cf->filename = g_strdup(fname);
455
456   /* Indicate whether it's a permanent or temporary file. */
457   cf->is_tempfile = is_tempfile;
458
459   /* No user changes yet. */
460   cf->unsaved_changes = FALSE;
461
462   cf->cd_t      = wtap_file_type_subtype(cf->wth);
463   cf->open_type = type;
464   cf->count     = 0;
465   cf->drops_known = FALSE;
466   cf->drops     = 0;
467   cf->snap      = wtap_snapshot_length(cf->wth);
468   nstime_set_zero(&cf->elapsed_time);
469   ref = NULL;
470   prev_dis = NULL;
471   prev_cap = NULL;
472
473   cf->state = FILE_READ_IN_PROGRESS;
474
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);
477
478   return CF_OK;
479
480 fail:
481   cfile_open_failure_message("sharkd", fname, *err, err_info);
482   return CF_ERROR;
483 }
484
485 /*
486  * General errors and warnings are reported with an console message
487  * in sharkd.
488  */
489 static void
490 failure_warning_message(const char *msg_format, va_list ap)
491 {
492   fprintf(stderr, "sharkd: ");
493   vfprintf(stderr, msg_format, ap);
494   fprintf(stderr, "\n");
495 }
496
497 /*
498  * Open/create errors are reported with an console message in sharkd.
499  */
500 static void
501 open_failure_message(const char *filename, int err, gboolean for_writing)
502 {
503   fprintf(stderr, "sharkd: ");
504   fprintf(stderr, file_open_error_message(err, for_writing), filename);
505   fprintf(stderr, "\n");
506 }
507
508 /*
509  * Read errors are reported with an console message in sharkd.
510  */
511 static void
512 read_failure_message(const char *filename, int err)
513 {
514   cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
515           filename, g_strerror(err));
516 }
517
518 /*
519  * Write errors are reported with an console message in sharkd.
520  */
521 static void
522 write_failure_message(const char *filename, int err)
523 {
524   cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
525           filename, g_strerror(err));
526 }
527
528 /*
529  * Report additional information for an error in command-line arguments.
530  */
531 static void
532 failure_message_cont(const char *msg_format, va_list ap)
533 {
534   vfprintf(stderr, msg_format, ap);
535   fprintf(stderr, "\n");
536 }
537
538 cf_status_t
539 sharkd_cf_open(const char *fname, unsigned int type, gboolean is_tempfile, int *err)
540 {
541   return cf_open(&cfile, fname, type, is_tempfile, err);
542 }
543
544 int
545 sharkd_load_cap_file(void)
546 {
547   return load_cap_file(&cfile, 0, 0);
548 }
549
550 int
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)
552 {
553   frame_data *fdata;
554   column_info *cinfo = (dissect_columns) ? &cfile.cinfo : NULL;
555   epan_dissect_t edt;
556   gboolean create_proto_tree;
557   struct wtap_pkthdr phdr; /* Packet header */
558   Buffer buf; /* Packet data */
559
560   int err;
561   char *err_info = NULL;
562
563   fdata = frame_data_sequence_find(cfile.frames, framenum);
564   if (fdata == NULL)
565     return -1;
566
567   wtap_phdr_init(&phdr);
568   ws_buffer_init(&buf, 1500);
569
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 */
573   }
574
575   create_proto_tree = (dissect_tree) || (cinfo && have_custom_cols(cinfo));
576   epan_dissect_init(&edt, cfile.epan, create_proto_tree, dissect_tree);
577
578   if (cinfo)
579     col_custom_prime_edt(&edt, cinfo);
580
581   /*
582    * XXX - need to catch an OutOfMemoryError exception and
583    * attempt to recover from it.
584    */
585   epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, cinfo);
586
587   if (cinfo) {
588     /* "Stringify" non frame_data vals */
589     epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
590   }
591
592   cb(&edt.pi, dissect_tree ? edt.tree : NULL, cinfo, dissect_bytes ? edt.pi.data_src : NULL, data);
593
594   epan_dissect_cleanup(&edt);
595   wtap_phdr_cleanup(&phdr);
596   ws_buffer_free(&buf);
597   return 0;
598 }
599
600 /* based on packet_list_dissect_and_cache_record */
601 int
602 sharkd_dissect_columns(int framenum, column_info *cinfo, gboolean dissect_color)
603 {
604   frame_data *fdata;
605   epan_dissect_t edt;
606   gboolean create_proto_tree;
607   struct wtap_pkthdr phdr; /* Packet header */
608   Buffer buf; /* Packet data */
609
610   int err;
611   char *err_info = NULL;
612
613   fdata = frame_data_sequence_find(cfile.frames, framenum);
614   if (fdata == NULL) {
615     col_fill_in_error(cinfo, fdata, FALSE, TRUE/* fill_fd_columns */);
616     return -1; /* error reading the record */
617   }
618
619   wtap_phdr_init(&phdr);
620   ws_buffer_init(&buf, 1500);
621
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 */
626   }
627
628   create_proto_tree = (dissect_color && color_filters_used()) || (cinfo && have_custom_cols(cinfo));
629
630   epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE /* proto_tree_visible */);
631
632   if (dissect_color) {
633     color_filters_prime_edt(&edt);
634     fdata->flags.need_colorize = 1;
635   }
636
637   if (cinfo)
638     col_custom_prime_edt(&edt, cinfo);
639
640   /*
641    * XXX - need to catch an OutOfMemoryError exception and
642    * attempt to recover from it.
643    */
644   epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, cinfo);
645
646   if (cinfo) {
647     /* "Stringify" non frame_data vals */
648     epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */);
649   }
650
651   epan_dissect_cleanup(&edt);
652   wtap_phdr_cleanup(&phdr);
653   ws_buffer_free(&buf);
654   return 0;
655 }
656
657 int
658 sharkd_retap(void)
659 {
660   guint32          framenum;
661   frame_data      *fdata;
662   Buffer           buf;
663   struct wtap_pkthdr phdr;
664   int err;
665   char *err_info = NULL;
666
667   guint         tap_flags;
668   gboolean      create_proto_tree;
669   epan_dissect_t edt;
670   column_info   *cinfo;
671
672   /* Get the union of the flags for all tap listeners. */
673   tap_flags = union_of_tap_listener_flags();
674
675   /* If any tap listeners require the columns, construct them. */
676   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cfile.cinfo : NULL;
677
678   /*
679    * Determine whether we need to create a protocol tree.
680    * We do if:
681    *
682    *    one of the tap listeners is going to apply a filter;
683    *
684    *    one of the tap listeners requires a protocol tree.
685    */
686   create_proto_tree =
687     (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
688
689   wtap_phdr_init(&phdr);
690   ws_buffer_init(&buf, 1500);
691   epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE);
692
693   reset_tap_listeners();
694
695   for (framenum = 1; framenum <= cfile.count; framenum++) {
696     fdata = frame_data_sequence_find(cfile.frames, framenum);
697
698     if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info))
699       break;
700
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);
703   }
704
705   wtap_phdr_cleanup(&phdr);
706   ws_buffer_free(&buf);
707   epan_dissect_cleanup(&edt);
708
709   draw_tap_listeners(TRUE);
710
711   return 0;
712 }
713
714 int
715 sharkd_filter(const char *dftext, guint8 **result)
716 {
717   dfilter_t  *dfcode = NULL;
718
719   guint32 framenum;
720   guint32 frames_count;
721   Buffer buf;
722   struct wtap_pkthdr phdr;
723   int err;
724   char *err_info = NULL;
725
726   guint8 *result_bits;
727   guint8  passed_bits;
728
729   epan_dissect_t edt;
730
731   if (!dfilter_compile(dftext, &dfcode, &err_info)) {
732     g_free(err_info);
733     return -1;
734   }
735
736   frames_count = cfile.count;
737
738   wtap_phdr_init(&phdr);
739   ws_buffer_init(&buf, 1500);
740   epan_dissect_init(&edt, cfile.epan, TRUE, FALSE);
741
742   passed_bits = 0;
743   result_bits = (guint8 *) g_malloc(2 + (frames_count / 8));
744
745   for (framenum = 1; framenum <= frames_count; framenum++) {
746     frame_data *fdata = frame_data_sequence_find(cfile.frames, framenum);
747
748     if ((framenum & 7) == 0) {
749       result_bits[(framenum / 8) - 1] = passed_bits;
750       passed_bits = 0;
751     }
752
753     if (!wtap_seek_read(cfile.wth, fdata->file_off, &phdr, &buf, &err, &err_info))
754       break;
755
756     /* frame_data_set_before_dissect */
757     epan_dissect_prime_with_dfilter(&edt, dfcode);
758
759     epan_dissect_run(&edt, cfile.cd_t, &phdr, frame_tvbuff_new_buffer(fdata, &buf), fdata, NULL);
760
761     if (dfilter_apply_edt(dfcode, &edt))
762       passed_bits |= (1 << (framenum % 8));
763
764     /* if passed or ref -> frame_data_set_after_dissect */
765
766     epan_dissect_reset(&edt);
767   }
768
769   if ((framenum & 7) == 0)
770       framenum--;
771   result_bits[framenum / 8] = passed_bits;
772
773   wtap_phdr_cleanup(&phdr);
774   ws_buffer_free(&buf);
775   epan_dissect_cleanup(&edt);
776
777   dfilter_free(dfcode);
778
779   *result = result_bits;
780
781   return framenum;
782 }
783
784 #include "version.h"
785 const char *sharkd_version(void)
786 {
787   /* based on get_ws_vcs_version_info(), but shorter */
788 #ifdef VCSVERSION
789   return VCSVERSION;
790 #else
791   return VERSION;
792 #endif
793 }
794
795 /*
796  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
797  *
798  * Local variables:
799  * c-basic-offset: 2
800  * tab-width: 8
801  * indent-tabs-mode: nil
802  * End:
803  *
804  * vi: set shiftwidth=2 tabstop=8 expandtab:
805  * :indentSize=2:tabSize=8:noTabs=true:
806  */