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