2 * Routines for packet disassembly
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/epan.h>
17 #include <epan/frame_data.h>
18 #include <epan/column-utils.h>
19 #include <epan/timestamp.h>
20 #include <wiretap/wtap.h>
21 #include <wsutil/ws_assert.h>
23 #define COMPARE_FRAME_NUM() ((fdata1->num < fdata2->num) ? -1 : \
24 (fdata1->num > fdata2->num) ? 1 : \
27 #define COMPARE_NUM(f) ((fdata1->f < fdata2->f) ? -1 : \
28 (fdata1->f > fdata2->f) ? 1 : \
31 /* Compare time stamps.
32 A packet whose time is a reference time is considered to have
33 a lower time stamp than any frame with a non-reference time;
34 if both packets' times are reference times, we compare the
35 times of the packets. */
36 #define COMPARE_TS_REAL(time1, time2) \
37 ((fdata1->ref_time && !fdata2->ref_time) ? -1 : \
38 (!fdata1->ref_time && fdata2->ref_time) ? 1 : \
39 ((time1).secs < (time2).secs) ? -1 : \
40 ((time1).secs > (time2).secs) ? 1 : \
41 ((time1).nsecs < (time2).nsecs) ? -1 :\
42 ((time1).nsecs > (time2).nsecs) ? 1 : \
45 #define COMPARE_TS(ts) COMPARE_TS_REAL(fdata1->ts, fdata2->ts)
48 frame_delta_abs_time(const struct epan_session
*epan
, const frame_data
*fdata
, uint32_t prev_num
, nstime_t
*delta
)
50 const nstime_t
*prev_abs_ts
= (prev_num
) ? epan_get_frame_ts(epan
, prev_num
) : NULL
;
53 nstime_delta(delta
, &fdata
->abs_ts
, prev_abs_ts
);
55 /* If we don't have the time stamp of the previous packet,
56 it's because we have no displayed/captured packets prior to this.
57 Set the delta time to zero. */
58 nstime_set_zero(delta
);
63 frame_data_time_delta_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
)
65 nstime_t del_cap_ts1
, del_cap_ts2
;
67 frame_delta_abs_time(epan
, fdata1
, fdata1
->num
- 1, &del_cap_ts1
);
68 frame_delta_abs_time(epan
, fdata2
, fdata2
->num
- 1, &del_cap_ts2
);
70 return COMPARE_TS_REAL(del_cap_ts1
, del_cap_ts2
);
74 frame_data_time_delta_rel_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
)
76 nstime_t del_rel_ts1
, del_rel_ts2
;
78 frame_delta_abs_time(epan
, fdata1
, fdata1
->frame_ref_num
, &del_rel_ts1
);
79 frame_delta_abs_time(epan
, fdata2
, fdata2
->frame_ref_num
, &del_rel_ts2
);
81 return COMPARE_TS_REAL(del_rel_ts1
, del_rel_ts2
);
85 frame_data_time_delta_dis_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
)
87 nstime_t del_dis_ts1
, del_dis_ts2
;
89 frame_delta_abs_time(epan
, fdata1
, fdata1
->prev_dis_num
, &del_dis_ts1
);
90 frame_delta_abs_time(epan
, fdata2
, fdata2
->prev_dis_num
, &del_dis_ts2
);
92 return COMPARE_TS_REAL(del_dis_ts1
, del_dis_ts2
);
96 frame_data_compare(const struct epan_session
*epan
, const frame_data
*fdata1
, const frame_data
*fdata2
, int field
)
100 return COMPARE_FRAME_NUM();
103 return COMPARE_NUM(dis_num
);
106 switch (timestamp_get_type()) {
108 case TS_ABSOLUTE_WITH_YMD
:
109 case TS_ABSOLUTE_WITH_YDOY
:
111 case TS_UTC_WITH_YMD
:
112 case TS_UTC_WITH_YDOY
:
114 return COMPARE_TS(abs_ts
);
117 return frame_data_time_delta_rel_compare(epan
, fdata1
, fdata2
);
120 return frame_data_time_delta_compare(epan
, fdata1
, fdata2
);
123 return frame_data_time_delta_dis_compare(epan
, fdata1
, fdata2
);
131 case COL_ABS_YMD_TIME
:
132 case COL_ABS_YDOY_TIME
:
134 case COL_UTC_YMD_TIME
:
135 case COL_UTC_YDOY_TIME
:
136 return COMPARE_TS(abs_ts
);
139 return frame_data_time_delta_rel_compare(epan
, fdata1
, fdata2
);
142 return frame_data_time_delta_compare(epan
, fdata1
, fdata2
);
144 case COL_DELTA_TIME_DIS
:
145 return frame_data_time_delta_dis_compare(epan
, fdata1
, fdata2
);
147 case COL_PACKET_LENGTH
:
148 return COMPARE_NUM(pkt_len
);
150 case COL_CUMULATIVE_BYTES
:
151 return COMPARE_NUM(cum_bytes
);
154 g_return_val_if_reached(0);
158 frame_data_init(frame_data
*fdata
, uint32_t num
, const wtap_rec
*rec
,
159 int64_t offset
, uint32_t cum_bytes
)
163 fdata
->dis_num
= num
;
164 fdata
->file_off
= offset
;
165 fdata
->passed_dfilter
= 1;
166 fdata
->dependent_of_displayed
= 0;
167 fdata
->dependent_frames
= NULL
;
168 fdata
->encoding
= PACKET_CHAR_ENC_CHAR_ASCII
;
173 fdata
->has_ts
= (rec
->presence_flags
& WTAP_HAS_TS
) ? 1 : 0;
174 fdata
->tcp_snd_manual_analysis
= 0;
175 switch (rec
->rec_type
) {
177 case REC_TYPE_PACKET
:
178 fdata
->pkt_len
= rec
->rec_header
.packet_header
.len
;
179 fdata
->cum_bytes
= cum_bytes
+ rec
->rec_header
.packet_header
.len
;
180 fdata
->cap_len
= rec
->rec_header
.packet_header
.caplen
;
183 case REC_TYPE_FT_SPECIFIC_EVENT
:
184 case REC_TYPE_FT_SPECIFIC_REPORT
:
188 fdata
->pkt_len
= rec
->rec_header
.ft_specific_header
.record_len
;
189 fdata
->cum_bytes
= cum_bytes
+ rec
->rec_header
.ft_specific_header
.record_len
;
190 fdata
->cap_len
= rec
->rec_header
.ft_specific_header
.record_len
;
193 case REC_TYPE_SYSCALL
:
195 * XXX - is cum_bytes supposed to count non-packet bytes?
197 fdata
->pkt_len
= rec
->rec_header
.syscall_header
.event_len
;
198 fdata
->cum_bytes
= cum_bytes
+ rec
->rec_header
.syscall_header
.event_len
;
199 fdata
->cap_len
= rec
->rec_header
.syscall_header
.event_filelen
;
202 case REC_TYPE_SYSTEMD_JOURNAL_EXPORT
:
204 * XXX - is cum_bytes supposed to count non-packet bytes?
206 fdata
->pkt_len
= rec
->rec_header
.systemd_journal_export_header
.record_len
;
207 fdata
->cum_bytes
= cum_bytes
+ rec
->rec_header
.systemd_journal_export_header
.record_len
;
208 fdata
->cap_len
= rec
->rec_header
.systemd_journal_export_header
.record_len
;
211 case REC_TYPE_CUSTOM_BLOCK
:
213 * XXX - is cum_bytes supposed to count non-packet bytes?
215 switch (rec
->rec_header
.custom_block_header
.pen
) {
217 fdata
->pkt_len
= rec
->rec_header
.custom_block_header
.length
- 4;
218 fdata
->cum_bytes
= cum_bytes
+ rec
->rec_header
.custom_block_header
.length
- 4;
219 fdata
->cap_len
= rec
->rec_header
.custom_block_header
.length
- 4;
222 fdata
->pkt_len
= rec
->rec_header
.custom_block_header
.length
;
223 fdata
->cum_bytes
= cum_bytes
+ rec
->rec_header
.custom_block_header
.length
;
224 fdata
->cap_len
= rec
->rec_header
.custom_block_header
.length
;
231 /* To save some memory, we coerce it into 4 bits */
232 ws_assert(rec
->tsprec
<= 0xF);
233 fdata
->tsprec
= (unsigned int)rec
->tsprec
;
234 fdata
->abs_ts
= rec
->ts
;
235 fdata
->has_modified_block
= 0;
236 fdata
->need_colorize
= 0;
237 fdata
->color_filter
= NULL
;
238 fdata
->shift_offset
.secs
= 0;
239 fdata
->shift_offset
.nsecs
= 0;
240 fdata
->frame_ref_num
= 0;
241 fdata
->prev_dis_num
= 0;
245 frame_data_set_before_dissect(frame_data
*fdata
,
246 nstime_t
*elapsed_time
,
247 const frame_data
**frame_ref
,
248 const frame_data
*prev_dis
)
252 /* If this frame doesn't have a time stamp, don't set it as the
253 * reference frame used for calculating time deltas, set elapsed
254 * time, etc. We also won't need to calculate the delta of this
255 * frame's timestamp to any other frame.
257 if (!fdata
->has_ts
) {
258 /* If it was marked as a reference time frame anyway (should we
259 * allow that?), clear the existing reference frame so that the
260 * next frame with a time stamp will become the reference frame.
262 if(fdata
->ref_time
) {
268 /* Don't have the reference frame, set to current */
269 if (*frame_ref
== NULL
)
272 /* if this frames is marked as a reference time frame,
273 set reference frame this frame */
277 /* Get the time elapsed between the first packet and this packet. */
278 nstime_delta(&rel_ts
, &fdata
->abs_ts
, &(*frame_ref
)->abs_ts
);
280 /* If it's greater than the current elapsed time, set the elapsed time
281 to it (we check for "greater than" so as not to be confused by
282 time moving backwards). */
283 if (nstime_cmp(elapsed_time
, &rel_ts
) < 0) {
284 *elapsed_time
= rel_ts
;
287 fdata
->frame_ref_num
= (*frame_ref
!= fdata
) ? (*frame_ref
)->num
: 0;
288 fdata
->prev_dis_num
= (prev_dis
) ? prev_dis
->num
: 0;
292 frame_data_set_after_dissect(frame_data
*fdata
,
295 /* This frame either passed the display filter list or is marked as
296 a time reference frame. All time reference frames are displayed
297 even if they don't pass the display filter */
299 /* if this was a TIME REF frame we should reset the cul bytes field */
300 *cum_bytes
= fdata
->pkt_len
;
301 fdata
->cum_bytes
= *cum_bytes
;
303 /* increase cum_bytes with this packets length */
304 *cum_bytes
+= fdata
->pkt_len
;
305 fdata
->cum_bytes
= *cum_bytes
;
310 frame_data_reset(frame_data
*fdata
)
315 g_slist_free(fdata
->pfd
);
319 if (fdata
->dependent_frames
) {
320 g_hash_table_destroy(fdata
->dependent_frames
);
321 fdata
->dependent_frames
= NULL
;
326 frame_data_destroy(frame_data
*fdata
)
329 g_slist_free(fdata
->pfd
);
333 if (fdata
->dependent_frames
) {
334 g_hash_table_destroy(fdata
->dependent_frames
);
335 fdata
->dependent_frames
= NULL
;
340 * Editor modelines - https://www.wireshark.org/tools/modelines.html
345 * indent-tabs-mode: nil
348 * vi: set shiftwidth=2 tabstop=8 expandtab:
349 * :indentSize=2:tabSize=8:noTabs=true: