Coverage Report

Created: 2026-09-28 06:52

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