Put
[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., 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 int num_tap_filters=0;
46
47 typedef struct _tap_dissector_t {
48         struct _tap_dissector_t *next;
49         char *name;
50 } tap_dissector_t;
51 static tap_dissector_t *tap_dissector_list=NULL;
52
53 /*
54  * This is the list of free and used packets queued for a tap.
55  * It is implemented here explicitely instead of using GLib objects
56  * in order to be as fast as possible as we need to build and tear down the
57  * queued list at least once for each packet we see, thus we must be able
58  * to build and tear it down as fast as possible.
59  */
60 typedef struct _tap_packet_t {
61         int tap_id;
62         packet_info *pinfo;
63         const void *tap_specific_data;
64 } tap_packet_t;
65
66 #define TAP_PACKET_QUEUE_LEN 100
67 static tap_packet_t tap_packet_array[TAP_PACKET_QUEUE_LEN];
68 static guint tap_packet_index;
69
70 typedef struct _tap_listener_t {
71         struct _tap_listener_t *next;
72         int tap_id;
73         int needs_redraw;
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(unsinged 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;
121
122         td=g_malloc(sizeof(tap_dissector_t));
123         td->next=NULL;
124         td->name = g_strdup(name);
125
126         if(!tap_dissector_list){
127                 tap_dissector_list=td;
128                 i=1;
129         } else {
130                 for(i=2,tdl=tap_dissector_list;tdl->next;i++,tdl=tdl->next)
131                         ;
132                 tdl->next=td;
133         }
134         return i;
135 }
136
137
138 /* Everytime the dissector has finished dissecting a packet (and all
139    subdissectors have returned) and if the dissector has been made "tappable"
140    it will push some data to everyone tapping this layer by a call
141    to tap_queue_packet().
142    The first parameter is the tap_id returned by the register_tap()
143    call for this dissector (so the tap system can keep track of who it came
144    from and who is listening to it)
145    The second is the packet_info structure which many tap readers will find
146    interesting.
147    The third argument is specific to each tap point or NULL if no additional 
148    data is available to this tap.  A tap point in say IP will probably want to
149    push the IP header structure here. Same thing for TCP and ONCRPC.
150   
151    The pinfo and the specific pointer are what is supplied to every listener
152    in the read_callback() call made to every one currently listening to this
153    tap.
154  
155    The tap reader is responsible to know how to parse any structure pointed 
156    to by the tap specific data pointer.
157 */
158 void 
159 tap_queue_packet(int tap_id, packet_info *pinfo, const void *tap_specific_data)
160 {
161         tap_packet_t *tpt;
162
163         if(!tapping_is_active){
164                 return;
165         }
166         /*
167          * XXX - should we allocate this with an ep_allocator,
168          * rather than having a fixed maximum number of entries?
169          */
170         if(tap_packet_index >= TAP_PACKET_QUEUE_LEN){
171                 g_warning("Too many taps queued");
172                 return;
173         }
174
175         tpt=&tap_packet_array[tap_packet_index];
176         tpt->tap_id=tap_id;
177         tpt->pinfo=pinfo;
178         tpt->tap_specific_data=tap_specific_data;
179         tap_packet_index++;
180 }
181
182
183
184
185
186 /* **********************************************************************
187  * Functions used by file.c to drive the tap subsystem
188  * ********************************************************************** */
189 /* This function is used to delete/initialize the tap queue and prime an
190    epan_dissect_t with all the filters for tap listeners.
191    To free the tap queue, we just prepend the used queue to the free queue.
192 */
193 void
194 tap_queue_init(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         tapping_is_active=TRUE;
204
205         tap_packet_index=0;
206
207         /* loop over all tap listeners and build the list of all
208            interesting hf_fields */
209         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
210                 if(tl->code){
211                         epan_dissect_prime_dfilter(edt, tl->code);
212                 }
213         }
214 }
215
216 /* this function is called after a packet has been fully dissected to push the tapped
217    data to all extensions that has callbacks registered.
218 */
219 void 
220 tap_push_tapped_queue(epan_dissect_t *edt)
221 {
222         tap_packet_t *tp;
223         tap_listener_t *tl;
224         guint i;
225
226         /* nothing to do, just return */
227         if(!tapping_is_active){
228                 return;
229         }
230
231         tapping_is_active=FALSE;
232
233         /* nothing to do, just return */
234         if(!tap_packet_index){
235                 return;
236         }
237
238         /* loop over all tap listeners and call the listener callback
239            for all packets that match the filter. */
240         for(i=0;i<tap_packet_index;i++){
241                 for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
242                         tp=&tap_packet_array[i];
243                         if(tp->tap_id==tl->tap_id){
244                                 int passed=TRUE;
245                                 if(tl->code){
246                                         passed=dfilter_apply_edt(tl->code, edt);
247                                 }
248                                 if(passed && tl->packet){
249                                         tl->needs_redraw|=tl->packet(tl->tapdata, tp->pinfo, edt, tp->tap_specific_data);
250                                 }
251                         }
252                 }
253         }
254 }
255
256
257 /* This function can be used by a dissector to fetch any tapped data before
258  * returning.
259  * This can be useful if one wants to extract the data inside dissector  BEFORE
260  * it exists as an alternative to the callbacks that are all called AFTER the 
261  * dissection has completed.
262  *
263  * Example: SMB2 uses this mechanism to extract the data tapped from NTLMSSP
264  * containing the account and domain names before exiting.
265  * Note that the SMB2 tap listener specifies all three callbacks as NULL.
266  *
267  * Beware: when using this mechanism to extract the tapped data you can not
268  * use "filters" and should specify the "filter" as NULL when registering
269  * the tap listener.
270  */
271 void * 
272 fetch_tapped_data(int tap_id, int idx)
273 {
274         tap_packet_t *tp;
275         guint i;
276
277         /* nothing to do, just return */
278         if(!tapping_is_active){
279                 return NULL;
280         }
281
282         /* nothing to do, just return */
283         if(!tap_packet_index){
284                 return NULL;
285         }
286
287         /* loop over all tapped packets and return the one with index idx */
288         for(i=0;i<tap_packet_index;i++){
289                 tp=&tap_packet_array[i];
290                 if(tp->tap_id==tap_id){
291                         if(!idx--){
292                                 return tp->tap_specific_data;
293                         }
294                 }
295         }
296
297         return NULL;
298 }
299
300 /* This function is called when we need to reset all tap listeners, for example
301    when we open/start a new capture or if we need to rescan the packet list.
302 */
303 void
304 reset_tap_listeners(void)
305 {
306         tap_listener_t *tl;
307
308         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
309                 if(tl->reset){
310                         tl->reset(tl->tapdata);
311                 }
312                 tl->needs_redraw=1;
313         }
314
315 }
316
317
318 /* This function is called when we need to redraw all tap listeners, for example
319    when we open/start a new capture or if we need to rescan the packet list.
320    this one should be called from a low priority thread say once every 3 seconds
321  
322    If draw_all is true, redraw all aplications regardless if they have 
323    changed or not.
324 */
325 void
326 draw_tap_listeners(gboolean draw_all)
327 {
328         tap_listener_t *tl;
329
330         for(tl=(tap_listener_t *)tap_listener_queue;tl;tl=tl->next){
331                 if(tl->needs_redraw || draw_all){
332                         if(tl->draw){
333                                 tl->draw(tl->tapdata);
334                         }
335                 }
336                 tl->needs_redraw=0;
337         }
338 }
339
340
341
342 /* **********************************************************************
343  * Functions used by tap to
344  * 1, register that a really simple extension is available for use by
345  *    Wireshark. 
346  * 2, start tapping from a subdissector 
347  * 3, close an already open tap
348  * ********************************************************************** */
349 /* this function will return the tap_id for the specific protocol tap
350    or 0 if no such tap was found.
351  */
352 int 
353 find_tap_id(const char *name)
354 {
355         tap_dissector_t *td;
356         int i;
357
358         for(i=1,td=tap_dissector_list;td;i++,td=td->next) {
359                 if(!strcmp(td->name,name)){
360                         return i;
361                 }
362         }
363         return 0;
364 }
365
366 /* this function attaches the tap_listener to the named tap.
367  * function returns :
368  *     NULL: ok.
369  * non-NULL: error, return value points to GString containing error
370  *           message.
371  */
372 GString *
373 register_tap_listener(const char *tapname, void *tapdata, const char *fstring, tap_reset_cb reset, tap_packet_cb packet, tap_draw_cb draw)
374 {
375         tap_listener_t *tl;
376         int tap_id;
377         GString *error_string;
378
379         tap_id=find_tap_id(tapname);
380         if(!tap_id){
381                 error_string = g_string_new("");
382                 g_string_sprintf(error_string, "Tap %s not found", tapname);
383                 return error_string;
384         }
385
386         tl=g_malloc(sizeof(tap_listener_t));
387         tl->code=NULL;
388         tl->needs_redraw=1;
389         if(fstring){
390                 if(!dfilter_compile(fstring, &tl->code)){
391                         error_string = g_string_new("");
392                         g_string_sprintf(error_string,
393                             "Filter \"%s\" is invalid - %s",
394                             fstring, dfilter_error_msg);
395                         g_free(tl);
396                         return error_string;
397                 } else {
398                         num_tap_filters++;
399                 }
400         }
401
402         tl->tap_id=tap_id;
403         tl->tapdata=tapdata;
404         tl->reset=reset;
405         tl->packet=packet;
406         tl->draw=draw;
407         tl->next=(tap_listener_t *)tap_listener_queue;
408
409         tap_listener_queue=tl;
410
411         return NULL;
412 }
413
414 /* this function removes a tap listener
415  */
416 void
417 remove_tap_listener(void *tapdata)
418 {
419         tap_listener_t *tl=NULL,*tl2;
420
421         if(!tap_listener_queue){
422                 return;
423         }
424
425         if(tap_listener_queue->tapdata==tapdata){
426                 tl=(tap_listener_t *)tap_listener_queue;
427                 tap_listener_queue=tap_listener_queue->next;
428         } else {
429                 for(tl2=(tap_listener_t *)tap_listener_queue;tl2->next;tl2=tl2->next){
430                         if(tl2->next->tapdata==tapdata){
431                                 tl=tl2->next;
432                                 tl2->next=tl2->next->next;
433                                 break;
434                         }
435                         
436                 }
437         }
438
439         if(tl){
440                 if(tl->code){
441                         dfilter_free(tl->code);
442                         num_tap_filters--;
443                 }
444                 g_free(tl);
445         }
446
447         return;
448 }
449
450 /*
451  * Return TRUE if we have tap listeners, FALSE otherwise.
452  * Checking "num_tap_filters" isn't the right way to check whether we need
453  * to do any dissection in order to run taps, as not all taps necessarily
454  * have filters, and "num_tap_filters" is the number of tap filters, not
455  * the number of tap listeners; it's only the right way to check whether
456  * we need to build a protocol tree when doing dissection.
457  */
458 gboolean
459 have_tap_listeners(void)
460 {
461         return tap_listener_queue != NULL;
462 }