Page MenuHomeFreeBSD

socket: Restore handling of IPPROTO_DIVERT
ClosedPublic

Authored by markj on Wed, Aug 19, 10:02 PM.
Tags
None
Referenced Files
F168262800: D59018.id184535.diff
Thu, Aug 27, 6:23 AM
F168222627: D59018.id184411.diff
Thu, Aug 27, 12:27 AM
F168219083: D59018.diff
Wed, Aug 26, 11:48 PM
Unknown Object (File)
Wed, Aug 26, 9:09 AM
Unknown Object (File)
Wed, Aug 26, 1:37 AM
Unknown Object (File)
Tue, Aug 25, 10:45 AM
Unknown Object (File)
Mon, Aug 24, 10:01 PM
Unknown Object (File)
Mon, Aug 24, 9:05 PM
Subscribers

Details

Summary

Python scripts which use divert sockets no longer work after commit
e967a2a03677; even if one patches socket() calls, getaddrlen() doesn't
work on divert sockets, needed to use recvfrom().

Restore compatibility when COMPAT_FREEBSD15 is defined.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

sys/netinet/in.h
256

Define __IPPROTO_DIVERT and use it instead of raw 258 in the compat block?

markj marked an inline comment as done.

Add a define

This revision is now accepted and ready to land.Thu, Aug 20, 1:05 PM

Do we need this just for old binaries or all binaries?

In D59018#1356062, @imp wrote:

Do we need this just for old binaries or all binaries?

All binaries. As I tried to explain on the lists a while back, a python script like:

with socket.socket(socket.AF_INET, socket.SOCK_RAW, IPPROTO_DIVERT) as fd:
    fd.bind(('0.0.0.0', 8000))
    r = fd.recvfrom(8192)
    ...
    fd.sendto(r[0], r[1])

does not work properly without this change. Changing the socket domain to PF_DIVERT does not fix the problem, because python does not know which sockaddr to use for recvfrom in that case.

This revision was automatically updated to reflect the committed changes.
In D59018#1356062, @imp wrote:

Do we need this just for old binaries or all binaries?

All binaries. As I tried to explain on the lists a while back, a python script like:

with socket.socket(socket.AF_INET, socket.SOCK_RAW, IPPROTO_DIVERT) as fd:
    fd.bind(('0.0.0.0', 8000))
    r = fd.recvfrom(8192)
    ...
    fd.sendto(r[0], r[1])

does not work properly without this change. Changing the socket domain to PF_DIVERT does not fix the problem, because python does not know which sockaddr to use for recvfrom in that case.

So this is more of an API justification than an ABI justification and is a bit of departure from how we've done compat in the past beyond system call availability. Usually for old behavior, we check the binary's API against some version on the old behavior and the new on newer.

I do understand that pyhton scripts don't follow this pattern, but I worry that it opens up the doors to situations I thought we were trying to avoid where the behavior is conditional on the #ifdef. Now every kernel needs this to behave properly it seems, and that seems undesireable. It may make sense here, but I don't want it to set a wider precident.

All binaries. As I tried to explain on the lists a while back, a python script like:

with socket.socket(socket.AF_INET, socket.SOCK_RAW, IPPROTO_DIVERT) as fd:
    fd.bind(('0.0.0.0', 8000))
    r = fd.recvfrom(8192)
    ...
    fd.sendto(r[0], r[1])

does not work properly without this change. Changing the socket domain to PF_DIVERT does not fix the problem, because python does not know which sockaddr to use for recvfrom in that case.

The sockaddr handling was fixed in python 3.13. See https://github.com/python/cpython/pull/142993 Python is very slow with processing submissions. And then our ports are very slow at switching python version. Thus the lag.

So this change added extra checks for every socket(2) syscall just for the sake of old python programs that aren't willing to adopt to PF_DIVERT.