[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(usagi-users 03465) IPv6 Multicast question - connect fails
- To: usagi-users@xxxxxxxxxxxxxx
- Subject: (usagi-users 03465) IPv6 Multicast question - connect fails
- From: Bas Vermeulen <bvermeul@xxxxxxxxxxxxxxxxxxx>
- Date: Mon, 08 Aug 2005 15:58:28 +0200
- Reply-to: usagi-users@xxxxxxxxxxxxxx
- Resent-date: Tue, 9 Aug 2005 16:28:11 +0900
- Resent-from: sekiya@xxxxxxxxxxxxxx
- Resent-message-id: <200508091628.FMLAAB16658.usagi-users@linux-ipv6.org>
- Resent-to: usagi-users@xxxxxxxxxxxxxx (moderated)
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 <bvermeul@xxxxxxxxxxxxxxxxxxx>
#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;
}