Hello enodev,
How do you create/bind the socket?
We use low level system calls, the udp4 socket creation/bind looks something like:
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("Failed to open socket: %d\n", errno);
return -1;
}
SOCKETADDRESS sa;
memset((char *)&sa, 0, sizeof(SOCKETADDRESS));
sa.sa4.sin_family = AF_INET;
sa.sa4.sin_port = 0;
sa.sa4.sin_addr.s_addr = htonl(0x0); // bind to wildcard
socklen_t len = sizeof(sa.sa4);
int res;
res = bind(fd, &sa.sa, len);
if (res < 0) {
printf("Failed to bind: %d\n", errno);
return -2;
}
and the udp46 socket creation/bind looks similar except for the additional setsockopt call which we do to disable IPv6_ONLY on that socket:
int fd;
fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd < 0) {
printf("Failed to open socket: %d\n", errno);
return -1;
}
// mark it as dual socket
int ipv6_only = 0; // dual socket
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6_only, sizeof(int)) < 0) {
return -2;
}
SOCKETADDRESS sa;
memset((char *)&sa, 0, sizeof(SOCKETADDRESS));
sa.sa6.sin6_family = AF_INET6;
sa.sa6.sin6_port = 0;
char caddr[16];
memset((char *)caddr, 0, 16); // wildcard
memcpy((void *)&sa.sa6.sin6_addr, caddr, sizeof(struct in6_addr));
socklen_t len = sizeof(sa.sa6);
int res;
res = bind(fd, &sa.sa, len);
if (res < 0) {
printf("Failed to bind: %d\n", errno);
return -3;
}
Both sockets above are owned by PID 89318, what PID is that?
Please ignore that process id. As I noted in the original description this process id is the reproducer code that we ran to reproduce this issue. So in this case, the reproducer first creates a udp4 socket and binds it to an ephemeral port (and lets it stay bound till the program exits) and then creates udp46 socket and binds it to an ephemeral port. Occasionally (but consistently), this programs ends up with the already in-use port being assigned to the udp46 socket bind call. So in this case, the process ids are the same but in reality (and in production), the processes are different and unrelated (for example: we have noticed that one of our program when it binds a udp46 socket with ephemeral port, it gets assigned the port which is already in use by the system's syslogd process which has it bound to udp4)