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>
39 /* Protocol-specific data attached to a frame_data structure - protocol
40 index and opaque pointer. */
41 typedef struct _frame_proto_data {
46 /* XXX - I declared this static, because it only seems to be used by
47 * p_get_proto_data and p_add_proto_data
49 static gint p_compare(gconstpointer a, gconstpointer b)
51 const frame_proto_data *ap = (const frame_proto_data *)a;
52 const frame_proto_data *bp = (const frame_proto_data *)b;
54 if (ap -> proto > bp -> proto)
56 else if (ap -> proto == bp -> proto)
64 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
66 frame_proto_data *p1 = se_alloc(sizeof(frame_proto_data));
69 p1->proto_data = proto_data;
71 /* Add it to the GSLIST */
73 fd -> pfd = g_slist_insert_sorted(fd -> pfd,
79 p_get_proto_data(frame_data *fd, int proto)
81 frame_proto_data temp, *p1;
85 temp.proto_data = NULL;
87 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
90 p1 = (frame_proto_data *)item->data;
91 return p1->proto_data;
99 p_remove_proto_data(frame_data *fd, int proto)
101 frame_proto_data temp;
105 temp.proto_data = NULL;
107 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
110 fd->pfd = g_slist_remove(fd->pfd, item->data);
114 #define COMPARE_FRAME_NUM() ((fdata1->num < fdata2->num) ? -1 : \
115 (fdata1->num > fdata2->num) ? 1 : \
118 #define COMPARE_NUM(f) ((fdata1->f < fdata2->f) ? -1 : \
119 (fdata1->f > fdata2->f) ? 1 : \
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 : \
137 frame_data_compare(const frame_data *fdata1, const frame_data *fdata2, int field)
141 return COMPARE_FRAME_NUM();
144 switch (timestamp_get_type()) {
146 case TS_ABSOLUTE_WITH_DATE:
148 return COMPARE_TS(abs_ts);
151 return COMPARE_TS(rel_ts);
154 return COMPARE_TS(del_cap_ts);
157 return COMPARE_TS(del_dis_ts);
165 case COL_ABS_DATE_TIME:
166 return COMPARE_TS(abs_ts);
169 return COMPARE_TS(rel_ts);
172 return COMPARE_TS(del_cap_ts);
174 case COL_DELTA_TIME_DIS:
175 return COMPARE_TS(del_dis_ts);
177 case COL_PACKET_LENGTH:
178 return COMPARE_NUM(pkt_len);
180 case COL_CUMULATIVE_BYTES:
181 return COMPARE_NUM(cum_bytes);
184 g_return_val_if_reached(0);
188 frame_data_init(frame_data *fdata, guint32 num,
189 const struct wtap_pkthdr *phdr, gint64 offset,
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 fdata->col_text_len = NULL;
213 fdata->col_text = NULL;
217 frame_data_set_before_dissect(frame_data *fdata,
218 nstime_t *elapsed_time,
220 nstime_t *prev_dis_ts,
221 nstime_t *prev_cap_ts)
223 /* If we don't have the time stamp of the first packet in the
224 capture, it's because this is the first packet. Save the time
225 stamp of this packet as the time stamp of the first packet. */
226 if (nstime_is_unset(first_ts))
227 *first_ts = fdata->abs_ts;
229 /* if this frames is marked as a reference time frame, reset
230 firstsec and firstusec to this frame */
231 if(fdata->flags.ref_time)
232 *first_ts = fdata->abs_ts;
234 /* If we don't have the time stamp of the previous captured packet,
235 it's because this is the first packet. Save the time
236 stamp of this packet as the time stamp of the previous captured
238 if (nstime_is_unset(prev_cap_ts))
239 *prev_cap_ts = fdata->abs_ts;
241 /* Get the time elapsed between the first packet and this packet. */
242 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, first_ts);
244 /* If it's greater than the current elapsed time, set the elapsed time
245 to it (we check for "greater than" so as not to be confused by
246 time moving backwards). */
247 if ((gint32)elapsed_time->secs < fdata->rel_ts.secs
248 || ((gint32)elapsed_time->secs == fdata->rel_ts.secs && (gint32)elapsed_time->nsecs < fdata->rel_ts.nsecs)) {
249 *elapsed_time = fdata->rel_ts;
252 /* Get the time elapsed between the previous displayed packet and
254 if (nstime_is_unset(prev_dis_ts))
255 /* If we don't have the time stamp of the previous displayed packet,
256 it's because we have no displayed packets prior to this.
257 Set the delta time to zero. */
258 nstime_set_zero(&fdata->del_dis_ts);
260 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, prev_dis_ts);
262 /* Get the time elapsed between the previous captured packet and
264 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, prev_cap_ts);
265 *prev_cap_ts = fdata->abs_ts;
269 frame_data_set_after_dissect(frame_data *fdata,
271 nstime_t *prev_dis_ts)
273 /* This frame either passed the display filter list or is marked as
274 a time reference frame. All time reference frames are displayed
275 even if they dont pass the display filter */
276 if(fdata->flags.ref_time){
277 /* if this was a TIME REF frame we should reset the cul bytes field */
278 *cum_bytes = fdata->pkt_len;
279 fdata->cum_bytes = *cum_bytes;
281 /* increase cum_bytes with this packets length */
282 *cum_bytes += fdata->pkt_len;
283 fdata->cum_bytes = *cum_bytes;
286 /* Set the time of the previous displayed frame to the time of this
288 *prev_dis_ts = fdata->abs_ts;
292 frame_data_cleanup(frame_data *fdata)
295 g_slist_free(fdata->pfd);