diff options
author | Guy Harris <gharris@sonic.net> | 2022-02-20 10:38:55 -0800 |
---|---|---|
committer | Guy Harris <gharris@sonic.net> | 2022-02-20 10:38:55 -0800 |
commit | c7f84156c0761e851d5cf222044bafc8d84261cd (patch) | |
tree | 795ebfef468b723a7666b600e33dc7e2dddb03be /wiretap | |
parent | b5d74c69a788376ee910011afbfbb852f65c0958 (diff) |
pcap/pcapng: byte-swap the CAN ID field in CAN pseudo-headers for SLL2.
As for LINUX_SLL, so for LINUX_SLL2.
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/pcap-common.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c index 53811ce75a..5e23fe5dc0 100644 --- a/wiretap/pcap-common.c +++ b/wiretap/pcap-common.c @@ -1918,11 +1918,14 @@ struct can_socketcan_hdr { }; /* - * The fake link-layer header of Linux cooked packets. + * CAN fake link-layer headers in Linux cooked packets. */ #define LINUX_SLL_PROTOCOL_OFFSET 14 /* protocol */ #define LINUX_SLL_LEN 16 /* length of the header */ +#define LINUX_SLL2_PROTOCOL_OFFSET 0 /* protocol */ +#define LINUX_SLL2_LEN 20 /* length of the header */ + /* * The protocols we have to check for. */ @@ -1973,6 +1976,49 @@ pcap_byteswap_linux_sll_pseudoheader(wtap_rec *rec, guint8 *pd) } static void +pcap_byteswap_linux_sll2_pseudoheader(wtap_rec *rec, guint8 *pd) +{ + guint packet_size; + guint16 protocol; + struct can_socketcan_hdr *can_socketcan_phdr; + + /* + * Minimum of captured and actual length (just in case the + * actual length < the captured length, which Should Never + * Happen). + */ + packet_size = rec->rec_header.packet_header.caplen; + if (packet_size > rec->rec_header.packet_header.len) + packet_size = rec->rec_header.packet_header.len; + + if (packet_size < LINUX_SLL2_LEN) { + /* Not enough data to have the protocol */ + return; + } + + protocol = pntoh16(&pd[LINUX_SLL2_PROTOCOL_OFFSET]); + if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD) { + /* Not a CAN packet; nothing to fix */ + return; + } + + /* + * Greasy hack, but we never directly dereference any of + * the fields in *can_socketcan_phdr, we just get offsets + * of and addresses of its members and byte-swap it with a + * byte-at-a-time macro, so it's alignment-safe. + */ + can_socketcan_phdr = (struct can_socketcan_hdr *)(void *)(pd + LINUX_SLL2_LEN); + + if (packet_size < LINUX_SLL2_LEN + sizeof(can_socketcan_phdr->can_id)) { + /* Not enough data to have the full CAN ID */ + return; + } + + PBSWAP32((guint8 *)&can_socketcan_phdr->can_id); +} + +static void pcap_byteswap_linux_usb_pseudoheader(wtap_rec *rec, guint8 *pd, gboolean header_len_64_bytes) { @@ -2373,6 +2419,11 @@ pcap_read_post_process(gboolean is_nokia, int wtap_encap, pcap_byteswap_linux_sll_pseudoheader(rec, pd); break; + case WTAP_ENCAP_SLL2: + if (bytes_swapped) + pcap_byteswap_linux_sll2_pseudoheader(rec, pd); + break; + case WTAP_ENCAP_USB_LINUX: if (bytes_swapped) pcap_byteswap_linux_usb_pseudoheader(rec, pd, FALSE); |