Page MenuHomeFreeBSD

linux(4): Avoid EISCONN if addr is specified for sendto()
Needs ReviewPublic

Authored by steven_chen3_dell.com on Dec 27 2023, 8:43 AM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Oct 22, 6:42 AM
Unknown Object (File)
Oct 7 2024, 12:33 AM
Unknown Object (File)
Oct 3 2024, 10:25 PM
Unknown Object (File)
Sep 2 2024, 11:53 PM
Unknown Object (File)
Sep 2 2024, 11:53 PM
Unknown Object (File)
Sep 2 2024, 11:49 PM
Unknown Object (File)
Aug 2 2024, 1:30 AM
Unknown Object (File)
Jul 25 2024, 9:59 AM
Subscribers

Details

Reviewers
dchagin
melifaro
Summary

To fix avoid EISCONN if addr is specified for sendto(), the old commit changed the linux_sendto() to ignore the target address if the socket state is in a connected/connecting state.

This commit causes many issues now, such as ARP packet sending failure, wpa_supplier failed to send L2 packets.

linux_sendto() is used for all kinds of socket, such as netlink, unix, l2 socket, etc. What more, for most socket(exclude udp and tcp), the socket state is always set to "connected" from it created.
so the old commit maybe cause these type sockets calling sendto() failure.

In fact, the socket that has the original issue is UDP protocol. When the socket has already called the connect(), if an address is specified in the sendto(), EISCONN error will be returned.

Therefore, to fix this type of socket issue is a better way than that: If addr is specified for sendto(), the connected address is ignored (just like Linux behavior).

Test Plan

Need to test socket types that can call connect(), so these protocols are UDP/TCP/UDP6/TCP6.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

the old commit changed the linux_sendto() to ignore the target address if the socket state is in a connected/connecting state.
This commit causes many issues now, such as ARP packet sending failure, wpa_supplier failed to send L2 packets.

Can you please name the old commit and provide a test scenario that it broke? It is hard to understand what is the problem we are trying to fix here.

sys/netinet/udp_usrreq.c
1241

This definitely changes behavior of non-Linux syscall as well and seems to me an undesired change. Same for IPv6.

the old commit changed the linux_sendto() to ignore the target address if the socket state is in a connected/connecting state.
This commit causes many issues now, such as ARP packet sending failure, wpa_supplier failed to send L2 packets.

Can you please name the old commit and provide a test scenario that it broke? It is hard to understand what is the problem we are trying to fix here.

this is the old commit:
commit db48fa8319825b4428795fcef9fb5458ac34c1a9
Author: Dmitry Chagin <dchagin@FreeBSD.org>
Date: Sat May 28 23:42:09 2022 +0300

linux(4): Avoid EISCONN if addr is specified for sendto()

If the socket is in a connected state, the target address should be
ignored.

MFC after:              2 weeks

this is my test program:
{F74575185}
It is complied in linux, and it can send arp in FreeBSD12, but it cannot run in FreeBSD14.

By the way, we have added an L2 socket module to receive/send packets in l2-layer,
in the l2sock_attacck(), it calls soisconnected(), so the l2 socket so_state is set to SS_ISCONNECTED.
So the original FreeBSD may not have such issues.

sys/netinet/udp_usrreq.c
1241

Yes, it changes FreeBSD syscall behavior. This branch means the UDP socket has been bound a destination address by calling connect() , the current behavior of sendto() with a valid dest_addr is failure if it connect() a address, this change is to use sendto() carring dest_addr to replace the connect() bound address, I think this change provides a better compatibility,dosen't it?

I have fixed a issue where a python program(simulate zoom) connect to zoom server failure on Freebsd client when using UDP, but the same program can be run on Linux and on iphone IOS. the reason of failure is the python code always call connect() bound a server before sendto() whether socket type is TCP or UDP.