Add Mike Garratt to the list of authors for (at the very least) his contributions...
[metze/wireshark/wip.git] / epan / tap.c
1 /* tap.c
2  * packet tap interface   2002 Ronnie Sahlberg
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h>
35 #endif
36
37 #include <string.h>
38 #include <epan/packet_info.h>
39 #include <epan/dfilter/dfilter.h>
40 #include <epan/tap.h>
41
42 static gboolean tapping_is_active=FALSE;
43
44 typedef struct _tap_dissector_t {
45         struct _tap_dissector_t *next;
46         char *name;
47 } tap_dissector_t;
48 static tap_dissector_t *tap_dissector_list=NULL;
49
50 /*
51  * This is the list of free and used packets queued for a tap.
52  * It is implemented here explicitly instead of using GLib objects
53  * in order to be as fast as possible as we need to build and tear down the
54  * queued list at least once for each packet we see and thus we must be able
55  * to build and tear it down as fast as possible.
56  */
57 typedef struct _tap_packet_t {
58         int tap_id;
59         packet_info *pinfo;
60         const void *tap_specific_data;
61 } tap_packet_t;
62
63 #define TAP_PACKET_QUEUE_LEN 100
64 static tap_packet_t tap_packet_array[TAP_PACKET_QUEUE_LEN];
65 static guint tap_packet_index;
66
67 typedef struct _tap_listener_t {
68         struct _tap_listener_t *next;
69         int tap_id;
70         gboolean needs_redraw;
71         guint flags;
72         dfilter_t *code;
73         void *tapdata;
74         tap_reset_cb reset;
75         tap_packet_cb packet;
76         tap_draw_cb draw;
77 } tap_listener_t;
78 static volatile tap_listener_t *tap_listener_queue=NULL;
79
80 /* **********************************************************************
81  * Init routine only called from epan at application startup
82  * ********************************************************************** */
83 /* This function is called once when wireshark starts up and is used
84    to init any data structures we may need later.
85 */
86 void
87 tap_init(void)
88 {
89         tap_packet_index=0;
90
91         return;
92 }
93
94 /* **********************************************************************
95  * Functions called from dissector when made tappable
96  * ********************************************************************** */
97 /* the following two functions are used from dissectors to
98    1. register the ability to tap packets from this subdissector
99    2. push packets encountered by the subdissector to anyone tapping
100 */
101
102 /* This function registers that a dissector has the packet tap ability
103    available.  The name parameter is the name of this tap and extensions can
104    use open_tap(char *name,... to specify that it wants to receive packets/
105    events from this tap.
106
107    This function is only to be called once, when the dissector initializes.
108
109    The return value from this call is later used as a parameter to the
110    tap_packet(unsigned int *tap_id,...
111    call so that the tap subsystem knows to which tap point this tapped
112    packet is associated.
113 */
114 int
115 register_tap(const char *name)
116 {
117         tap_dissector_t *td, *tdl;
118         int i, tap_id;
119
120         if(tap_dissector_list){
121                 tap_id=find_tap_id(name);
122                 if (tap_id)
123                         return tap_id;
124         }
125
126         td=(tap_dissector_t *)g_malloc(sizeof(tap_dissector_t));
127         td->next=NULL;
128         td->name = g_strdup(name);
129
130         if(!tap_dissector_list){
131                 tap_dissector_list=td;
132                 i=1;
133         } else {
134                 for(i=2,tdl=tap_dissector_list;tdl->next;i++,tdl=tdl->next)
135                         ;
136                 tdl->next=td;
137         }
138         return i;
139 }
140
141
142 /* Everytime the dissector has finished dissecting a packet (and all
143    subdissectors have returned) and if the dissector has been made "tappable"
144    it will push some data to everyone tapping this layer by a call
145    to tap_queue_packet().
146    The first parameter is the tap_id returned by the register_tap()
147    call for this dissector (so the tap system can keep track of who it came
148    from and who is listening to it)
149    The second is the packet_info structure which many tap readers will find
150    interesting.
151    The third argument is specific to each tap point or NULL if no additional
152    data is available to this tap.  A tap point in say IP will probably want to
153    push the IP header structure here. Same thing for TCP and ONCRPC.
154
155    The pinfo and the specific pointer are what is supplied to every listener
156    in the read_callback() call made to every one currently listening to this
157    tap.
158
159    The tap reader is responsible to know how to parse any structure pointed
160    to by the tap specific data pointer.
161 */
162 void
163 tap_queue_packet(int tap_id, packet_info *pinfo, const void *tap_specific_data)
164 {
165         tap_packet_t *tpt;
166
167         if(!tapping_is_active){
168                 return;
169         }
170         /*
171          * XXX - should we allocate this with an ep_allocator,
172          * rather than having a fixed maximum number of entries?
173          */
174         if(tap_packet_index >= TAP_PACKET_QUEUE_LEN){
175                 g_warning("Too many taps queued");
176                 return;
177         }
178
179         tpt=&tap_packet_array[tap_packet_index];
180         tpt->tap_id=tap_id;
181         tpt->pinfo=pinfo;
182         tpt->tap_specific_data=tap_specific_data;
183         tap_packet_index++;
184 }
185
186
187
188
189
190 /* **********************************************************************
191  * Functions used by file.c to drive the tap subsystem
192  * ********************************************************************** */
193
194 void tap_build_interesting (epan_dissect_t *edt)
195 {
196         tap_listener_t *tl;
197
198         /* nothing to do, just return */
199         if(!tap_listener_queue){
200                 return;
201         }
202
203         /* loop over all tap listeners and build the list of all
204            interesting hf_fields */
205         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
206                 if(tl->code){
207                         epan_dissect_prime_dfilter(edt, tl->code);
208                 }
209         }
210 }
211
212 /* This function is used to delete/initialize the tap queue and prime an
213    epan_dissect_t with all the filters for tap listeners.
214    To free the tap queue, we just prepend the used queue to the free queue.
215 */
216 void
217 tap_queue_init(epan_dissect_t *edt)
218 {
219         /* nothing to do, just return */
220         if(!tap_listener_queue){
221                 return;
222         }
223
224         tapping_is_active=TRUE;
225
226         tap_packet_index=0;
227
228         tap_build_interesting (edt);
229 }
230
231 /* this function is called after a packet has been fully dissected to push the tapped
232    data to all extensions that has callbacks registered.
233 */
234 void
235 tap_push_tapped_queue(epan_dissect_t *edt)
236 {
237         tap_packet_t *tp;
238         tap_listener_t *tl;
239         guint i;
240
241         /* nothing to do, just return */
242         if(!tapping_is_active){
243                 return;
244         }
245
246         tapping_is_active=FALSE;
247
248         /* nothing to do, just return */
249         if(!tap_packet_index){
250                 return;
251         }
252
253         /* loop over all tap listeners and call the listener callback
254            for all packets that match the filter. */
255         for(i=0;i<tap_packet_index;i++){
256                 for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
257                         tp=&tap_packet_array[i];
258                         if(tp->tap_id==tl->tap_id){
259                                 gboolean passed=TRUE;
260                                 if(tl->code){
261                                         passed=dfilter_apply_edt(tl->code, edt);
262                                 }
263                                 if(passed && tl->packet){
264                                         tl->needs_redraw|=tl->packet(tl->tapdata, tp->pinfo, edt, tp->tap_specific_data);
265                                 }
266                         }
267                 }
268         }
269 }
270
271
272 /* This function can be used by a dissector to fetch any tapped data before
273  * returning.
274  * This can be useful if one wants to extract the data inside dissector  BEFORE
275  * it exists as an alternative to the callbacks that are all called AFTER the
276  * dissection has completed.
277  *
278  * Example: SMB2 uses this mechanism to extract the data tapped from NTLMSSP
279  * containing the account and domain names before exiting.
280  * Note that the SMB2 tap listener specifies all three callbacks as NULL.
281  *
282  * Beware: when using this mechanism to extract the tapped data you can not
283  * use "filters" and should specify the "filter" as NULL when registering
284  * the tap listener.
285  */
286 const void *
287 fetch_tapped_data(int tap_id, int idx)
288 {
289         tap_packet_t *tp;
290         guint i;
291
292         /* nothing to do, just return */
293         if(!tapping_is_active){
294                 return NULL;
295         }
296
297         /* nothing to do, just return */
298         if(!tap_packet_index){
299                 return NULL;
300         }
301
302         /* loop over all tapped packets and return the one with index idx */
303         for(i=0;i<tap_packet_index;i++){
304                 tp=&tap_packet_array[i];
305                 if(tp->tap_id==tap_id){
306                         if(!idx--){
307                                 return tp->tap_specific_data;
308                         }
309                 }
310         }
311
312         return NULL;
313 }
314
315 /* This function is called when we need to reset all tap listeners, for example
316    when we open/start a new capture or if we need to rescan the packet list.
317 */
318 void
319 reset_tap_listeners(void)
320 {
321         tap_listener_t *tl;
322
323         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
324                 if(tl->reset){
325                         tl->reset(tl->tapdata);
326                 }
327                 tl->needs_redraw=TRUE;
328         }
329
330 }
331
332
333 /* This function is called when we need to redraw all tap listeners, for example
334    when we open/start a new capture or if we need to rescan the packet list.
335    It should be called from a low priority thread say once every 3 seconds
336
337    If draw_all is true, redraw all aplications regardless if they have
338    changed or not.
339 */
340 void
341 draw_tap_listeners(gboolean draw_all)
342 {
343         tap_listener_t *tl;
344
345         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
346                 if(tl->needs_redraw || draw_all){
347                         if(tl->draw){
348                                 tl->draw(tl->tapdata);
349                         }
350                 }
351                 tl->needs_redraw=FALSE;
352         }
353 }
354
355
356
357 /* **********************************************************************
358  * Functions used by tap to
359  * 1. register that a really simple extension is available for use by
360  *    Wireshark.
361  * 2. start tapping from a subdissector
362  * 3. close an already open tap
363  * ********************************************************************** */
364 /* this function will return the tap_id for the specific protocol tap
365    or 0 if no such tap was found.
366  */
367 int
368 find_tap_id(const char *name)
369 {
370         tap_dissector_t *td;
371         int i;
372
373         for(i=1,td=tap_dissector_list;td;i++,td=td->next) {
374                 if(!strcmp(td->name,name)){
375                         return i;
376                 }
377         }
378         return 0;
379 }
380
381 /* this function attaches the tap_listener to the named tap.
382  * function returns :
383  *     NULL: ok.
384  * non-NULL: error, return value points to GString containing error
385  *           message.
386  */
387 GString *
388 register_tap_listener(const char *tapname, void *tapdata, const char *fstring,
389     guint flags, tap_reset_cb reset, tap_packet_cb packet, tap_draw_cb draw)
390 {
391         tap_listener_t *tl;
392         int tap_id;
393         GString *error_string;
394
395         tap_id=find_tap_id(tapname);
396         if(!tap_id){
397                 error_string = g_string_new("");
398                 g_string_printf(error_string, "Tap %s not found", tapname);
399                 return error_string;
400         }
401
402         tl=(tap_listener_t *)g_malloc(sizeof(tap_listener_t));
403         tl->code=NULL;
404         tl->needs_redraw=TRUE;
405         tl->flags=flags;
406         if(fstring){
407                 if(!dfilter_compile(fstring, &tl->code)){
408                         error_string = g_string_new("");
409                         g_string_printf(error_string,
410                             "Filter \"%s\" is invalid - %s",
411                             fstring, dfilter_error_msg);
412                         g_free(tl);
413                         return error_string;
414                 }
415         }
416
417         tl->tap_id=tap_id;
418         tl->tapdata=tapdata;
419         tl->reset=reset;
420         tl->packet=packet;
421         tl->draw=draw;
422         tl->next=(tap_listener_t *)tap_listener_queue;
423
424         tap_listener_queue=tl;
425
426         return NULL;
427 }
428
429 /* this function sets a new dfilter to a tap listener
430  */
431 GString *
432 set_tap_dfilter(void *tapdata, const char *fstring)
433 {
434         tap_listener_t *tl=NULL,*tl2;
435         GString *error_string;
436
437         if(!tap_listener_queue){
438                 return NULL;
439         }
440
441         if(tap_listener_queue->tapdata==tapdata){
442                 tl=(tap_listener_t *)tap_listener_queue;
443         } else {
444                 for(tl2=(tap_listener_t *)tap_listener_queue;tl2->next;tl2=tl2->next){
445                         if(tl2->next->tapdata==tapdata){
446                                 tl=tl2->next;
447                                 break;
448                         }
449
450                 }
451         }
452
453         if(tl){
454                 if(tl->code){
455                         dfilter_free(tl->code);
456                         tl->code=NULL;
457                 }
458                 tl->needs_redraw=TRUE;
459                 if(fstring){
460                         if(!dfilter_compile(fstring, &tl->code)){
461                                 error_string = g_string_new("");
462                                 g_string_printf(error_string,
463                                                  "Filter \"%s\" is invalid - %s",
464                                                  fstring, dfilter_error_msg);
465                                 return error_string;
466                         }
467                 }
468         }
469
470         return NULL;
471 }
472
473 /* this function removes a tap listener
474  */
475 void
476 remove_tap_listener(void *tapdata)
477 {
478         tap_listener_t *tl=NULL,*tl2;
479
480         if(!tap_listener_queue){
481                 return;
482         }
483
484         if(tap_listener_queue->tapdata==tapdata){
485                 tl=(tap_listener_t *)tap_listener_queue;
486                 tap_listener_queue=tap_listener_queue->next;
487         } else {
488                 for(tl2=(tap_listener_t *)tap_listener_queue;tl2->next;tl2=tl2->next){
489                         if(tl2->next->tapdata==tapdata){
490                                 tl=tl2->next;
491                                 tl2->next=tl2->next->next;
492                                 break;
493                         }
494
495                 }
496         }
497
498         if(tl){
499                 if(tl->code){
500                         dfilter_free(tl->code);
501                 }
502                 g_free(tl);
503         }
504
505         return;
506 }
507
508 /*
509  * Return TRUE if we have one or more tap listeners that require dissection,
510  * FALSE otherwise.
511  */
512 gboolean
513 tap_listeners_require_dissection(void)
514 {
515         volatile tap_listener_t *tap_queue = tap_listener_queue;
516
517         while(tap_queue) {
518                 if(!(tap_queue->flags & TL_IS_DISSECTOR_HELPER))
519                         return TRUE;
520
521                 tap_queue = tap_queue->next;
522         }
523
524         return FALSE;
525
526 }
527
528 /* Returns TRUE there is an active tap listener for the specified tap id. */
529 gboolean
530 have_tap_listener(int tap_id)
531 {
532         volatile tap_listener_t *tap_queue = tap_listener_queue;
533
534         while(tap_queue) {
535                 if(tap_queue->tap_id == tap_id)
536                         return TRUE;
537
538                 tap_queue = tap_queue->next;
539         }
540
541         return FALSE;
542 }
543
544 /*
545  * Return TRUE if we have any tap listeners with filters, FALSE otherwise.
546  */
547 gboolean
548 have_filtering_tap_listeners(void)
549 {
550         tap_listener_t *tl;
551
552         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
553                 if(tl->code)
554                         return TRUE;
555         }
556         return FALSE;
557 }
558
559 /*
560  * Get the union of all the flags for all the tap listeners; that gives
561  * an indication of whether the protocol tree, or the columns, are
562  * required by any taps.
563  */
564 guint
565 union_of_tap_listener_flags(void)
566 {
567         tap_listener_t *tl;
568         guint flags = 0;
569
570         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
571                 flags|=tl->flags;
572         }
573         return flags;
574 }