Coverage Report

Created: 2025-04-03 08:43

/src/wireshark/epan/tap.c
Line
Count
Source (jump to first uncovered line)
1
/* tap.c
2
 * packet tap interface   2002 Ronnie Sahlberg
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include <config.h>
12
0
#define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
13
14
#include <stdio.h>
15
16
#include <sys/types.h>
17
18
#ifdef HAVE_NETINET_IN_H
19
# include <netinet/in.h>
20
#endif
21
22
#include <string.h>
23
24
#include <glib.h>
25
26
#include <epan/packet_info.h>
27
#include <epan/dfilter/dfilter.h>
28
#include <epan/tap.h>
29
#include <wsutil/wslog.h>
30
31
static bool tapping_is_active=false;
32
static dfilter_t *main_filter;
33
34
typedef struct _tap_dissector_t {
35
  struct _tap_dissector_t *next;
36
  char *name;
37
} tap_dissector_t;
38
static tap_dissector_t *tap_dissector_list;
39
40
/*
41
 * This is the list of free and used packets queued for a tap.
42
 * It is implemented here explicitly instead of using GLib objects
43
 * in order to be as fast as possible as we need to build and tear down the
44
 * queued list at least once for each packet we see and thus we must be able
45
 * to build and tear it down as fast as possible.
46
 *
47
 * XXX - some fields in packet_info get overwritten in the dissection
48
 * process, such as the addresses and the "this is an error packet" flag.
49
 * A packet may be queued at multiple protocol layers, but the packet_info
50
 * structure will, when the tap listeners are run, contain the values as
51
 * set by the topmost protocol layers.
52
 *
53
 * This means that the tap listener code can't rely on pinfo->flags.in_error_pkt
54
 * to determine whether the packet should be handed to the listener, as, for
55
 * a protocol with error report packets that include a copy of the
56
 * packet in error (ICMP, ICMPv6, CLNP), that flag changes during the
57
 * processing of the packet depending on whether we're currently dissecting
58
 * the packet in error or not.
59
 *
60
 * It also means that a tap listener can't depend on the source and destination
61
 * addresses being the correct ones for the packet being processed if, for
62
 * example, you have some tunneling that causes multiple layers of the same
63
 * protocol.
64
 *
65
 * For now, we handle the error packet flag by setting a bit in the flags
66
 * field of the tap_packet_t structure.  We may ultimately want stacks of
67
 * addresses for this and other reasons.
68
 */
69
typedef struct _tap_packet_t {
70
  int tap_id;
71
  uint32_t flags;
72
  packet_info *pinfo;
73
  const void *tap_specific_data;
74
} tap_packet_t;
75
76
0
#define TAP_PACKET_IS_ERROR_PACKET  0x00000001  /* packet being queued is an error packet */
77
78
0
#define TAP_PACKET_QUEUE_LEN 5000
79
static tap_packet_t tap_packet_array[TAP_PACKET_QUEUE_LEN];
80
static unsigned tap_packet_index;
81
82
typedef struct _tap_listener_t {
83
  struct _tap_listener_t *next;
84
  int tap_id;
85
  bool needs_redraw;
86
  bool failed;
87
  unsigned flags;
88
  char *fstring;
89
  dfilter_t *code;
90
  void *tapdata;
91
  tap_reset_cb reset;
92
  tap_packet_cb packet;
93
  tap_draw_cb draw;
94
  tap_finish_cb finish;
95
} tap_listener_t;
96
97
static tap_listener_t *tap_listener_queue;
98
99
static GSList *tap_plugins;
100
101
#ifdef HAVE_PLUGINS
102
void
103
tap_register_plugin(const tap_plugin *plug)
104
0
{
105
0
  tap_plugins = g_slist_prepend(tap_plugins, (tap_plugin *)plug);
106
0
}
107
#else /* HAVE_PLUGINS */
108
void
109
tap_register_plugin(const tap_plugin *plug _U_)
110
{
111
  ws_warning("built without support for binary plugins");
112
}
113
#endif /* HAVE_PLUGINS */
114
115
static void
116
call_plugin_register_tap_listener(void *data, void *user_data _U_)
117
0
{
118
0
  tap_plugin *plug = (tap_plugin *)data;
119
120
0
  if (plug->register_tap_listener) {
121
0
    plug->register_tap_listener();
122
0
  }
123
0
}
124
125
/*
126
 * For all taps, call their register routines.
127
 *
128
 * The table of register routines is part of the main program, not
129
 * part of libwireshark, so it must be passed to us as an argument.
130
 */
131
void
132
register_all_tap_listeners(tap_reg_t const *tap_reg_listeners)
133
0
{
134
  /* we register the plugin taps before the other taps because
135
         * stats_tree taps plugins will be registered as tap listeners
136
         * by stats_tree_stat.c and need to registered before that */
137
0
  g_slist_foreach(tap_plugins, call_plugin_register_tap_listener, NULL);
138
139
  /* Register all builtin listeners. */
140
0
  for (tap_reg_t const *t = &tap_reg_listeners[0]; t->cb_func != NULL; t++) {
141
0
    t->cb_func();
142
0
  }
143
0
}
144
145
/* **********************************************************************
146
 * Init routine only called from epan at application startup
147
 * ********************************************************************** */
148
/* This function is called once when wireshark starts up and is used
149
   to init any data structures we may need later.
150
*/
151
void
152
tap_init(void)
153
2
{
154
2
  tap_packet_index=0;
155
2
}
156
157
/* **********************************************************************
158
 * Functions called from dissector when made tappable
159
 * ********************************************************************** */
160
/* the following two functions are used from dissectors to
161
   1. register the ability to tap packets from this subdissector
162
   2. push packets encountered by the subdissector to anyone tapping
163
*/
164
165
/* This function registers that a dissector has the packet tap ability
166
   available.  The name parameter is the name of this tap and extensions can
167
   use open_tap(char *name,... to specify that it wants to receive packets/
168
   events from this tap.
169
170
   This function is only to be called once, when the dissector initializes.
171
172
   The return value from this call is later used as a parameter to the
173
   tap_packet(unsigned int *tap_id,...
174
   call so that the tap subsystem knows to which tap point this tapped
175
   packet is associated.
176
*/
177
int
178
register_tap(const char *name)
179
352
{
180
352
  tap_dissector_t *td, *tdl = NULL, *tdl_prev = NULL;
181
352
  int i=0;
182
183
352
  if(tap_dissector_list){
184
    /* Check if we already have the name registered, if it is return the tap_id of that tap.
185
     * After the for loop tdl_prev will point to the last element of the list, add the new one there.
186
     */
187
28.6k
    for (i = 1, tdl = tap_dissector_list; tdl; i++, tdl_prev = tdl, tdl = tdl->next) {
188
28.3k
      if (!strcmp(tdl->name, name)) {
189
22
        return i;
190
22
      }
191
28.3k
    }
192
328
    tdl = tdl_prev;
193
328
  }
194
195
330
  td=g_new(tap_dissector_t, 1);
196
330
  td->next=NULL;
197
330
  td->name = g_strdup(name);
198
199
330
  if(!tap_dissector_list){
200
2
    tap_dissector_list=td;
201
2
    i=1;
202
328
  } else {
203
328
    tdl->next=td;
204
328
  }
205
330
  return i;
206
352
}
207
208
209
/* Every time the dissector has finished dissecting a packet (and all
210
   subdissectors have returned) and if the dissector has been made "tappable"
211
   it will push some data to everyone tapping this layer by a call
212
   to tap_queue_packet().
213
   The first parameter is the tap_id returned by the register_tap()
214
   call for this dissector (so the tap system can keep track of who it came
215
   from and who is listening to it)
216
   The second is the packet_info structure which many tap readers will find
217
   interesting.
218
   The third argument is specific to each tap point or NULL if no additional
219
   data is available to this tap.  A tap point in say IP will probably want to
220
   push the IP header structure here. Same thing for TCP and ONCRPC.
221
222
   The pinfo and the specific pointer are what is supplied to every listener
223
   in the read_callback() call made to every one currently listening to this
224
   tap.
225
226
   The tap reader is responsible to know how to parse any structure pointed
227
   to by the tap specific data pointer.
228
*/
229
void
230
tap_queue_packet(int tap_id, packet_info *pinfo, const void *tap_specific_data)
231
291k
{
232
291k
  tap_packet_t *tpt;
233
234
291k
  if(!tapping_is_active){
235
291k
    return;
236
291k
  }
237
  /*
238
   * XXX - should we allocate this with an ep_allocator,
239
   * rather than having a fixed maximum number of entries?
240
   */
241
0
  if(tap_packet_index >= TAP_PACKET_QUEUE_LEN){
242
0
    ws_warning("Too many taps queued");
243
0
    return;
244
0
  }
245
246
0
  tpt=&tap_packet_array[tap_packet_index];
247
0
  tpt->tap_id=tap_id;
248
0
  tpt->flags = 0;
249
0
  if (pinfo->flags.in_error_pkt)
250
0
    tpt->flags |= TAP_PACKET_IS_ERROR_PACKET;
251
0
  tpt->pinfo=pinfo;
252
0
  tpt->tap_specific_data=tap_specific_data;
253
0
  tap_packet_index++;
254
0
}
255
256
257
258
259
260
/* **********************************************************************
261
 * Functions used by file.c to drive the tap subsystem
262
 * ********************************************************************** */
263
264
void tap_build_interesting (epan_dissect_t *edt)
265
0
{
266
0
  tap_listener_t *tl;
267
0
  bool need_protocols = false;
268
0
  bool need_main_filter = false;
269
270
  /* nothing to do, just return */
271
0
  if(!tap_listener_queue){
272
0
    return;
273
0
  }
274
275
  /* loop over all tap listeners and build the list of all
276
     interesting hf_fields */
277
0
  for(tl=tap_listener_queue;tl;tl=tl->next){
278
0
    if(tl->code){
279
0
      epan_dissect_prime_with_dfilter(edt, tl->code);
280
0
    }
281
0
    if(tl->flags & TL_REQUIRES_PROTOCOLS){
282
0
      need_protocols = true;
283
0
    }
284
0
    if(tl->flags & TL_LIMIT_TO_DISPLAY_FILTER){
285
0
      need_main_filter = true;
286
0
    }
287
0
  }
288
0
  if (need_main_filter && main_filter) {
289
0
    epan_dissect_prime_with_dfilter(edt, main_filter);
290
0
  }
291
0
  if (need_protocols) {
292
0
    epan_dissect_fake_protocols(edt, false);
293
0
  }
294
0
}
295
296
/* This function is used to delete/initialize the tap queue and prime an
297
   epan_dissect_t with all the filters for tap listeners.
298
   To free the tap queue, we just prepend the used queue to the free queue.
299
*/
300
void
301
tap_queue_init(epan_dissect_t *edt)
302
0
{
303
  /* nothing to do, just return */
304
0
  if(!tap_listener_queue){
305
0
    return;
306
0
  }
307
308
0
  tapping_is_active=true;
309
310
0
  tap_packet_index=0;
311
312
0
  tap_build_interesting (edt);
313
0
}
314
315
/* this function is called after a packet has been fully dissected to push the tapped
316
   data to all extensions that has callbacks registered.
317
*/
318
void
319
tap_push_tapped_queue(epan_dissect_t *edt)
320
0
{
321
0
  tap_packet_t *tp;
322
0
  tap_listener_t *tl;
323
0
  unsigned i;
324
325
  /* nothing to do, just return */
326
0
  if(!tapping_is_active){
327
0
    return;
328
0
  }
329
330
0
  tapping_is_active=false;
331
332
  /* nothing to do, just return */
333
0
  if(!tap_packet_index){
334
0
    return;
335
0
  }
336
337
  /* loop over all tap listeners and call the listener callback
338
     for all packets that match the filter. */
339
0
  for(i=0;i<tap_packet_index;i++){
340
0
    for(tl=tap_listener_queue;tl;tl=tl->next){
341
0
      tp=&tap_packet_array[i];
342
      /* Don't tap the packet if it's an "error packet"
343
       * unless the listener has requested that we do so.
344
       */
345
0
      if (!(tp->flags & TAP_PACKET_IS_ERROR_PACKET) || (tl->flags & TL_REQUIRES_ERROR_PACKETS))
346
0
      {
347
0
        if(tp->tap_id==tl->tap_id){
348
0
          if(!tl->packet){
349
            /* There isn't a per-packet
350
             * routine for this tap.
351
             */
352
0
            continue;
353
0
          }
354
0
          if(tl->failed){
355
            /* A previous call failed,
356
             * meaning "stop running this
357
             * tap", so don't call the
358
             * packet routine.
359
             */
360
0
            continue;
361
0
          }
362
363
          /* If we have a filter, see if the
364
           * packet passes.
365
           */
366
0
          unsigned flags = tl->flags;
367
0
          if((tl->flags & TL_LIMIT_TO_DISPLAY_FILTER) && main_filter) {
368
369
0
            if (!dfilter_apply_edt(main_filter, edt)){
370
              /* The packet didn't
371
               * pass the filter. */
372
0
              if (tl->flags & TL_IGNORE_DISPLAY_FILTER)
373
0
                flags |= TL_DISPLAY_FILTER_IGNORED;
374
0
              else
375
0
                continue;
376
0
            }
377
0
          }
378
0
          if(tl->code){
379
0
            if (!dfilter_apply_edt(tl->code, edt)){
380
              /* The packet didn't
381
               * pass the filter. */
382
0
              if (tl->flags & TL_IGNORE_DISPLAY_FILTER)
383
0
                flags |= TL_DISPLAY_FILTER_IGNORED;
384
0
              else
385
0
                continue;
386
0
            }
387
0
          }
388
389
          /* So call the per-packet routine. */
390
0
          tap_packet_status status;
391
392
0
          status = tl->packet(tl->tapdata, tp->pinfo, edt, tp->tap_specific_data, flags);
393
394
0
          switch (status) {
395
396
0
          case TAP_PACKET_DONT_REDRAW:
397
0
            break;
398
399
0
          case TAP_PACKET_REDRAW:
400
0
            tl->needs_redraw=true;
401
0
            break;
402
403
0
          case TAP_PACKET_FAILED:
404
0
            tl->failed=true;
405
0
            break;
406
0
          }
407
0
        }
408
0
      }
409
0
    }
410
0
  }
411
0
}
412
413
414
/* This function can be used by a dissector to fetch any tapped data before
415
 * returning.
416
 * This can be useful if one wants to extract the data inside dissector  BEFORE
417
 * it exists as an alternative to the callbacks that are all called AFTER the
418
 * dissection has completed.
419
 *
420
 * Example: SMB2 uses this mechanism to extract the data tapped from NTLMSSP
421
 * containing the account and domain names before exiting.
422
 * Note that the SMB2 tap listener specifies all three callbacks as NULL.
423
 *
424
 * Beware: when using this mechanism to extract the tapped data you can not
425
 * use "filters" and should specify the "filter" as NULL when registering
426
 * the tap listener.
427
 */
428
const void *
429
fetch_tapped_data(int tap_id, int idx)
430
1
{
431
1
  tap_packet_t *tp;
432
1
  unsigned i;
433
434
  /* nothing to do, just return */
435
1
  if(!tapping_is_active){
436
1
    return NULL;
437
1
  }
438
439
  /* nothing to do, just return */
440
0
  if(!tap_packet_index){
441
0
    return NULL;
442
0
  }
443
444
  /* loop over all tapped packets and return the one with index idx */
445
0
  for(i=0;i<tap_packet_index;i++){
446
0
    tp=&tap_packet_array[i];
447
0
    if(tp->tap_id==tap_id){
448
0
      if(!idx--){
449
0
        return tp->tap_specific_data;
450
0
      }
451
0
    }
452
0
  }
453
454
0
  return NULL;
455
0
}
456
457
/* This function is called when we need to reset all tap listeners, for example
458
   when we open/start a new capture or if we need to rescan the packet list.
459
*/
460
void
461
reset_tap_listeners(void)
462
0
{
463
0
  tap_listener_t *tl;
464
465
0
  for(tl=tap_listener_queue;tl;tl=tl->next){
466
0
    if(tl->reset){
467
0
      tl->reset(tl->tapdata);
468
0
    }
469
0
    tl->needs_redraw=true;
470
0
    tl->failed=false;
471
0
  }
472
473
0
}
474
475
476
/* This function is called when we need to redraw all tap listeners, for example
477
   when we open/start a new capture or if we need to rescan the packet list.
478
   It should be called from a low priority thread say once every 3 seconds
479
480
   If draw_all is true, redraw all applications regardless if they have
481
   changed or not.
482
*/
483
void
484
draw_tap_listeners(bool draw_all)
485
0
{
486
0
  tap_listener_t *tl;
487
488
0
  for(tl=tap_listener_queue;tl;tl=tl->next){
489
0
    if(tl->needs_redraw || draw_all){
490
0
      if(tl->draw){
491
0
        tl->draw(tl->tapdata);
492
0
      }
493
0
    }
494
0
    tl->needs_redraw=false;
495
0
  }
496
0
}
497
498
/* Gets a GList of the tap names. The content of the list
499
   is owned by the tap table and should not be modified or freed.
500
   Use g_list_free() when done using the list. */
501
GList*
502
get_tap_names(void)
503
0
{
504
0
  GList *list = NULL;
505
0
  tap_dissector_t *td;
506
507
0
  for(td=tap_dissector_list; td; td=td->next) {
508
0
    list = g_list_prepend(list, td->name);
509
0
  }
510
511
0
  return g_list_reverse(list);
512
0
}
513
514
/* **********************************************************************
515
 * Functions used by tap to
516
 * 1. register that a really simple extension is available for use by
517
 *    Wireshark.
518
 * 2. start tapping from a subdissector
519
 * 3. close an already open tap
520
 * ********************************************************************** */
521
/* this function will return the tap_id for the specific protocol tap
522
   or 0 if no such tap was found.
523
 */
524
int
525
find_tap_id(const char *name)
526
32
{
527
32
  tap_dissector_t *td;
528
32
  int i;
529
530
1.68k
  for(i=1,td=tap_dissector_list;td;i++,td=td->next) {
531
1.67k
    if(!strcmp(td->name,name)){
532
30
      return i;
533
30
    }
534
1.67k
  }
535
2
  return 0;
536
32
}
537
538
static void
539
free_tap_listener(tap_listener_t *tl)
540
0
{
541
  /* The free_tap_listener is called in the error path of
542
   * register_tap_listener (when the dfilter fails to be registered)
543
   * and the finish callback is set after that.
544
   * If this is changed make sure the finish callback is not called
545
   * twice to prevent double-free errors.
546
   */
547
0
  if (tl->finish) {
548
0
    tl->finish(tl->tapdata);
549
0
  }
550
0
  dfilter_free(tl->code);
551
0
  g_free(tl->fstring);
552
0
  g_free(tl);
553
0
}
554
555
/* this function attaches the tap_listener to the named tap.
556
 * function returns :
557
 *     NULL: ok.
558
 * non-NULL: error, return value points to GString containing error
559
 *           message.
560
 */
561
GString *
562
register_tap_listener(const char *tapname, void *tapdata, const char *fstring,
563
          unsigned flags, tap_reset_cb reset, tap_packet_cb packet,
564
          tap_draw_cb draw, tap_finish_cb finish)
565
1
{
566
1
  tap_listener_t *tl;
567
1
  int tap_id;
568
1
  dfilter_t *code=NULL;
569
1
  GString *error_string;
570
1
  df_error_t *df_err;
571
572
1
  tap_id=find_tap_id(tapname);
573
1
  if(!tap_id){
574
0
    error_string = g_string_new("");
575
0
    g_string_printf(error_string, "Tap %s not found", tapname);
576
0
    return error_string;
577
0
  }
578
579
1
  tl=g_new0(tap_listener_t, 1);
580
1
  tl->needs_redraw=true;
581
1
  tl->failed=false;
582
1
  if (flags & TL_REQUIRES_PROTOCOLS) {
583
    /* Requiring protocols implies needing a protocol tree.
584
     * XXX - Warn?
585
     */
586
0
    flags |= TL_REQUIRES_PROTO_TREE;
587
0
  }
588
1
  tl->flags=flags;
589
1
  if(fstring && *fstring){
590
0
    if(!dfilter_compile(fstring, &code, &df_err)){
591
0
      error_string = g_string_new("");
592
0
      g_string_printf(error_string,
593
0
          "Filter \"%s\" is invalid - %s",
594
0
          fstring, df_err->msg);
595
0
      df_error_free(&df_err);
596
0
      free_tap_listener(tl);
597
0
      return error_string;
598
0
    }
599
0
    tl->fstring=g_strdup(fstring);
600
0
    tl->code=code;
601
0
  }
602
603
1
  tl->tap_id=tap_id;
604
1
  tl->tapdata=tapdata;
605
1
  tl->reset=reset;
606
1
  tl->packet=packet;
607
1
  tl->draw=draw;
608
1
  tl->finish=finish;
609
1
  tl->next=tap_listener_queue;
610
611
1
  tap_listener_queue=tl;
612
613
1
  return NULL;
614
1
}
615
616
/* this function sets a new dfilter to a tap listener
617
 */
618
GString *
619
set_tap_dfilter(void *tapdata, const char *fstring)
620
0
{
621
0
  tap_listener_t *tl=NULL,*tl2;
622
0
  dfilter_t *code=NULL;
623
0
  GString *error_string;
624
0
  df_error_t *df_err;
625
626
0
  if(!tap_listener_queue){
627
0
    return NULL;
628
0
  }
629
630
0
  if(tap_listener_queue->tapdata==tapdata){
631
0
    tl=tap_listener_queue;
632
0
  } else {
633
0
    for(tl2=tap_listener_queue;tl2->next;tl2=tl2->next){
634
0
      if(tl2->next->tapdata==tapdata){
635
0
        tl=tl2->next;
636
0
        break;
637
0
      }
638
639
0
    }
640
0
  }
641
642
0
  if(tl){
643
0
    if(tl->code){
644
0
      dfilter_free(tl->code);
645
0
      tl->code=NULL;
646
0
    }
647
0
    tl->needs_redraw=true;
648
0
    g_free(tl->fstring);
649
0
    if(fstring){
650
0
      if(!dfilter_compile(fstring, &code, &df_err)){
651
0
        tl->fstring=NULL;
652
0
        error_string = g_string_new("");
653
0
        g_string_printf(error_string,
654
0
             "Filter \"%s\" is invalid - %s",
655
0
             fstring, df_err->msg);
656
0
        df_error_free(&df_err);
657
0
        return error_string;
658
0
      }
659
0
    }
660
0
    tl->fstring=g_strdup(fstring);
661
0
    tl->code=code;
662
0
  }
663
664
0
  return NULL;
665
0
}
666
667
GString *
668
set_tap_flags(void *tapdata, unsigned flags)
669
0
{
670
  /* This never fails, and hence always returns NULL.
671
   * It could fail on an unknown flag, but that's a
672
   * programming error, not a runtime error (a bad filter
673
   * above can be a runtime error. Also like the above,
674
   * there's no failure notification on an unknown listener.
675
   */
676
0
  tap_listener_t *tl=NULL,*tl2;
677
678
0
  if(!tap_listener_queue){
679
0
    return NULL;
680
0
  }
681
682
0
  if(tap_listener_queue->tapdata==tapdata){
683
0
    tl=tap_listener_queue;
684
0
  } else {
685
0
    for(tl2=tap_listener_queue;tl2->next;tl2=tl2->next){
686
0
      if(tl2->next->tapdata==tapdata){
687
0
        tl=tl2->next;
688
0
        break;
689
0
      }
690
691
0
    }
692
0
  }
693
694
0
  if(tl && tl->flags != flags) {
695
0
    tl->needs_redraw=true;
696
0
    tl->flags=flags;
697
0
  }
698
699
0
  return NULL;
700
0
}
701
702
/* this function recompiles dfilter for all registered tap listeners
703
 */
704
void
705
tap_listeners_dfilter_recompile(void)
706
0
{
707
0
  tap_listener_t *tl;
708
0
  dfilter_t *code;
709
710
0
  for(tl=tap_listener_queue;tl;tl=tl->next){
711
0
    if(tl->code){
712
0
      dfilter_free(tl->code);
713
0
      tl->code=NULL;
714
0
    }
715
0
    tl->needs_redraw=true;
716
0
    code=NULL;
717
0
    if(tl->fstring){
718
0
      if(!dfilter_compile(tl->fstring, &code, NULL)){
719
        /* Not valid, make a dfilter matching no packets */
720
0
        dfilter_compile("frame.number == 0", &code, NULL);
721
0
      }
722
0
    }
723
0
    tl->code=code;
724
0
  }
725
0
}
726
727
/* this function removes a tap listener
728
 */
729
void
730
remove_tap_listener(void *tapdata)
731
0
{
732
0
  tap_listener_t *tl=NULL,*tl2;
733
734
0
  if(!tap_listener_queue){
735
0
    return;
736
0
  }
737
738
0
  if(tap_listener_queue->tapdata==tapdata){
739
0
    tl=tap_listener_queue;
740
0
    tap_listener_queue=tap_listener_queue->next;
741
0
  } else {
742
0
    for(tl2=tap_listener_queue;tl2->next;tl2=tl2->next){
743
0
      if(tl2->next->tapdata==tapdata){
744
0
        tl=tl2->next;
745
0
        tl2->next=tl2->next->next;
746
0
        break;
747
0
      }
748
749
0
    }
750
0
    if(!tl) {
751
0
      ws_warning("no listener found with that tap data");
752
0
      return;
753
0
    }
754
0
  }
755
0
  free_tap_listener(tl);
756
0
}
757
758
/*
759
 * Return true if we have one or more tap listeners that require dissection,
760
 * false otherwise.
761
 */
762
bool
763
tap_listeners_require_dissection(void)
764
0
{
765
0
  tap_listener_t *tap_queue = tap_listener_queue;
766
767
0
  while(tap_queue) {
768
0
    if(!(tap_queue->flags & TL_IS_DISSECTOR_HELPER))
769
0
      return true;
770
771
0
    tap_queue = tap_queue->next;
772
0
  }
773
774
0
  return false;
775
776
0
}
777
778
/*
779
 * Return true if we have one or more tap listeners that require the columns,
780
 * false otherwise.
781
 */
782
bool
783
tap_listeners_require_columns(void)
784
0
{
785
0
  tap_listener_t *tap_queue = tap_listener_queue;
786
787
0
  while(tap_queue) {
788
0
    if(tap_queue->flags & TL_REQUIRES_COLUMNS)
789
0
      return true;
790
791
0
    if(dfilter_requires_columns(tap_queue->code))
792
0
      return true;
793
794
0
    tap_queue = tap_queue->next;
795
0
  }
796
797
0
  return false;
798
799
0
}
800
801
/* Returns true there is an active tap listener for the specified tap id. */
802
bool
803
have_tap_listener(int tap_id)
804
4.71M
{
805
4.71M
  tap_listener_t *tap_queue = tap_listener_queue;
806
807
9.32M
  while(tap_queue) {
808
4.61M
    if(tap_queue->tap_id == tap_id)
809
0
      return true;
810
811
4.61M
    tap_queue = tap_queue->next;
812
4.61M
  }
813
814
4.71M
  return false;
815
4.71M
}
816
817
/*
818
 * Return true if we have any tap listeners with filters, false otherwise.
819
 */
820
bool
821
have_filtering_tap_listeners(void)
822
0
{
823
0
  tap_listener_t *tl;
824
825
0
  for(tl=tap_listener_queue;tl;tl=tl->next){
826
0
    if(tl->code)
827
0
      return true;
828
0
    if((tl->flags & TL_LIMIT_TO_DISPLAY_FILTER) && main_filter)
829
0
      return true;
830
0
  }
831
0
  return false;
832
0
}
833
834
void
835
tap_listeners_load_field_references(epan_dissect_t *edt)
836
0
{
837
0
  tap_listener_t *tl;
838
839
0
  for(tl=tap_listener_queue;tl;tl=tl->next){
840
0
    if(tl->code)
841
0
      dfilter_load_field_references_edt(tl->code, edt);
842
0
  }
843
0
}
844
845
/*
846
 * Get the union of all the flags for all the tap listeners; that gives
847
 * an indication of whether the protocol tree, or the columns, are
848
 * required by any taps.
849
 */
850
unsigned
851
union_of_tap_listener_flags(void)
852
0
{
853
0
  tap_listener_t *tl;
854
0
  unsigned flags = 0;
855
856
0
  for(tl=tap_listener_queue;tl;tl=tl->next){
857
0
    flags|=tl->flags;
858
0
  }
859
0
  return flags;
860
0
}
861
862
void tap_cleanup(void)
863
0
{
864
0
  tap_listener_t *elem_lq;
865
0
  tap_listener_t *head_lq = tap_listener_queue;
866
0
  tap_dissector_t *elem_dl;
867
0
  tap_dissector_t *head_dl = tap_dissector_list;
868
869
0
  while(head_lq){
870
0
    elem_lq = head_lq;
871
0
    head_lq = head_lq->next;
872
0
    free_tap_listener(elem_lq);
873
0
  }
874
0
  tap_listener_queue = NULL;
875
876
0
  while(head_dl){
877
0
    elem_dl = head_dl;
878
0
    head_dl = head_dl->next;
879
0
    g_free(elem_dl->name);
880
0
    g_free((void *)elem_dl);
881
0
  }
882
0
  tap_dissector_list = NULL;
883
884
0
  g_slist_free(tap_plugins);
885
0
  tap_plugins = NULL;
886
0
}
887
888
void tap_load_main_filter(dfilter_t *dfcode)
889
0
{
890
  /* Does not take ownership. This is not const because too
891
   * much of the dfilter API does not accept a const dfilter_t.
892
   */
893
0
  main_filter = dfcode;
894
0
}
895
896
/*
897
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
898
 *
899
 * Local variables:
900
 * c-basic-offset: 8
901
 * tab-width: 8
902
 * indent-tabs-mode: t
903
 * End:
904
 *
905
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
906
 * :indentSize=8:tabSize=8:noTabs=false:
907
 */