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

Missing support for Source Specific Multicast #89415

Closed
ciresnave mannequin opened this issue Sep 21, 2021 · 11 comments
Closed

Missing support for Source Specific Multicast #89415

ciresnave mannequin opened this issue Sep 21, 2021 · 11 comments
Assignees
Labels
3.12 bugs and security fixes easy extension-modules C modules in the Modules dir stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@ciresnave
Copy link
Mannequin

ciresnave mannequin commented Sep 21, 2021

BPO 45252
Nosy @ciresnave

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2021-09-21.00:26:04.617>
labels = ['type-feature', 'library', '3.11']
title = 'Missing support for Source Specific Multicast'
updated_at = <Date 2021-09-24.23:41:45.383>
user = 'https://github.com/ciresnave'

bugs.python.org fields:

activity = <Date 2021-09-24.23:41:45.383>
actor = 'terry.reedy'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2021-09-21.00:26:04.617>
creator = 'ciresnave'
dependencies = []
files = []
hgrepos = []
issue_num = 45252
keywords = []
message_count = 1.0
messages = ['402283']
nosy_count = 1.0
nosy_names = ['ciresnave']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue45252'
versions = ['Python 3.11']

Linked PRs

@ciresnave
Copy link
Mannequin Author

ciresnave mannequin commented Sep 21, 2021

It appears that Python's socket module is missing support for the IGMPv3 socket options needed to support Source Specific Multicast. Many developers appear to be adding the necessary constants through something like:

if not hasattr(socket, "IP_UNBLOCK_SOURCE"):
    setattr(socket, "IP_UNBLOCK_SOURCE", 37)
if not hasattr(socket, "IP_BLOCK_SOURCE"):
    setattr(socket, "IP_BLOCK_SOURCE", 38)
if not hasattr(socket, "IP_ADD_SOURCE_MEMBERSHIP"):
    setattr(socket, "IP_ADD_SOURCE_MEMBERSHIP", 39)
if not hasattr(socket, "IP_DROP_SOURCE_MEMBERSHIP"):
    setattr(socket, "IP_DROP_SOURCE_MEMBERSHIP", 40)

...but it would be nice if these were added to the official module as they are supported under current versions of Windows, Linux, and BSD at the least.

@ciresnave ciresnave mannequin added 3.7 (EOL) end of life 3.8 (EOL) end of life 3.9 only security fixes 3.10 only security fixes 3.11 only security fixes stdlib Python modules in the Lib dir type-feature A feature request or enhancement labels Sep 21, 2021
@terryjreedy terryjreedy removed 3.7 (EOL) end of life 3.8 (EOL) end of life 3.9 only security fixes 3.10 only security fixes labels Sep 24, 2021
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@multiplemonomials
Copy link

Note that the code posted there is not correct for Windows, where the constant values are different. I think a more correct version would be something like:

if platform.system().lower().startswith('win'):
    if not hasattr(socket, "IP_UNBLOCK_SOURCE"):
        setattr(socket, "IP_UNBLOCK_SOURCE", 18)
    if not hasattr(socket, "IP_BLOCK_SOURCE"):
        setattr(socket, "IP_BLOCK_SOURCE", 17)
    if not hasattr(socket, "IP_ADD_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_ADD_SOURCE_MEMBERSHIP", 15)
    if not hasattr(socket, "IP_DROP_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_DROP_SOURCE_MEMBERSHIP", 16)
else:
    if not hasattr(socket, "IP_UNBLOCK_SOURCE"):
        setattr(socket, "IP_UNBLOCK_SOURCE", 37)
    if not hasattr(socket, "IP_BLOCK_SOURCE"):
        setattr(socket, "IP_BLOCK_SOURCE", 38)
    if not hasattr(socket, "IP_ADD_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_ADD_SOURCE_MEMBERSHIP", 39)
    if not hasattr(socket, "IP_DROP_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_DROP_SOURCE_MEMBERSHIP", 40)

@danrossi
Copy link

I've been trying to figure out SSM suipport. confirm the flags on windows was causing errors. I've got passed this with the flag change. However the minimal code examples out there any attempt to use "SOL_IP" causes invalid argument.

Is this the correct method for SSM ? 0.0.0.0 works for asm not sure for ssm yet.

multicast_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)

multicast_socket.bind(("0.0.0.0", multicast_port))

mreq=struct.pack("=4s4s4s", 
                 socket.inet_aton(multicast_group), 
                 socket.inet_aton(source_address), 
                 socket.inet_aton(iface))
 multicast_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_SOURCE_MEMBERSHIP, mreq)

@arhadthedev
Copy link
Member

@gpshead (as listed in the socket experts list) Any ideas if @multiplemonomials's snippet can be reliably used?

@danrossi
Copy link

Yes I just tested it in windows and those flags needed to change. For SSM multicast in windows the bind address needs to be '' also but for asm "0.0.0.0" seems ok. Ive yet to check on the network with the cisco router if I get data yet.

multicast_socket.bind(('', multicast_port))

@gpshead gpshead added 3.12 bugs and security fixes and removed 3.11 only security fixes labels Jul 29, 2022
@gpshead
Copy link
Member

gpshead commented Jul 29, 2022

You need to look in the header files on your target platforms to determine if the snippet above adding the constants works. Regardless, this issue really is pretty much about plumbing. When these constants are defined we should expose them in the socket module. Much like we already do for many others. That'd obviate the need for hacks like the above.

@gpshead gpshead added extension-modules C modules in the Modules dir easy labels Jul 29, 2022
@gpshead
Copy link
Member

gpshead commented Jul 29, 2022

For anyone who wants to contribute a PR, it should pretty much just be adding stuff like you see in https://github.com/python/cpython/blob/main/Modules/socketmodule.c#L8104 with ifdef and PyModule_AddIntMacro.

@danrossi
Copy link

That is what I figured it needs to match the constant flags on the OS. For darwin it says 70. So mac needs something different ?

https://github.com/apple/darwin-xnu/blob/8f02f2a044b9bb1ad951987ef5bab20ec9486310/bsd/netinet/in.h

@danrossi
Copy link

I found a header for win 10 SDK. It says 15.

https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/ws2ipdef.h

@danrossi
Copy link

I'm sorry to ask if getting the right flags setup. Is socket.IPPROTO_IP the correct way to setup SSM because the old examples out there using socket.SOL_IP cause endless "invalid argument" errors. The struct packing is similar to the windows docs. Needs to join the group, source ip, then local ip

@danrossi
Copy link

Here is a patch for windows and macOS I've come up with. Will eventually test on macOS but Windows first.

platform = platform.system()
if (platform == "Windows"):
    if not hasattr(socket, "IP_UNBLOCK_SOURCE"):
        setattr(socket, "IP_UNBLOCK_SOURCE", 18)
    if not hasattr(socket, "IP_BLOCK_SOURCE"):
        setattr(socket, "IP_BLOCK_SOURCE", 17)
    if not hasattr(socket, "IP_ADD_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_ADD_SOURCE_MEMBERSHIP", 15)
    if not hasattr(socket, "IP_DROP_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_DROP_SOURCE_MEMBERSHIP", 16)
elif (platform == 'Darwin'):
    if not hasattr(socket, "IP_UNBLOCK_SOURCE"):
        setattr(socket, "IP_UNBLOCK_SOURCE", 73)
    if not hasattr(socket, "IP_BLOCK_SOURCE"):
        setattr(socket, "IP_BLOCK_SOURCE", 72)
    if not hasattr(socket, "IP_ADD_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_ADD_SOURCE_MEMBERSHIP", 70)
    if not hasattr(socket, "IP_DROP_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_DROP_SOURCE_MEMBERSHIP", 71)
else:
    if not hasattr(socket, "IP_UNBLOCK_SOURCE"):
        setattr(socket, "IP_UNBLOCK_SOURCE", 37)
    if not hasattr(socket, "IP_BLOCK_SOURCE"):
        setattr(socket, "IP_BLOCK_SOURCE", 38)
    if not hasattr(socket, "IP_ADD_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_ADD_SOURCE_MEMBERSHIP", 39)
    if not hasattr(socket, "IP_DROP_SOURCE_MEMBERSHIP"):
        setattr(socket, "IP_DROP_SOURCE_MEMBERSHIP", 40)

rmehyde added a commit to rmehyde/cpython that referenced this issue Apr 22, 2023
@gpshead gpshead self-assigned this Apr 27, 2023
gpshead pushed a commit that referenced this issue Apr 27, 2023
…103684)

Add socket options for source-specific multicast when present as C #defines.

Co-authored-by: Oleg Iarygin <dralife@yandex.ru>
@gpshead gpshead closed this as completed Apr 27, 2023
marmarek added a commit to marmarek/cpython that referenced this issue Apr 27, 2023
marmarek added a commit to marmarek/cpython that referenced this issue Apr 27, 2023
marmarek added a commit to marmarek/cpython that referenced this issue Apr 27, 2023
sobolevn added a commit to sobolevn/cpython that referenced this issue Jun 3, 2023
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Jun 3, 2023
…e docs (pythonGH-105266)

(cherry picked from commit eaff9c3)

Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
gpshead pushed a commit that referenced this issue Jun 3, 2023
…he docs (GH-105266) (#105270)

gh-89415: Mention new `IP_*` constants in `socket` module in the docs (GH-105266)
(cherry picked from commit eaff9c3)

Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes easy extension-modules C modules in the Modules dir stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

5 participants