Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

J1939 - sendto failed: Cannot assign requested address #557

Open
alisonbelow opened this issue Aug 12, 2024 · 1 comment
Open

J1939 - sendto failed: Cannot assign requested address #557

alisonbelow opened this issue Aug 12, 2024 · 1 comment

Comments

@alisonbelow
Copy link

Looking for some assistance here - I am trying to create a simple program to send a j1939 message on a vcan interface.

My goals:

  • bind() socket to name 0x1 and address 0x80
  • use sendto() to send a message to peer 0x41
int main() {
    int fd = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
    if (fd < 0) {
        int err = errno;
        std::cerr << "Failed to create socket: " << strerror(err) << " (errno: " << err << ")" << std::endl;
        throw std::runtime_error("Failed to open CAN socket");
    }
	    
	struct sockaddr_can addr;
    memset(&addr, 0, sizeof(addr));
    addr.can_ifindex = if_nametoindex("vcan0");
    addr.can_addr.j1939.name = 0x01;    // peer, name = 1
    addr.can_addr.j1939.addr = 0x80;    // peer, address = 128
    addr.can_addr.j1939.pgn = 0xFFD0;
    addr.can_family = AF_CAN;  
   
    if (bind(fd, (const struct sockaddr*)&addr, sizeof(sockaddr_can)) < 0) {
        perror ("bind failed");
        close(fd);
        return 1;
    }

    struct sockaddr_can peer;
    memset(&peer, 0, sizeof(peer));
    peer.can_ifindex = if_nametoindex("vcan0");
    peer.can_addr.j1939.name = J1939_NO_NAME;
    peer.can_addr.j1939.addr = 0x41;
    peer.can_addr.j1939.pgn = 0xFFD0;
    peer.can_family = AF_CAN;

    struct can_frame frame;
    memset(&frame, 0, sizeof(frame));
    frame.can_id = 0xFFD0;
    frame.can_dlc = 8;
    std::memset(frame.data, 0xAA, sizeof(frame.data));
      		
    if (sendto(fd, frame.data, sizeof(frame.data), 0, reinterpret_cast<const sockaddr*>(&peer), sizeof(sockaddr_can)) < 0) {
        perror ("send failed");
        close(fd);
        return 1;
    }
    close(fd);
    return 0;
}

When I run this binary, I get error "sendto failed: Cannot assign requested address".

Is there anything distinctly I'm doing wrong here? I tried to find the configured addressing/names but I do not have a /proc/net/can/j1939 file to cat.

I've confirmed the vcan interface is configured and up:

sudo ip -details link show vcan0
5: vcan0: <NOARP,UP,LOWER_UP> mtu 72 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/can  promiscuity 0 minmtu 0 maxmtu 0 
    vcan numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 

and sudo modprobe vcan is successful.

@olerem
Copy link
Contributor

olerem commented Aug 13, 2024

Hi @alisonbelow ,

You are setting NAME for the bind address:
addr.can_addr.j1939.name = 0x01; // peer, name = 1

If you are doing it, you need to do address claiming and the kernel stack should see the address claiming on the bus. So, you should use j1939acd to claim the address, or add own code to do it, or set J1939_NO_NAME. Especially if you areldy set the address, name is not needed.
Except of this, you are trying to send a can frame as payload, this makes no sense. Payload is just a payload, everything else is done by the kernel stack. For example if it is more then 8 byte, it will be split and transferred by using transport protocol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants