1303980Sngie/* $NetBSD: mcast.c,v 1.3 2015/05/28 10:19:17 ozaki-r Exp $ */ 2303980Sngie 3303980Sngie/*- 4303980Sngie * Copyright (c) 2014 The NetBSD Foundation, Inc. 5303980Sngie * All rights reserved. 6303980Sngie * 7303980Sngie * This code is derived from software contributed to The NetBSD Foundation 8303980Sngie * by Christos Zoulas. 9303980Sngie * 10303980Sngie * Redistribution and use in source and binary forms, with or without 11303980Sngie * modification, are permitted provided that the following conditions 12303980Sngie * are met: 13303980Sngie * 1. Redistributions of source code must retain the above copyright 14303980Sngie * notice, this list of conditions and the following disclaimer. 15303980Sngie * 2. Redistributions in binary form must reproduce the above copyright 16303980Sngie * notice, this list of conditions and the following disclaimer in the 17303980Sngie * documentation and/or other materials provided with the distribution. 18303980Sngie * 19303980Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20303980Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21303980Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22303980Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23303980Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24303980Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25303980Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26303980Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27303980Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28303980Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29303980Sngie * POSSIBILITY OF SUCH DAMAGE. 30303980Sngie */ 31303980Sngie#include <sys/cdefs.h> 32303980Sngie#ifdef __RCSID 33303980Sngie__RCSID("$NetBSD: mcast.c,v 1.3 2015/05/28 10:19:17 ozaki-r Exp $"); 34303980Sngie#else 35303980Sngieextern const char *__progname; 36303980Sngie#define getprogname() __progname 37303980Sngie#endif 38303980Sngie 39303980Sngie#include <sys/types.h> 40303980Sngie#include <sys/socket.h> 41303980Sngie#include <sys/wait.h> 42303980Sngie#include <sys/time.h> 43303980Sngie#include <netinet/in.h> 44303980Sngie 45303980Sngie#include <assert.h> 46303980Sngie#include <netdb.h> 47303980Sngie#include <time.h> 48303980Sngie#include <signal.h> 49303980Sngie#include <stdio.h> 50303980Sngie#include <string.h> 51303980Sngie#include <stdlib.h> 52303980Sngie#include <unistd.h> 53303980Sngie#include <err.h> 54303980Sngie#include <errno.h> 55303980Sngie#include <poll.h> 56303980Sngie#include <stdbool.h> 57303980Sngie 58303980Sngie#ifdef ATF 59303980Sngie#include <atf-c.h> 60303980Sngie 61303980Sngie#define ERRX(ev, msg, ...) ATF_REQUIRE_MSG(0, msg, __VA_ARGS__) 62303980Sngie#define ERRX0(ev, msg) ATF_REQUIRE_MSG(0, msg) 63303980Sngie 64303980Sngie#define SKIPX(ev, msg, ...) do { \ 65303980Sngie atf_tc_skip(msg, __VA_ARGS__); \ 66303980Sngie return; \ 67303980Sngie} while(/*CONSTCOND*/0) 68303980Sngie 69303980Sngie#else 70303980Sngie#define ERRX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) 71303980Sngie#define ERRX0(ev, msg) errx(ev, msg) 72303980Sngie#define SKIPX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) 73303980Sngie#endif 74303980Sngie 75303980Sngiestatic int debug; 76303980Sngie 77303980Sngie#define TOTAL 10 78303980Sngie#define PORT_V4MAPPED "6666" 79303980Sngie#define HOST_V4MAPPED "::FFFF:239.1.1.1" 80303980Sngie#define PORT_V4 "6666" 81303980Sngie#define HOST_V4 "239.1.1.1" 82303980Sngie#define PORT_V6 "6666" 83303980Sngie#define HOST_V6 "FF05:1:0:0:0:0:0:1" 84303980Sngie 85303980Sngiestruct message { 86303980Sngie size_t seq; 87303980Sngie struct timespec ts; 88303980Sngie}; 89303980Sngie 90303980Sngiestatic int 91303980Sngieaddmc(int s, struct addrinfo *ai, bool bug) 92303980Sngie{ 93303980Sngie struct ip_mreq m4; 94303980Sngie struct ipv6_mreq m6; 95303980Sngie struct sockaddr_in *s4; 96303980Sngie struct sockaddr_in6 *s6; 97303980Sngie unsigned int ifc; 98303980Sngie 99303980Sngie switch (ai->ai_family) { 100303980Sngie case AF_INET: 101303980Sngie s4 = (void *)ai->ai_addr; 102303980Sngie assert(sizeof(*s4) == ai->ai_addrlen); 103303980Sngie m4.imr_multiaddr = s4->sin_addr; 104303980Sngie m4.imr_interface.s_addr = htonl(INADDR_ANY); 105303980Sngie return setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, 106303980Sngie &m4, sizeof(m4)); 107303980Sngie case AF_INET6: 108303980Sngie s6 = (void *)ai->ai_addr; 109303980Sngie /* 110303980Sngie * Linux: Does not support the v6 ioctls on v4 mapped 111303980Sngie * sockets but it does support the v4 ones and 112303980Sngie * it works. 113303980Sngie * MacOS/X: Supports the v6 ioctls on v4 mapped sockets, 114303980Sngie * but does not work and also does not support 115303980Sngie * the v4 ioctls. So no way to make multicasting 116303980Sngie * work with mapped addresses. 117303980Sngie * NetBSD: Supports both and works for both. 118303980Sngie */ 119303980Sngie if (bug && IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) { 120303980Sngie memcpy(&m4.imr_multiaddr, &s6->sin6_addr.s6_addr[12], 121303980Sngie sizeof(m4.imr_multiaddr)); 122303980Sngie m4.imr_interface.s_addr = htonl(INADDR_ANY); 123303980Sngie return setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, 124303980Sngie &m4, sizeof(m4)); 125303980Sngie } 126303980Sngie assert(sizeof(*s6) == ai->ai_addrlen); 127303980Sngie memset(&m6, 0, sizeof(m6)); 128303980Sngie#if 0 129303980Sngie ifc = 1; 130303980Sngie if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 131303980Sngie &ifc, sizeof(ifc)) == -1) 132303980Sngie return -1; 133303980Sngie ifc = 224; 134303980Sngie if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 135303980Sngie &ifc, sizeof(ifc)) == -1) 136303980Sngie return -1; 137303980Sngie ifc = 1; /* XXX should pick a proper interface */ 138303980Sngie if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifc, 139303980Sngie sizeof(ifc)) == -1) 140303980Sngie return -1; 141303980Sngie#else 142303980Sngie ifc = 0; /* Let pick an appropriate interface */ 143303980Sngie#endif 144303980Sngie m6.ipv6mr_interface = ifc; 145303980Sngie m6.ipv6mr_multiaddr = s6->sin6_addr; 146303980Sngie return setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, 147303980Sngie &m6, sizeof(m6)); 148303980Sngie default: 149303980Sngie errno = EOPNOTSUPP; 150303980Sngie return -1; 151303980Sngie } 152303980Sngie} 153303980Sngie 154303980Sngiestatic int 155303980Sngieallowv4mapped(int s, struct addrinfo *ai) 156303980Sngie{ 157303980Sngie struct sockaddr_in6 *s6; 158303980Sngie int zero = 0; 159303980Sngie 160303980Sngie if (ai->ai_family != AF_INET6) 161303980Sngie return 0; 162303980Sngie 163303980Sngie s6 = (void *)ai->ai_addr; 164303980Sngie 165303980Sngie if (!IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) 166303980Sngie return 0; 167303980Sngie return setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)); 168303980Sngie} 169303980Sngie 170303980Sngiestatic struct sockaddr_storage ss; 171303980Sngiestatic int 172303980Sngieconnector(int fd, const struct sockaddr *sa, socklen_t slen) 173303980Sngie{ 174303980Sngie assert(sizeof(ss) > slen); 175303980Sngie memcpy(&ss, sa, slen); 176303980Sngie return 0; 177303980Sngie} 178303980Sngie 179303980Sngiestatic void 180303980Sngieshow(const char *prefix, const struct message *msg) 181303980Sngie{ 182303980Sngie printf("%10.10s: %zu [%jd.%ld]\n", prefix, msg->seq, (intmax_t) 183303980Sngie msg->ts.tv_sec, msg->ts.tv_nsec); 184303980Sngie} 185303980Sngie 186303980Sngiestatic int 187303980Sngiegetsocket(const char *host, const char *port, 188303980Sngie int (*f)(int, const struct sockaddr *, socklen_t), socklen_t *slen, 189303980Sngie bool bug) 190303980Sngie{ 191303980Sngie int e, s, lasterrno = 0; 192303980Sngie struct addrinfo hints, *ai0, *ai; 193303980Sngie const char *cause = "?"; 194303980Sngie 195303980Sngie memset(&hints, 0, sizeof(hints)); 196303980Sngie hints.ai_family = AF_UNSPEC; 197303980Sngie hints.ai_socktype = SOCK_DGRAM; 198303980Sngie e = getaddrinfo(host, port, &hints, &ai0); 199303980Sngie if (e) 200303980Sngie ERRX(EXIT_FAILURE, "Can't resolve %s:%s (%s)", host, port, 201303980Sngie gai_strerror(e)); 202303980Sngie 203303980Sngie s = -1; 204303980Sngie for (ai = ai0; ai; ai = ai->ai_next) { 205303980Sngie s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 206303980Sngie if (s == -1) { 207303980Sngie lasterrno = errno; 208303980Sngie cause = "socket"; 209303980Sngie continue; 210303980Sngie } 211303980Sngie if (allowv4mapped(s, ai) == -1) { 212303980Sngie cause = "allow v4 mapped"; 213303980Sngie goto out; 214303980Sngie } 215303980Sngie if ((*f)(s, ai->ai_addr, ai->ai_addrlen) == -1) { 216303980Sngie cause = f == bind ? "bind" : "connect"; 217303980Sngie goto out; 218303980Sngie } 219303980Sngie if ((f == bind || f == connector) && addmc(s, ai, bug) == -1) { 220303980Sngie cause = "join group"; 221303980Sngie goto out; 222303980Sngie } 223303980Sngie *slen = ai->ai_addrlen; 224303980Sngie break; 225303980Sngieout: 226303980Sngie lasterrno = errno; 227303980Sngie close(s); 228303980Sngie s = -1; 229303980Sngie continue; 230303980Sngie } 231303980Sngie freeaddrinfo(ai0); 232303980Sngie if (s == -1) 233303980Sngie ERRX(EXIT_FAILURE, "%s (%s)", cause, strerror(lasterrno)); 234303980Sngie return s; 235303980Sngie} 236303980Sngie 237303980Sngiestatic int 238303980Sngiesynchronize(const int fd, bool waiter) 239303980Sngie{ 240303980Sngie int syncmsg = 0; 241303980Sngie int r; 242303980Sngie struct pollfd pfd; 243303980Sngie 244303980Sngie if (waiter) { 245303980Sngie pfd.fd = fd; 246303980Sngie pfd.events = POLLIN; 247303980Sngie 248303980Sngie /* We use poll to avoid lock up when the peer died unexpectedly */ 249303980Sngie r = poll(&pfd, 1, 10000); 250303980Sngie if (r == -1) 251303980Sngie ERRX(EXIT_FAILURE, "poll (%s)", strerror(errno)); 252303980Sngie if (r == 0) 253303980Sngie /* Timed out */ 254303980Sngie return -1; 255303980Sngie 256303980Sngie if (read(fd, &syncmsg, sizeof(syncmsg)) == -1) 257303980Sngie ERRX(EXIT_FAILURE, "read (%s)", strerror(errno)); 258303980Sngie } else { 259303980Sngie if (write(fd, &syncmsg, sizeof(syncmsg)) == -1) 260303980Sngie ERRX(EXIT_FAILURE, "write (%s)", strerror(errno)); 261303980Sngie } 262303980Sngie 263303980Sngie return 0; 264303980Sngie} 265303980Sngie 266303980Sngiestatic int 267303980Sngiesender(const int fd, const char *host, const char *port, size_t n, bool conn, 268303980Sngie bool bug) 269303980Sngie{ 270303980Sngie int s; 271303980Sngie ssize_t l; 272303980Sngie struct message msg; 273303980Sngie 274303980Sngie socklen_t slen; 275303980Sngie 276303980Sngie s = getsocket(host, port, conn ? connect : connector, &slen, bug); 277303980Sngie 278303980Sngie /* Wait until receiver gets ready. */ 279303980Sngie if (synchronize(fd, true) == -1) 280303980Sngie return -1; 281303980Sngie 282303980Sngie for (msg.seq = 0; msg.seq < n; msg.seq++) { 283303980Sngie#ifdef CLOCK_MONOTONIC 284303980Sngie if (clock_gettime(CLOCK_MONOTONIC, &msg.ts) == -1) 285303980Sngie ERRX(EXIT_FAILURE, "clock (%s)", strerror(errno)); 286303980Sngie#else 287303980Sngie struct timeval tv; 288303980Sngie if (gettimeofday(&tv, NULL) == -1) 289303980Sngie ERRX(EXIT_FAILURE, "clock (%s)", strerror(errno)); 290303980Sngie msg.ts.tv_sec = tv.tv_sec; 291303980Sngie msg.ts.tv_nsec = tv.tv_usec * 1000; 292303980Sngie#endif 293303980Sngie if (debug) 294303980Sngie show("sending", &msg); 295303980Sngie l = conn ? send(s, &msg, sizeof(msg), 0) : 296303980Sngie sendto(s, &msg, sizeof(msg), 0, (void *)&ss, slen); 297303980Sngie if (l == -1) 298303980Sngie ERRX(EXIT_FAILURE, "send (%s)", strerror(errno)); 299303980Sngie usleep(100); 300303980Sngie } 301303980Sngie 302303980Sngie /* Wait until receiver finishes its work. */ 303303980Sngie if (synchronize(fd, true) == -1) 304303980Sngie return -1; 305303980Sngie 306303980Sngie return 0; 307303980Sngie} 308303980Sngie 309303980Sngiestatic void 310303980Sngiereceiver(const int fd, const char *host, const char *port, size_t n, bool conn, 311303980Sngie bool bug) 312303980Sngie{ 313303980Sngie int s; 314303980Sngie ssize_t l; 315303980Sngie size_t seq; 316303980Sngie struct message msg; 317303980Sngie struct pollfd pfd; 318303980Sngie socklen_t slen; 319303980Sngie 320303980Sngie s = getsocket(host, port, bind, &slen, bug); 321303980Sngie pfd.fd = s; 322303980Sngie pfd.events = POLLIN; 323303980Sngie 324303980Sngie /* Tell I'm ready */ 325303980Sngie synchronize(fd, false); 326303980Sngie 327303980Sngie for (seq = 0; seq < n; seq++) { 328303980Sngie if (poll(&pfd, 1, 10000) == -1) 329303980Sngie ERRX(EXIT_FAILURE, "poll (%s)", strerror(errno)); 330303980Sngie l = conn ? recv(s, &msg, sizeof(msg), 0) : 331303980Sngie recvfrom(s, &msg, sizeof(msg), 0, (void *)&ss, &slen); 332303980Sngie if (l == -1) 333303980Sngie ERRX(EXIT_FAILURE, "recv (%s)", strerror(errno)); 334303980Sngie if (debug) 335303980Sngie show("got", &msg); 336303980Sngie if (seq != msg.seq) 337303980Sngie ERRX(EXIT_FAILURE, "seq: expect=%zu actual=%zu", 338303980Sngie seq, msg.seq); 339303980Sngie } 340303980Sngie 341303980Sngie /* Tell I'm finished */ 342303980Sngie synchronize(fd, false); 343303980Sngie} 344303980Sngie 345303980Sngiestatic void 346303980Sngierun(const char *host, const char *port, size_t n, bool conn, bool bug) 347303980Sngie{ 348303980Sngie pid_t pid; 349303980Sngie int status; 350303980Sngie int syncfds[2]; 351303980Sngie int error; 352303980Sngie 353303980Sngie if (socketpair(AF_UNIX, SOCK_STREAM, 0, syncfds) == -1) 354303980Sngie ERRX(EXIT_FAILURE, "socketpair (%s)", strerror(errno)); 355303980Sngie 356303980Sngie switch ((pid = fork())) { 357303980Sngie case 0: 358303980Sngie receiver(syncfds[0], host, port, n, conn, bug); 359303980Sngie return; 360303980Sngie case -1: 361303980Sngie ERRX(EXIT_FAILURE, "fork (%s)", strerror(errno)); 362303980Sngie default: 363303980Sngie error = sender(syncfds[1], host, port, n, conn, bug); 364303980Sngie again: 365303980Sngie switch (waitpid(pid, &status, WNOHANG)) { 366303980Sngie case -1: 367303980Sngie ERRX(EXIT_FAILURE, "wait (%s)", strerror(errno)); 368303980Sngie case 0: 369303980Sngie if (error == 0) 370303980Sngie /* 371303980Sngie * Receiver is still alive, but we know 372303980Sngie * it will exit soon. 373303980Sngie */ 374303980Sngie goto again; 375303980Sngie 376303980Sngie if (kill(pid, SIGTERM) == -1) 377303980Sngie ERRX(EXIT_FAILURE, "kill (%s)", 378303980Sngie strerror(errno)); 379303980Sngie goto again; 380303980Sngie default: 381303980Sngie if (WIFSIGNALED(status)) { 382303980Sngie if (WTERMSIG(status) == SIGTERM) 383303980Sngie ERRX0(EXIT_FAILURE, 384303980Sngie "receiver failed and was killed" \ 385303980Sngie "by sender"); 386303980Sngie else 387303980Sngie ERRX(EXIT_FAILURE, 388303980Sngie "receiver got signaled (%s)", 389303980Sngie strsignal(WTERMSIG(status))); 390303980Sngie } else if (WIFEXITED(status)) { 391303980Sngie if (WEXITSTATUS(status) != 0) 392303980Sngie ERRX(EXIT_FAILURE, 393303980Sngie "receiver exited with status %d", 394303980Sngie WEXITSTATUS(status)); 395303980Sngie } else { 396303980Sngie ERRX(EXIT_FAILURE, 397303980Sngie "receiver exited with unexpected status %d", 398303980Sngie status); 399303980Sngie } 400303980Sngie break; 401303980Sngie } 402303980Sngie return; 403303980Sngie } 404303980Sngie} 405303980Sngie 406303980Sngie#ifndef ATF 407303980Sngieint 408303980Sngiemain(int argc, char *argv[]) 409303980Sngie{ 410303980Sngie const char *host, *port; 411303980Sngie int c; 412303980Sngie size_t n; 413303980Sngie bool conn, bug; 414303980Sngie 415303980Sngie host = HOST_V4; 416303980Sngie port = PORT_V4; 417303980Sngie n = TOTAL; 418303980Sngie bug = conn = false; 419303980Sngie 420303980Sngie while ((c = getopt(argc, argv, "46bcdmn:")) != -1) 421303980Sngie switch (c) { 422303980Sngie case '4': 423303980Sngie host = HOST_V4; 424303980Sngie port = PORT_V4; 425303980Sngie break; 426303980Sngie case '6': 427303980Sngie host = HOST_V6; 428303980Sngie port = PORT_V6; 429303980Sngie break; 430303980Sngie case 'b': 431303980Sngie bug = true; 432303980Sngie break; 433303980Sngie case 'c': 434303980Sngie conn = true; 435303980Sngie break; 436303980Sngie case 'd': 437303980Sngie debug++; 438303980Sngie break; 439303980Sngie case 'm': 440303980Sngie host = HOST_V4MAPPED; 441303980Sngie port = PORT_V4MAPPED; 442303980Sngie break; 443303980Sngie case 'n': 444303980Sngie n = atoi(optarg); 445303980Sngie break; 446303980Sngie default: 447303980Sngie fprintf(stderr, "Usage: %s [-cdm46] [-n <tot>]", 448303980Sngie getprogname()); 449303980Sngie return 1; 450303980Sngie } 451303980Sngie 452303980Sngie run(host, port, n, conn, bug); 453303980Sngie return 0; 454303980Sngie} 455303980Sngie#else 456303980Sngie 457303980SngieATF_TC(conninet4); 458303980SngieATF_TC_HEAD(conninet4, tc) 459303980Sngie{ 460303980Sngie atf_tc_set_md_var(tc, "descr", "Checks connected multicast for ipv4"); 461303980Sngie} 462303980Sngie 463303980SngieATF_TC_BODY(conninet4, tc) 464303980Sngie{ 465303980Sngie run(HOST_V4, PORT_V4, TOTAL, true, false); 466303980Sngie} 467303980Sngie 468303980SngieATF_TC(connmappedinet4); 469303980SngieATF_TC_HEAD(connmappedinet4, tc) 470303980Sngie{ 471303980Sngie atf_tc_set_md_var(tc, "descr", "Checks connected multicast for mapped ipv4"); 472303980Sngie} 473303980Sngie 474303980SngieATF_TC_BODY(connmappedinet4, tc) 475303980Sngie{ 476303980Sngie run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, true, false); 477303980Sngie} 478303980Sngie 479303980SngieATF_TC(connmappedbuginet4); 480303980SngieATF_TC_HEAD(connmappedbuginet4, tc) 481303980Sngie{ 482303980Sngie atf_tc_set_md_var(tc, "descr", "Checks connected multicast for mapped ipv4 using the v4 ioctls"); 483303980Sngie} 484303980Sngie 485303980SngieATF_TC_BODY(connmappedbuginet4, tc) 486303980Sngie{ 487303980Sngie run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, true, true); 488303980Sngie} 489303980Sngie 490303980SngieATF_TC(conninet6); 491303980SngieATF_TC_HEAD(conninet6, tc) 492303980Sngie{ 493303980Sngie atf_tc_set_md_var(tc, "descr", "Checks connected multicast for ipv6"); 494303980Sngie} 495303980Sngie 496303980SngieATF_TC_BODY(conninet6, tc) 497303980Sngie{ 498303980Sngie run(HOST_V6, PORT_V6, TOTAL, true, false); 499303980Sngie} 500303980Sngie 501303980SngieATF_TC(unconninet4); 502303980SngieATF_TC_HEAD(unconninet4, tc) 503303980Sngie{ 504303980Sngie atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for ipv4"); 505303980Sngie} 506303980Sngie 507303980SngieATF_TC_BODY(unconninet4, tc) 508303980Sngie{ 509303980Sngie run(HOST_V4, PORT_V4, TOTAL, false, false); 510303980Sngie} 511303980Sngie 512303980SngieATF_TC(unconnmappedinet4); 513303980SngieATF_TC_HEAD(unconnmappedinet4, tc) 514303980Sngie{ 515303980Sngie atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for mapped ipv4"); 516303980Sngie} 517303980Sngie 518303980SngieATF_TC_BODY(unconnmappedinet4, tc) 519303980Sngie{ 520303980Sngie run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, false, false); 521303980Sngie} 522303980Sngie 523303980SngieATF_TC(unconnmappedbuginet4); 524303980SngieATF_TC_HEAD(unconnmappedbuginet4, tc) 525303980Sngie{ 526303980Sngie atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for mapped ipv4 using the v4 ioctls"); 527303980Sngie} 528303980Sngie 529303980SngieATF_TC_BODY(unconnmappedbuginet4, tc) 530303980Sngie{ 531303980Sngie run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, false, true); 532303980Sngie} 533303980Sngie 534303980SngieATF_TC(unconninet6); 535303980SngieATF_TC_HEAD(unconninet6, tc) 536303980Sngie{ 537303980Sngie atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for ipv6"); 538303980Sngie} 539303980Sngie 540303980SngieATF_TC_BODY(unconninet6, tc) 541303980Sngie{ 542303980Sngie run(HOST_V6, PORT_V6, TOTAL, false, false); 543303980Sngie} 544303980Sngie 545303980SngieATF_TP_ADD_TCS(tp) 546303980Sngie{ 547303980Sngie debug++; 548303980Sngie ATF_TP_ADD_TC(tp, conninet4); 549303980Sngie ATF_TP_ADD_TC(tp, connmappedinet4); 550303980Sngie ATF_TP_ADD_TC(tp, connmappedbuginet4); 551303980Sngie ATF_TP_ADD_TC(tp, conninet6); 552303980Sngie ATF_TP_ADD_TC(tp, unconninet4); 553303980Sngie ATF_TP_ADD_TC(tp, unconnmappedinet4); 554303980Sngie ATF_TP_ADD_TC(tp, unconnmappedbuginet4); 555303980Sngie ATF_TP_ADD_TC(tp, unconninet6); 556303980Sngie 557303980Sngie return atf_no_error(); 558303980Sngie} 559303980Sngie#endif 560