the-tcpdump-group / tcpdump

the TCPdump network dissector
https://www.tcpdump.org/
Other
2.72k stars 849 forks source link

[Patch] Support for printing SocketCAN formated frames #253

Open guyharris opened 11 years ago

guyharris commented 11 years ago

Converted from SourceForge issue 2876645, submitted by asu_fo

Libpcap gets extended to capture CAN frames via the SocketCAN interface.

This patch enabled tcpdump to print that captured frames for testing purposes and convenience. The printing routine is taken from the can-utlis of SocketCAN.

infrastation commented 10 years ago

The suggested patch:

From d1a300b24ffff269ef012b03a6018a0be6611555 Mon Sep 17 00:00:00 2001
From: Felix Obenhuber <felix@obenhuber.de>
Date: Sun, 11 Oct 2009 23:11:15 +0200
Subject: [PATCH] Support for SocketCAN

Print struct can_frame for the Linux SocketCAN implementation almost the same
way candump does. Uses libpcap SocketCAN patch.
---
 CREDITS           |    1 +
 INSTALL.txt       |    1 +
 Makefile.in       |   15 ++++----
 interface.h       |    1 +
 print-socketcan.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tcpdump.c         |    3 ++
 6 files changed, 111 insertions(+), 7 deletions(-)
 create mode 100644 print-socketcan.c

diff --git a/CREDITS b/CREDITS
index 3579d73..db7223e 100644
--- a/CREDITS
+++ b/CREDITS
@@ -51,6 +51,7 @@ Additional people who have contributed patches:
    Eddie Kohler            <xexd at sourceforge dot net>
    Elmar Kirchner          <elmar at juniper dot net>
    Fang Wang           <fangwang at sourceforge dot net>
+   Felix Obenhuber         <felix at obenhuber dot de>
    Florent Drouin          <Florent dot Drouin at alcatel-lucent dot fr>
    Florian Forster         <octo at verplant dot org>
    Francis Dupont          <Francis dot Dupont at enst-bretagne dot fr>
diff --git a/INSTALL.txt b/INSTALL.txt
index a03e2c0..0d0bed5 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -211,6 +211,7 @@ print-sll.c - Linux "cooked" capture printer routines
 print-slow.c   - IEEE "slow protocol" (802.3ad) printer routines
 print-smb.c    - SMB/CIFS printer routines
 print-snmp.c   - Simple Network Management Protocol printer routines
+print-socketcan.c - SocketCAN printer routines
 print-stp.c    - IEEE 802.1d spanning tree protocol printer routines
 print-sunatm.c - SunATM DLPI capture printer routines
 print-sunrpc.c - Sun Remote Procedure Call printer routines
diff --git a/Makefile.in b/Makefile.in
index 633c59d..e95bade 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -80,17 +80,18 @@ CSRC =  addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c
    print-igrp.c print-ip.c print-ipcomp.c print-ipfc.c \
    print-ipx.c print-isoclns.c print-juniper.c print-krb.c \
    print-l2tp.c print-lane.c print-ldp.c print-lldp.c print-llc.c \
-        print-lmp.c print-lspping.c print-lwapp.c \
+   print-lmp.c print-lspping.c print-lwapp.c \
    print-lwres.c print-mobile.c print-mpcp.c print-mpls.c print-msdp.c \
    print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
    print-pgm.c print-pim.c print-ppp.c print-pppoe.c print-pptp.c \
    print-radius.c print-raw.c print-rip.c print-rrcp.c print-rsvp.c \
-   print-rx.c print-sctp.c print-sflow.c print-sip.c print-sl.c print-sll.c \
-   print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
-   print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \
-   print-timed.c print-token.c print-udld.c print-udp.c print-usb.c \
-   print-vjc.c print-vqp.c print-vrrp.c print-vtp.c \
-   print-wb.c print-zephyr.c signature.c setsignal.c tcpdump.c util.c
+   print-rx.c print-sctp.c print-sflow.c print-socketcan.c print-sip.c \
+   print-sl.c print-sll.c print-slow.c print-snmp.c print-stp.c \
+   print-sunatm.c print-sunrpc.c print-symantec.c print-syslog.c \
+   print-tcp.c print-telnet.c print-tftp.c print-timed.c print-token.c \
+   print-udld.c print-udp.c print-usb.c print-vjc.c print-vqp.c \
+   print-vrrp.c print-vtp.c print-wb.c print-zephyr.c signature.c \
+   setsignal.c tcpdump.c util.c

 LIBNETDISSECT_SRC=print-isakmp.c
 LIBNETDISSECT_OBJ=$(LIBNETDISSECT_SRC:.c=.o)
diff --git a/interface.h b/interface.h
index afeaee9..6c62b3b 100644
--- a/interface.h
+++ b/interface.h
@@ -323,6 +323,7 @@ extern void sip_print(const u_char *, u_int);
 extern void syslog_print(const u_char *, u_int);
 extern u_int bt_if_print(const struct pcap_pkthdr *, const u_char *);
 extern u_int usb_linux_print(const struct pcap_pkthdr *, const u_char *);
+extern u_int socketcan_print(const struct pcap_pkthdr *, const u_char *);

 #ifdef INET6
 extern void ip6_print(const u_char *, u_int);
diff --git a/print-socketcan.c b/print-socketcan.c
new file mode 100644
index 0000000..93f0283
--- /dev/null
+++ b/print-socketcan.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Support for the SocketCAN
+ *
+ * Original code taken from can-utils in SocketCAN
+ * http://developer.berlios.de/projects/socketcan/
+ *
+ * Modified Felix Obenhuber <felix@obenhuber.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <pcap.h>
+#include <stdio.h>
+
+#include <linux/can.h>
+
+u_int
+socketcan_print(const struct pcap_pkthdr *h, const u_char *p)
+{
+   int i, j, dlen, offset;
+   struct can_frame *cf = (struct can_frame*)p;
+   int dlc = (cf->can_dlc > 8)? 8 : cf->can_dlc;
+   char buf[45];                /* max length */
+   
+        sprintf(buf, "%s ", "CAN");
+   offset = 4;
+
+   if (cf->can_id & CAN_ERR_FLAG)
+   {
+       sprintf(buf+offset, "%8X  ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
+       offset += 10;
+   }
+   else if (cf->can_id & CAN_EFF_FLAG)
+   {
+       sprintf(buf+offset, "%8X  ", cf->can_id & CAN_EFF_MASK);
+       offset += 10;
+   }
+   else
+   {
+       sprintf(buf+offset, "%3X  ", cf->can_id & CAN_SFF_MASK);
+       offset += 5;
+   }
+
+   sprintf(buf+offset, "[%d]", dlc);
+   offset += 3;
+
+                                
+   if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
+   {
+       sprintf(buf+offset, " remote request");
+       printf("%s", buf );
+       return;
+   }
+
+   dlen = 3; /* _AA */
+   for (i = 0; i < dlc; i++)
+   {
+       sprintf(buf+offset, " %02X", cf->data[i]);
+       offset += dlen;
+   }
+
+   if (cf->can_id & CAN_ERR_FLAG)
+       sprintf(buf+offset, "%*s", dlen*(8-dlc)+13, "ERRORFRAME");
+   else
+   {
+       j = dlen*(8-dlc)+4;
+       sprintf(buf+offset, "%*s", j, "'");
+       offset += j;
+       for (i = 0; i < dlc; i++)
+           if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
+               buf[offset++] = cf->data[i];
+       else
+           buf[offset++] = '.';
+
+       sprintf(buf+offset, "'");
+   }
+
+   printf("%s", buf );
+   return (sizeof(struct can_frame));
+}
diff --git a/tcpdump.c b/tcpdump.c
index 18c7af4..b3cc2c6 100644
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -282,6 +282,9 @@ static struct printer printers[] = {
 #if defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX_MMAPPED)
    { usb_linux_print, DLT_USB_LINUX_MMAPPED},
 #endif
+#ifdef DLT_CAN_SOCKETCAN
+   { socketcan_print, DLT_CAN_SOCKETCAN},
+#endif
    { NULL,         0 },
 };

-- 
1.6.3.3
Adraub commented 7 years ago

+1! Does it just output the same thing as the "candump" socketCAN library? I was disappointed when i tried to pipe through SSH SocketCAN frames to Wireshark (just the same as you can do with Ethernet frames), and tcpdump told me it wasn't possible. It is really useful when you try to debug embedded systems. I scripted something that works with python but i can help to migrate it :) It could be a great feature for a future version.

EDIT: it's possible using the -w flag: tcpdump: packet printing is not supported for link type CAN_SOCKETCAN: use -w

for example, you just have to do a ssh tunnel with this and it works

tcpdump -s0 -U -n -w - -i vcan0 | wireshark -k -i -

infrastation commented 7 years ago

@Adraub, do you have a packet capture of this type?

Adraub commented 7 years ago

On ubuntu using socketcan you can easily create a capture @infrastation

$ modprobe vcan $ sudo ip link add dev vcan0 type vcan $ sudo ip link set up vcan0

let this run in a terminal: cangen vcan0

in another launch: tcpdump -s0 -U -n -w - -i vcan0 | wireshark -k -i -

Here you are, you can save your can file as pcap.

Please note that sadly, i see on my device can frame send twice, one as a "kernel" request, and another as a received frame. This is linux cooked capture and it doesnt seem possible to filter it directly with tcpdump.

guyharris commented 7 years ago

it's possible using the -w flag

Yes, for all link-layer header types, even Ethernet, if you want to run tcpdump and pipe its output to Wireshark, you need -w.