Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/netinet/broadcast.c
39483 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2025 Gleb Smirnoff <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/param.h>
29
#include <sys/socket.h>
30
#include <netinet/in.h>
31
#include <net/if.h>
32
#include <arpa/inet.h>
33
#include <errno.h>
34
#include <ifaddrs.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <unistd.h>
39
40
#include <atf-c.h>
41
42
static const char buf[] = "Hello";
43
44
/* Create a UDP socket with SO_BROADCAST set. */
45
static int
46
bcastsock(void)
47
{
48
int s;
49
50
ATF_REQUIRE((s = socket(PF_INET, SOCK_DGRAM, 0)) > 0);
51
ATF_REQUIRE(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &(int){1},
52
sizeof(int)) == 0);
53
return (s);
54
}
55
56
/* Send on socket 's' with address 'to', confirm receive on 'r'. */
57
static void
58
bcastecho(int s, struct sockaddr_in *to, int r)
59
{
60
char rbuf[sizeof(buf)];
61
62
printf("Sending to %s\n", inet_ntoa(to->sin_addr));
63
ATF_REQUIRE_MSG(sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)to,
64
sizeof(*to)) == sizeof(buf), "sending of broadcast failed: %d",
65
errno);
66
ATF_REQUIRE(recv(r, rbuf, sizeof(rbuf), 0) == sizeof(rbuf));
67
ATF_REQUIRE_MSG(memcmp(buf, rbuf, sizeof(buf)) == 0,
68
"failed to receive own broadcast");
69
}
70
71
/* Find a first broadcast capable interface and copy its broadcast address. */
72
static void
73
firstbcast(struct in_addr *out)
74
{
75
struct ifaddrs *ifa0, *ifa;
76
struct sockaddr_in sin;
77
78
ATF_REQUIRE(getifaddrs(&ifa0) == 0);
79
for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next)
80
if (ifa->ifa_addr->sa_family == AF_INET &&
81
(ifa->ifa_flags & IFF_BROADCAST))
82
break;
83
if (ifa == NULL) {
84
freeifaddrs(ifa0);
85
atf_tc_skip("No broadcast address found");
86
}
87
memcpy(&sin, ifa->ifa_broadaddr, sizeof(struct sockaddr_in));
88
*out = sin.sin_addr;
89
freeifaddrs(ifa0);
90
}
91
92
/* Application sends to INADDR_BROADCAST, and this goes on the wire. */
93
ATF_TC(INADDR_BROADCAST);
94
ATF_TC_HEAD(INADDR_BROADCAST, tc)
95
{
96
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
97
}
98
ATF_TC_BODY(INADDR_BROADCAST, tc)
99
{
100
struct sockaddr_in sin = {
101
.sin_family = AF_INET,
102
.sin_len = sizeof(struct sockaddr_in),
103
};
104
socklen_t slen = sizeof(sin);
105
int l, s;
106
107
l = bcastsock();
108
ATF_REQUIRE(bind(l, (struct sockaddr *)&sin, sizeof(sin)) == 0);
109
ATF_REQUIRE(getsockname(l, (struct sockaddr *)&sin, &slen) == 0);
110
sin.sin_addr.s_addr = htonl(INADDR_BROADCAST);
111
112
s = bcastsock();
113
bcastecho(s, &sin, l);
114
115
close(s);
116
close(l);
117
}
118
119
/*
120
* Application sends on broadcast address of an interface, INADDR_BROADCAST
121
* goes on the wire of the selected interface.
122
*/
123
ATF_TC_WITHOUT_HEAD(IP_ONESBCAST);
124
ATF_TC_BODY(IP_ONESBCAST, tc)
125
{
126
struct ifaddrs *ifa0, *ifa;
127
struct sockaddr_in sin = {
128
.sin_family = AF_INET,
129
.sin_len = sizeof(struct sockaddr_in),
130
};
131
socklen_t slen = sizeof(sin);
132
int s, l;
133
in_port_t port;
134
bool skip = true;
135
136
s = bcastsock();
137
ATF_REQUIRE(setsockopt(s, IPPROTO_IP, IP_ONESBCAST, &(int){1},
138
sizeof(int)) == 0);
139
140
l = bcastsock();
141
ATF_REQUIRE(bind(l, (struct sockaddr *)&sin, sizeof(sin)) == 0);
142
ATF_REQUIRE(getsockname(l, (struct sockaddr *)&sin, &slen) == 0);
143
port = sin.sin_port;
144
145
ATF_REQUIRE(getifaddrs(&ifa0) == 0);
146
for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) {
147
if (ifa->ifa_addr->sa_family != AF_INET)
148
continue;
149
if (!(ifa->ifa_flags & IFF_BROADCAST))
150
continue;
151
skip = false;
152
memcpy(&sin, ifa->ifa_broadaddr, sizeof(struct sockaddr_in));
153
sin.sin_port = port;
154
bcastecho(s, &sin, l);
155
}
156
freeifaddrs(ifa0);
157
close(s);
158
close(l);
159
if (skip)
160
atf_tc_skip("No broadcast address found");
161
}
162
163
/*
164
* Application sends on broadcast address of an interface, and this is what
165
* goes out the wire.
166
*/
167
ATF_TC_WITHOUT_HEAD(local_broadcast);
168
ATF_TC_BODY(local_broadcast, tc)
169
{
170
struct sockaddr_in sin = {
171
.sin_family = AF_INET,
172
.sin_len = sizeof(struct sockaddr_in),
173
};
174
socklen_t slen = sizeof(sin);
175
int s, l;
176
177
s = bcastsock();
178
l = bcastsock();
179
ATF_REQUIRE(bind(l, (struct sockaddr *)&sin, sizeof(sin)) == 0);
180
ATF_REQUIRE(getsockname(l, (struct sockaddr *)&sin, &slen) == 0);
181
firstbcast(&sin.sin_addr);
182
183
bcastecho(s, &sin, l);
184
185
close(s);
186
close(l);
187
}
188
189
ATF_TP_ADD_TCS(tp)
190
{
191
ATF_TP_ADD_TC(tp, INADDR_BROADCAST);
192
ATF_TP_ADD_TC(tp, IP_ONESBCAST);
193
ATF_TP_ADD_TC(tp, local_broadcast);
194
195
return (atf_no_error());
196
}
197
198