rerun pidl
[metze/wireshark/wip.git] / epan / frame_data.c
1 /* frame_data.c
2  * Routines for packet disassembly
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include "config.h"
27
28 #include <glib.h>
29
30 #include <epan/epan.h>
31 #include <wiretap/wtap.h>
32 #include <epan/frame_data.h>
33 #include <epan/packet.h>
34 #include <epan/emem.h>
35 #include <epan/wmem/wmem.h>
36 #include <epan/timestamp.h>
37 #include <epan/packet_info.h>
38
39
40 /* Protocol-specific data attached to a frame_data structure - protocol
41    index and opaque pointer. */
42 typedef struct _frame_proto_data {
43   int   proto;
44   guint32 key;
45   void *proto_data;
46 } frame_proto_data;
47
48 /* XXX - I declared this static, because it only seems to be used by
49  * p_get_proto_data and p_add_proto_data
50  */
51 static gint
52 p_compare(gconstpointer a, gconstpointer b)
53 {
54   const frame_proto_data *ap = (const frame_proto_data *)a;
55   const frame_proto_data *bp = (const frame_proto_data *)b;
56
57   if (ap -> proto > bp -> proto){
58     return 1;
59   }else if (ap -> proto == bp -> proto){
60     if (ap -> key > bp -> key){
61       return 1;
62     }else if (ap -> key == bp -> key){
63       return 0;
64         }
65     return -1;
66   }else{
67     return -1;
68   }
69 }
70
71 void
72 p_add_proto_data(wmem_allocator_t *scope, struct _packet_info* pinfo, int proto, guint32 key, void *proto_data)
73 {
74   frame_proto_data *p1;
75   GSList** proto_list;
76
77   if (scope == pinfo->pool) {
78     p1 = (frame_proto_data *)wmem_alloc(scope, sizeof(frame_proto_data));
79     proto_list = &pinfo->proto_data;
80   } else {
81     p1 = (frame_proto_data *)wmem_alloc(wmem_file_scope(), sizeof(frame_proto_data));
82     proto_list = &pinfo->fd->pfd;
83   }
84
85   p1->proto = proto;
86   p1->key = key;
87   p1->proto_data = proto_data;
88
89   /* Add it to the GSLIST */
90   *proto_list = g_slist_insert_sorted(*proto_list,
91                     (gpointer *)p1,
92                     p_compare);
93 }
94
95 void *
96 p_get_proto_data(wmem_allocator_t *scope, struct _packet_info* pinfo, int proto, guint32 key)
97 {
98   frame_proto_data  temp, *p1;
99   GSList           *item;
100
101   temp.proto = proto;
102   temp.key = key;
103   temp.proto_data = NULL;
104
105   if (scope == pinfo->pool) {
106     item = g_slist_find_custom(pinfo->proto_data, (gpointer *)&temp, p_compare);
107   } else {
108     item = g_slist_find_custom(pinfo->fd->pfd, (gpointer *)&temp, p_compare);
109   }
110
111   if (item) {
112     p1 = (frame_proto_data *)item->data;
113     return p1->proto_data;
114   }
115
116   return NULL;
117
118 }
119
120 void
121 p_remove_proto_data(wmem_allocator_t *scope, struct _packet_info* pinfo, int proto, guint32 key)
122 {
123   frame_proto_data  temp;
124   GSList           *item;
125   GSList** proto_list;
126
127   temp.proto = proto;
128   temp.key = key;
129   temp.proto_data = NULL;
130
131   if (scope == pinfo->pool) {
132     item = g_slist_find_custom(pinfo->fd->pfd, (gpointer *)&temp, p_compare);
133     proto_list = &pinfo->proto_data;
134   } else {
135     item = g_slist_find_custom(pinfo->fd->pfd, (gpointer *)&temp, p_compare);
136     proto_list = &pinfo->fd->pfd;
137   }
138
139   if (item) {
140     *proto_list = g_slist_remove(*proto_list, item->data);
141   }
142
143 }
144
145 gchar *
146 p_get_proto_name_and_key(wmem_allocator_t *scope, struct _packet_info* pinfo, guint pfd_index){
147         frame_proto_data  *temp;
148
149   if (scope == pinfo->pool) {
150         temp = (frame_proto_data*)g_slist_nth_data(pinfo->proto_data, pfd_index);
151   } else {
152         temp = (frame_proto_data*)g_slist_nth_data(pinfo->fd->pfd, pfd_index);
153   }
154
155   return ep_strdup_printf("[%s, key %u]",proto_get_protocol_name(temp->proto), temp->key);
156 }
157
158 #define COMPARE_FRAME_NUM()     ((fdata1->num < fdata2->num) ? -1 : \
159                                  (fdata1->num > fdata2->num) ? 1 : \
160                                  0)
161
162 #define COMPARE_NUM(f)  ((fdata1->f < fdata2->f) ? -1 : \
163                          (fdata1->f > fdata2->f) ? 1 : \
164                          COMPARE_FRAME_NUM())
165
166 /* Compare time stamps.
167    A packet whose time is a reference time is considered to have
168    a lower time stamp than any frame with a non-reference time;
169    if both packets' times are reference times, we compare the
170    times of the packets. */
171 #define COMPARE_TS_REAL(time1, time2) \
172                 ((fdata1->flags.ref_time && !fdata2->flags.ref_time) ? -1 : \
173                  (!fdata1->flags.ref_time && fdata2->flags.ref_time) ? 1 : \
174                  ((time1).secs < (time2).secs) ? -1 : \
175                  ((time1).secs > (time2).secs) ? 1 : \
176                  ((time1).nsecs < (time2).nsecs) ? -1 :\
177                  ((time1).nsecs > (time2).nsecs) ? 1 : \
178                  COMPARE_FRAME_NUM())
179
180 #define COMPARE_TS(ts) COMPARE_TS_REAL(fdata1->ts, fdata2->ts)
181
182 void
183 frame_delta_abs_time(const struct epan_session *epan, const frame_data *fdata, guint32 prev_num, nstime_t *delta)
184 {
185   const nstime_t *prev_abs_ts = (prev_num) ? epan_get_frame_ts(epan, prev_num) : NULL;
186
187   if (prev_abs_ts) {
188     nstime_delta(delta, &fdata->abs_ts, prev_abs_ts);
189   } else {
190     /* If we don't have the time stamp of the previous packet,
191        it's because we have no displayed/captured packets prior to this.
192        Set the delta time to zero. */
193     nstime_set_zero(delta);
194   }
195 }
196
197 static gint
198 frame_data_time_delta_compare(const struct epan_session *epan, const frame_data *fdata1, const frame_data *fdata2)
199 {
200   nstime_t del_cap_ts1, del_cap_ts2;
201
202   frame_delta_abs_time(epan, fdata1, fdata1->num - 1, &del_cap_ts1);
203   frame_delta_abs_time(epan, fdata2, fdata2->num - 1, &del_cap_ts2);
204
205   return COMPARE_TS_REAL(del_cap_ts1, del_cap_ts2);
206 }
207
208 static gint
209 frame_data_time_delta_rel_compare(const struct epan_session *epan, const frame_data *fdata1, const frame_data *fdata2)
210 {
211   nstime_t del_rel_ts1, del_rel_ts2;
212
213   frame_delta_abs_time(epan, fdata1, fdata1->frame_ref_num, &del_rel_ts1);
214   frame_delta_abs_time(epan, fdata2, fdata2->frame_ref_num, &del_rel_ts2);
215
216   return COMPARE_TS_REAL(del_rel_ts1, del_rel_ts2);
217 }
218
219 static gint
220 frame_data_time_delta_dis_compare(const struct epan_session *epan, const frame_data *fdata1, const frame_data *fdata2)
221 {
222   nstime_t del_dis_ts1, del_dis_ts2;
223
224   frame_delta_abs_time(epan, fdata1, fdata1->prev_dis_num, &del_dis_ts1);
225   frame_delta_abs_time(epan, fdata2, fdata2->prev_dis_num, &del_dis_ts2);
226
227   return COMPARE_TS_REAL(del_dis_ts1, del_dis_ts2);
228 }
229
230 gint
231 frame_data_compare(const struct epan_session *epan, const frame_data *fdata1, const frame_data *fdata2, int field)
232 {
233   switch (field) {
234   case COL_NUMBER:
235     return COMPARE_FRAME_NUM();
236
237   case COL_CLS_TIME:
238     switch (timestamp_get_type()) {
239     case TS_ABSOLUTE:
240     case TS_ABSOLUTE_WITH_YMD:
241     case TS_ABSOLUTE_WITH_YDOY:
242     case TS_UTC:
243     case TS_UTC_WITH_YMD:
244     case TS_UTC_WITH_YDOY:
245     case TS_EPOCH:
246       return COMPARE_TS(abs_ts);
247
248     case TS_RELATIVE:
249       return frame_data_time_delta_rel_compare(epan, fdata1, fdata2);
250
251     case TS_DELTA:
252       return frame_data_time_delta_compare(epan, fdata1, fdata2);
253
254     case TS_DELTA_DIS:
255       return frame_data_time_delta_dis_compare(epan, fdata1, fdata2);
256
257     case TS_NOT_SET:
258       return 0;
259     }
260     return 0;
261
262   case COL_ABS_TIME:
263   case COL_ABS_YMD_TIME:
264   case COL_ABS_YDOY_TIME:
265   case COL_UTC_TIME:
266   case COL_UTC_YMD_TIME:
267   case COL_UTC_YDOY_TIME:
268     return COMPARE_TS(abs_ts);
269
270   case COL_REL_TIME:
271     return frame_data_time_delta_rel_compare(epan, fdata1, fdata2);
272
273   case COL_DELTA_TIME:
274     return frame_data_time_delta_compare(epan, fdata1, fdata2);
275
276   case COL_DELTA_TIME_DIS:
277     return frame_data_time_delta_dis_compare(epan, fdata1, fdata2);
278
279   case COL_PACKET_LENGTH:
280     return COMPARE_NUM(pkt_len);
281
282   case COL_CUMULATIVE_BYTES:
283     return COMPARE_NUM(cum_bytes);
284
285   }
286   g_return_val_if_reached(0);
287 }
288
289 void
290 frame_data_init(frame_data *fdata, guint32 num,
291                 const struct wtap_pkthdr *phdr, gint64 offset,
292                 guint32 cum_bytes)
293 {
294   fdata->pfd = NULL;
295   fdata->num = num;
296   fdata->pkt_len = phdr->len;
297   fdata->cum_bytes = cum_bytes + phdr->len;
298   fdata->cap_len = phdr->caplen;
299   fdata->file_off = offset;
300   fdata->subnum = 0;
301   /* To save some memory, we coerce it into a gint16 */
302   g_assert(phdr->pkt_encap <= G_MAXINT16);
303   fdata->lnk_t = (gint16) phdr->pkt_encap;
304   fdata->flags.passed_dfilter = 0;
305   fdata->flags.dependent_of_displayed = 0;
306   fdata->flags.encoding = PACKET_CHAR_ENC_CHAR_ASCII;
307   fdata->flags.visited = 0;
308   fdata->flags.marked = 0;
309   fdata->flags.ref_time = 0;
310   fdata->flags.ignored = 0;
311   fdata->flags.has_ts = (phdr->presence_flags & WTAP_HAS_TS) ? 1 : 0;
312   fdata->flags.has_phdr_comment = (phdr->opt_comment != NULL);
313   fdata->flags.has_user_comment = 0;
314   fdata->color_filter = NULL;
315   fdata->abs_ts.secs = phdr->ts.secs;
316   fdata->abs_ts.nsecs = phdr->ts.nsecs;
317   fdata->shift_offset.secs = 0;
318   fdata->shift_offset.nsecs = 0;
319   fdata->frame_ref_num = 0;
320   fdata->prev_dis_num = 0;
321 }
322
323 void
324 frame_data_set_before_dissect(frame_data *fdata,
325                 nstime_t *elapsed_time,
326                 const frame_data **frame_ref,
327                 const frame_data *prev_dis)
328 {
329   nstime_t rel_ts;
330
331   /* Don't have the reference frame, set to current */
332   if (*frame_ref == NULL)
333     *frame_ref = fdata;
334
335   /* if this frames is marked as a reference time frame,
336      set reference frame this frame */
337   if(fdata->flags.ref_time)
338     *frame_ref = fdata;
339
340   /* Get the time elapsed between the first packet and this packet. */
341   nstime_delta(&rel_ts, &fdata->abs_ts, &(*frame_ref)->abs_ts);
342
343   /* If it's greater than the current elapsed time, set the elapsed time
344      to it (we check for "greater than" so as not to be confused by
345      time moving backwards). */
346   if ((gint32)elapsed_time->secs < rel_ts.secs
347     || ((gint32)elapsed_time->secs == rel_ts.secs && (gint32)elapsed_time->nsecs < rel_ts.nsecs)) {
348     *elapsed_time = rel_ts;
349   }
350
351   fdata->frame_ref_num = (*frame_ref != fdata) ? (*frame_ref)->num : 0;
352   fdata->prev_dis_num = (prev_dis) ? prev_dis->num : 0;
353 }
354
355 void
356 frame_data_set_after_dissect(frame_data *fdata,
357                 guint32 *cum_bytes)
358 {
359   /* This frame either passed the display filter list or is marked as
360      a time reference frame.  All time reference frames are displayed
361      even if they dont pass the display filter */
362   if(fdata->flags.ref_time){
363     /* if this was a TIME REF frame we should reset the cul bytes field */
364     *cum_bytes = fdata->pkt_len;
365     fdata->cum_bytes = *cum_bytes;
366   } else {
367     /* increase cum_bytes with this packets length */
368     *cum_bytes += fdata->pkt_len;
369     fdata->cum_bytes = *cum_bytes;
370   }
371 }
372
373 void
374 frame_data_reset(frame_data *fdata)
375 {
376   fdata->flags.visited = 0;
377
378   if (fdata->pfd) {
379     g_slist_free(fdata->pfd);
380     fdata->pfd = NULL;
381   }
382 }
383
384 void
385 frame_data_destroy(frame_data *fdata)
386 {
387   if (fdata->pfd) {
388     g_slist_free(fdata->pfd);
389     fdata->pfd = NULL;
390   }
391 }
392
393 /*
394  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
395  *
396  * Local variables:
397  * c-basic-offset: 2
398  * tab-width: 8
399  * indent-tabs-mode: nil
400  * End:
401  *
402  * vi: set shiftwidth=2 tabstop=8 expandtab:
403  * :indentSize=2:tabSize=8:noTabs=true:
404  */