[Bug 193246] Bug in IPv6 multicast join(), uncovered by Jenkins

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 10 Aug 2026 21:14:09 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=193246

Michael Osipov <michaelo@FreeBSD.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|michael.osipov@innomotics.c |
                   |om                          |

--- Comment #33 from Michael Osipov <michaelo@FreeBSD.org> ---
(In reply to Adrian Chadd from comment #32)

Picked this up, updated to lastest from HEAD and OpenJDK 25, three-line Java
program. I don't have any IPv6 in use beyond ::1 on lo0.

Minimalist test:
import java.net.InetAddress; import java.net.MulticastSocket;

public class Join {

        public static void main(String... args) throws Exception {
                var g = InetAddress.getAllByName("228.5.6.7"); var z = new
MulticastSocket(6790);
                z.joinGroup(g[0]);
        }
}


Then had AI to generate the dtrace code. Output was:
# dtrace -s java-sockets.d -c 'java Join'
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=11
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
Exception in thread "main" java.net.SocketException: joinGroup failed
        at
java.base/sun.nio.ch.DatagramSocketAdaptor.joinGroup(DatagramSocketAdaptor.java:423)
        at
java.base/java.net.MulticastSocket.joinGroup(MulticastSocket.java:294)
        at Join.main(Join.java:7)
Caused by: java.lang.IllegalArgumentException: IPv6 socket cannot join IPv4
multicast group
        at
java.base/sun.nio.ch.DatagramChannelImpl.innerJoin(DatagramChannelImpl.java:1505)
        at
java.base/sun.nio.ch.DatagramChannelImpl.join(DatagramChannelImpl.java:1586)
        at
java.base/sun.nio.ch.DatagramSocketAdaptor.joinGroup(DatagramSocketAdaptor.java:469)
        at
java.base/sun.nio.ch.DatagramSocketAdaptor.joinGroup(DatagramSocketAdaptor.java:420)
        ... 2 more
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=sh fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=3
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:17 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=1 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=28 type=1 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=28 type=1 proto=0
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=4 level=65535 opt=512
val=82b9faebc len=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=28 type=1 proto=6
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=5 level=6 opt=256
val=82b9fa9dc len=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=28 type=1 proto=6
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=5 level=6 opt=1024
val=82b9fa9dc len=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=28 type=1 proto=6
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=5 level=6 opt=512
val=82b9fa9dc len=4
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=5
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=28 type=2 proto=0
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=5 level=41 opt=27
val=82b9fb6b0 len=4
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=5 level=65535 opt=512
val=82b9fb680 len=4
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=5 level=65535 opt=4
val=82b9fb680 len=4
2026 Aug 10 22:49:18 setsockopt pid=51581 comm=java fd=5 level=65535 opt=32
val=82b9fb680 len=4
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=28 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6
2026 Aug 10 22:49:18 socket     pid=51581 comm=java domain=2 type=2 proto=0
2026 Aug 10 22:49:18 close      pid=51581 comm=java fd=6

based on this it wrote a sample C program which mimics Java's behavior:
# cat mcast_repro.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

static void die(const char *msg) {
    perror(msg);
    exit(1);
}

static void usage(const char *prog) {
    fprintf(stderr,
        "usage: %s 4|6 [v6only 0|1]\n"
        "  4      use PF_INET\n"
        "  6      use PF_INET6\n"
        "  v6only only meaningful with PF_INET6 (default: 1)\n",
        prog);
    exit(2);
}

static void print_errno(const char *what) {
    fprintf(stderr, "%s failed: %s (errno=%d)\n", what, strerror(errno),
errno);
}

int main(int argc, char **argv) {
    int fd;
    int family = 0;
    int on = 1;
    const char *group_str = "228.5.6.7";

    if (argc < 2 || argc > 3)
        usage(argv[0]);

    if (strcmp(argv[1], "4") == 0)
        family = PF_INET;
    else if (strcmp(argv[1], "6") == 0)
        family = PF_INET6;
    else
        usage(argv[0]);

    if (argc == 3)
        on = atoi(argv[2]) ? 1 : 0;

    printf("mode: family=%s", family == PF_INET ? "PF_INET" : "PF_INET6");
    if (family == PF_INET6)
        printf(" v6only=%d", on);
    printf("\n");

    fd = socket(family, SOCK_DGRAM, 0);
    if (fd < 0)
        die("socket");

    printf("socket() ok -> fd=%d\n", fd);

    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
        die("SO_REUSEADDR");
    printf("setsockopt(SO_REUSEADDR) ok\n");

    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
        die("SO_REUSEPORT");
    printf("setsockopt(SO_REUSEPORT) ok\n");

    if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
        die("SO_BROADCAST");
    printf("setsockopt(SO_BROADCAST) ok\n");

    if (family == PF_INET6) {
        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
            die("IPV6_V6ONLY");
        printf("setsockopt(IPV6_V6ONLY=%d) ok\n", on);
    }

    if (family == PF_INET) {
        struct sockaddr_in sa4;
        struct ip_mreq mreq4;

        memset(&sa4, 0, sizeof(sa4));
        sa4.sin_len = sizeof(sa4);
        sa4.sin_family = AF_INET;
        sa4.sin_port = htons(6790);
        sa4.sin_addr.s_addr = htonl(INADDR_ANY);

        if (bind(fd, (struct sockaddr *)&sa4, sizeof(sa4)) < 0) {
            print_errno("bind(AF_INET)");
            close(fd);
            return 1;
        }
        printf("bind(AF_INET 0.0.0.0:6790) ok\n");

        memset(&mreq4, 0, sizeof(mreq4));
        if (inet_pton(AF_INET, group_str, &mreq4.imr_multiaddr) != 1)
            die("inet_pton(AF_INET)");

        mreq4.imr_interface.s_addr = htonl(INADDR_ANY);

        printf("attempting IP_ADD_MEMBERSHIP for %s\n", group_str);
        if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq4,
sizeof(mreq4)) < 0) {
            print_errno("IP_ADD_MEMBERSHIP");
            close(fd);
            return 1;
        }

        printf("IP_ADD_MEMBERSHIP ok -> joined IPv4 multicast successfully on
PF_INET\n");
    } else {
        struct sockaddr_in6 sa6;
        struct ip_mreq mreq4;

        memset(&sa6, 0, sizeof(sa6));
        sa6.sin6_len = sizeof(sa6);
        sa6.sin6_family = AF_INET6;
        sa6.sin6_port = htons(6790);
        sa6.sin6_addr = in6addr_any;

        if (bind(fd, (struct sockaddr *)&sa6, sizeof(sa6)) < 0) {
            print_errno("bind(AF_INET6)");
            close(fd);
            return 1;
        }
        printf("bind(AF_INET6 :::6790) ok\n");

        memset(&mreq4, 0, sizeof(mreq4));
        if (inet_pton(AF_INET, group_str, &mreq4.imr_multiaddr) != 1)
            die("inet_pton(AF_INET)");

        mreq4.imr_interface.s_addr = htonl(INADDR_ANY);

        printf("attempting IP_ADD_MEMBERSHIP for %s\n", group_str);
        if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq4,
sizeof(mreq4)) < 0) {
            print_errno("IP_ADD_MEMBERSHIP");
            close(fd);
            return 1;
        }

        printf("IP_ADD_MEMBERSHIP ok -> joined IPv4 multicast successfully on
PF_INET6\n");
    }

    close(fd);
    return 0;
}

$ cc -Wall -Wextra -o mcast_repro mcast_repro.c
$ ./mcast_repro 4
mode: family=PF_INET
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
bind(AF_INET 0.0.0.0:6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP ok -> joined IPv4 multicast successfully on PF_INET
$ ./mcast_repro 6 0
mode: family=PF_INET6 v6only=0
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=0) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP failed: Invalid argument (errno=22)
$ ./mcast_repro 6 1
mode: family=PF_INET6 v6only=1
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=1) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP failed: Invalid argument (errno=22)
$ ./mcast_repro 6 0
mode: family=PF_INET6 v6only=0
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=0) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP failed: Invalid argument (errno=22)

Same program on HP-UX 11.31:
osipovmi@deblndw028v:~
$ ./mcast_repro 4
mode: family=PF_INET
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
bind(AF_INET 0.0.0.0:6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP ok -> joined IPv4 multicast successfully on PF_INET
osipovmi@deblndw028v:~
$ ./mcast_repro 6
mode: family=PF_INET6 v6only=1
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=1) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP failed: Operation not supported (errno=223)
osipovmi@deblndw028v:~
$ ./mcast_repro 6 0
mode: family=PF_INET6 v6only=0
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=0) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP failed: Operation not supported (errno=223)
osipovmi@deblndw028v:~
$ ./mcast_repro 6 1
mode: family=PF_INET6 v6only=1
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=1) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP failed: Operation not supported (errno=223)

and RHEL 8.x:
osipovmi@deblndw012x:~
$ ./mcast_repro 4
mode: family=PF_INET
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
bind(AF_INET 0.0.0.0:6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP ok -> joined IPv4 multicast successfully on PF_INET

osipovmi@deblndw012x:~
$ ./mcast_repro 6
mode: family=PF_INET6 v6only=1
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=1) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP ok -> joined IPv4 multicast successfully on PF_INET6

osipovmi@deblndw012x:~
$ ./mcast_repro 6 0
mode: family=PF_INET6 v6only=0
socket() ok -> fd=3
setsockopt(SO_REUSEADDR) ok
setsockopt(SO_REUSEPORT) ok
setsockopt(SO_BROADCAST) ok
setsockopt(IPV6_V6ONLY=0) ok
bind(AF_INET6 :::6790) ok
attempting IP_ADD_MEMBERSHIP for 228.5.6.7
IP_ADD_MEMBERSHIP ok -> joined IPv4 multicast successfully on PF_INET6


I am not an expert, let me know whether my approach is wrong and where to go
from here.

-- 
You are receiving this mail because:
You are on the CC list for the bug.