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.
30 #include <wiretap/wtap.h>
31 #include <epan/frame_data.h>
32 #include <epan/packet.h>
33 #include <epan/emem.h>
34 #include <epan/wmem/wmem.h>
35 #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
{
46 /* XXX - I declared this static, because it only seems to be used by
47 * p_get_proto_data and p_add_proto_data
50 p_compare(gconstpointer a
, gconstpointer b
)
52 const frame_proto_data
*ap
= (const frame_proto_data
*)a
;
53 const frame_proto_data
*bp
= (const frame_proto_data
*)b
;
55 if (ap
-> proto
> bp
-> proto
){
57 }else if (ap
-> proto
== bp
-> proto
){
58 if (ap
-> key
> bp
-> key
){
60 }else if (ap
-> key
== bp
-> key
){
70 p_add_proto_data(frame_data
*fd
, int proto
, guint8 key
, void *proto_data
)
72 frame_proto_data
*p1
= (frame_proto_data
*)wmem_alloc(wmem_file_scope(), sizeof(frame_proto_data
));
76 p1
->proto_data
= proto_data
;
78 /* Add it to the GSLIST */
80 fd
-> pfd
= g_slist_insert_sorted(fd
-> pfd
,
86 p_get_proto_data(frame_data
*fd
, int proto
, guint8 key
)
88 frame_proto_data temp
, *p1
;
93 temp
.proto_data
= NULL
;
95 item
= g_slist_find_custom(fd
->pfd
, (gpointer
*)&temp
, p_compare
);
98 p1
= (frame_proto_data
*)item
->data
;
99 return p1
->proto_data
;
107 p_remove_proto_data(frame_data
*fd
, int proto
, guint8 key
)
109 frame_proto_data temp
;
114 temp
.proto_data
= NULL
;
116 item
= g_slist_find_custom(fd
->pfd
, (gpointer
*)&temp
, p_compare
);
119 fd
->pfd
= g_slist_remove(fd
->pfd
, item
->data
);
124 p_get_proto_name_and_key(frame_data
*fd
, guint pfd_index
){
125 frame_proto_data
*temp
;
127 temp
= (frame_proto_data
*)g_slist_nth_data(fd
->pfd
, pfd_index
);
129 return ep_strdup_printf("[%s, key %u]",proto_get_protocol_name(temp
->proto
), temp
->key
);
133 #define COMPARE_FRAME_NUM() ((fdata1->num < fdata2->num) ? -1 : \
134 (fdata1->num > fdata2->num) ? 1 : \
137 #define COMPARE_NUM(f) ((fdata1->f < fdata2->f) ? -1 : \
138 (fdata1->f > fdata2->f) ? 1 : \
141 /* Compare time stamps.
142 A packet whose time is a reference time is considered to have
143 a lower time stamp than any frame with a non-reference time;
144 if both packets' times are reference times, we compare the
145 times of the packets. */
146 #define COMPARE_TS_REAL(time1, time2) \
147 ((fdata1->flags.ref_time && !fdata2->flags.ref_time) ? -1 : \
148 (!fdata1->flags.ref_time && fdata2->flags.ref_time) ? 1 : \
149 ((time1).secs < (time2).secs) ? -1 : \
150 ((time1).secs > (time2).secs) ? 1 : \
151 ((time1).nsecs < (time2).nsecs) ? -1 :\
152 ((time1).nsecs > (time2).nsecs) ? 1 : \
155 #define COMPARE_TS(ts) COMPARE_TS_REAL(fdata1->ts, fdata2->ts)
158 frame_delta_abs_time(const struct epan_session
*epan
, const frame_data
*fdata
, guint32 prev_num
, nstime_t
*delta
)
160 const nstime_t
*prev_abs_ts
= (prev_num
) ? epan_get_frame_ts(epan
, prev_num
) : NULL
;
163 nstime_delta(delta
, &fdata
->abs_ts
, prev_abs_ts
);
165 /* If we don't have the time stamp of the previous packet,
166 it's because we have no displayed/captured packets prior to this.
167 Set the delta time to zero. */
168 nstime_set_zero(delta
);
173 frame_data_time_delta_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
)
175 nstime_t del_cap_ts1
, del_cap_ts2
;
177 frame_delta_abs_time(epan
, fdata1
, fdata1
->num
- 1, &del_cap_ts1
);
178 frame_delta_abs_time(epan
, fdata2
, fdata2
->num
- 1, &del_cap_ts2
);
180 return COMPARE_TS_REAL(del_cap_ts1
, del_cap_ts2
);
184 frame_data_time_delta_rel_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
)
186 nstime_t del_rel_ts1
, del_rel_ts2
;
188 frame_delta_abs_time(epan
, fdata1
, fdata1
->frame_ref_num
, &del_rel_ts1
);
189 frame_delta_abs_time(epan
, fdata2
, fdata2
->frame_ref_num
, &del_rel_ts2
);
191 return COMPARE_TS_REAL(del_rel_ts1
, del_rel_ts2
);
195 frame_data_time_delta_dis_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
)
197 nstime_t del_dis_ts1
, del_dis_ts2
;
199 frame_delta_abs_time(epan
, fdata1
, fdata1
->prev_dis_num
, &del_dis_ts1
);
200 frame_delta_abs_time(epan
, fdata2
, fdata2
->prev_dis_num
, &del_dis_ts2
);
202 return COMPARE_TS_REAL(del_dis_ts1
, del_dis_ts2
);
206 frame_data_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
, int field
)
210 return COMPARE_FRAME_NUM();
213 switch (timestamp_get_type()) {
215 case TS_ABSOLUTE_WITH_YMD
:
216 case TS_ABSOLUTE_WITH_YDOY
:
218 case TS_UTC_WITH_YMD
:
219 case TS_UTC_WITH_YDOY
:
221 return COMPARE_TS(abs_ts
);
224 return frame_data_time_delta_rel_compare(epan
, fdata1
, fdata2
);
227 return frame_data_time_delta_compare(epan
, fdata1
, fdata2
);
230 return frame_data_time_delta_dis_compare(epan
, fdata1
, fdata2
);
238 case COL_ABS_YMD_TIME
:
239 case COL_ABS_YDOY_TIME
:
241 case COL_UTC_YMD_TIME
:
242 case COL_UTC_YDOY_TIME
:
243 return COMPARE_TS(abs_ts
);
246 return frame_data_time_delta_rel_compare(epan
, fdata1
, fdata2
);
249 return frame_data_time_delta_compare(epan
, fdata1
, fdata2
);
251 case COL_DELTA_TIME_DIS
:
252 return frame_data_time_delta_dis_compare(epan
, fdata1
, fdata2
);
254 case COL_PACKET_LENGTH
:
255 return COMPARE_NUM(pkt_len
);
257 case COL_CUMULATIVE_BYTES
:
258 return COMPARE_NUM(cum_bytes
);
261 g_return_val_if_reached(0);
265 frame_data_init(frame_data
*fdata
, guint32 num
,
266 const struct wtap_pkthdr
*phdr
, gint64 offset
,
271 fdata
->pkt_len
= phdr
->len
;
272 fdata
->cum_bytes
= cum_bytes
+ phdr
->len
;
273 fdata
->cap_len
= phdr
->caplen
;
274 fdata
->file_off
= offset
;
276 /* To save some memory, we coerce it into a gint16 */
277 g_assert(phdr
->pkt_encap
<= G_MAXINT16
);
278 fdata
->lnk_t
= (gint16
) phdr
->pkt_encap
;
279 fdata
->flags
.passed_dfilter
= 0;
280 fdata
->flags
.dependent_of_displayed
= 0;
281 fdata
->flags
.encoding
= PACKET_CHAR_ENC_CHAR_ASCII
;
282 fdata
->flags
.visited
= 0;
283 fdata
->flags
.marked
= 0;
284 fdata
->flags
.ref_time
= 0;
285 fdata
->flags
.ignored
= 0;
286 fdata
->flags
.has_ts
= (phdr
->presence_flags
& WTAP_HAS_TS
) ? 1 : 0;
287 fdata
->flags
.has_phdr_comment
= (phdr
->opt_comment
!= NULL
);
288 fdata
->flags
.has_user_comment
= 0;
289 fdata
->color_filter
= NULL
;
290 fdata
->abs_ts
.secs
= phdr
->ts
.secs
;
291 fdata
->abs_ts
.nsecs
= phdr
->ts
.nsecs
;
292 fdata
->shift_offset
.secs
= 0;
293 fdata
->shift_offset
.nsecs
= 0;
294 fdata
->frame_ref_num
= 0;
295 fdata
->prev_dis_num
= 0;
299 frame_data_set_before_dissect(frame_data
*fdata
,
300 nstime_t
*elapsed_time
,
301 const frame_data
**frame_ref
,
302 const frame_data
*prev_dis
)
306 /* Don't have the reference frame, set to current */
307 if (*frame_ref
== NULL
)
310 /* if this frames is marked as a reference time frame,
311 set reference frame this frame */
312 if(fdata
->flags
.ref_time
)
315 /* Get the time elapsed between the first packet and this packet. */
316 nstime_delta(&rel_ts
, &fdata
->abs_ts
, &(*frame_ref
)->abs_ts
);
318 /* If it's greater than the current elapsed time, set the elapsed time
319 to it (we check for "greater than" so as not to be confused by
320 time moving backwards). */
321 if ((gint32
)elapsed_time
->secs
< rel_ts
.secs
322 || ((gint32
)elapsed_time
->secs
== rel_ts
.secs
&& (gint32
)elapsed_time
->nsecs
< rel_ts
.nsecs
)) {
323 *elapsed_time
= rel_ts
;
326 fdata
->frame_ref_num
= (*frame_ref
!= fdata
) ? (*frame_ref
)->num
: 0;
327 fdata
->prev_dis_num
= (prev_dis
) ? prev_dis
->num
: 0;
331 frame_data_set_after_dissect(frame_data
*fdata
,
334 /* This frame either passed the display filter list or is marked as
335 a time reference frame. All time reference frames are displayed
336 even if they dont pass the display filter */
337 if(fdata
->flags
.ref_time
){
338 /* if this was a TIME REF frame we should reset the cul bytes field */
339 *cum_bytes
= fdata
->pkt_len
;
340 fdata
->cum_bytes
= *cum_bytes
;
342 /* increase cum_bytes with this packets length */
343 *cum_bytes
+= fdata
->pkt_len
;
344 fdata
->cum_bytes
= *cum_bytes
;
349 frame_data_reset(frame_data
*fdata
)
351 fdata
->flags
.visited
= 0;
354 g_slist_free(fdata
->pfd
);
360 frame_data_destroy(frame_data
*fdata
)
363 g_slist_free(fdata
->pfd
);
369 * Editor modelines - http://www.wireshark.org/tools/modelines.html
374 * indent-tabs-mode: nil
377 * vi: set shiftwidth=2 tabstop=8 expandtab:
378 * :indentSize=2:tabSize=8:noTabs=true: