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");
  }
}

      

+3


source to share





All Articles