From eb6cfd8feae85b67529bb3c82f6a97bfd98c73f3 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Mon, 12 Feb 2024 13:34:14 -0800 Subject: [PATCH] socketcan: put the first field of a CAN XL header in big-endian order. Old CAN XL-unaware versions of libpcap did so, as they thought it was the CAN ID field. So that readers of LINKTYPE_CAN_SOCKETCAN files can handle those captures and fixed captures, we make that field big-endian. We continue to make the other two multi-byte fields of the CAN XL header little-endian, as those old versions of libpcap didn't change tham, and most if not all CAN XL captures were done on little-endian platforms. --- pcap-linux.c | 61 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/pcap-linux.c b/pcap-linux.c index f92a3e0443..2b3075a0fb 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -4059,43 +4059,52 @@ static int pcap_handle_packet_mmap( * This is a CAN XL frame. * * DLT_CAN_SOCKETCAN is specified as having - * the Priority ID, payload length, and - * Acceptance Field in little-endian byte - * order, but capturing on a CAN device + * the Priority ID/VCID field in big-- + * endian byte order, and the payload length + * and Acceptance Field in little-endian byte + * order. but capturing on a CAN device * provides them in host byte order. - * Convert them to little-endian byte order. + * Convert them to the appropriate byte + * orders. + * + * The reason we put the first field + * into big-endian byte order is that + * older libpcap code, ignorant of + * CAN XL, treated it as the CAN ID + * field and put it into big-endian + * byte order, and we don't want to + * break code that understands CAN XL + * headers, and treats that field as + * being big-endian. * - * In addition, the first field of the - * header is currently a 32-bit value, - * the lower 11 bits of which are a - * priority value, but there's a patch - * pending to add a VCID field in the - * upper 16 bits of the 32-bit value. - * So, on a little-endian machine, the - * first 16 bits would be the priority - * and the next 16 bits would be the - * VCID, and, on a big-endian machine, - * the first 16 bits would be the VCID - * and the next 16 bits would be the - * priority. + * The other fields are put in little- + * endian byte order is that older + * libpcap code, ignorant of CAN XL, + * left those fields alone, and the + * processors on which the CAN XL + * frames were captured are likely + * to be little-endian processors. */ + pcap_can_socketcan_xl_hdr *canxl_hdr = (pcap_can_socketcan_xl_hdr *)bp; + #if __BYTE_ORDER == __LITTLE_ENDIAN /* * We're capturing on a little-endian - * machine, so the header is already - * in the correct format. + * machine, so we put the priority/VCID + * field into big-endian byte order, and + * leave the payload length and acceptance + * field in little-endian byte order. */ + /* Byte-swap priority/VCID. */ + canxl_hdr->priority_vcid = SWAPLONG(canxl_hdr->priority_vcid); #elif __BYTE_ORDER == __BIG_ENDIAN /* * We're capturing on a big-endian - * machine, so we want to swap all - * multi-byte values to little-endian. + * machine, so we want to leave the + * priority/VCID field alone, and byte-swap + * the payload length and acceptance + * fields to little-endian. */ - pcap_can_socketcan_xl_hdr *canxl_hdr = (pcap_can_socketcan_xl_hdr *)bp; - - /* Byte-swap priority/VCID. */ - canxl_hdr->priority_vcid = SWAPLONG(canxl_hdr->priority_vcid); - /* Byte-swap the payload length */ canxl_hdr->payload_length = SWAPSHORT(canxl_hdr->payload_length);