FreeBSD/tools/regression/netinet/ipmulticast/ipmulticast.c
/*
 * Test the IPv4 ASM API.
 * Repeatedly join, block sources, unblock and leave groups.
 */
Test the IPv4 ASM API.
Repeatedly join, block sources, unblock and leave groups.
Test the IPv4 ASM API . Repeatedly join block sources unblock and leave groups .
static int
do_asm_ipv4(void)
{
	int			 error;
	char			 gaddrbuf[ADDRBUF_LEN];
	int			 i;
	sockunion_t		 laddr;
	struct ip_mreq		 mreq;
	struct ip_mreq_source	 mreqs;
	in_addr_t		 ngroupbase;
	char			 saddrbuf[ADDRBUF_LEN];
	int			 sock;
	sockunion_t		 tmpgroup;
	sockunion_t		 tmpsource;
	memset(&mreq, 0, sizeof(struct ip_mreq));
	memset(&mreqs, 0, sizeof(struct ip_mreq_source));
	memset(&laddr, 0, sizeof(sockunion_t));
	if (dobindaddr) {
		laddr = ifaddr;
	} else {
		laddr.sin.sin_family = AF_INET;
		laddr.sin.sin_len = sizeof(struct sockaddr_in);
		laddr.sin.sin_addr.s_addr = INADDR_ANY;
	}
	laddr.sin.sin_port = htons(portno);
	tmpgroup = basegroup;
	ngroupbase = ntohl(basegroup.sin.sin_addr.s_addr) + 1;	
	tmpgroup.sin.sin_addr.s_addr = htonl(ngroupbase);
	sock = open_and_bind_socket(&laddr);
	if (sock == -1)
		return (EX_OSERR);
	for (i = 0; i < (signed)nmcastgroups; i++) {
		mreq.imr_multiaddr.s_addr = htonl((ngroupbase + i));
		mreq.imr_interface = ifaddr.sin.sin_addr;
		if (doverbose) {
			inet_ntop(AF_INET, &mreq.imr_multiaddr, gaddrbuf,
			    sizeof(gaddrbuf));
			fprintf(stderr, "IP_ADD_MEMBERSHIP %s %s\n",
			    gaddrbuf, inet_ntoa(mreq.imr_interface));
		}
		error = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
		    &mreq, sizeof(struct ip_mreq));
		if (error < 0) {
			warn("setsockopt IP_ADD_MEMBERSHIP");
			close(sock);
			return (EX_OSERR);
		}
	}
	if (nmcastsources == 0)
		goto skipsources;
	for (i = 0; i < (signed)nmcastsources; i++) {
		mreqs.imr_multiaddr = tmpgroup.sin.sin_addr;
		mreqs.imr_interface = ifaddr.sin.sin_addr;
		mreqs.imr_sourceaddr = ipv4_sources[i];
		if (doverbose) {
			inet_ntop(AF_INET, &mreqs.imr_multiaddr, gaddrbuf,
			    sizeof(gaddrbuf));
			inet_ntop(AF_INET, &mreqs.imr_sourceaddr, saddrbuf,
			    sizeof(saddrbuf));
			fprintf(stderr, "IP_BLOCK_SOURCE %s %s %s\n",
			    gaddrbuf, inet_ntoa(mreqs.imr_interface),
			    saddrbuf);
		}
		error = setsockopt(sock, IPPROTO_IP, IP_BLOCK_SOURCE, &mreqs,
		    sizeof(struct ip_mreq_source));
		if (error < 0) {
			warn("setsockopt IP_BLOCK_SOURCE");
			close(sock);
			return (EX_OSERR);
		}
	}
	memset(&tmpsource, 0, sizeof(sockunion_t));
	tmpsource.sin.sin_family = AF_INET;
	tmpsource.sin.sin_len = sizeof(struct sockaddr_in);
	tmpsource.sin.sin_addr = ipv4_sources[0];
	error = recv_loop_with_match(sock, &tmpgroup, &tmpsource);
	for (i = nmcastsources-1; i >= 0; i--) {
		mreqs.imr_multiaddr = tmpgroup.sin.sin_addr;
		mreqs.imr_interface = ifaddr.sin.sin_addr;
		mreqs.imr_sourceaddr = ipv4_sources[i];
		if (doverbose) {
			inet_ntop(AF_INET, &mreqs.imr_multiaddr, gaddrbuf,
			    sizeof(gaddrbuf));
			inet_ntop(AF_INET, &mreqs.imr_sourceaddr, saddrbuf,
			    sizeof(saddrbuf));
			fprintf(stderr, "IP_UNBLOCK_SOURCE %s %s %s\n",
			    gaddrbuf, inet_ntoa(mreqs.imr_interface),
			    saddrbuf);
		}
		error = setsockopt(sock, IPPROTO_IP, IP_UNBLOCK_SOURCE, &mreqs,
		    sizeof(struct ip_mreq_source));
		if (error < 0) {
			warn("setsockopt IP_UNBLOCK_SOURCE");
			close(sock);
			return (EX_OSERR);
		}
	}
skipsources:
	for (i = nmcastgroups-1; i >= 0; i--) {
		mreq.imr_multiaddr.s_addr = htonl((ngroupbase + i));
		mreq.imr_interface = ifaddr.sin.sin_addr;
		if (doverbose) {
			inet_ntop(AF_INET, &mreq.imr_multiaddr, gaddrbuf,
			    sizeof(gaddrbuf));
			fprintf(stderr, "IP_DROP_MEMBERSHIP %s %s\n",
			    gaddrbuf, inet_ntoa(mreq.imr_interface));
		}
		error = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
		    &mreq, sizeof(struct ip_mreq));
		if (error < 0) {
			warn("setsockopt IP_DROP_MEMBERSHIP");
			close(sock);
			return (EX_OSERR);
		}
	}
	return (0);
}
static int do_asm_ipv4 ( void ) { int error ; char gaddrbuf [ ADDRBUF_LEN ] ; int i ; sockunion_t laddr ; struct ip_mreq mreq ; struct ip_mreq_source mreqs ; in_addr_t ngroupbase ; char saddrbuf [ ADDRBUF_LEN ] ; int sock ; sockunion_t tmpgroup ; sockunion_t tmpsource ; memset ( & mreq , 0 , sizeof ( struct ip_mreq ) ) ; memset ( & mreqs , 0 , sizeof ( struct ip_mreq_source ) ) ; memset ( & laddr , 0 , sizeof ( sockunion_t ) ) ; if ( dobindaddr ) { laddr = ifaddr ; } else { laddr . sin . sin_family = AF_INET ; laddr . sin . sin_len = sizeof ( struct sockaddr_in ) ; laddr . sin . sin_addr . s_addr = INADDR_ANY ; } laddr . sin . sin_port = htons ( portno ) ; tmpgroup = basegroup ; ngroupbase = ntohl ( basegroup . sin . sin_addr . s_addr ) + 1 ; tmpgroup . sin . sin_addr . s_addr = htonl ( ngroupbase ) ; sock = open_and_bind_socket ( & laddr ) ; if ( sock == -1 ) return ( EX_OSERR ) ; for ( i = 0 ; i < ( signed ) nmcastgroups ; i ++ ) { mreq . imr_multiaddr . s_addr = htonl ( ( ngroupbase + i ) ) ; mreq . imr_interface = ifaddr . sin . sin_addr ; if ( doverbose ) { inet_ntop ( AF_INET , & mreq . imr_multiaddr , gaddrbuf , sizeof ( gaddrbuf ) ) ; fprintf ( stderr , " \n " , gaddrbuf , inet_ntoa ( mreq . imr_interface ) ) ; } error = setsockopt ( sock , IPPROTO_IP , IP_ADD_MEMBERSHIP , & mreq , sizeof ( struct ip_mreq ) ) ; if ( error < 0 ) { warn ( " " ) ; close ( sock ) ; return ( EX_OSERR ) ; } } if ( nmcastsources == 0 ) goto skipsources ; for ( i = 0 ; i < ( signed ) nmcastsources ; i ++ ) { mreqs . imr_multiaddr = tmpgroup . sin . sin_addr ; mreqs . imr_interface = ifaddr . sin . sin_addr ; mreqs . imr_sourceaddr = ipv4_sources [ i ] ; if ( doverbose ) { inet_ntop ( AF_INET , & mreqs . imr_multiaddr , gaddrbuf , sizeof ( gaddrbuf ) ) ; inet_ntop ( AF_INET , & mreqs . imr_sourceaddr , saddrbuf , sizeof ( saddrbuf ) ) ; fprintf ( stderr , " \n " , gaddrbuf , inet_ntoa ( mreqs . imr_interface ) , saddrbuf ) ; } error = setsockopt ( sock , IPPROTO_IP , IP_BLOCK_SOURCE , & mreqs , sizeof ( struct ip_mreq_source ) ) ; if ( error < 0 ) { warn ( " " ) ; close ( sock ) ; return ( EX_OSERR ) ; } } memset ( & tmpsource , 0 , sizeof ( sockunion_t ) ) ; tmpsource . sin . sin_family = AF_INET ; tmpsource . sin . sin_len = sizeof ( struct sockaddr_in ) ; tmpsource . sin . sin_addr = ipv4_sources [ 0 ] ; error = recv_loop_with_match ( sock , & tmpgroup , & tmpsource ) ; for ( i = nmcastsources - 1 ; i >= 0 ; i -- ) { mreqs . imr_multiaddr = tmpgroup . sin . sin_addr ; mreqs . imr_interface = ifaddr . sin . sin_addr ; mreqs . imr_sourceaddr = ipv4_sources [ i ] ; if ( doverbose ) { inet_ntop ( AF_INET , & mreqs . imr_multiaddr , gaddrbuf , sizeof ( gaddrbuf ) ) ; inet_ntop ( AF_INET , & mreqs . imr_sourceaddr , saddrbuf , sizeof ( saddrbuf ) ) ; fprintf ( stderr , " \n " , gaddrbuf , inet_ntoa ( mreqs . imr_interface ) , saddrbuf ) ; } error = setsockopt ( sock , IPPROTO_IP , IP_UNBLOCK_SOURCE , & mreqs , sizeof ( struct ip_mreq_source ) ) ; if ( error < 0 ) { warn ( " " ) ; close ( sock ) ; return ( EX_OSERR ) ; } } skipsources : for ( i = nmcastgroups - 1 ; i >= 0 ; i -- ) { mreq . imr_multiaddr . s_addr = htonl ( ( ngroupbase + i ) ) ; mreq . imr_interface = ifaddr . sin . sin_addr ; if ( doverbose ) { inet_ntop ( AF_INET , & mreq . imr_multiaddr , gaddrbuf , sizeof ( gaddrbuf ) ) ; fprintf ( stderr , " \n " , gaddrbuf , inet_ntoa ( mreq . imr_interface ) ) ; } error = setsockopt ( sock , IPPROTO_IP , IP_DROP_MEMBERSHIP , & mreq , sizeof ( struct ip_mreq ) ) ; if ( error < 0 ) { warn ( " " ) ; close ( sock ) ; return ( EX_OSERR ) ; } } return ( 0 ) ; }
Test the IPv4 ASM API.
Test the IPv4 ASM API .
/* XXX */ /*
	 * If no test sources auto-generated or specified on command line,
	 * skip source filter portion of ASM test.
	*/ /*
	 * Begin blocking sources on the first group chosen.
	 */ /*
	 * Choose the first group and source for a match.
	 * Enter the I/O loop.
	 */ /*
	 * Unblock sources.
	 */ /*
	 * Leave groups.
	 */