aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/pcap-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'wiretap/pcap-common.c')
-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);