Why does the UDP connection ignore the multicast loopback route, but sendto works without a connection?
I have set up a UDP socket with the same remote address in the multicast range. One sends 224.2.0.6:6666, the other sends 224.2.0.7:6666. I rely on the Linux routing table to determine which interface to send packets to.
In both cases, I configured the socket at the start, installed my sockopts, and done sendto()
. I am not setting specific IP_MULTICAST_IF
.
However, in the first case, I also do a connect()
before the first sendto()
.
In the case of the connect()
OS, it ignores the loopback route and sends all packets through the default route and interface.
In the non-case, the connect()
OS respects the loopback route and all packets are sent through the loopback interface.
Why socket()
- connect()
- sendto()
with route through lo
makes the OS ignore it, but simply socket()
- sendto()
with route through is lo
routed correctly?
My ip route
:
224.2.0.0/16 via 127.0.0.1 dev lo
default via 172.16.5.1 dev eth0
Note that this problem only exists if the route is associated with a loopback interface. If I set the route through "real" interface - the actual, macvlan, dummy, either - then both connect()
and sendto()
will equally apply to the route and to operate normally.
UPDATE:
Original code. The formatting got messed up as it was a code edit by another user trying to manually clean up, sorry for the mess:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>
int fd, fd2;
struct in_addr interface_addr;
int addr_size;
int optval = 1, recv_len = 4;
char *remote_ip = "224.2.0.6", *remote_ip2 = "224.2.0.7";
char *remote_port = "6666";
char *buf = "conn", *buf2 = "send";
struct addrinfo *remote_address_info, *remote_address_info2;
int main() {
// create first and second socket
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket() failed");
}
if ((fd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket2() failed");
}
// set socket options on both
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) < 0) {
perror("setsockopt(SO_REUSEADDR) failed");
}
if (setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) < 0) {
perror("setsockopt2(SO_REUSEADDR) failed");
}
addr_size = sizeof(interface_addr);
// structure the addr
if (getaddrinfo(remote_ip, remote_port, NULL, &remote_address_info) != 0) {
perror("getaddrinfo(remote_ip) failed");
}
if (getaddrinfo(remote_ip2, remote_port, NULL, &remote_address_info2) != 0) {
perror("getaddrinfo2(remote_ip) failed");
}
// connect ON FIRST SOCKET ONLY
if (connect(fd, remote_address_info->ai_addr, remote_address_info->ai_addrlen) != 0) {
perror("connect() failed");
}
// sendto first and second
// same result if use send() or sendto() on first socket
if (sendto(fd, buf, recv_len, 0, remote_address_info->ai_addr, remote_address_info->ai_addrlen) == -1) {
perror("sendto() failed");
}
if (sendto(fd2, buf2, recv_len, 0, remote_address_info2->ai_addr, remote_address_info2->ai_addrlen) == -1) {
perror("sendto2() failed");
}
}
source to share
No one has answered this question yet
See similar questions:
or similar: