(usagi-users 03465) IPv6 Multicast question - connect fails

Bas Vermeulen <[email protected]>
Newsgroups gmane.linux.ipv6.usagi.users
Message-ID <[email protected]>
Hi,

I've got some code that does the following:

Takes an IPv6 multicast address, and opens an UDP socket with
socket(). It then sets the SO_REUSABLE sockopt, and binds the socket to
in6addr_any and port 5060. I then connect() to the IPv6 multicast
address (FF35::d:d44).

This works when the default interface has a global IPv6 address, but
fails with a site-local (FEC0::1) or link-local (FE80::1) address.

Does anyone know why, and where I can find more information on this
behaviour? I've included my test program. Any comments are welcome.

Thanks in advance,

-- 
Bas Vermeulen <[email protected]>
socket_test.c (text/x-csrc, 1.8 KB)
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char **argv)
{
	struct in6_addr addr6;
	char* interface;
	int err = 0;
	printf("Trying to connect to %s: ", argv[1]);
	if ((interface = strchr(argv[1], '%')) != NULL)
	{
		*interface = '\0';
		interface++;
	}

	if (inet_pton(AF_INET6, argv[1], &addr6) == 1)
	{
		int s, i = 1, ttl = 16;
		struct sockaddr_in6 my_addr;
		struct sockaddr_in6 dest_addr;
		struct ipv6_mreq mreq;

		if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) { err = 1; goto done; }
		if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) { close(s); err = 2; goto done; }
		memset(&my_addr, 0, sizeof(my_addr));
		my_addr.sin6_family = AF_INET6;
		memcpy(&my_addr.sin6_addr, &in6addr_any, sizeof(my_addr.sin6_addr));
		my_addr.sin6_port = htons(0);
		if (bind(s, &my_addr, sizeof(my_addr)) < 0) { close(s); err = 3; goto done; }

		memset(&dest_addr, 0, sizeof(dest_addr));
		dest_addr.sin6_family = AF_INET6;
		memcpy(&dest_addr.sin6_addr, &addr6, sizeof(dest_addr.sin6_addr));
		dest_addr.sin6_port = htons(5060);
		if (interface)
			dest_addr.sin6_scope_id = if_nametoindex(interface);
		if (connect(s, &dest_addr, sizeof(dest_addr)) < 0) { close(s); err = 4; goto done; }
		setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
		printf("success.\n");
		return 0;
	}
done:
	switch (err)
	{
	case 0: printf("failed - not an IPv6 address.\n"); break;
	case 1: printf("failed - socket() - %s.\n", strerror(errno)); break;
	case 2: printf("failed - setsockopt(SO_REUSEADDR) - %s.\n", strerror(errno)); break;
	case 3: printf("failed - bind() - %s.\n", strerror(errno)); break;
	case 4: printf("failed - connect() - %s.\n", strerror(errno)); break;
	case 5: printf("failed - setsockopt(JOIN_GROUP) - %s.\n", strerror(errno)); break;
	}
	return 0;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.