linux-can / can-utils

Linux-CAN / SocketCAN user space applications
2.31k stars 698 forks source link

Any write to CAN_BCM socket returns -1 with errno = 22 #505

Open JuraszekL opened 4 months ago

JuraszekL commented 4 months ago

Hi guys! I am just a beginner so please, be patient to my ineptitude.

I was trying to write simple code to test BCM sockets, but anytime i want to add some new rule, the write function returns an error and errno is set to 22. I decided then to run bcmserver and add rule through a socket, but the results are the same. Here are the details:

I am using RaspberryPi 4 with CAN FD shield.

juraszekl@raspberrypi:~ $ uname -a 
Linux raspberrypi 6.1.0-rpi8-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.73-1+rpt1 (2024-01-25) aarch64 GNU/Linux

First, simple configuration of interface:

juraszekl@raspberrypi:~ $ sudo ip link set can0 up type can bitrate 100000

Next loading can_bcm module:

juraszekl@raspberrypi:~ $ sudo modprobe can-bcm
juraszekl@raspberrypi:~ $ sudo lsmod | grep can
can_bcm                24576  0
can                    28672  1 can_bcm
can_dev                40960  1 mcp251xfd

I've add a few printf's to the original bcmserver.c file, then recompiled. if i send the command:

juraszekl@raspberrypi:~ $ echo "< can0 A 1 0 123 8 11 22 33 44 55 66 77 88 >" | nc 0.0.0.0 28600

the output from bcmserver is:

juraszekl@raspberrypi:~/Temp/can-utils $ ./bcmserver 
listening
forking
BCM socket opened, sc = 5
BCM socket connected
read '< can0 A 1 0 123 8 11 22 33 44 55 66 77 88 >'
sscanf ok! items = 14
res = -1, errno = 22

code that gives the last line looks like this:

if (!ioctl(sc, SIOCGIFINDEX, &ifr)) {
    caddr.can_ifindex = ifr.ifr_ifindex;
    res = sendto(sc, &msg, sizeof(msg), 0,
            (struct sockaddr*)&caddr, sizeof(caddr));
        printf("res = %d, errno = %d\n", res, errno);
        }

After two days and many different combinations with msg structure, interface numbers and socket options i must give up.

Please tell me what am i doing wrong.

BR. Łukasz

hartkopp commented 4 months ago

Hi Łukasz,

I tried your exact setup with a virtual CAN interface "vcan0" echo "< vcan0 A 1 0 123 8 11 22 33 44 55 66 77 88 >" | nc 0.0.0.0 28600

and it works as expected:

$ candump any -td
 (000.000000)  vcan0  123   [8]  11 22 33 44 55 66 77 88
 (001.000135)  vcan0  123   [8]  11 22 33 44 55 66 77 88
 (001.000146)  vcan0  123   [8]  11 22 33 44 55 66 77 88
...

Maybe there's something wrong with your can0 interface?!?

Can you please check if your system runs fine with a virtual CAN interface?

hartkopp commented 4 months ago

I have another idea what might be wrong.

juraszekl@raspberrypi:~ $ uname -a 
Linux raspberrypi 6.1.0-rpi8-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.73-1+rpt1 (2024-01-25) aarch64 GNU/Linux

Can you please check whether the bcmserver is a 64 bit binary too?

E.g. with file bcmserver On my 64 bit X86 it looks like this:

$ file bcmserver
bcmserver: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=eee7e8c285a5dbdb9c0b6bfcf3ceb5f29667fcca, for GNU/Linux 3.2.0, not stripped
JuraszekL commented 4 months ago

Can you please check if your system runs fine with a virtual CAN interface?

So, i have both modules:

$ lsmod | grep can
can_bcm                24576  0
can                    28672  1 can_bcm
vcan                   16384  0
can_dev                40960  2 mcp251xfd,vcan

and operating vcan0:

$ sudo ip link add dev vcan0 type vcan
$ sudo ip link set vcan0 up
$ ip link show vcan0
6: vcan0: <NOARP,UP,LOWER_UP> mtu 72 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/can 

but output is the same:

$ ./bcmserver 
listening
forking
BCM socket opened, sc = 5
BCM socket connected
read '< vcan0 A 1 0 123 8 11 22 33 44 55 66 77 88 >'
sscanf ok! items = 14
res = -1, errno = 22

Can you please check whether the bcmserver is a 64 bit binary too?

Bingo!

$ file bcmserver
bcmserver: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=1bd7bfb49bc9c25fab7e00675c1ccc1e1f807487, for GNU/Linux 3.2.0, not stripped

How can i solve this issue? I've checked other exec files that were compiled in the same way, all of them are 32-bit and all of them work fine with f.e. RAW sockets.

Just to make that clear - i use Raspbian directly to compile files (no cross-compilation).

hartkopp commented 4 months ago

IIRC there was a discussion some time ago.

Can you try to add (or change) arm_64bit=0

into /boot/config.txt

JuraszekL commented 4 months ago

In my case the right file is under /boot/firmware/config.txt

This solution works fine!

candump can1
  can1  123   [8]  11 22 33 44 55 66 77 88
  can1  123   [8]  11 22 33 44 55 66 77 88
  can1  123   [8]  11 22 33 44 55 66 77 88
  can1  123   [8]  11 22 33 44 55 66 77 88
  can1  123   [8]  11 22 33 44 55 66 77 88

Can You please tell me what is wrong? I just want to understand the issue as a beginner.

Thank You. Łukasz

JuraszekL commented 4 months ago

How about downgrade my OS to Bullseye and use external toolchain like this one?

hartkopp commented 4 months ago

Hi Łukasz,

the problem is, that the

struct bcm_msg_head {
    __u32 opcode;
    __u32 flags;
    __u32 count;
    struct bcm_timeval ival1, ival2;
    canid_t can_id;
    __u32 nframes;
    struct can_frame frames[];
};

has this

struct bcm_timeval {
    long tv_sec;
    long tv_usec;
};

where the long can be either 32 or 64 bit. And this is the problem: You have a 32 bit user space running on a 64 bit kernel. And therefore the length check for the sizeof(struct bcm_mag_head) fails with errno 22 ("invalid argument"). That's the story.

IIRC Marc prepared a patch to solve this. I have to take a look at it.