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