diff options
Diffstat (limited to 'pcap-common.c')
-rw-r--r-- | pcap-common.c | 433 |
1 files changed, 0 insertions, 433 deletions
diff --git a/pcap-common.c b/pcap-common.c index 80851cf7..9738325b 100644 --- a/pcap-common.c +++ b/pcap-common.c @@ -28,15 +28,6 @@ #include <pcap-types.h> #include "pcap-int.h" -#include "extract.h" -#include "pcap/sll.h" -#include "pcap/usb.h" -#include "pcap/nflog.h" -#include "pcap/can_socketcan.h" - -#include "pflog.h" - -#include "pcap-usb-linux-common.h" #include "pcap-common.h" @@ -1440,427 +1431,3 @@ max_snaplen_for_dlt(int dlt) return MAXIMUM_SNAPLEN; } } - -/* - * Most versions of the DLT_PFLOG pseudo-header have UID and PID fields - * that are saved in host byte order. - * - * When reading a DLT_PFLOG packet, we need to convert those fields from - * the byte order of the host that wrote the file to this host's byte - * order. - */ -static void -swap_pflog_header(const struct pcap_pkthdr *hdr, u_char *buf) -{ - u_int caplen = hdr->caplen; - u_int length = hdr->len; - u_int pfloghdr_length; - struct pfloghdr *pflhdr = (struct pfloghdr *)buf; - - if (caplen < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid) || - length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) { - /* Not enough data to have the uid field */ - return; - } - - pfloghdr_length = pflhdr->length; - - if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) { - /* Header doesn't include uid field */ - return; - } - pflhdr->uid = SWAPLONG(pflhdr->uid); - - if (caplen < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid) || - length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) { - /* Not enough data to have the pid field */ - return; - } - if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) { - /* Header doesn't include pid field */ - return; - } - pflhdr->pid = SWAPLONG(pflhdr->pid); - - if (caplen < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid) || - length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) { - /* Not enough data to have the rule_uid field */ - return; - } - if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) { - /* Header doesn't include rule_uid field */ - return; - } - pflhdr->rule_uid = SWAPLONG(pflhdr->rule_uid); - - if (caplen < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid) || - length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) { - /* Not enough data to have the rule_pid field */ - return; - } - if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) { - /* Header doesn't include rule_pid field */ - return; - } - pflhdr->rule_pid = SWAPLONG(pflhdr->rule_pid); -} - -/* - * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or - * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload, - * with the CAN ID being in host byte order. - * - * When reading a DLT_LINUX_SLL packet, we need to check for those - * packets and convert the CAN ID from the byte order of the host that - * wrote the file to this host's byte order. - */ -static void -swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf) -{ - u_int caplen = hdr->caplen; - u_int length = hdr->len; - struct sll_header *shdr = (struct sll_header *)buf; - uint16_t protocol; - pcap_can_socketcan_hdr *chdr; - - if (caplen < (u_int) sizeof(struct sll_header) || - length < (u_int) sizeof(struct sll_header)) { - /* Not enough data to have the protocol field */ - return; - } - - protocol = EXTRACT_BE_U_2(&shdr->sll_protocol); - if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD) - return; - - /* - * SocketCAN packet; fix up the packet's header. - */ - chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header)); - if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) || - length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) { - /* Not enough data to have the CAN ID */ - return; - } - chdr->can_id = SWAPLONG(chdr->can_id); -} - -/* - * The same applies for DLT_LINUX_SLL2. - */ -static void -swap_linux_sll2_header(const struct pcap_pkthdr *hdr, u_char *buf) -{ - u_int caplen = hdr->caplen; - u_int length = hdr->len; - struct sll2_header *shdr = (struct sll2_header *)buf; - uint16_t protocol; - pcap_can_socketcan_hdr *chdr; - - if (caplen < (u_int) sizeof(struct sll2_header) || - length < (u_int) sizeof(struct sll2_header)) { - /* Not enough data to have the protocol field */ - return; - } - - protocol = EXTRACT_BE_U_2(&shdr->sll2_protocol); - if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD) - return; - - /* - * SocketCAN packet; fix up the packet's header. - */ - chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll2_header)); - if (caplen < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id) || - length < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id)) { - /* Not enough data to have the CAN ID */ - return; - } - chdr->can_id = SWAPLONG(chdr->can_id); -} - -/* - * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host - * byte order when capturing (it's supplied directly from a - * memory-mapped buffer shared by the kernel). - * - * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED packet, we - * need to convert it from the byte order of the host that wrote the - * file to this host's byte order. - */ -static void -swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, - int header_len_64_bytes) -{ - pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf; - bpf_u_int32 offset = 0; - - /* - * "offset" is the offset *past* the field we're swapping; - * we skip the field *before* checking to make sure - * the captured data length includes the entire field. - */ - - /* - * The URB id is a totally opaque value; do we really need to - * convert it to the reading host's byte order??? - */ - offset += 8; /* skip past id */ - if (hdr->caplen < offset) - return; - uhdr->id = SWAPLL(uhdr->id); - - offset += 4; /* skip past various 1-byte fields */ - - offset += 2; /* skip past bus_id */ - if (hdr->caplen < offset) - return; - uhdr->bus_id = SWAPSHORT(uhdr->bus_id); - - offset += 2; /* skip past various 1-byte fields */ - - offset += 8; /* skip past ts_sec */ - if (hdr->caplen < offset) - return; - uhdr->ts_sec = SWAPLL(uhdr->ts_sec); - - offset += 4; /* skip past ts_usec */ - if (hdr->caplen < offset) - return; - uhdr->ts_usec = SWAPLONG(uhdr->ts_usec); - - offset += 4; /* skip past status */ - if (hdr->caplen < offset) - return; - uhdr->status = SWAPLONG(uhdr->status); - - offset += 4; /* skip past urb_len */ - if (hdr->caplen < offset) - return; - uhdr->urb_len = SWAPLONG(uhdr->urb_len); - - offset += 4; /* skip past data_len */ - if (hdr->caplen < offset) - return; - uhdr->data_len = SWAPLONG(uhdr->data_len); - - if (uhdr->transfer_type == URB_ISOCHRONOUS) { - offset += 4; /* skip past s.iso.error_count */ - if (hdr->caplen < offset) - return; - uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count); - - offset += 4; /* skip past s.iso.numdesc */ - if (hdr->caplen < offset) - return; - uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc); - } else - offset += 8; /* skip USB setup header */ - - /* - * With the old header, there are no isochronous descriptors - * after the header. - * - * With the new header, the actual number of descriptors in - * the header is not s.iso.numdesc, it's ndesc - only the - * first N descriptors, for some value of N, are put into - * the header, and ndesc is set to the actual number copied. - * In addition, if s.iso.numdesc is negative, no descriptors - * are captured, and ndesc is set to 0. - */ - if (header_len_64_bytes) { - /* - * This is either the "version 1" header, with - * 16 bytes of additional fields at the end, or - * a "version 0" header from a memory-mapped - * capture, with 16 bytes of zeroed-out padding - * at the end. Byte swap them as if this were - * a "version 1" header. - */ - offset += 4; /* skip past interval */ - if (hdr->caplen < offset) - return; - uhdr->interval = SWAPLONG(uhdr->interval); - - offset += 4; /* skip past start_frame */ - if (hdr->caplen < offset) - return; - uhdr->start_frame = SWAPLONG(uhdr->start_frame); - - offset += 4; /* skip past xfer_flags */ - if (hdr->caplen < offset) - return; - uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags); - - offset += 4; /* skip past ndesc */ - if (hdr->caplen < offset) - return; - uhdr->ndesc = SWAPLONG(uhdr->ndesc); - - if (uhdr->transfer_type == URB_ISOCHRONOUS) { - /* swap the values in struct linux_usb_isodesc */ - usb_isodesc *pisodesc; - uint32_t i; - - pisodesc = (usb_isodesc *)(void *)(buf+offset); - for (i = 0; i < uhdr->ndesc; i++) { - offset += 4; /* skip past status */ - if (hdr->caplen < offset) - return; - pisodesc->status = SWAPLONG(pisodesc->status); - - offset += 4; /* skip past offset */ - if (hdr->caplen < offset) - return; - pisodesc->offset = SWAPLONG(pisodesc->offset); - - offset += 4; /* skip past len */ - if (hdr->caplen < offset) - return; - pisodesc->len = SWAPLONG(pisodesc->len); - - offset += 4; /* skip past padding */ - - pisodesc++; - } - } - } -} - -/* - * The DLT_NFLOG "packets" have a mixture of big-endian and host-byte-order - * data. They begin with a fixed-length header with big-endian fields, - * followed by a set of TLVs, where the type and length are in host - * byte order but the values are either big-endian or are a raw byte - * sequence that's the same regardless of the host's byte order. - * - * When reading a DLT_NFLOG packet, we need to convert the type and - * length values from the byte order of the host that wrote the file - * to the byte order of this host. - */ -static void -swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf) -{ - u_char *p = buf; - nflog_hdr_t *nfhdr = (nflog_hdr_t *)buf; - nflog_tlv_t *tlv; - u_int caplen = hdr->caplen; - u_int length = hdr->len; - uint16_t size; - - if (caplen < (u_int) sizeof(nflog_hdr_t) || - length < (u_int) sizeof(nflog_hdr_t)) { - /* Not enough data to have any TLVs. */ - return; - } - - if (nfhdr->nflog_version != 0) { - /* Unknown NFLOG version */ - return; - } - - length -= sizeof(nflog_hdr_t); - caplen -= sizeof(nflog_hdr_t); - p += sizeof(nflog_hdr_t); - - while (caplen >= sizeof(nflog_tlv_t)) { - tlv = (nflog_tlv_t *) p; - - /* Swap the type and length. */ - tlv->tlv_type = SWAPSHORT(tlv->tlv_type); - tlv->tlv_length = SWAPSHORT(tlv->tlv_length); - - /* Get the length of the TLV. */ - size = tlv->tlv_length; - if (size % 4 != 0) - size += 4 - size % 4; - - /* Is the TLV's length less than the minimum? */ - if (size < sizeof(nflog_tlv_t)) { - /* Yes. Give up now. */ - return; - } - - /* Do we have enough data for the full TLV? */ - if (caplen < size || length < size) { - /* No. */ - return; - } - - /* Skip over the TLV. */ - length -= size; - caplen -= size; - p += size; - } -} - -void -swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data) -{ - /* - * Convert pseudo-headers from the byte order of - * the host on which the file was saved to our - * byte order, as necessary. - */ - switch (linktype) { - - case DLT_PFLOG: - swap_pflog_header(hdr, data); - break; - - case DLT_LINUX_SLL: - swap_linux_sll_header(hdr, data); - break; - - case DLT_LINUX_SLL2: - swap_linux_sll2_header(hdr, data); - break; - - case DLT_USB_LINUX: - swap_linux_usb_header(hdr, data, 0); - break; - - case DLT_USB_LINUX_MMAPPED: - swap_linux_usb_header(hdr, data, 1); - break; - - case DLT_NFLOG: - swap_nflog_header(hdr, data); - break; - } -} - -void -fixup_pcap_pkthdr(int linktype, struct pcap_pkthdr *hdr, const u_char *data) -{ - const pcap_usb_header_mmapped *usb_hdr; - - usb_hdr = (const pcap_usb_header_mmapped *) data; - if (linktype == DLT_USB_LINUX_MMAPPED && - hdr->caplen >= sizeof (pcap_usb_header_mmapped)) { - /* - * In older versions of libpcap, in memory-mapped captures, - * the "on-the-bus length" for completion events for - * incoming isochronous transfers was miscalculated; it - * needed to be calculated based on the* offsets and lengths - * in the descriptors, not on the raw URB length, but it - * wasn't. - * - * If this packet contains transferred data (yes, data_flag - * is 0 if we *do* have data), and the total on-the-network - * length is equal to the value calculated from the raw URB - * length, then it might be one of those transfers. - * - * We only do this if we hae the full USB pseudo-header. - */ - if (!usb_hdr->data_flag && - hdr->len == sizeof(pcap_usb_header_mmapped) + - (usb_hdr->ndesc * sizeof (usb_isodesc)) + usb_hdr->urb_len) { - /* - * It might need fixing; fix it if it's a completion - * event for an incoming isochronous transfer. - */ - fix_linux_usb_mmapped_length(hdr, data); - } - } -} |