Open MihaelBercic opened 6 months ago
https://stackoverflow.com/questions/65534342/receiving-udp-multicast-on-macos-big-sur suggests that the firewall blocks receiving multicast packets unless "Block all incoming connections" and "stealth mode" are disabled. From a quick search more people seem to be having problems with multicast support on macOS in general. Not just with rust.
https://stackoverflow.com/questions/65534342/receiving-udp-multicast-on-macos-big-sur suggests that the firewall blocks receiving multicast packets unless "Block all incoming connections" and "stealth mode" are disabled. From a quick search more people seem to be having problems with multicast support on macOS in general. Not just with rust.
Hello, thank you for the reply. I have both disabled but still unable to receive any multicast packets.
In JVM (Kotlin and Java), I was able to receive multicast packets just fine.
Is the java executable signed? If so "Automatically allow downloaded signed software to receive incoming connections" would apply to it, unlike rustc compiled executables, which you probably need to allowlist manually.
Is the java executable signed? If so "Automatically allow downloaded signed software to receive incoming connections" would apply to it, unlike rustc compiled executables, which you probably need to allowlist manually.
But if that'd be the case, after disabling the firewall I would be able to receive the packets right? However even if disabling the firewall, nothing changes.
Yeah, it should. Can you check if a C program is able to receive UDP multicast packets as sanity check?
Yeah, it should. Can you check if a C program is able to receive UDP multicast packets as sanity check?
I will give it my best. I'm not that familiar with C but once i have it written I'll reply to this issue.
Yeah, it should. Can you check if a C program is able to receive UDP multicast packets as sanity check?
https://gist.github.com/MihaelBercic/557a0386b45e5e912ff493725dfff1f2
This code doesn't work either, can you check if it's the code issue or is it actually not working.
I don't see anything obviously bad with it, but I'm not all that familiar with the socket api either. In any case for me on linux running that program seems to work as expected when I use iperf to send it multicast packets.
I don't see anything obviously bad with it, but I'm not all that familiar with the socket api either. In any case for me on linux running that program seems to work as expected when I use iperf to send it multicast packets.
Does the code also catch packets that are not sent by yourself? Such as tvs, spotify mdns queries and such?
I looked in wireshark for any multicast packets that are sent my direction by other devices at home, but the only ones I could find were not udp multicast packets and thus wouldn't get caught by this test program.
Just to add some color to this ticket, here's my program:
the python counterpart works just fine: https://github.com/security-union/rust-projects-to-inspire-you/blob/master/control-accelerometer/server.py
My firewall is off.
same code works flawlessly on Debian
EDIT: this is almost certainly unrelated as it was due to lo0
not having 127.0.0.1
as an alias for that interface on my machine. Although adding that alias via sudo ifconfig lo0 alias 127.0.0.1
"fixes" the below code, it does not fix the code posted by @MihaelBercic above.
I am running into this as well on macOS. Here is a simple repro:
$ cat > example.rs
use std::net::TcpListener;
fn main() {
let _ = TcpListener::bind("127.0.0.1:0").unwrap();
}
$ rustc example.rs && ./example
thread 'main' panicked at example.rs:4:44:
called `Result::unwrap()` on an `Err` value: Os { code: 49, kind: AddrNotAvailable, message: "Can't assign requested address" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Nightly has the same bug:
$ rustc --version
rustc 1.80.0-nightly (78a775127 2024-05-11)
$ rustc example.rs && ./example
thread 'main' panicked at example.rs:4:44:
called `Result::unwrap()` on an `Err` value: Os { code: 49, kind: AddrNotAvailable, message: "Can't assign requested address" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
% uname -a
Darwin ok.localdomain 23.4.0 Darwin Kernel Version 23.4.0: Wed Feb 21 21:44:54 PST 2024; root:xnu-10063.101.15~2/RELEASE_ARM64_T6031 arm64
% rustc --version
rustc 1.78.0 (9b00956e5 2024-04-29)
EDIT: disregard, please see https://github.com/rust-lang/rust/issues/123715#issuecomment-2106082837
Ugh. This is probably a macOS thing:
$ cat ok.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int sockfd;
struct sockaddr_in server_addr;
socklen_t addr_len = sizeof(server_addr);
// Create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// Bind to 127.0.0.1:0
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
server_addr.sin_port = 0; // Let the OS choose the port
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
// Get the chosen port
if (getsockname(sockfd, (struct sockaddr *)&server_addr, &addr_len) < 0) {
perror("Getsockname failed");
exit(EXIT_FAILURE);
}
// Print the chosen port
printf("Chosen port: %d\n", ntohs(server_addr.sin_port));
return 0;
}
$ clang ok.c -o ok && ./ok
Bind failed: Can't assign requested address
That said, this code works on macOS, so there is something interesting that Python is doing that seems to allow for things to "just work": python3 -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'
@abhillman
The python example is not equivalent to others; an empty string implies binding to any interface (INADDR_ANY
).
EDIT: likely unrelated, see https://github.com/rust-lang/rust/issues/123715#issuecomment-2106082837
@abhillman
The python example is not equivalent to others; an empty string implies binding to any interface (
INADDR_ANY
).
Thanks for the reminder. Indeed. And the C code above does work if we change to INADDR_ANY
.
So far tested on:
The following code
produces the following error:
It is expected for the socket to join the group (in documentation it also says setting interface to 0 allows for the OS to decide on the interface).
However instead of that, on macOS the above error happens. On windows however, it does not and works as expected.
Meta
rustc --version --verbose
: