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