2 * Routines for packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
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>
38 /* Protocol-specific data attached to a frame_data structure - protocol
39 index and opaque pointer. */
40 typedef struct _frame_proto_data {
45 /* XXX - I declared this static, because it only seems to be used by
46 * p_get_proto_data and p_add_proto_data
48 static gint p_compare(gconstpointer a, gconstpointer b)
50 const frame_proto_data *ap = (const frame_proto_data *)a;
51 const frame_proto_data *bp = (const frame_proto_data *)b;
53 if (ap -> proto > bp -> proto)
55 else if (ap -> proto == bp -> proto)
63 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
65 frame_proto_data *p1 = se_alloc(sizeof(frame_proto_data));
68 p1->proto_data = proto_data;
70 /* Add it to the GSLIST */
72 fd -> pfd = g_slist_insert_sorted(fd -> pfd,
78 p_get_proto_data(frame_data *fd, int proto)
80 frame_proto_data temp, *p1;
84 temp.proto_data = NULL;
86 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
89 p1 = (frame_proto_data *)item->data;
90 return p1->proto_data;
98 p_remove_proto_data(frame_data *fd, int proto)
100 frame_proto_data temp;
104 temp.proto_data = NULL;
106 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
109 fd->pfd = g_slist_remove(fd->pfd, item->data);
113 #define COMPARE_FRAME_NUM() ((fdata1->num < fdata2->num) ? -1 : \
114 (fdata1->num > fdata2->num) ? 1 : \
117 #define COMPARE_NUM(f) ((fdata1->f < fdata2->f) ? -1 : \
118 (fdata1->f > fdata2->f) ? 1 : \
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 : \
136 frame_data_compare(const frame_data *fdata1, const frame_data *fdata2, int field)
140 return COMPARE_FRAME_NUM();
143 switch (timestamp_get_type()) {
145 case TS_ABSOLUTE_WITH_DATE:
147 case TS_UTC_WITH_DATE:
149 return COMPARE_TS(abs_ts);
152 return COMPARE_TS(rel_ts);
155 return COMPARE_TS(del_cap_ts);
158 return COMPARE_TS(del_dis_ts);
166 case COL_ABS_DATE_TIME:
168 case COL_UTC_DATE_TIME:
169 return COMPARE_TS(abs_ts);
172 return COMPARE_TS(rel_ts);
175 return COMPARE_TS(del_cap_ts);
177 case COL_DELTA_TIME_DIS:
178 return COMPARE_TS(del_dis_ts);
180 case COL_PACKET_LENGTH:
181 return COMPARE_NUM(pkt_len);
183 case COL_CUMULATIVE_BYTES:
184 return COMPARE_NUM(cum_bytes);
187 g_return_val_if_reached(0);
191 frame_data_init(frame_data *fdata, guint32 num,
192 const struct wtap_pkthdr *phdr, gint64 offset,
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;
216 frame_data_set_before_dissect(frame_data *fdata,
217 nstime_t *elapsed_time,
219 nstime_t *prev_dis_ts,
220 nstime_t *prev_cap_ts)
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;
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;
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
237 if (nstime_is_unset(prev_cap_ts))
238 *prev_cap_ts = fdata->abs_ts;
240 /* Get the time elapsed between the first packet and this packet. */
241 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, first_ts);
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;
251 /* Get the time elapsed between the previous displayed packet and
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);
259 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, prev_dis_ts);
261 /* Get the time elapsed between the previous captured packet and
263 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, prev_cap_ts);
264 *prev_cap_ts = fdata->abs_ts;
268 frame_data_set_after_dissect(frame_data *fdata,
270 nstime_t *prev_dis_ts)
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;
280 /* increase cum_bytes with this packets length */
281 *cum_bytes += fdata->pkt_len;
282 fdata->cum_bytes = *cum_bytes;
285 /* Set the time of the previous displayed frame to the time of this
287 *prev_dis_ts = fdata->abs_ts;
291 frame_data_cleanup(frame_data *fdata)
294 g_slist_free(fdata->pfd);