aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <gharris@sonic.net>2022-02-20 10:38:55 -0800
committerGuy Harris <gharris@sonic.net>2022-02-20 10:38:55 -0800
commitc7f84156c0761e851d5cf222044bafc8d84261cd (patch)
tree795ebfef468b723a7666b600e33dc7e2dddb03be /wiretap
parentb5d74c69a788376ee910011afbfbb852f65c0958 (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.c53
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);