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