From Luis Ontanon:
[obnox/wireshark/wip.git] / plugins / mate / packet-mate.c
1 /* packet-mate.c
2  * Routines for the mate Facility's Pseudo-Protocol dissection
3  *
4  * Copyright 2004, Luis E. Garcia Ontanon <gopo@webflies.org>
5  *
6  * $Id$
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27
28 /**************************************************************************
29  * This is the pseudo protocol dissector for the mate module.          ***
30  * It is intended for this to be just the user interface to the module. ***
31  **************************************************************************/
32
33 #include "mate.h"
34
35 static int mate_tap_data = 0;
36 static mate_config* mc = NULL;
37
38 static int proto_mate = -1;
39
40 static char* pref_mate_config_filename = "";
41
42 static proto_item *mate_i = NULL;
43
44 void attrs_tree(proto_tree* tree, tvbuff_t *tvb,mate_item* item) {
45         AVPN* c;
46         proto_item *avpl_i;
47         proto_tree *avpl_t;
48         int* hfi_p;
49         
50         avpl_i = proto_tree_add_text(tree,tvb,0,0,"%s Attributes",item->cfg->name);
51         avpl_t = proto_item_add_subtree(avpl_i, item->cfg->ett_attr);
52
53         for ( c = item->avpl->null.next; c->avp; c = c->next) {
54                 hfi_p = g_hash_table_lookup(item->cfg->my_hfids,c->avp->n);
55
56                 if (hfi_p) {
57                         proto_tree_add_string(avpl_t,*hfi_p,tvb,0,0,c->avp->v);
58                 } else {
59                         g_warning("MATE: error: undefined attribute: mate.%s.%s",item->cfg->name,c->avp->n);
60                         proto_tree_add_text(avpl_t,tvb,0,0,"Undefined attribute: %s=%s",c->avp->n, c->avp->v);
61                 }
62         }
63 }
64
65 void mate_gop_tree(proto_tree* pdu_tree, tvbuff_t *tvb, mate_gop* gop);
66
67 void mate_gog_tree(proto_tree* tree, tvbuff_t *tvb, mate_gog* gog, mate_gop* gop) {
68         proto_item *gog_item;
69         proto_tree *gog_tree;
70         proto_item *gog_time_item;
71         proto_tree *gog_time_tree;
72         proto_item *gog_gop_item;
73         proto_tree *gog_gop_tree;
74         mate_gop* gog_gops;
75 #ifdef _MATE_DEBUGGING
76         proto_item* gog_key_item;
77         proto_tree* gog_key_tree;
78         guint i;
79 #endif
80         
81         gog_item = proto_tree_add_uint(tree,gog->cfg->hfid,tvb,0,0,gog->id);
82         gog_tree = proto_item_add_subtree(gog_item,gog->cfg->ett);
83                         
84         attrs_tree(gog_tree,tvb,gog);
85         
86         if (gog->cfg->show_times) {
87                 gog_time_item = proto_tree_add_text(gog_tree,tvb,0,0,"%s Times",gog->cfg->name);
88                 gog_time_tree = proto_item_add_subtree(gog_time_item, gog->cfg->ett_times);
89                 
90                 proto_tree_add_float(gog_time_tree, gog->cfg->hfid_start_time, tvb, 0, 0, gog->start_time);
91                 proto_tree_add_float(gog_time_tree, gog->cfg->hfid_last_time, tvb, 0, 0, gog->last_time - gog->start_time); 
92         }
93         
94         gog_gop_item = proto_tree_add_uint(gog_tree, gog->cfg->hfid_gog_num_of_gops,
95                                                                            tvb, 0, 0, gog->num_of_gops);
96         
97         gog_gop_tree = proto_item_add_subtree(gog_gop_item, gog->cfg->ett_children);
98         
99         for (gog_gops = gog->gops; gog_gops; gog_gops = gog_gops->next) {
100                 
101                 if (gop != gog_gops) {
102                         if (gog->cfg->gop_as_subtree) {
103                                 mate_gop_tree(gog_gop_tree, tvb, gog_gops);
104                         } else {
105                                 proto_tree_add_uint(gog_gop_tree,gog_gops->cfg->hfid,tvb,0,0,gog_gops->id);
106                         }
107                 } else {
108                          proto_tree_add_uint_format(gog_gop_tree,gop->cfg->hfid,tvb,0,0,gop->id,"%s of current frame: %d",gop->cfg->name,gop->id);
109                 }
110         }
111 }
112
113 void mate_gop_tree(proto_tree* tree, tvbuff_t *tvb, mate_gop* gop) {
114         proto_item *gop_item;
115         proto_tree *gop_time_tree;
116         proto_item *gop_time_item;
117         proto_tree *gop_tree;
118         proto_item *gop_pdu_item;
119         proto_tree *gop_pdu_tree;
120         mate_pdu* gop_pdus;
121         float  rel_time;
122         float  gop_time;
123         guint8* pdu_str;
124         guint8* type_str;
125         guint32 pdu_item;
126         
127         gop_item = proto_tree_add_uint(tree,gop->cfg->hfid,tvb,0,0,gop->id);
128         gop_tree = proto_item_add_subtree(gop_item, gop->cfg->ett);
129         
130         if (gop->gop_key) proto_tree_add_text(gop_tree,tvb,0,0,"GOP Key: %s",gop->gop_key);
131         
132         attrs_tree(gop_tree,tvb,gop);
133         
134         if (gop->cfg->show_times) {
135                 gop_time_item = proto_tree_add_text(gop_tree,tvb,0,0,"%s Times",gop->cfg->name);
136                 gop_time_tree = proto_item_add_subtree(gop_time_item, gop->cfg->ett_times);
137                 
138                 proto_tree_add_float(gop_time_tree, gop->cfg->hfid_start_time, tvb, 0, 0, gop->start_time);
139                 
140                 if (gop->released) { 
141                         proto_tree_add_float(gop_time_tree, gop->cfg->hfid_stop_time, tvb, 0, 0, gop->release_time - gop->start_time);
142                         proto_tree_add_float(gop_time_tree, gop->cfg->hfid_last_time, tvb, 0, 0, gop->last_time - gop->start_time); 
143                 } else {
144                         proto_tree_add_float(gop_time_tree, gop->cfg->hfid_last_time, tvb, 0, 0, gop->last_time - gop->start_time); 
145                 }
146         }
147         
148         gop_pdu_item = proto_tree_add_uint(gop_tree, gop->cfg->hfid_gop_num_pdus, tvb, 0, 0,gop->num_of_pdus);
149
150         if (gop->cfg->show_pdu_tree != mc->no_tree) {
151                 
152                 gop_pdu_tree = proto_item_add_subtree(gop_pdu_item, gop->cfg->ett_children);
153
154                 rel_time = gop_time = gop->start_time;
155
156                 type_str = (gop->cfg->show_pdu_tree == mc->frame_tree ) ? "in frame:" : "id:";
157                 
158                 for (gop_pdus = gop->pdus; gop_pdus; gop_pdus = gop_pdus->next) {
159
160                         pdu_item = (gop->cfg->show_pdu_tree == mc->frame_tree ) ? gop_pdus->frame : gop_pdus->id;
161
162                         if (gop_pdus->is_start) {
163                                 pdu_str = "Start ";
164                         } else if (gop_pdus->is_stop) {
165                                 pdu_str = "Stop ";
166                         } else if (gop_pdus->after_release) {
167                                 pdu_str = "After stop ";
168                         } else {
169                                 pdu_str = "";
170                         }
171                         
172                         proto_tree_add_uint_format(gop_pdu_tree,gop->cfg->hfid_gop_pdu,tvb,0,0,pdu_item,
173                                                                            "%sPDU: %s %i (%f : %f)",pdu_str, type_str,
174                                                                            pdu_item, gop_pdus->time_in_gop,
175                                                                            gop_pdus->time_in_gop - rel_time);
176                         
177                         rel_time = gop_pdus->time_in_gop;
178                         
179                 }
180         }
181 }
182
183
184 void mate_pdu_tree(mate_pdu *pdu, tvbuff_t *tvb, proto_tree* tree) {
185         proto_item *pdu_item;
186         proto_tree *pdu_tree;
187         
188         if ( ! pdu ) return;
189         
190         if (pdu->gop && pdu->gop->gog) {
191                 proto_item_append_text(mate_i," %s:%d->%s:%d->%s:%d",
192                                                            pdu->cfg->name,pdu->id,
193                                                            pdu->gop->cfg->name,pdu->gop->id,
194                                                            pdu->gop->gog->cfg->name,pdu->gop->gog->id);
195         } else if (pdu->gop) {
196                 proto_item_append_text(mate_i," %s:%d->%s:%d",
197                                                            pdu->cfg->name,pdu->id,
198                                                            pdu->gop->cfg->name,pdu->gop->id);
199         } else {
200                 proto_item_append_text(mate_i," %s:%d",pdu->cfg->name,pdu->id);
201         }
202         
203         pdu_item = proto_tree_add_uint(tree,pdu->cfg->hfid,tvb,0,0,pdu->id);
204         pdu_tree = proto_item_add_subtree(pdu_item, pdu->cfg->ett);
205         proto_tree_add_float(pdu_tree,pdu->cfg->hfid_pdu_rel_time, tvb, 0, 0, pdu->rel_time);           
206
207         if (pdu->gop) {
208                 proto_tree_add_float(pdu_tree,pdu->cfg->hfid_pdu_time_in_gop, tvb, 0, 0, pdu->time_in_gop);             
209                 mate_gop_tree(pdu_tree,tvb,pdu->gop);
210
211                 if (pdu->gop->gog)
212                         mate_gog_tree(pdu_tree,tvb,pdu->gop->gog,pdu->gop);
213         }
214         
215         if (pdu->avpl) {
216                 attrs_tree(pdu_tree,tvb,pdu);
217         }
218 }
219
220 extern void mate_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
221         mate_pdu* pdus;
222         proto_tree *mate_t;
223         
224         if ( ! mc || ! tree ) return;
225
226         analyze_frame(pinfo,tree);
227
228         if (( pdus = mate_get_pdus(pinfo->fd->num) )) {
229                 for ( ; pdus; pdus = pdus->next_in_frame) {
230                         mate_i = proto_tree_add_text(tree,tvb,0,0,"mate");
231                         mate_t = proto_item_add_subtree(mate_i, mc->ett_root);                  
232                         mate_pdu_tree(pdus,tvb,mate_t);
233                 }
234         }
235 }
236
237 static void init_mate(void) {
238         GString* tap_error = NULL;
239
240         tap_error = register_tap_listener("frame", &mate_tap_data,
241                                                                           mc->tap_filter,
242                                                                           (tap_reset_cb) NULL,
243                                                                           mate_packet,
244                                                                           (tap_draw_cb) NULL);
245         
246         if ( tap_error ) {
247                 g_warning("mate: couldn't (re)register tap: %s",tap_error->str);
248                 g_string_free(tap_error, TRUE);
249                 mate_tap_data = 0;
250                 return;
251         } else {
252                 mate_tap_data = 1;
253         }
254         
255         initialize_mate_runtime();
256 }
257
258 extern
259 void
260 proto_reg_handoff_mate(void)
261 {
262         if ( *pref_mate_config_filename != '\0' ) {
263                 
264                 mc = mate_make_config(pref_mate_config_filename);
265                 
266                 if (mc) {
267                         proto_register_field_array(proto_mate, (hf_register_info*) mc->hfrs->data, mc->hfrs->len );
268                         proto_register_subtree_array((gint**) mc->ett->data, mc->ett->len);
269                         register_init_routine(init_mate);
270                 }
271         }
272 }
273
274 extern
275 void
276 proto_register_mate(void)
277 {
278         module_t *mate_module;
279
280         proto_mate = proto_register_protocol("Meta Analysis Tracing Engine", "mate", "mate");
281         register_dissector("mate",mate_tree,proto_mate);
282         mate_module = prefs_register_protocol(proto_mate, proto_reg_handoff_mate);
283         prefs_register_string_preference(mate_module, "config_filename",
284                                                                          "Configuration Filename",
285                                                                          "The name of the file containing the mate module's configuration",
286                                                                          &pref_mate_config_filename);
287 }
288