IPv6 multicast sendto() 'operation not supported'
Donald McLachlan
don at mainframe.dgrc.crc.ca
Thu Feb 26 08:27:47 PST 2004
Hello,
[ I'm new to freebsd. This seems like the most related mailing list.
If there is a better mailing list I should post to, please point me
in the right direction. ]
In preparation for writing an IPv6 multicast application I wrote a little
test program (shown below). This program worked on linux (RedHat), but
when I try it on a FreeBSD box (5.0, running zebra router and pim6dd)
sendto() fails with "Operation not supported" ... ???
To verify my app was OK, I installed a solaris box on the LAN beside the
linux box and the app compiled and worked fine.
Thinking it might be a bug in 5.0 or an interaction with zebra/pim6dd I
installed a FreeBSD 5.2 box on the lan beside the other 2 app boxes and
I get the same error again. Anyone know what is missing/wrong in my test app?
[ I'm guessing FreeBSD wants some extra socket options set, but I don't know
which ones. ]
Thanks,
Don
/*
mcast6.c
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <net/if.h>
extern int errno;
void start_sender(int sock, struct sockaddr_in6 *sin);
void start_listener(int sock);
int main(int argc, char *argv[])
{
int sock, hops;
unsigned int ifindex;
struct sockaddr_in6 sin;
struct ipv6_mreq mreq;
char ifname[IF_NAMESIZE];
static unsigned char the_addr[16];
inet_pton(AF_INET6, "ff05::abcd", the_addr);
if ((sock=socket(AF_INET6, SOCK_DGRAM, 0)) < 0) /* connect to socket */
{
perror("socket");
exit(3);
}
bzero((char *)&sin, (int)sizeof(sin)); /* setup address info */
bcopy(the_addr, (char *)&sin.sin6_addr, sizeof(the_addr));
sin.sin6_family = AF_INET6;
sin.sin6_port = htons(3000);
/* bind addr to sock */
if(bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("bind");
exit(errno);
}
hops = 255;
if(setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0)
{
perror("setsockopt(IPV6_MULTICAST_HOPS)");
exit(errno);
}
ifindex = 0;
#ifdef ORIG
strcpy(ifname, "xl1");
ifindex = if_nametoindex(ifname);
if(ifindex == 0)
{
perror("if_nametoindex()");
exit(errno);
}
if(setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
{
perror("setsockopt(IPV6_MULTICAST_IF)");
exit(errno);
}
#endif
/* setup group info */
bcopy(the_addr, (char *)&mreq.ipv6mr_multiaddr, sizeof(the_addr));
mreq.ipv6mr_interface = ifindex; /* and I/F index */
/* join group */
if(setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq, sizeof(mreq)) < 0)
{
perror("setsockopt(IPV6_JOIN_GROUP)");
exit(21);
}
start_sender(sock, &sin);
start_listener(sock);
while(wait((int *)0) != -1); /* wait for all children to die */
return(0);
}
void start_sender(int sock, struct sockaddr_in6 *sin)
{
char bitbucket[2000];
pid_t pid;
pid = fork();
switch(pid)
{
case 0: /* child */
while(1)
{ /* TX mcast PDU */
strcpy(bitbucket, "How now brown cow?");
if(sendto(sock, bitbucket, strlen(bitbucket)+1, 0, (struct sockaddr *)sin, sizeof(*sin)) < 0)
{
perror("sendto(sender)");
exit(23);
}
sleep(10);
}
break;
case -1: /* parent fork failed */
printf("fork(sender): failed\n");
fflush(stdout);
break;
default: /* parent fork passed */
printf("sender PID = %d\n", (int)pid);
fflush(stdout);
break;
}
}
void start_listener(int sock)
{
pid_t pid;
unsigned int fromlen;
struct sockaddr_in6 from;
char bitbucket[2000], addrstr[INET6_ADDRSTRLEN];
pid = fork();
switch(pid)
{
case 0: /* child */
while(1)
{
bitbucket[0] = '\0';
fromlen = sizeof(from);
if(recvfrom(sock, bitbucket, sizeof(bitbucket),
0, (struct sockaddr *)&from,
&fromlen) < 0)
{
perror("listener: recvfrom()");
exit(21);
}
inet_ntop(AF_INET6, &from.sin6_addr, addrstr,
sizeof(addrstr));
printf("< %s : \"%s\"\n", addrstr, bitbucket);
fflush(stdout);
}
break;
case -1: /* parent fork failed */
printf("fork(listerner): failed\n");
fflush(stdout);
break;
default: /* parent fork passed */
printf("listener PID = %d\n", (int)pid);
fflush(stdout);
break;
}
}
More information about the freebsd-net
mailing list