]>
The Tcpdump Group git mirrors - libpcap/blob - pcap-util.c
2 * Copyright (c) 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 * pcap-util.c - common code for various files
28 #include <pcap-types.h>
32 #include "pcap-usb-linux-common.h"
34 #include "pcap-util.h"
37 #include "pcap/can_socketcan.h"
40 #include "pcap/nflog.h"
43 * Most versions of the DLT_PFLOG pseudo-header have UID and PID fields
44 * that are saved in host byte order.
46 * When reading a DLT_PFLOG packet, we need to convert those fields from
47 * the byte order of the host that wrote the file to this host's byte
51 swap_pflog_header(const struct pcap_pkthdr
*hdr
, u_char
*buf
)
53 u_int caplen
= hdr
->caplen
;
54 u_int length
= hdr
->len
;
55 u_int pfloghdr_length
;
56 struct pfloghdr
*pflhdr
= (struct pfloghdr
*)buf
;
58 if (caplen
< (u_int
) (offsetof(struct pfloghdr
, uid
) + sizeof pflhdr
->uid
) ||
59 length
< (u_int
) (offsetof(struct pfloghdr
, uid
) + sizeof pflhdr
->uid
)) {
60 /* Not enough data to have the uid field */
64 pfloghdr_length
= pflhdr
->length
;
66 if (pfloghdr_length
< (u_int
) (offsetof(struct pfloghdr
, uid
) + sizeof pflhdr
->uid
)) {
67 /* Header doesn't include uid field */
70 pflhdr
->uid
= SWAPLONG(pflhdr
->uid
);
72 if (caplen
< (u_int
) (offsetof(struct pfloghdr
, pid
) + sizeof pflhdr
->pid
) ||
73 length
< (u_int
) (offsetof(struct pfloghdr
, pid
) + sizeof pflhdr
->pid
)) {
74 /* Not enough data to have the pid field */
77 if (pfloghdr_length
< (u_int
) (offsetof(struct pfloghdr
, pid
) + sizeof pflhdr
->pid
)) {
78 /* Header doesn't include pid field */
81 pflhdr
->pid
= SWAPLONG(pflhdr
->pid
);
83 if (caplen
< (u_int
) (offsetof(struct pfloghdr
, rule_uid
) + sizeof pflhdr
->rule_uid
) ||
84 length
< (u_int
) (offsetof(struct pfloghdr
, rule_uid
) + sizeof pflhdr
->rule_uid
)) {
85 /* Not enough data to have the rule_uid field */
88 if (pfloghdr_length
< (u_int
) (offsetof(struct pfloghdr
, rule_uid
) + sizeof pflhdr
->rule_uid
)) {
89 /* Header doesn't include rule_uid field */
92 pflhdr
->rule_uid
= SWAPLONG(pflhdr
->rule_uid
);
94 if (caplen
< (u_int
) (offsetof(struct pfloghdr
, rule_pid
) + sizeof pflhdr
->rule_pid
) ||
95 length
< (u_int
) (offsetof(struct pfloghdr
, rule_pid
) + sizeof pflhdr
->rule_pid
)) {
96 /* Not enough data to have the rule_pid field */
99 if (pfloghdr_length
< (u_int
) (offsetof(struct pfloghdr
, rule_pid
) + sizeof pflhdr
->rule_pid
)) {
100 /* Header doesn't include rule_pid field */
103 pflhdr
->rule_pid
= SWAPLONG(pflhdr
->rule_pid
);
107 * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
108 * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
109 * with the CAN ID being in host byte order.
111 * When reading a DLT_LINUX_SLL packet, we need to check for those
112 * packets and convert the CAN ID from the byte order of the host that
113 * wrote the file to this host's byte order.
116 swap_linux_sll_header(const struct pcap_pkthdr
*hdr
, u_char
*buf
)
118 u_int caplen
= hdr
->caplen
;
119 u_int length
= hdr
->len
;
120 struct sll_header
*shdr
= (struct sll_header
*)buf
;
122 pcap_can_socketcan_hdr
*chdr
;
124 if (caplen
< (u_int
) sizeof(struct sll_header
) ||
125 length
< (u_int
) sizeof(struct sll_header
)) {
126 /* Not enough data to have the protocol field */
130 protocol
= EXTRACT_BE_U_2(&shdr
->sll_protocol
);
131 if (protocol
!= LINUX_SLL_P_CAN
&& protocol
!= LINUX_SLL_P_CANFD
)
135 * SocketCAN packet; fix up the packet's header.
137 chdr
= (pcap_can_socketcan_hdr
*)(buf
+ sizeof(struct sll_header
));
138 if (caplen
< (u_int
) sizeof(struct sll_header
) + sizeof(chdr
->can_id
) ||
139 length
< (u_int
) sizeof(struct sll_header
) + sizeof(chdr
->can_id
)) {
140 /* Not enough data to have the CAN ID */
143 chdr
->can_id
= SWAPLONG(chdr
->can_id
);
147 * The same applies for DLT_LINUX_SLL2.
150 swap_linux_sll2_header(const struct pcap_pkthdr
*hdr
, u_char
*buf
)
152 u_int caplen
= hdr
->caplen
;
153 u_int length
= hdr
->len
;
154 struct sll2_header
*shdr
= (struct sll2_header
*)buf
;
156 pcap_can_socketcan_hdr
*chdr
;
158 if (caplen
< (u_int
) sizeof(struct sll2_header
) ||
159 length
< (u_int
) sizeof(struct sll2_header
)) {
160 /* Not enough data to have the protocol field */
164 protocol
= EXTRACT_BE_U_2(&shdr
->sll2_protocol
);
165 if (protocol
!= LINUX_SLL_P_CAN
&& protocol
!= LINUX_SLL_P_CANFD
)
169 * SocketCAN packet; fix up the packet's header.
171 chdr
= (pcap_can_socketcan_hdr
*)(buf
+ sizeof(struct sll2_header
));
172 if (caplen
< (u_int
) sizeof(struct sll2_header
) + sizeof(chdr
->can_id
) ||
173 length
< (u_int
) sizeof(struct sll2_header
) + sizeof(chdr
->can_id
)) {
174 /* Not enough data to have the CAN ID */
177 chdr
->can_id
= SWAPLONG(chdr
->can_id
);
181 * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
182 * byte order when capturing (it's supplied directly from a
183 * memory-mapped buffer shared by the kernel).
185 * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED packet, we
186 * need to convert it from the byte order of the host that wrote the
187 * file to this host's byte order.
190 swap_linux_usb_header(const struct pcap_pkthdr
*hdr
, u_char
*buf
,
191 int header_len_64_bytes
)
193 pcap_usb_header_mmapped
*uhdr
= (pcap_usb_header_mmapped
*)buf
;
194 bpf_u_int32 offset
= 0;
197 * "offset" is the offset *past* the field we're swapping;
198 * we skip the field *before* checking to make sure
199 * the captured data length includes the entire field.
203 * The URB id is a totally opaque value; do we really need to
204 * convert it to the reading host's byte order???
206 offset
+= 8; /* skip past id */
207 if (hdr
->caplen
< offset
)
209 uhdr
->id
= SWAPLL(uhdr
->id
);
211 offset
+= 4; /* skip past various 1-byte fields */
213 offset
+= 2; /* skip past bus_id */
214 if (hdr
->caplen
< offset
)
216 uhdr
->bus_id
= SWAPSHORT(uhdr
->bus_id
);
218 offset
+= 2; /* skip past various 1-byte fields */
220 offset
+= 8; /* skip past ts_sec */
221 if (hdr
->caplen
< offset
)
223 uhdr
->ts_sec
= SWAPLL(uhdr
->ts_sec
);
225 offset
+= 4; /* skip past ts_usec */
226 if (hdr
->caplen
< offset
)
228 uhdr
->ts_usec
= SWAPLONG(uhdr
->ts_usec
);
230 offset
+= 4; /* skip past status */
231 if (hdr
->caplen
< offset
)
233 uhdr
->status
= SWAPLONG(uhdr
->status
);
235 offset
+= 4; /* skip past urb_len */
236 if (hdr
->caplen
< offset
)
238 uhdr
->urb_len
= SWAPLONG(uhdr
->urb_len
);
240 offset
+= 4; /* skip past data_len */
241 if (hdr
->caplen
< offset
)
243 uhdr
->data_len
= SWAPLONG(uhdr
->data_len
);
245 if (uhdr
->transfer_type
== URB_ISOCHRONOUS
) {
246 offset
+= 4; /* skip past s.iso.error_count */
247 if (hdr
->caplen
< offset
)
249 uhdr
->s
.iso
.error_count
= SWAPLONG(uhdr
->s
.iso
.error_count
);
251 offset
+= 4; /* skip past s.iso.numdesc */
252 if (hdr
->caplen
< offset
)
254 uhdr
->s
.iso
.numdesc
= SWAPLONG(uhdr
->s
.iso
.numdesc
);
256 offset
+= 8; /* skip USB setup header */
259 * With the old header, there are no isochronous descriptors
262 * With the new header, the actual number of descriptors in
263 * the header is not s.iso.numdesc, it's ndesc - only the
264 * first N descriptors, for some value of N, are put into
265 * the header, and ndesc is set to the actual number copied.
266 * In addition, if s.iso.numdesc is negative, no descriptors
267 * are captured, and ndesc is set to 0.
269 if (header_len_64_bytes
) {
271 * This is either the "version 1" header, with
272 * 16 bytes of additional fields at the end, or
273 * a "version 0" header from a memory-mapped
274 * capture, with 16 bytes of zeroed-out padding
275 * at the end. Byte swap them as if this were
276 * a "version 1" header.
278 offset
+= 4; /* skip past interval */
279 if (hdr
->caplen
< offset
)
281 uhdr
->interval
= SWAPLONG(uhdr
->interval
);
283 offset
+= 4; /* skip past start_frame */
284 if (hdr
->caplen
< offset
)
286 uhdr
->start_frame
= SWAPLONG(uhdr
->start_frame
);
288 offset
+= 4; /* skip past xfer_flags */
289 if (hdr
->caplen
< offset
)
291 uhdr
->xfer_flags
= SWAPLONG(uhdr
->xfer_flags
);
293 offset
+= 4; /* skip past ndesc */
294 if (hdr
->caplen
< offset
)
296 uhdr
->ndesc
= SWAPLONG(uhdr
->ndesc
);
298 if (uhdr
->transfer_type
== URB_ISOCHRONOUS
) {
299 /* swap the values in struct linux_usb_isodesc */
300 usb_isodesc
*pisodesc
;
303 pisodesc
= (usb_isodesc
*)(void *)(buf
+offset
);
304 for (i
= 0; i
< uhdr
->ndesc
; i
++) {
305 offset
+= 4; /* skip past status */
306 if (hdr
->caplen
< offset
)
308 pisodesc
->status
= SWAPLONG(pisodesc
->status
);
310 offset
+= 4; /* skip past offset */
311 if (hdr
->caplen
< offset
)
313 pisodesc
->offset
= SWAPLONG(pisodesc
->offset
);
315 offset
+= 4; /* skip past len */
316 if (hdr
->caplen
< offset
)
318 pisodesc
->len
= SWAPLONG(pisodesc
->len
);
320 offset
+= 4; /* skip past padding */
329 * The DLT_NFLOG "packets" have a mixture of big-endian and host-byte-order
330 * data. They begin with a fixed-length header with big-endian fields,
331 * followed by a set of TLVs, where the type and length are in host
332 * byte order but the values are either big-endian or are a raw byte
333 * sequence that's the same regardless of the host's byte order.
335 * When reading a DLT_NFLOG packet, we need to convert the type and
336 * length values from the byte order of the host that wrote the file
337 * to the byte order of this host.
340 swap_nflog_header(const struct pcap_pkthdr
*hdr
, u_char
*buf
)
343 nflog_hdr_t
*nfhdr
= (nflog_hdr_t
*)buf
;
345 u_int caplen
= hdr
->caplen
;
346 u_int length
= hdr
->len
;
349 if (caplen
< (u_int
) sizeof(nflog_hdr_t
) ||
350 length
< (u_int
) sizeof(nflog_hdr_t
)) {
351 /* Not enough data to have any TLVs. */
355 if (nfhdr
->nflog_version
!= 0) {
356 /* Unknown NFLOG version */
360 length
-= sizeof(nflog_hdr_t
);
361 caplen
-= sizeof(nflog_hdr_t
);
362 p
+= sizeof(nflog_hdr_t
);
364 while (caplen
>= sizeof(nflog_tlv_t
)) {
365 tlv
= (nflog_tlv_t
*) p
;
367 /* Swap the type and length. */
368 tlv
->tlv_type
= SWAPSHORT(tlv
->tlv_type
);
369 tlv
->tlv_length
= SWAPSHORT(tlv
->tlv_length
);
371 /* Get the length of the TLV. */
372 size
= tlv
->tlv_length
;
374 size
+= 4 - size
% 4;
376 /* Is the TLV's length less than the minimum? */
377 if (size
< sizeof(nflog_tlv_t
)) {
378 /* Yes. Give up now. */
382 /* Do we have enough data for the full TLV? */
383 if (caplen
< size
|| length
< size
) {
388 /* Skip over the TLV. */
396 swap_pseudo_headers(int linktype
, struct pcap_pkthdr
*hdr
, u_char
*data
)
399 * Convert pseudo-headers from the byte order of
400 * the host on which the file was saved to our
401 * byte order, as necessary.
406 swap_pflog_header(hdr
, data
);
410 swap_linux_sll_header(hdr
, data
);
414 swap_linux_sll2_header(hdr
, data
);
418 swap_linux_usb_header(hdr
, data
, 0);
421 case DLT_USB_LINUX_MMAPPED
:
422 swap_linux_usb_header(hdr
, data
, 1);
426 swap_nflog_header(hdr
, data
);
432 pcapint_post_process(int linktype
, int swapped
, struct pcap_pkthdr
*hdr
,
436 swap_pseudo_headers(linktype
, hdr
, data
);
438 pcapint_fixup_pcap_pkthdr(linktype
, hdr
, data
);
442 pcapint_fixup_pcap_pkthdr(int linktype
, struct pcap_pkthdr
*hdr
, const u_char
*data
)
444 const pcap_usb_header_mmapped
*usb_hdr
;
446 usb_hdr
= (const pcap_usb_header_mmapped
*) data
;
447 if (linktype
== DLT_USB_LINUX_MMAPPED
&&
448 hdr
->caplen
>= sizeof (pcap_usb_header_mmapped
)) {
450 * In older versions of libpcap, in memory-mapped captures,
451 * the "on-the-bus length" for completion events for
452 * incoming isochronous transfers was miscalculated; it
453 * needed to be calculated based on the* offsets and lengths
454 * in the descriptors, not on the raw URB length, but it
457 * If this packet contains transferred data (yes, data_flag
458 * is 0 if we *do* have data), and the total on-the-network
459 * length is equal to the value calculated from the raw URB
460 * length, then it might be one of those transfers.
462 * We only do this if we have the full USB pseudo-header.
464 if (!usb_hdr
->data_flag
&&
465 hdr
->len
== sizeof(pcap_usb_header_mmapped
) +
466 (usb_hdr
->ndesc
* sizeof (usb_isodesc
)) + usb_hdr
->urb_len
) {
468 * It might need fixing; fix it if it's a completion
469 * event for an incoming isochronous transfer.
471 fix_linux_usb_mmapped_length(hdr
, data
);