1 /*
2 * Copyright (c) 2025 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <darwintest.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32
33 #include "net_test_lib.h"
34
35 network_interface interface;
36
37 static void
cleanup(void)38 cleanup(void)
39 {
40 network_interface_destroy(&interface);
41 }
42
43 T_DECL(net_multicast_igmp_ssm, "IGMP SSM test", T_META_ASROOT(true))
44 {
45 int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
46
47 T_ATEND(cleanup);
48 network_interface_create(&interface, FETH_NAME);
49 struct in_addr addr;
50 addr.s_addr = inet_addr("192.168.55.1");
51 struct in_addr mask;
52 mask.s_addr = inet_addr("255.255.255.0");
53 ifnet_add_ip_address(interface.if_name, addr, mask);
54
55 struct ip_mreq_source mr = {};
56 mr.imr_sourceaddr.s_addr = inet_addr("192.168.55.2");
57 mr.imr_multiaddr.s_addr = inet_addr("239.1.2.3");
58 mr.imr_interface.s_addr = INADDR_ANY;
59
60 for (int i = 0; i < 20; i++) {
61 mr.imr_sourceaddr.s_addr += i;
62 T_ASSERT_POSIX_SUCCESS(setsockopt(s, IPPROTO_IP,
63 IP_ADD_SOURCE_MEMBERSHIP, &mr,
64 sizeof(mr)),
65 "IP_ADD_SOURCE_MEMBERSHIP");
66 }
67 close(s);
68 }
69
70 T_DECL(net_multicast_mld_ssm, "MLD SSM test", T_META_ASROOT(true))
71 {
72 int s6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
73
74 T_ATEND(cleanup);
75 network_interface_create(&interface, FETH_NAME);
76 ifnet_start_ipv6(interface.if_name);
77
78 struct sockaddr_storage group_storage = {}, source_storage = {};
79
80 struct sockaddr_in6 *group = (struct sockaddr_in6 *)&group_storage;
81
82 group->sin6_family = AF_INET6;
83 group->sin6_len = sizeof(*group);
84 char address[128] = {};
85 snprintf(address, sizeof(address), "ff02::1234%%%s", interface.if_name);
86 inet_pton(AF_INET6, address, &group->sin6_addr);
87
88 struct sockaddr_in6 *source = (struct sockaddr_in6 *)&source_storage;
89 source->sin6_family = AF_INET6;
90 source->sin6_len = sizeof(*source);
91 inet_pton(AF_INET6, "2001:db8::1", &source->sin6_addr);
92
93 struct group_source_req gr = {};
94 gr.gsr_interface = interface.if_index;
95 gr.gsr_group = group_storage;
96 gr.gsr_source = source_storage;
97
98 for (int i = 0; i < 20; i++) {
99 ((struct sockaddr_in6 *)&gr.gsr_source)->sin6_addr.__u6_addr.__u6_addr8[15] += i;
100 T_ASSERT_POSIX_SUCCESS(setsockopt(s6, IPPROTO_IPV6,
101 MCAST_JOIN_SOURCE_GROUP, &gr,
102 sizeof(gr)),
103 "MCAST_JOIN_SOURCE_GROUP");
104 }
105 }
106