Add lua_nstime_to_sec()
[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 <wiretap/wtap.h>
29 #include <epan/frame_data.h>
30 #include <epan/packet.h>
31 #include <epan/emem.h>
32 #include <epan/timestamp.h>
33
34 #include <glib.h>
35
36 /* Protocol-specific data attached to a frame_data structure - protocol
37    index and opaque pointer. */
38 typedef struct _frame_proto_data {
39   int proto;
40   void *proto_data;
41 } frame_proto_data;
42
43 /* XXX - I declared this static, because it only seems to be used by
44  * p_get_proto_data and p_add_proto_data
45  */
46 static gint p_compare(gconstpointer a, gconstpointer b)
47 {
48   const frame_proto_data *ap = (const frame_proto_data *)a;
49   const frame_proto_data *bp = (const frame_proto_data *)b;
50
51   if (ap -> proto > bp -> proto)
52     return 1;
53   else if (ap -> proto == bp -> proto)
54     return 0;
55   else
56     return -1;
57
58 }
59
60 void
61 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
62 {
63   frame_proto_data *p1 = se_alloc(sizeof(frame_proto_data));
64
65   p1->proto = proto;
66   p1->proto_data = proto_data;
67
68   /* Add it to the GSLIST */
69
70   fd -> pfd = g_slist_insert_sorted(fd -> pfd,
71                     (gpointer *)p1,
72                     p_compare);
73 }
74
75 void *
76 p_get_proto_data(frame_data *fd, int proto)
77 {
78   frame_proto_data temp, *p1;
79   GSList *item;
80
81   temp.proto = proto;
82   temp.proto_data = NULL;
83
84   item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
85
86   if (item) {
87     p1 = (frame_proto_data *)item->data;
88     return p1->proto_data;
89   }
90
91   return NULL;
92
93 }
94
95 void
96 p_remove_proto_data(frame_data *fd, int proto)
97 {
98   frame_proto_data temp;
99   GSList *item;
100
101   temp.proto = proto;
102   temp.proto_data = NULL;
103
104   item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
105
106   if (item) {
107     fd->pfd = g_slist_remove(fd->pfd, item->data);
108   }
109 }
110
111 #define COMPARE_FRAME_NUM()     ((fdata1->num < fdata2->num) ? -1 : \
112                                  (fdata1->num > fdata2->num) ? 1 : \
113                                  0)
114
115 #define COMPARE_NUM(f)  ((fdata1->f < fdata2->f) ? -1 : \
116                          (fdata1->f > fdata2->f) ? 1 : \
117                          COMPARE_FRAME_NUM())
118
119 /* Compare time stamps.
120    A packet whose time is a reference time is considered to have
121    a lower time stamp than any frame with a non-reference time;
122    if both packets' times are reference times, we compare the
123    times of the packets. */
124 #define COMPARE_TS(ts) \
125                 ((fdata1->flags.ref_time && !fdata2->flags.ref_time) ? -1 : \
126                  (!fdata1->flags.ref_time && fdata2->flags.ref_time) ? 1 : \
127                  (fdata1->ts.secs < fdata2->ts.secs) ? -1 : \
128                  (fdata1->ts.secs > fdata2->ts.secs) ? 1 : \
129                  (fdata1->ts.nsecs < fdata2->ts.nsecs) ? -1 :\
130                  (fdata1->ts.nsecs > fdata2->ts.nsecs) ? 1 : \
131                  COMPARE_FRAME_NUM())
132
133 gint
134 frame_data_compare(const frame_data *fdata1, const frame_data *fdata2, int field)
135 {
136     switch (field) {
137         case COL_NUMBER:
138             return COMPARE_FRAME_NUM();
139
140         case COL_CLS_TIME:
141             switch (timestamp_get_type()) {
142                 case TS_ABSOLUTE:
143                 case TS_ABSOLUTE_WITH_DATE:
144                 case TS_UTC:
145                 case TS_UTC_WITH_DATE:
146                 case TS_EPOCH:
147                     return COMPARE_TS(abs_ts);
148
149                 case TS_RELATIVE:
150                     return COMPARE_TS(rel_ts);
151
152                 case TS_DELTA:
153                     return COMPARE_TS(del_cap_ts);
154
155                 case TS_DELTA_DIS:
156                     return COMPARE_TS(del_dis_ts);
157
158                 case TS_NOT_SET:
159                     return 0;
160             }
161             return 0;
162
163         case COL_ABS_TIME:
164         case COL_ABS_DATE_TIME:
165         case COL_UTC_TIME:
166         case COL_UTC_DATE_TIME:
167             return COMPARE_TS(abs_ts);
168
169         case COL_REL_TIME:
170             return COMPARE_TS(rel_ts);
171
172         case COL_DELTA_TIME:
173             return COMPARE_TS(del_cap_ts);
174
175         case COL_DELTA_TIME_DIS:
176             return COMPARE_TS(del_dis_ts);
177
178         case COL_PACKET_LENGTH:
179             return COMPARE_NUM(pkt_len);
180
181         case COL_CUMULATIVE_BYTES:
182             return COMPARE_NUM(cum_bytes);
183
184     }
185     g_return_val_if_reached(0);
186 }
187
188 void
189 frame_data_init(frame_data *fdata, guint32 num,
190                 const struct wtap_pkthdr *phdr, gint64 offset,
191                 guint32 cum_bytes)
192 {
193   fdata->pfd = NULL;
194   fdata->num = num;
195   fdata->interface_id = phdr->interface_id;
196   fdata->pkt_len = phdr->len;
197   fdata->cum_bytes = cum_bytes + phdr->len;
198   fdata->cap_len = phdr->caplen;
199   fdata->file_off = offset;
200   fdata->subnum = 0;
201   /* To save some memory, we coerce it into a gint16 */
202   g_assert(phdr->pkt_encap <= G_MAXINT16);
203   fdata->lnk_t = (gint16) phdr->pkt_encap;
204   fdata->flags.passed_dfilter = 0;
205   fdata->flags.dependent_of_displayed = 0;
206   fdata->flags.encoding = PACKET_CHAR_ENC_CHAR_ASCII;
207   fdata->flags.visited = 0;
208   fdata->flags.marked = 0;
209   fdata->flags.ref_time = 0;
210   fdata->flags.ignored = 0;
211   fdata->flags.has_ts = (phdr->presence_flags & WTAP_HAS_TS) ? 1 : 0;
212   fdata->flags.has_if_id = (phdr->presence_flags & WTAP_HAS_INTERFACE_ID) ? 1 : 0;
213   fdata->color_filter = NULL;
214   fdata->abs_ts.secs = phdr->ts.secs;
215   fdata->abs_ts.nsecs = phdr->ts.nsecs;
216   fdata->shift_offset.secs = 0;
217   fdata->shift_offset.nsecs = 0;
218   fdata->rel_ts.secs = 0;
219   fdata->rel_ts.nsecs = 0;
220   fdata->del_dis_ts.secs = 0;
221   fdata->del_dis_ts.nsecs = 0;
222   fdata->del_cap_ts.secs = 0;
223   fdata->del_cap_ts.nsecs = 0;
224   fdata->opt_comment = phdr->opt_comment;
225 }
226
227 void
228 frame_data_set_before_dissect(frame_data *fdata,
229                 nstime_t *elapsed_time,
230                 nstime_t *first_ts,
231                 nstime_t *prev_dis_ts,
232                 nstime_t *prev_cap_ts)
233 {
234   /* If we don't have the time stamp of the first packet in the
235      capture, it's because this is the first packet.  Save the time
236      stamp of this packet as the time stamp of the first packet. */
237   if (nstime_is_unset(first_ts))
238     *first_ts = fdata->abs_ts;
239
240   /* if this frames is marked as a reference time frame, reset
241      firstsec and firstusec to this frame */
242   if(fdata->flags.ref_time)
243     *first_ts = fdata->abs_ts;
244
245   /* If we don't have the time stamp of the previous captured packet,
246      it's because this is the first packet.  Save the time
247      stamp of this packet as the time stamp of the previous captured
248      packet. */
249   if (nstime_is_unset(prev_cap_ts))
250     *prev_cap_ts = fdata->abs_ts;
251
252   /* Get the time elapsed between the first packet and this packet. */
253   nstime_delta(&fdata->rel_ts, &fdata->abs_ts, first_ts);
254
255   /* If it's greater than the current elapsed time, set the elapsed time
256      to it (we check for "greater than" so as not to be confused by
257      time moving backwards). */
258   if ((gint32)elapsed_time->secs < fdata->rel_ts.secs
259     || ((gint32)elapsed_time->secs == fdata->rel_ts.secs && (gint32)elapsed_time->nsecs < fdata->rel_ts.nsecs)) {
260     *elapsed_time = fdata->rel_ts;
261   }
262
263   /* Get the time elapsed between the previous displayed packet and
264      this packet. */
265   if (nstime_is_unset(prev_dis_ts))
266     /* If we don't have the time stamp of the previous displayed packet,
267        it's because we have no displayed packets prior to this.
268        Set the delta time to zero. */
269     nstime_set_zero(&fdata->del_dis_ts);
270   else
271     nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, prev_dis_ts);
272
273   /* Get the time elapsed between the previous captured packet and
274      this packet. */
275   nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, prev_cap_ts);
276   *prev_cap_ts = fdata->abs_ts;
277 }
278
279 void
280 frame_data_set_after_dissect(frame_data *fdata,
281                 guint32 *cum_bytes,
282                 nstime_t *prev_dis_ts)
283 {
284   /* This frame either passed the display filter list or is marked as
285      a time reference frame.  All time reference frames are displayed
286      even if they dont pass the display filter */
287   if(fdata->flags.ref_time){
288     /* if this was a TIME REF frame we should reset the cul bytes field */
289     *cum_bytes = fdata->pkt_len;
290     fdata->cum_bytes = *cum_bytes;
291   } else {
292     /* increase cum_bytes with this packets length */
293     *cum_bytes += fdata->pkt_len;
294     fdata->cum_bytes = *cum_bytes;
295   }
296
297   /* Set the time of the previous displayed frame to the time of this
298      frame. */
299   *prev_dis_ts = fdata->abs_ts;
300 }
301
302 void
303 frame_data_cleanup(frame_data *fdata)
304 {
305   if (fdata->pfd) {
306     g_slist_free(fdata->pfd);
307     fdata->pfd = NULL;
308   }
309
310   /* XXX, frame_data_cleanup() is called when redissecting (rescan_packets()),
311    *      which might be triggered by lot of things, like: preferences change, setting manual address resolve, etc.. (grep by redissect_packets)
312    *      fdata->opt_comment can be set by user, which we must not discard when redissecting.
313    */
314 #if 0
315   if (fdata->opt_comment) {
316     g_free(fdata->opt_comment);
317     fdata->opt_comment = NULL;
318   }
319 #endif
320 }