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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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>
36 /* Protocol-specific data attached to a frame_data structure - protocol
37 index and opaque pointer. */
38 typedef struct _frame_proto_data {
43 /* XXX - I declared this static, because it only seems to be used by
44 * p_get_proto_data and p_add_proto_data
46 static gint p_compare(gconstpointer a, gconstpointer b)
48 const frame_proto_data *ap = (const frame_proto_data *)a;
49 const frame_proto_data *bp = (const frame_proto_data *)b;
51 if (ap -> proto > bp -> proto)
53 else if (ap -> proto == bp -> proto)
61 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
63 frame_proto_data *p1 = se_alloc(sizeof(frame_proto_data));
66 p1->proto_data = proto_data;
68 /* Add it to the GSLIST */
70 fd -> pfd = g_slist_insert_sorted(fd -> pfd,
76 p_get_proto_data(frame_data *fd, int proto)
78 frame_proto_data temp, *p1;
82 temp.proto_data = NULL;
84 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
87 p1 = (frame_proto_data *)item->data;
88 return p1->proto_data;
96 p_remove_proto_data(frame_data *fd, int proto)
98 frame_proto_data temp;
102 temp.proto_data = NULL;
104 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
107 fd->pfd = g_slist_remove(fd->pfd, item->data);
111 #define COMPARE_FRAME_NUM() ((fdata1->num < fdata2->num) ? -1 : \
112 (fdata1->num > fdata2->num) ? 1 : \
115 #define COMPARE_NUM(f) ((fdata1->f < fdata2->f) ? -1 : \
116 (fdata1->f > fdata2->f) ? 1 : \
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 : \
134 frame_data_compare(const frame_data *fdata1, const frame_data *fdata2, int field)
138 return COMPARE_FRAME_NUM();
141 switch (timestamp_get_type()) {
143 case TS_ABSOLUTE_WITH_DATE:
145 case TS_UTC_WITH_DATE:
147 return COMPARE_TS(abs_ts);
150 return COMPARE_TS(rel_ts);
153 return COMPARE_TS(del_cap_ts);
156 return COMPARE_TS(del_dis_ts);
164 case COL_ABS_DATE_TIME:
166 case COL_UTC_DATE_TIME:
167 return COMPARE_TS(abs_ts);
170 return COMPARE_TS(rel_ts);
173 return COMPARE_TS(del_cap_ts);
175 case COL_DELTA_TIME_DIS:
176 return COMPARE_TS(del_dis_ts);
178 case COL_PACKET_LENGTH:
179 return COMPARE_NUM(pkt_len);
181 case COL_CUMULATIVE_BYTES:
182 return COMPARE_NUM(cum_bytes);
185 g_return_val_if_reached(0);
189 frame_data_init(frame_data *fdata, guint32 num,
190 const struct wtap_pkthdr *phdr, gint64 offset,
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;
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;
228 frame_data_set_before_dissect(frame_data *fdata,
229 nstime_t *elapsed_time,
231 nstime_t *prev_dis_ts,
232 nstime_t *prev_cap_ts)
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;
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;
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
249 if (nstime_is_unset(prev_cap_ts))
250 *prev_cap_ts = fdata->abs_ts;
252 /* Get the time elapsed between the first packet and this packet. */
253 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, first_ts);
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;
263 /* Get the time elapsed between the previous displayed packet and
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);
271 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, prev_dis_ts);
273 /* Get the time elapsed between the previous captured packet and
275 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, prev_cap_ts);
276 *prev_cap_ts = fdata->abs_ts;
280 frame_data_set_after_dissect(frame_data *fdata,
282 nstime_t *prev_dis_ts)
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;
292 /* increase cum_bytes with this packets length */
293 *cum_bytes += fdata->pkt_len;
294 fdata->cum_bytes = *cum_bytes;
297 /* Set the time of the previous displayed frame to the time of this
299 *prev_dis_ts = fdata->abs_ts;
303 frame_data_cleanup(frame_data *fdata)
306 g_slist_free(fdata->pfd);
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.
315 if (fdata->opt_comment) {
316 g_free(fdata->opt_comment);
317 fdata->opt_comment = NULL;