Felix Obenhuber wrote:
2. The can frame struct is defined like this (from linux/can.h):
/**
* struct can_frame - basic CAN frame structure
* @can_id: the CAN ID of the frame and CAN_*_FLAG flags, see above.
* @can_dlc: the data length field of the CAN frame
* @data: the CAN frame payload.
*/
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* data length code: 0 .. 8 */
__u8 data[8] __attribute__((aligned(8)));
};
Gianluca Varenni noted a CAN2.0B spec exists at
http://www.winpcap.org/gianluca/can.html
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PAD | Identifier A | Identifier B |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PAD | DLC | Data ( variable length ) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+-+-+-+-+-+-+-+-+
*CAN 2.0B Packet Block Format.*
The meaning of the fields is:
* PAD: 3 bits of padding for byte alignment.
* Identifier A: The 11 bits of the CAN 2.0B Identfier from a CAN
2.0B frame.
* Identifier B: The 18 bits of the CAN 2.0B Extended Identfier
from a CAN 2.0B frame.
* PAD: 4 bits of padding for byte alignment.
* DLC: The length of Data in bytes. This corresponds to the DLC in
a CAN 2.0B frame.
* Data: The payload of the block. Up to 8 bytes in length, the
length should correspond to the value of the DLC.
Apart from the three bytes of padding that the
__attribute__((aligned(8))) adds, this appears to be roughly the same in
layout. However, although canid_t is a 32-bit field with the
EFF/SFF/RTR flags packed into the three bits marked as PAD in the
diagram above, the order of the identifiers seems to be different. In
linux/can.h, you have
|||/
|//* special address description flags for the CAN_ID *//
||#*define* CAN_EFF_FLAG 0x80000000U //* EFF/SFF is set in the MSB *//
||#*define* CAN_RTR_FLAG 0x40000000U //* remote transmission request *//
||#*define* CAN_ERR_FLAG 0x20000000U //* error frame *//
||
||//* valid bits in CAN ID for frame formats *//
||#*define* CAN_SFF_MASK 0x000007FFU //* standard frame format (SFF) *//
||#*define* CAN_EFF_MASK 0x1FFFFFFFU //* extended frame format (EFF) *//
||#*define* CAN_ERR_MASK 0x1FFFFFFFU //* omit EFF, RTR, ERR flags *//
||
||//*
/||/ * Controller Area Network Identifier structure
/||/ *
/||/ * bit 0-28 : CAN identifier (11/29 bit)
/||/ * bit 29 : error frame flag (0 = data frame, 1 = error frame)
/||/ * bit 30 : remote transmission request flag (1 = rtr frame)
/||/ * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29
bit)
/||/ *//
||*typedef* __u32 canid_t;
|
/|
Furthermore, the Linux canid_t keeps all of these bits in a
(byte-ordered) 32-bit integer, which would give the following layouts:
Big-endian:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|R|E| Identifier B | Identifier A |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little-endian (Intel):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Lo Id A | Lo Id B |HiIdA| Mid Id B |F|R|E| Hi Id B |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
(The little-endian one only looks so chopped up because the bits are
shown in big-endian order, which is what these sorts of packet block
diagrams always use - I don't know anything about CAN transmission order
and in any case this is strictly an in-memory layout).
Given these differences between the two frame formats I would suggest
that you use a new DLT for SocketCAN, especially as there would be no
way to know for sure whether the flags were present or just padding (a
packet with all zero flags would be indistinguishable). If you ever
think that SocketCAN/libpcap will be used on big-endian systems, you
might want to "canonicalize" the layout in the big-endian format above
for a more comprehensible diagram, and because little-endian systems
have htonl/ntohl macros that are not no-ops, making portable user-level
coding simpler (if you standardize the little-endian format, portable
code has to use #ifdefs to determine byte-order and then call a swap()
function/macro on big-endian systems).
@alex
--
Alexander Dupuy
Senior Secure Systems Engineer
Trusted Computer Solutions
2350 Corporate Park Drive, Suite 500
Herndon, VA 20171-4848
mailto:adu...@trustedcs.com
-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.