xref: /netbsd-src/tests/net/inpcb/inpcb_bind.c (revision ae0059cb3002fe09e4535b55a0a162cb84131690)
1*ae0059cbSozaki-r /* $NetBSD: inpcb_bind.c,v 1.2 2022/11/17 08:38:58 ozaki-r Exp $ */
20fca6c42Sozaki-r /* $OpenBSD: runtest.c,v 1.7 2022/04/10 14:08:35 claudio Exp $ */
30fca6c42Sozaki-r /*
40fca6c42Sozaki-r  * Copyright (c) 2015 Vincent Gross <vincent.gross@kilob.yt>
50fca6c42Sozaki-r  *
60fca6c42Sozaki-r  * Permission to use, copy, modify, and distribute this software for any
70fca6c42Sozaki-r  * purpose with or without fee is hereby granted, provided that the above
80fca6c42Sozaki-r  * copyright notice and this permission notice appear in all copies.
90fca6c42Sozaki-r  *
100fca6c42Sozaki-r  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
110fca6c42Sozaki-r  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
120fca6c42Sozaki-r  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
130fca6c42Sozaki-r  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
140fca6c42Sozaki-r  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
150fca6c42Sozaki-r  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
160fca6c42Sozaki-r  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
170fca6c42Sozaki-r  */
180fca6c42Sozaki-r 
190fca6c42Sozaki-r #include <errno.h>
200fca6c42Sozaki-r #include <stdio.h>
210fca6c42Sozaki-r #include <stdlib.h>
220fca6c42Sozaki-r #include <unistd.h>
230fca6c42Sozaki-r #include <string.h>
240fca6c42Sozaki-r #include <err.h>
250fca6c42Sozaki-r #include <netdb.h>
260fca6c42Sozaki-r 
270fca6c42Sozaki-r #include <sys/types.h>
280fca6c42Sozaki-r #include <sys/socket.h>
290fca6c42Sozaki-r #include <netinet/in.h>
300fca6c42Sozaki-r #include <net/if.h>
310fca6c42Sozaki-r #include <ifaddrs.h>
320fca6c42Sozaki-r 
33*ae0059cbSozaki-r static int
runtest(int * sockp,struct addrinfo * ai,int reuseaddr,int reuseport,void * mreq,int expected)340fca6c42Sozaki-r runtest(int *sockp, struct addrinfo *ai, int reuseaddr, int reuseport,
350fca6c42Sozaki-r     void *mreq, int expected)
360fca6c42Sozaki-r {
370fca6c42Sozaki-r 	int error, optval;
380fca6c42Sozaki-r 
390fca6c42Sozaki-r 	*sockp = socket(ai->ai_family, ai->ai_socktype, 0);
400fca6c42Sozaki-r 	if (*sockp == -1) {
410fca6c42Sozaki-r 		warn("%s : socket()", ai->ai_canonname);
420fca6c42Sozaki-r 		return (3);
430fca6c42Sozaki-r 	}
440fca6c42Sozaki-r 
450fca6c42Sozaki-r 	if (reuseaddr) {
460fca6c42Sozaki-r 		optval = 1;
470fca6c42Sozaki-r 		error = setsockopt(*sockp, SOL_SOCKET, SO_REUSEADDR,
480fca6c42Sozaki-r 		    &optval, sizeof(int));
490fca6c42Sozaki-r 		if (error) {
500fca6c42Sozaki-r 			warn("%s : setsockopt(SO_REUSEADDR)", ai->ai_canonname);
510fca6c42Sozaki-r 			return (2);
520fca6c42Sozaki-r 		}
530fca6c42Sozaki-r 	}
540fca6c42Sozaki-r 
550fca6c42Sozaki-r 	if (reuseport) {
560fca6c42Sozaki-r 		optval = 1;
570fca6c42Sozaki-r 		error = setsockopt(*sockp, SOL_SOCKET, SO_REUSEPORT,
580fca6c42Sozaki-r 		    &optval, sizeof(int));
590fca6c42Sozaki-r 		if (error) {
600fca6c42Sozaki-r 			warn("%s : setsockopt(SO_REUSEPORT)", ai->ai_canonname);
610fca6c42Sozaki-r 			return (2);
620fca6c42Sozaki-r 		}
630fca6c42Sozaki-r 	}
640fca6c42Sozaki-r 
650fca6c42Sozaki-r 	if (mreq) {
660fca6c42Sozaki-r 		switch (ai->ai_family) {
670fca6c42Sozaki-r 		case AF_INET6:
680fca6c42Sozaki-r 			error = setsockopt(*sockp, IPPROTO_IPV6, IPV6_JOIN_GROUP,
690fca6c42Sozaki-r 			    mreq, sizeof(struct ipv6_mreq));
700fca6c42Sozaki-r 			if (error) {
710fca6c42Sozaki-r 				warn("%s : setsockopt(IPV6_JOIN_GROUP)",
720fca6c42Sozaki-r 				    ai->ai_canonname);
730fca6c42Sozaki-r 				return (2);
740fca6c42Sozaki-r 			}
750fca6c42Sozaki-r 			break;
760fca6c42Sozaki-r 		case AF_INET:
770fca6c42Sozaki-r 			error = setsockopt(*sockp, IPPROTO_IP, IP_ADD_MEMBERSHIP,
780fca6c42Sozaki-r 			    mreq, sizeof(struct ip_mreq));
790fca6c42Sozaki-r 			if (error) {
800fca6c42Sozaki-r 				warn("%s : setsockopt(IP_ADD_MEMBERSHIP)",
810fca6c42Sozaki-r 				    ai->ai_canonname);
820fca6c42Sozaki-r 				return (2);
830fca6c42Sozaki-r 			}
840fca6c42Sozaki-r 			break;
850fca6c42Sozaki-r 		default:
860fca6c42Sozaki-r 			warnx("%s : trying to join multicast group in unknown AF",
870fca6c42Sozaki-r 			    ai->ai_canonname);
880fca6c42Sozaki-r 			return (2);
890fca6c42Sozaki-r 		}
900fca6c42Sozaki-r 	}
910fca6c42Sozaki-r 
920fca6c42Sozaki-r 
930fca6c42Sozaki-r 	error = bind(*sockp, ai->ai_addr, ai->ai_addrlen);
940fca6c42Sozaki-r 	if (error && (expected == 0 || expected != errno)) {
950fca6c42Sozaki-r 		warn("bind(%s,%s,%s)", ai->ai_canonname,
960fca6c42Sozaki-r 		    reuseaddr ? "REUSEADDR" : "", reuseport ? "REUSEPORT" : "");
970fca6c42Sozaki-r 		return (1);
980fca6c42Sozaki-r 	}
990fca6c42Sozaki-r 	if (error == 0 && expected != 0) {
1000fca6c42Sozaki-r 		warnx("bind(%s,%s,%s) succeeded, expected : %s", ai->ai_canonname,
1010fca6c42Sozaki-r 		    reuseaddr ? "REUSEADDR" : "", reuseport ? "REUSEPORT" : "",
1020fca6c42Sozaki-r 		    strerror(expected));
1030fca6c42Sozaki-r 		return (1);
1040fca6c42Sozaki-r 	}
1050fca6c42Sozaki-r 
1060fca6c42Sozaki-r 	return (0);
1070fca6c42Sozaki-r }
1080fca6c42Sozaki-r 
109*ae0059cbSozaki-r static void
cleanup(int * fds,int num_fds)1100fca6c42Sozaki-r cleanup(int *fds, int num_fds)
1110fca6c42Sozaki-r {
1120fca6c42Sozaki-r 	while (num_fds-- > 0)
1130fca6c42Sozaki-r 		if (close(*fds++) && errno != EBADF)
1140fca6c42Sozaki-r 			err(2, "unable to clean up sockets, aborting");
1150fca6c42Sozaki-r }
1160fca6c42Sozaki-r 
117*ae0059cbSozaki-r static int
unicast_testsuite(struct addrinfo * local,struct addrinfo * any)1180fca6c42Sozaki-r unicast_testsuite(struct addrinfo *local, struct addrinfo *any)
1190fca6c42Sozaki-r {
1200fca6c42Sozaki-r 	int test_rc, rc, *s;
1210fca6c42Sozaki-r 	int sockets[4];
1220fca6c42Sozaki-r 
1230fca6c42Sozaki-r 	test_rc = 0;
1240fca6c42Sozaki-r 	rc = 0; s = sockets;
1250fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, NULL, 0);
1260fca6c42Sozaki-r 	rc |= runtest(s++, any,   0, 0, NULL, EADDRINUSE);
1270fca6c42Sozaki-r 	rc |= runtest(s++, any,   1, 0, NULL, 0);
1280fca6c42Sozaki-r 	cleanup(sockets, 3);
1290fca6c42Sozaki-r 	test_rc |= rc;
1300fca6c42Sozaki-r 	if (rc)
1310fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 1);
1320fca6c42Sozaki-r 
1330fca6c42Sozaki-r 	rc = 0; s = sockets;
1340fca6c42Sozaki-r 	rc |= runtest(s++, any,   0, 0, NULL, 0);
1350fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, NULL, EADDRINUSE);
1360fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, NULL, 0);
1370fca6c42Sozaki-r 	cleanup(sockets, 3);
1380fca6c42Sozaki-r 	test_rc |= rc;
1390fca6c42Sozaki-r 	if (rc)
1400fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 2);
1410fca6c42Sozaki-r 
1420fca6c42Sozaki-r 	rc = 0; s = sockets;
1430fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, NULL, 0);
1440fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, NULL, 0);
1450fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, NULL, EADDRINUSE);
1460fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, NULL, EADDRINUSE);
1470fca6c42Sozaki-r 	cleanup(sockets, 4);
1480fca6c42Sozaki-r 	test_rc |= rc;
1490fca6c42Sozaki-r 	if (rc)
1500fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 3);
1510fca6c42Sozaki-r 
1520fca6c42Sozaki-r 	rc = 0; s = sockets;
1530fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 1, NULL, 0);
1540fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 1, NULL, 0);
1550fca6c42Sozaki-r 	rc |= runtest(s++, any, 1, 0, NULL, EADDRINUSE);
1560fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 0, NULL, EADDRINUSE);
1570fca6c42Sozaki-r 	cleanup(sockets, 4);
1580fca6c42Sozaki-r 	test_rc |= rc;
1590fca6c42Sozaki-r 	if (rc)
1600fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 4);
1610fca6c42Sozaki-r 
1620fca6c42Sozaki-r 	rc = 0; s = sockets;
1630fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, NULL, 0);
1640fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, NULL, EADDRINUSE);
1650fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, NULL, EADDRINUSE);
1660fca6c42Sozaki-r 	cleanup(sockets, 3);
1670fca6c42Sozaki-r 	test_rc |= rc;
1680fca6c42Sozaki-r 	if (rc)
1690fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 5);
1700fca6c42Sozaki-r 
1710fca6c42Sozaki-r 	rc = 0; s = sockets;
1720fca6c42Sozaki-r 	rc |= runtest(s++, any, 1, 0, NULL, 0);
1730fca6c42Sozaki-r 	rc |= runtest(s++, any, 1, 0, NULL, EADDRINUSE);
1740fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 1, NULL, EADDRINUSE);
1750fca6c42Sozaki-r 	cleanup(sockets, 3);
1760fca6c42Sozaki-r 	test_rc |= rc;
1770fca6c42Sozaki-r 	if (rc)
1780fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 6);
1790fca6c42Sozaki-r 
1800fca6c42Sozaki-r 	return (test_rc);
1810fca6c42Sozaki-r }
1820fca6c42Sozaki-r 
183*ae0059cbSozaki-r static int
mcast_reuse_testsuite(struct addrinfo * local,void * mr)1840fca6c42Sozaki-r mcast_reuse_testsuite(struct addrinfo *local, void *mr)
1850fca6c42Sozaki-r {
1860fca6c42Sozaki-r 	int test_rc, rc, *s;
1870fca6c42Sozaki-r 	int sockets[6];
1880fca6c42Sozaki-r 
1890fca6c42Sozaki-r 	test_rc = 0;
1900fca6c42Sozaki-r 	rc = 0; s = sockets;
1910fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, mr, 0);
1920fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, EADDRINUSE);
1930fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, EADDRINUSE);
1940fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, EADDRINUSE);
1950fca6c42Sozaki-r 	cleanup(sockets, 4);
1960fca6c42Sozaki-r 	test_rc |= rc;
1970fca6c42Sozaki-r 	if (rc)
1980fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 1);
1990fca6c42Sozaki-r 
2000fca6c42Sozaki-r 	rc = 0; s = sockets;
2010fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, 0);
2020fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, mr, EADDRINUSE);
2030fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, 0);
2040fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2050fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2060fca6c42Sozaki-r 	cleanup(sockets, 5);
2070fca6c42Sozaki-r 	test_rc |= rc;
2080fca6c42Sozaki-r 	if (rc)
2090fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 2);
2100fca6c42Sozaki-r 
2110fca6c42Sozaki-r 	rc = 0; s = sockets;
2120fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2130fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, mr, EADDRINUSE);
2140fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2150fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, 0);
2160fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2170fca6c42Sozaki-r 	cleanup(sockets, 5);
2180fca6c42Sozaki-r 	test_rc |= rc;
2190fca6c42Sozaki-r 	if (rc)
2200fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 3);
2210fca6c42Sozaki-r 
2220fca6c42Sozaki-r 	rc = 0; s = sockets;
2230fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2240fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, mr, EADDRINUSE);
2250fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, 0);
2260fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2270fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2280fca6c42Sozaki-r 	cleanup(sockets, 5);
2290fca6c42Sozaki-r 	test_rc |= rc;
2300fca6c42Sozaki-r 	if (rc)
2310fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 4);
2320fca6c42Sozaki-r 
2330fca6c42Sozaki-r #if 0
2340fca6c42Sozaki-r 	rc = 0; s = sockets;
2350fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2360fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2370fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, 0);
2380fca6c42Sozaki-r 	cleanup(sockets, 3);
2390fca6c42Sozaki-r 	test_rc |= rc;
2400fca6c42Sozaki-r 	if (rc)
2410fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 5);
2420fca6c42Sozaki-r 
2430fca6c42Sozaki-r 	rc = 0; s = sockets;
2440fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2450fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2460fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2470fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2480fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, 0);
2490fca6c42Sozaki-r 	cleanup(sockets, 5);
2500fca6c42Sozaki-r 	test_rc |= rc;
2510fca6c42Sozaki-r 	if (rc)
2520fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 6);
2530fca6c42Sozaki-r 
2540fca6c42Sozaki-r 	rc = 0; s = sockets;
2550fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2560fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2570fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 1, mr, 0);
2580fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, mr, 0);
2590fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, mr, 0);
2600fca6c42Sozaki-r 	cleanup(sockets, 5);
2610fca6c42Sozaki-r 	test_rc |= rc;
2620fca6c42Sozaki-r 	if (rc)
2630fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 7);
2640fca6c42Sozaki-r #endif
2650fca6c42Sozaki-r 	return (test_rc);
2660fca6c42Sozaki-r }
2670fca6c42Sozaki-r 
268*ae0059cbSozaki-r static int
mcast6_testsuite(struct addrinfo * local,struct ipv6_mreq * local_mreq,struct addrinfo * any,struct ipv6_mreq * any_mreq)2690fca6c42Sozaki-r mcast6_testsuite(struct addrinfo *local, struct ipv6_mreq *local_mreq,
2700fca6c42Sozaki-r     struct addrinfo *any, struct ipv6_mreq *any_mreq)
2710fca6c42Sozaki-r {
2720fca6c42Sozaki-r 	int test_rc, rc, *s;
2730fca6c42Sozaki-r 	int sockets[4];
2740fca6c42Sozaki-r 
2750fca6c42Sozaki-r 	test_rc = 0;
2760fca6c42Sozaki-r 	rc = 0; s = sockets;
2770fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, local_mreq, 0);
2780fca6c42Sozaki-r 	rc |= runtest(s++, any,   0, 0, any_mreq,   EADDRINUSE);
2790fca6c42Sozaki-r 	rc |= runtest(s++, any,   1, 0, any_mreq,   0);
2800fca6c42Sozaki-r 	cleanup(sockets, 3);
2810fca6c42Sozaki-r 	test_rc |= rc;
2820fca6c42Sozaki-r 	if (rc)
2830fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 1);
2840fca6c42Sozaki-r 
2850fca6c42Sozaki-r 	rc = 0; s = sockets;
2860fca6c42Sozaki-r 	rc |= runtest(s++, any,   0, 0, any_mreq,   0);
2870fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, local_mreq, EADDRINUSE);
2880fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, local_mreq, 0);
2890fca6c42Sozaki-r 	cleanup(sockets, 3);
2900fca6c42Sozaki-r 	test_rc |= rc;
2910fca6c42Sozaki-r 	if (rc)
2920fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 2);
2930fca6c42Sozaki-r 
2940fca6c42Sozaki-r 	rc = 0; s = sockets;
2950fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, local_mreq, 0);
2960fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, local_mreq, 0);
2970fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, local_mreq, 0);
2980fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, local_mreq, EADDRINUSE);
2990fca6c42Sozaki-r 	cleanup(sockets, 4);
3000fca6c42Sozaki-r 	test_rc |= rc;
3010fca6c42Sozaki-r 	if (rc)
3020fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 3);
3030fca6c42Sozaki-r 
3040fca6c42Sozaki-r 	/*
3050fca6c42Sozaki-r 	 * :: is not a multicast address, SO_REUSEADDR and SO_REUSEPORT
3060fca6c42Sozaki-r 	 * keep their unicast semantics although we are binding on multicast
3070fca6c42Sozaki-r 	 */
3080fca6c42Sozaki-r 
3090fca6c42Sozaki-r 	rc = 0; s = sockets;
3100fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 1, any_mreq, 0);
3110fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 1, any_mreq, 0);
3120fca6c42Sozaki-r 	rc |= runtest(s++, any, 1, 0, any_mreq, EADDRINUSE);
3130fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 0, any_mreq, EADDRINUSE);
3140fca6c42Sozaki-r 	cleanup(sockets, 4);
3150fca6c42Sozaki-r 	test_rc |= rc;
3160fca6c42Sozaki-r 	if (rc)
3170fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 4);
3180fca6c42Sozaki-r 
3190fca6c42Sozaki-r 	rc = 0; s = sockets;
3200fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, local_mreq, 0);
3210fca6c42Sozaki-r 	rc |= runtest(s++, local, 1, 0, local_mreq, 0);
3220fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 1, local_mreq, 0);
3230fca6c42Sozaki-r 	rc |= runtest(s++, local, 0, 0, local_mreq, EADDRINUSE);
3240fca6c42Sozaki-r 	cleanup(sockets, 4);
3250fca6c42Sozaki-r 	test_rc |= rc;
3260fca6c42Sozaki-r 	if (rc)
3270fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 5);
3280fca6c42Sozaki-r 
3290fca6c42Sozaki-r 	/* See above */
3300fca6c42Sozaki-r 
3310fca6c42Sozaki-r 	rc = 0; s = sockets;
3320fca6c42Sozaki-r 	rc |= runtest(s++, any, 1, 0, any_mreq, 0);
3330fca6c42Sozaki-r 	rc |= runtest(s++, any, 1, 0, any_mreq, EADDRINUSE);
3340fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 1, any_mreq, EADDRINUSE);
3350fca6c42Sozaki-r 	rc |= runtest(s++, any, 0, 0, any_mreq, EADDRINUSE);
3360fca6c42Sozaki-r 	cleanup(sockets, 4);
3370fca6c42Sozaki-r 	test_rc |= rc;
3380fca6c42Sozaki-r 	if (rc)
3390fca6c42Sozaki-r 		warnx("%s : test #%d failed", __func__, 6);
3400fca6c42Sozaki-r 
3410fca6c42Sozaki-r 	return (test_rc);
3420fca6c42Sozaki-r }
3430fca6c42Sozaki-r 
3440fca6c42Sozaki-r int
main(int argc,char * argv[])3450fca6c42Sozaki-r main(int argc, char *argv[])
3460fca6c42Sozaki-r {
3470fca6c42Sozaki-r 	int error, rc;
3480fca6c42Sozaki-r 	char *baddr_s, *bport_s, *bmifa_s;
3490fca6c42Sozaki-r 	struct addrinfo hints, *baddr, *any, *mifa;
3500fca6c42Sozaki-r 	struct ifaddrs *ifap, *curifa;
351*ae0059cbSozaki-r 	struct ip_mreq local_imr;
3520fca6c42Sozaki-r 	struct ipv6_mreq local_i6mr, any_i6mr;
3530fca6c42Sozaki-r 	struct sockaddr_in *sin;
3540fca6c42Sozaki-r 	struct sockaddr_in6 *sin6;
3550fca6c42Sozaki-r 
3560fca6c42Sozaki-r 	memset(&hints, 0, sizeof(hints));
3570fca6c42Sozaki-r 	hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST | AI_NUMERICSERV | \
3580fca6c42Sozaki-r 	    AI_PASSIVE;
3590fca6c42Sozaki-r 	hints.ai_socktype = SOCK_DGRAM;
3600fca6c42Sozaki-r 
3610fca6c42Sozaki-r 	baddr_s = argv[1];
3620fca6c42Sozaki-r 	bport_s = argv[2];
3630fca6c42Sozaki-r 
3640fca6c42Sozaki-r 	if ((error = getaddrinfo(baddr_s, bport_s, &hints, &baddr)))
3650fca6c42Sozaki-r 		errx(2, "getaddrinfo(%s,%s): %s", baddr_s, bport_s,
3660fca6c42Sozaki-r 		    gai_strerror(error));
3670fca6c42Sozaki-r 	baddr->ai_canonname = baddr_s;
3680fca6c42Sozaki-r 
3690fca6c42Sozaki-r 	hints.ai_family = baddr->ai_family;
3700fca6c42Sozaki-r 	if ((error = getaddrinfo(NULL, bport_s, &hints, &any)))
3710fca6c42Sozaki-r 		errx(2, "getaddrinfo(NULL,%s): %s", bport_s,
3720fca6c42Sozaki-r 		    gai_strerror(error));
373*ae0059cbSozaki-r 	any->ai_canonname = strdup("*");
3740fca6c42Sozaki-r 
3750fca6c42Sozaki-r 	switch (baddr->ai_family) {
3760fca6c42Sozaki-r 	case AF_INET:
3770fca6c42Sozaki-r 		sin = (struct sockaddr_in *)baddr->ai_addr;
3780fca6c42Sozaki-r 		if (!IN_MULTICAST( ntohl(sin->sin_addr.s_addr) )) {
3790fca6c42Sozaki-r 			puts("executing unicast testsuite");
3800fca6c42Sozaki-r 			return unicast_testsuite(baddr, any);
3810fca6c42Sozaki-r 		}
3820fca6c42Sozaki-r 		bmifa_s = argv[3];
3830fca6c42Sozaki-r 		hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
3840fca6c42Sozaki-r 
3850fca6c42Sozaki-r 		if ((error = getaddrinfo(bmifa_s, NULL, &hints, &mifa)))
3860fca6c42Sozaki-r 			errx(2, "getaddrinfo(%s,NULL): %s", bmifa_s,
3870fca6c42Sozaki-r 			    gai_strerror(error));
3880fca6c42Sozaki-r 
3890fca6c42Sozaki-r 		local_imr.imr_interface =
3900fca6c42Sozaki-r 		    ((struct sockaddr_in *)mifa->ai_addr)->sin_addr;
3910fca6c42Sozaki-r 		local_imr.imr_multiaddr =
3920fca6c42Sozaki-r 		    ((struct sockaddr_in *)baddr->ai_addr)->sin_addr;
3930fca6c42Sozaki-r 
3940fca6c42Sozaki-r 		puts("executing ipv4 multicast testsuite");
3950fca6c42Sozaki-r 
3960fca6c42Sozaki-r 		/* no 'any' mcast group in ipv4 */
3970fca6c42Sozaki-r 		return mcast_reuse_testsuite(baddr, &local_imr);
3980fca6c42Sozaki-r 	case AF_INET6:
3990fca6c42Sozaki-r 		sin6 = (struct sockaddr_in6 *)baddr->ai_addr;
4000fca6c42Sozaki-r 		if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
4010fca6c42Sozaki-r 			puts("executing unicast testsuite");
4020fca6c42Sozaki-r 			return unicast_testsuite(baddr, any);
4030fca6c42Sozaki-r 		}
4040fca6c42Sozaki-r 		bmifa_s = argv[3];
4050fca6c42Sozaki-r 		hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
4060fca6c42Sozaki-r 
4070fca6c42Sozaki-r 		if ((error = getaddrinfo(bmifa_s, NULL, &hints, &mifa)))
4080fca6c42Sozaki-r 			errx(2, "getaddrinfo(%s,NULL): %s", bmifa_s,
4090fca6c42Sozaki-r 			    gai_strerror(error));
4100fca6c42Sozaki-r 
4110fca6c42Sozaki-r 		if (getifaddrs(&ifap))
4120fca6c42Sozaki-r 			err(2, "getifaddrs()");
4130fca6c42Sozaki-r 		curifa = ifap;
4140fca6c42Sozaki-r 		while (curifa) {
4150fca6c42Sozaki-r 			if (curifa->ifa_addr != NULL &&
4160fca6c42Sozaki-r 			    memcmp(curifa->ifa_addr,
4170fca6c42Sozaki-r 			    mifa->ai_addr,
4180fca6c42Sozaki-r 			    mifa->ai_addrlen) == 0)
4190fca6c42Sozaki-r 				break;
4200fca6c42Sozaki-r 			curifa = curifa->ifa_next;
4210fca6c42Sozaki-r 		}
4220fca6c42Sozaki-r 		if (curifa == NULL)
4230fca6c42Sozaki-r 			errx(2, "no interface configured with %s", argv[4]);
4240fca6c42Sozaki-r 		local_i6mr.ipv6mr_interface =
4250fca6c42Sozaki-r 		    if_nametoindex(curifa->ifa_name);
4260fca6c42Sozaki-r 		if (local_i6mr.ipv6mr_interface == 0)
4270fca6c42Sozaki-r 			errx(2, "unable to get \"%s\" index",
4280fca6c42Sozaki-r 			    curifa->ifa_name);
4290fca6c42Sozaki-r 		freeifaddrs(ifap);
4300fca6c42Sozaki-r 
4310fca6c42Sozaki-r 		local_i6mr.ipv6mr_multiaddr =
4320fca6c42Sozaki-r 		    ((struct sockaddr_in6 *)baddr->ai_addr)->sin6_addr;
4330fca6c42Sozaki-r 
4340fca6c42Sozaki-r 		any_i6mr.ipv6mr_interface = local_i6mr.ipv6mr_interface;
4350fca6c42Sozaki-r 		any_i6mr.ipv6mr_multiaddr =
4360fca6c42Sozaki-r 		    ((struct sockaddr_in6 *)any->ai_addr)->sin6_addr;
4370fca6c42Sozaki-r 
4380fca6c42Sozaki-r 		puts("executing ipv6 multicast testsuite");
4390fca6c42Sozaki-r 
4400fca6c42Sozaki-r 		rc = 0;
4410fca6c42Sozaki-r 		rc |= mcast_reuse_testsuite(baddr, &local_i6mr);
4420fca6c42Sozaki-r 		if (geteuid() == 0)
4430fca6c42Sozaki-r 			rc |= mcast6_testsuite(baddr, &local_i6mr, any, &any_i6mr);
4440fca6c42Sozaki-r 		else
4450fca6c42Sozaki-r 			warnx("skipping mcast6_testsuite() due to insufficient privs, please run again as root");
4460fca6c42Sozaki-r 		return (rc);
4470fca6c42Sozaki-r 	default:
4480fca6c42Sozaki-r 		errx(2,"unknown AF");
4490fca6c42Sozaki-r 	}
4500fca6c42Sozaki-r 
4510fca6c42Sozaki-r 	return (2);
4520fca6c42Sozaki-r }
453