diff options
Diffstat (limited to 'pcap-common.c')
-rw-r--r-- | pcap-common.c | 192 |
1 files changed, 142 insertions, 50 deletions
diff --git a/pcap-common.c b/pcap-common.c index a68e03221528..84368f6cefa6 100644 --- a/pcap-common.c +++ b/pcap-common.c @@ -25,9 +25,9 @@ #include "config.h" #endif -#ifdef WIN32 +#ifdef _WIN32 #include <pcap-stdinc.h> -#else /* WIN32 */ +#else /* _WIN32 */ #if HAVE_INTTYPES_H #include <inttypes.h> #elif HAVE_STDINT_H @@ -37,11 +37,14 @@ #include <sys/bitypes.h> #endif #include <sys/types.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #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 "pcap-common.h" @@ -351,7 +354,7 @@ #define LINKTYPE_GPRS_LLC 169 /* GPRS LLC */ #define LINKTYPE_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ -#define LINKTYPE_GPF_F 171 /* GPF-T (ITU-T G.7041/Y.1303) */ +#define LINKTYPE_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */ /* * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line @@ -386,7 +389,7 @@ /* * Juniper-private data link type, as per request from - * Hannes Gredler <hannes@juniper.net>. + * Hannes Gredler <hannes@juniper.net>. * The Link Types are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames @@ -403,7 +406,7 @@ /* * Juniper-private data link type, as per request from - * Hannes Gredler <hannes@juniper.net>. + * Hannes Gredler <hannes@juniper.net>. * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ @@ -426,10 +429,17 @@ #define LINKTYPE_A653_ICM 185 /* - * USB packets, beginning with a USB setup header; requested by - * Paolo Abeni <paolo.abeni@email.it>. + * This used to be "USB packets, beginning with a USB setup header; + * requested by Paolo Abeni <paolo.abeni@email.it>." + * + * However, that header didn't work all that well - it left out some + * useful information - and was abandoned in favor of the DLT_USB_LINUX + * header. + * + * This is now used by FreeBSD for its BPF taps for USB; that has its + * own headers. So it is written, so it is done. */ -#define LINKTYPE_USB 186 +#define LINKTYPE_USB_FREEBSD 186 /* * Bluetooth HCI UART transport layer (part H:4); requested by @@ -478,7 +488,7 @@ /* * Juniper-private data link type, as per request from - * Hannes Gredler <hannes@juniper.net>. + * Hannes Gredler <hannes@juniper.net>. * The DLT_ is used for internal communication with a * integrated service module (ISM). */ @@ -519,7 +529,7 @@ /* * Juniper-private data link type, as per request from - * Hannes Gredler <hannes@juniper.net>. + * Hannes Gredler <hannes@juniper.net>. * The DLT_ is used for capturing data on a secure tunnel interface. */ #define LINKTYPE_JUNIPER_ST 200 @@ -611,11 +621,11 @@ */ #define LINKTYPE_IEEE802_15_4_NONASK_PHY 215 -/* +/* * David Gibson <david@gibson.dropbear.id.au> requested this for * captures from the Linux kernel /dev/input/eventN devices. This * is used to communicate keystrokes and mouse movements from the - * Linux kernel to display systems, such as Xorg. + * Linux kernel to display systems, such as Xorg. */ #define LINKTYPE_LINUX_EVDEV 216 @@ -736,8 +746,10 @@ /* * CAN (Controller Area Network) frames, with a pseudo-header as supplied - * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux - * source. + * by Linux SocketCAN, and with multi-byte numerical fields in that header + * in big-endian byte order. + * + * See Documentation/networking/can.txt in the Linux source. * * Requested by Felix Obenhuber <felix@obenhuber.de>. */ @@ -777,7 +789,7 @@ /* * Juniper-private data link type, as per request from - * Hannes Gredler <hannes@juniper.net>. + * Hannes Gredler <hannes@juniper.net>. */ #define LINKTYPE_JUNIPER_VS 232 #define LINKTYPE_JUNIPER_SRX_E2E 233 @@ -809,12 +821,12 @@ /* * Juniper-private data link type, as per request from - * Hannes Gredler <hannes@juniper.net>. + * Hannes Gredler <hannes@juniper.net>. */ #define LINKTYPE_JUNIPER_ATM_CEMIC 238 /* - * NetFilter LOG messages + * NetFilter LOG messages * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) * * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl> @@ -922,7 +934,7 @@ /* * Link-layer header type for upper-protocol layer PDU saves from wireshark. - * + * * the actual contents are determined by two TAGs stored with each * packet: * EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the @@ -959,7 +971,6 @@ */ #define LINKTYPE_PROFIBUS_DL 257 - /* * Apple's DLT_PKTAP headers. * @@ -994,7 +1005,30 @@ */ #define LINKTYPE_IPMI_HPM_2 260 -#define LINKTYPE_MATCHING_MAX 260 /* highest value in the "matching" range */ +/* + * per Joshua Wright <jwright@hasborg.com>, formats for Zwave captures. + */ +#define LINKTYPE_ZWAVE_R1_R2 261 +#define LINKTYPE_ZWAVE_R3 262 + +/* + * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper + * Digital Lighting Management room bus serial protocol captures. + */ +#define LINKTYPE_WATTSTOPPER_DLM 263 + +/* + * ISO 14443 contactless smart card messages. + */ +#define LINKTYPE_ISO_14443 264 + +/* + * Radio data system (RDS) groups. IEC 62106. + * Per Jonathan Brucker <jonathan.brucke@gmail.com>. + */ +#define LINKTYPE_RDS 265 + +#define LINKTYPE_MATCHING_MAX 265 /* highest value in the "matching" range */ static struct linktype_map { int dlt; @@ -1141,6 +1175,48 @@ linktype_to_dlt(int linktype) return linktype; } +#define EXTRACT_ + +/* + * 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 capture file, 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; + u_int16_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_16BITS(&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 DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host * byte order when capturing (it's supplied directly from a @@ -1156,8 +1232,6 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, { pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf; bpf_u_int32 offset = 0; - usb_isodesc *pisodesc; - int32_t numdesc, i; /* * "offset" is the offset *past* the field we're swapping; @@ -1166,7 +1240,7 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, */ /* - * The URB id is a totally opaque value; do we really need to + * 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 */ @@ -1221,6 +1295,17 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, } 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 @@ -1249,31 +1334,33 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, if (hdr->caplen < offset) return; uhdr->ndesc = SWAPLONG(uhdr->ndesc); - } - if (uhdr->transfer_type == URB_ISOCHRONOUS) { - /* swap the values in struct linux_usb_isodesc */ - pisodesc = (usb_isodesc *)(void *)(buf+offset); - numdesc = uhdr->s.iso.numdesc; - for (i = 0; i < numdesc; 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++; + if (uhdr->transfer_type == URB_ISOCHRONOUS) { + /* swap the values in struct linux_usb_isodesc */ + usb_isodesc *pisodesc; + u_int32_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++; + } } } } @@ -1299,12 +1386,13 @@ swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf) u_int length = hdr->len; u_int16_t size; - if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) { + 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) { + if (nfhdr->nflog_version != 0) { /* Unknown NFLOG version */ return; } @@ -1354,6 +1442,10 @@ swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data) */ switch (linktype) { + case DLT_LINUX_SLL: + swap_linux_sll_header(hdr, data); + break; + case DLT_USB_LINUX: swap_linux_usb_header(hdr, data, 0); break; |