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)
65 p_add_proto_data(frame_data *fd, int proto, void *proto_data)
67 frame_proto_data *p1 = se_alloc(sizeof(frame_proto_data));
72 p1 -> proto_data = proto_data;
74 /* Add it to the GSLIST */
76 fd -> pfd = g_slist_insert_sorted(fd -> pfd,
83 p_get_proto_data(frame_data *fd, int proto)
85 frame_proto_data temp, *p1;
89 temp.proto_data = NULL;
91 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
94 p1 = (frame_proto_data *)item->data;
95 return p1->proto_data;
103 p_remove_proto_data(frame_data *fd, int proto)
105 frame_proto_data temp;
109 temp.proto_data = NULL;
111 item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, p_compare);
114 fd->pfd = g_slist_remove(fd->pfd, item->data);
118 #define COMPARE_FRAME_NUM() ((fdata1->num < fdata2->num) ? -1 : \
119 (fdata1->num > fdata2->num) ? 1 : \
122 #define COMPARE_NUM(f) ((fdata1->f < fdata2->f) ? -1 : \
123 (fdata1->f > fdata2->f) ? 1 : \
126 /* Compare time stamps.
127 A packet whose time is a reference time is considered to have
128 a lower time stamp than any frame with a non-reference time;
129 if both packets' times are reference times, we compare the
130 times of the packets. */
131 #define COMPARE_TS(ts) \
132 ((fdata1->flags.ref_time && !fdata2->flags.ref_time) ? -1 : \
133 (!fdata1->flags.ref_time && fdata2->flags.ref_time) ? 1 : \
134 (fdata1->ts.secs < fdata2->ts.secs) ? -1 : \
135 (fdata1->ts.secs > fdata2->ts.secs) ? 1 : \
136 (fdata1->ts.nsecs < fdata2->ts.nsecs) ? -1 :\
137 (fdata1->ts.nsecs > fdata2->ts.nsecs) ? 1 : \
141 frame_data_compare(const frame_data *fdata1, const frame_data *fdata2, int field)
145 return COMPARE_FRAME_NUM();
148 switch (timestamp_get_type()) {
150 case TS_ABSOLUTE_WITH_DATE:
152 return COMPARE_TS(abs_ts);
155 return COMPARE_TS(rel_ts);
158 return COMPARE_TS(del_cap_ts);
161 return COMPARE_TS(del_dis_ts);
169 case COL_ABS_DATE_TIME:
170 return COMPARE_TS(abs_ts);
173 return COMPARE_TS(rel_ts);
176 return COMPARE_TS(del_cap_ts);
178 case COL_DELTA_TIME_DIS:
179 return COMPARE_TS(del_dis_ts);
181 case COL_PACKET_LENGTH:
182 return COMPARE_NUM(pkt_len);
184 case COL_CUMULATIVE_BYTES:
185 return COMPARE_NUM(cum_bytes);
188 g_return_val_if_reached(0);
192 frame_data_init(frame_data *fdata, guint32 num,
193 nstime_t *elapsed_time,
194 const struct wtap_pkthdr *phdr, gint64 offset,
197 nstime_t *prev_dis_ts,
198 nstime_t *prev_cap_ts)
204 fdata->pkt_len = phdr->len;
205 *cum_bytes += phdr->len;
206 fdata->cum_bytes = *cum_bytes;
207 fdata->cap_len = phdr->caplen;
208 fdata->file_off = offset;
209 /* To save some memory, we coarcese it into a gint8 */
210 g_assert(phdr->pkt_encap <= G_MAXINT8);
211 fdata->lnk_t = (gint8) phdr->pkt_encap;
212 fdata->abs_ts.secs = phdr->ts.secs;
213 fdata->abs_ts.nsecs = phdr->ts.nsecs;
214 fdata->flags.passed_dfilter = 0;
215 fdata->flags.encoding = CHAR_ASCII;
216 fdata->flags.visited = 0;
217 fdata->flags.marked = 0;
218 fdata->flags.ref_time = 0;
219 fdata->color_filter = NULL;
221 /* If we don't have the time stamp of the first packet in the
222 capture, it's because this is the first packet. Save the time
223 stamp of this packet as the time stamp of the first packet. */
224 if (nstime_is_unset(first_ts)) {
225 *first_ts = fdata->abs_ts;
228 /* If we don't have the time stamp of the previous captured packet,
229 it's because this is the first packet. Save the time
230 stamp of this packet as the time stamp of the previous captured
232 if (nstime_is_unset(prev_cap_ts)) {
233 *prev_cap_ts = fdata->abs_ts;
236 /* Get the time elapsed between the first packet and this packet. */
237 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, first_ts);
239 /* If it's greater than the current elapsed time, set the elapsed time
240 to it (we check for "greater than" so as not to be confused by
241 time moving backwards). */
242 if ((gint32)elapsed_time->secs < fdata->rel_ts.secs
243 || ((gint32)elapsed_time->secs == fdata->rel_ts.secs && (gint32)elapsed_time->nsecs < fdata->rel_ts.nsecs)) {
244 *elapsed_time = fdata->rel_ts;
247 /* If we don't have the time stamp of the previous displayed packet,
248 it's because this is the first packet that's being displayed. Save the time
249 stamp of this packet as the time stamp of the previous displayed
251 if (nstime_is_unset(prev_dis_ts))
252 *prev_dis_ts = fdata->abs_ts;
254 /* Get the time elapsed between the previous displayed packet and
256 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, prev_dis_ts);
258 /* Get the time elapsed between the previous captured packet and
260 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, prev_cap_ts);
261 *prev_cap_ts = fdata->abs_ts;
265 frame_data_cleanup(frame_data *fdata)
268 g_slist_free(fdata->pfd);