/src/SockFuzzer/fuzz/net_fuzzer.cc
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2021 Google LLC |
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 <fuzzer/FuzzedDataProvider.h> |
30 | | #include <stddef.h> |
31 | | #include <stdint.h> |
32 | | #include <string.h> |
33 | | |
34 | | #include <iostream> |
35 | | #include <memory> |
36 | | #include <vector> |
37 | | |
38 | | #include "net_fuzzer.pb.h" |
39 | | #include "src/libfuzzer/libfuzzer_macro.h" |
40 | | |
41 | | extern "C" { |
42 | | #include "api/backend.h" |
43 | | #include "api/syscall_wrappers.h" |
44 | | #include "types.h" |
45 | | } |
46 | | |
47 | | /* |
48 | | TODO(nedwill) |
49 | | |
50 | | Fuzz vsock domain |
51 | | */ |
52 | | |
53 | | // TODO(nedwill): support multiple addresses of each type below, |
54 | | // not just one of each type |
55 | 747k | void get_in6_addr(struct in6_addr *sai, enum In6Addr addr) { |
56 | 747k | memset(sai, 0, sizeof(*sai)); |
57 | 747k | switch (addr) { |
58 | 5.57k | case IN6_ADDR_SELF: { |
59 | 5.57k | sai->__u6_addr.__u6_addr32[0] = 16810238; |
60 | 5.57k | sai->__u6_addr.__u6_addr32[0] = 0; |
61 | 5.57k | sai->__u6_addr.__u6_addr32[0] = 0; |
62 | 5.57k | sai->__u6_addr.__u6_addr32[0] = 16777216; |
63 | | // assert(IN6_IS_ADDR_SELF(sai)); |
64 | 5.57k | break; |
65 | 0 | } |
66 | 3.30k | case IN6_ADDR_LINK_LOCAL: { |
67 | 3.30k | sai->s6_addr[0] = 0xfe; |
68 | 3.30k | sai->s6_addr[1] = 0x80; |
69 | | // TODO(nedwill): set other fields? |
70 | 3.30k | assert(IN6_IS_ADDR_LINKLOCAL(sai)); |
71 | 3.30k | break; |
72 | 3.30k | } |
73 | 351k | case IN6_ADDR_LOOPBACK: { |
74 | 351k | *sai = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)addr}; |
75 | 351k | assert(IN6_IS_ADDR_LOOPBACK(sai)); |
76 | 351k | break; |
77 | 351k | } |
78 | 351k | case IN6_ADDR_REAL: |
79 | 11.4k | case MAYBE_LOCALHOST: { |
80 | 11.4k | *sai = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)addr}; |
81 | 11.4k | break; |
82 | 10.6k | } |
83 | 4.49k | case IN6_ADDR_V4COMPAT: { |
84 | 4.49k | sai->s6_addr[12] = 1; |
85 | 4.49k | assert(IN6_IS_ADDR_V4COMPAT(sai)); |
86 | 4.49k | break; |
87 | 4.49k | } |
88 | 31.1k | case IN6_ADDR_V4MAPPED: { |
89 | 31.1k | *(uint32_t *)&sai->s6_addr[8] = 0xffff0000; |
90 | 31.1k | assert(IN6_IS_ADDR_V4MAPPED(sai)); |
91 | 31.1k | break; |
92 | 31.1k | } |
93 | 31.1k | case IN6_ADDR_6TO4: { |
94 | 632 | sai->s6_addr16[0] = ntohs(0x2002); |
95 | 632 | assert(IN6_IS_ADDR_6TO4(sai)); |
96 | 632 | break; |
97 | 632 | } |
98 | 4.27k | case IN6_ADDR_LINKLOCAL: { |
99 | 4.27k | sai->s6_addr[0] = 0xfe; |
100 | 4.27k | sai->s6_addr[1] = 0x80; |
101 | 4.27k | assert(IN6_IS_ADDR_LINKLOCAL(sai)); |
102 | 4.27k | break; |
103 | 4.27k | } |
104 | 4.27k | case IN6_ADDR_SITELOCAL: { |
105 | 1.04k | sai->s6_addr[0] = 0xfe; |
106 | 1.04k | sai->s6_addr[1] = 0xc0; |
107 | 1.04k | assert(IN6_IS_ADDR_SITELOCAL(sai)); |
108 | 1.04k | break; |
109 | 1.04k | } |
110 | 2.83k | case IN6_ADDR_MULTICAST: { |
111 | 2.83k | sai->s6_addr[0] = 0xff; |
112 | 2.83k | assert(IN6_IS_ADDR_MULTICAST(sai)); |
113 | 2.83k | break; |
114 | 2.83k | } |
115 | 2.83k | case IN6_ADDR_UNIQUE_LOCAL: { |
116 | 1.76k | sai->s6_addr[0] = 0xfc; |
117 | 1.76k | assert(IN6_IS_ADDR_UNIQUE_LOCAL(sai)); |
118 | 1.76k | break; |
119 | 1.76k | } |
120 | 1.76k | case IN6_ADDR_MC_NODELOCAL: { |
121 | 1.54k | sai->s6_addr[0] = 0xff; |
122 | 1.54k | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_NODELOCAL; |
123 | 1.54k | assert(IN6_IS_ADDR_MC_NODELOCAL(sai)); |
124 | 1.54k | break; |
125 | 1.54k | } |
126 | 1.54k | case IN6_ADDR_MC_INTFACELOCAL: { |
127 | 510 | sai->s6_addr[0] = 0xff; |
128 | 510 | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_INTFACELOCAL; |
129 | 510 | assert(IN6_IS_ADDR_MC_INTFACELOCAL(sai)); |
130 | 510 | break; |
131 | 510 | } |
132 | 13.7k | case IN6_ADDR_MC_LINKLOCAL: { |
133 | 13.7k | sai->s6_addr[0] = 0xff; |
134 | 13.7k | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_LINKLOCAL; |
135 | 13.7k | assert(IN6_IS_ADDR_MC_LINKLOCAL(sai)); |
136 | 13.7k | break; |
137 | 13.7k | } |
138 | 13.7k | case IN6_ADDR_MC_SITELOCAL: { |
139 | 1.99k | sai->s6_addr[0] = 0xff; |
140 | 1.99k | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_SITELOCAL; |
141 | 1.99k | assert(IN6_IS_ADDR_MC_SITELOCAL(sai)); |
142 | 1.99k | break; |
143 | 1.99k | } |
144 | 1.99k | case IN6_ADDR_MC_ORGLOCAL: { |
145 | 555 | sai->s6_addr[0] = 0xff; |
146 | 555 | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_ORGLOCAL; |
147 | 555 | assert(IN6_IS_ADDR_MC_ORGLOCAL(sai)); |
148 | 555 | break; |
149 | 555 | } |
150 | 1.02k | case IN6_ADDR_MC_GLOBAL: { |
151 | 1.02k | sai->s6_addr[0] = 0xff; |
152 | 1.02k | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_GLOBAL; |
153 | 1.02k | assert(IN6_IS_ADDR_MC_GLOBAL(sai)); |
154 | 1.02k | break; |
155 | 1.02k | } |
156 | 10.1k | case IN6_ADDR_UNSPECIFIED: |
157 | 307k | case IN6_ADDR_ANY: { |
158 | 307k | assert(IN6_IS_ADDR_UNSPECIFIED(sai)); |
159 | 307k | break; |
160 | 307k | } |
161 | 307k | case IN6_ADDR_LOCAL_ADDRESS: { |
162 | | // Discovered this address dynamically |
163 | | // fe80:0001:0000:0000:a8aa:aaaa:aaaa:aaaa |
164 | 2.30k | sai->s6_addr16[0] = 0xfe80; |
165 | 2.30k | sai->s6_addr16[1] = 0x0001; |
166 | 2.30k | sai->s6_addr16[4] = 0xa8aa; |
167 | 2.30k | sai->s6_addr16[5] = 0xaaaa; |
168 | 2.30k | sai->s6_addr16[6] = 0xaaaa; |
169 | 2.30k | sai->s6_addr16[7] = 0xaaaa; |
170 | 2.30k | } |
171 | | // *sai = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)addr}; |
172 | 747k | } |
173 | 747k | } |
174 | | |
175 | 115k | void get_sockaddr6(struct sockaddr_in6 *sai, const SockAddr6 &sa6) { |
176 | 115k | sai->sin6_len = sizeof(struct sockaddr_in6); |
177 | 115k | sai->sin6_family = (sa_family_t)AF_INET6; // sa6.family(); |
178 | 115k | sai->sin6_port = (in_port_t)sa6.port(); |
179 | 115k | sai->sin6_flowinfo = sa6.flow_info(); |
180 | 115k | get_in6_addr(&sai->sin6_addr, sa6.sin6_addr()); |
181 | 115k | sai->sin6_scope_id = sa6.sin6_scope_id(); |
182 | 115k | } |
183 | | |
184 | 1.47M | std::string get_sockaddr(const SockAddr &sockaddr) { |
185 | 1.47M | std::string dat; |
186 | 1.47M | switch (sockaddr.sockaddr_case()) { |
187 | 115k | case SockAddr::kSockaddrGeneric: { |
188 | 115k | const SockAddrGeneric &sag = sockaddr.sockaddr_generic(); |
189 | | // data size + sizeof(sa_len) + sizeof(sa_family) |
190 | 115k | struct sockaddr_generic sag_s = { |
191 | 115k | .sa_len = (uint8_t)(sizeof(sockaddr_generic) + sag.sa_data().size()), |
192 | 115k | .sa_family = (uint8_t)sag.sa_family(), |
193 | 115k | }; |
194 | | |
195 | 115k | dat = std::string((char *)&sag_s, (char *)&sag_s + sizeof(sag_s)); |
196 | 115k | dat += sag.sa_data(); |
197 | 115k | break; |
198 | 0 | } |
199 | 70.5k | case SockAddr::kSockaddr4: { |
200 | 70.5k | struct sockaddr_in sai = { |
201 | 70.5k | .sin_len = sizeof(struct sockaddr_in), |
202 | 70.5k | .sin_family = |
203 | 70.5k | AF_INET, // (unsigned char)sockaddr.sockaddr4().sin_family(), |
204 | 70.5k | .sin_port = (unsigned short)sockaddr.sockaddr4().sin_port(), |
205 | 70.5k | .sin_addr = {(unsigned int)sockaddr.sockaddr4().sin_addr()}, |
206 | 70.5k | .sin_zero = {}, |
207 | 70.5k | }; |
208 | 70.5k | dat = std::string((char *)&sai, (char *)&sai + sizeof(sai)); |
209 | 70.5k | break; |
210 | 0 | } |
211 | 48.5k | case SockAddr::kSockaddr6: { |
212 | 48.5k | struct sockaddr_in6 sai = {}; |
213 | 48.5k | get_sockaddr6(&sai, sockaddr.sockaddr6()); |
214 | 48.5k | dat = std::string((char *)&sai, (char *)&sai + sizeof(sai)); |
215 | 48.5k | break; |
216 | 0 | } |
217 | | // case SockAddr::kRawBytes: { |
218 | | // dat = sockaddr.raw_bytes(); |
219 | | // break; |
220 | | // } |
221 | 1.23M | case SockAddr::SOCKADDR_NOT_SET: { |
222 | 1.23M | break; |
223 | 0 | } |
224 | 1.47M | } |
225 | 1.47M | return dat; |
226 | 1.47M | } |
227 | | |
228 | 316k | std::string get_ip6_hdr(const Ip6Hdr &hdr, uint16_t expected_size) { |
229 | 316k | struct ip6_hdr ip6_hdr; |
230 | 316k | memset(&ip6_hdr, 0, sizeof(ip6_hdr)); |
231 | 316k | get_in6_addr(&ip6_hdr.ip6_src, hdr.ip6_src()); |
232 | 316k | get_in6_addr(&ip6_hdr.ip6_dst, hdr.ip6_src()); |
233 | 316k | ip6_hdr.ip6_ctlun.ip6_un2_vfc = IPV6_VERSION; |
234 | | // How TF does flow work? |
235 | | // ip6_hdr.ip6_ctlun.ip6_un1.ip6_un1_flow = hdr.ip6_hdrctl().ip6_un1_flow(); |
236 | 316k | ip6_hdr.ip6_ctlun.ip6_un1.ip6_un1_plen = |
237 | 316k | __builtin_bswap16(expected_size); // hdr.ip6_hdrctl().ip6_un1_plen(); |
238 | 316k | ip6_hdr.ip6_ctlun.ip6_un1.ip6_un1_nxt = hdr.ip6_hdrctl().ip6_un1_nxt(); |
239 | 316k | ip6_hdr.ip6_ctlun.ip6_un1.ip6_un1_hlim = hdr.ip6_hdrctl().ip6_un1_hlim(); |
240 | 316k | std::string dat((char *)&ip6_hdr, (char *)&ip6_hdr + sizeof(ip6_hdr)); |
241 | 316k | return dat; |
242 | 316k | } |
243 | | |
244 | 234k | std::string get_ip_hdr(const IpHdr &hdr, size_t expected_size) { |
245 | 234k | struct in_addr ip_src = {.s_addr = (unsigned int)hdr.ip_src()}; |
246 | 234k | struct in_addr ip_dst = {.s_addr = (unsigned int)hdr.ip_dst()}; |
247 | 234k | struct ip ip_hdr = { |
248 | 234k | .ip_hl = 5, // TODO(nedwill): support options // hdr.ip_hl(), |
249 | 234k | .ip_v = IPV4, // hdr.ip_v(), |
250 | 234k | .ip_tos = (u_char)hdr.ip_tos(), |
251 | 234k | .ip_len = (u_short)__builtin_bswap16(expected_size), |
252 | 234k | .ip_id = (u_short)hdr.ip_id(), |
253 | 234k | .ip_off = (u_short)hdr.ip_off(), |
254 | 234k | .ip_ttl = (u_char)hdr.ip_ttl(), |
255 | 234k | .ip_p = (u_char)hdr.ip_p(), |
256 | 234k | .ip_sum = 0, |
257 | 234k | .ip_src = ip_src, |
258 | 234k | .ip_dst = ip_dst, |
259 | 234k | }; |
260 | 234k | std::string dat((char *)&ip_hdr, (char *)&ip_hdr + sizeof(ip_hdr)); |
261 | 234k | return dat; |
262 | 234k | } |
263 | | |
264 | | // message TcpHdr { |
265 | | // required Port th_sport = 1; |
266 | | // required Port th_dport = 2; |
267 | | // required uint32 th_seq = 3; |
268 | | // required uint32 th_ack = 4; |
269 | | // required uint32 th_off = 5; |
270 | | // repeated TcpFlag th_flags = 6; |
271 | | // required uint32 th_win = 7; |
272 | | // required uint32 th_sum = 8; |
273 | | // required uint32 th_urp = 9; |
274 | | // } |
275 | | |
276 | 71.9k | std::string get_tcp_hdr(const TcpHdr &hdr) { |
277 | 71.9k | struct tcphdr tcphdr = { |
278 | 71.9k | .th_sport = (unsigned short)hdr.th_sport(), |
279 | 71.9k | .th_dport = (unsigned short)hdr.th_dport(), |
280 | 71.9k | .th_seq = __builtin_bswap32(hdr.th_seq()), |
281 | 71.9k | .th_ack = __builtin_bswap32(hdr.th_ack()), |
282 | 71.9k | .th_off = hdr.th_off(), |
283 | 71.9k | .th_flags = 0, |
284 | 71.9k | .th_win = (unsigned short)hdr.th_win(), |
285 | 71.9k | .th_sum = 0, |
286 | 71.9k | .th_urp = (unsigned short)hdr.th_urp(), |
287 | 71.9k | }; |
288 | | |
289 | 71.9k | for (const int flag : hdr.th_flags()) { |
290 | 24.2k | tcphdr.th_flags ^= flag; |
291 | 24.2k | } |
292 | | |
293 | | // Prefer pure syn |
294 | 71.9k | if (hdr.is_pure_syn()) { |
295 | 3.96k | tcphdr.th_flags &= ~(TH_RST | TH_ACK); |
296 | 3.96k | tcphdr.th_flags |= TH_SYN; |
297 | 67.9k | } else if (hdr.is_pure_ack()) { |
298 | 3.97k | tcphdr.th_flags &= ~(TH_RST | TH_SYN); |
299 | 3.97k | tcphdr.th_flags |= TH_ACK; |
300 | 3.97k | } |
301 | | |
302 | 71.9k | std::string dat((char *)&tcphdr, (char *)&tcphdr + sizeof(tcphdr)); |
303 | 71.9k | return dat; |
304 | 71.9k | } |
305 | | |
306 | 0 | std::string get_icmp6_hdr(const Icmp6Hdr &hdr) { |
307 | 0 | struct icmp6_hdr icmp6_hdr = { |
308 | 0 | .icmp6_type = (uint8_t)hdr.icmp6_type(), |
309 | 0 | .icmp6_code = (uint8_t)hdr.icmp6_code(), |
310 | 0 | .icmp6_cksum = 0, |
311 | 0 | }; |
312 | 0 | icmp6_hdr.icmp6_dataun.icmp6_un_data32[0] = hdr.icmp6_dataun(); |
313 | |
|
314 | 0 | std::string dat((char *)&icmp6_hdr, (char *)&icmp6_hdr + sizeof(icmp6_hdr)); |
315 | 0 | return dat; |
316 | 0 | } |
317 | | |
318 | 0 | std::string get_ip6_route_hdr(const Ip6RtHdr &hdr) { |
319 | 0 | struct ip6_rthdr ip6_rthdr = { |
320 | 0 | .ip6r_nxt = (uint8_t)hdr.ip6r_nxt(), |
321 | 0 | .ip6r_len = (uint8_t)hdr.ip6r_len(), |
322 | 0 | .ip6r_type = (uint8_t)hdr.ip6r_type(), |
323 | 0 | .ip6r_segleft = (uint8_t)hdr.ip6r_segleft(), |
324 | 0 | }; |
325 | |
|
326 | 0 | std::string dat((char *)&ip6_rthdr, (char *)&ip6_rthdr + sizeof(ip6_rthdr)); |
327 | 0 | return dat; |
328 | 0 | } |
329 | | |
330 | 0 | std::string get_ip6_route0_hdr(const Ip6Rt0Hdr &hdr) { |
331 | 0 | struct ip6_rthdr0 ip6_rthdr0 = {}; |
332 | 0 | ip6_rthdr0.ip6r0_nxt = hdr.ip6r0_nxt(); |
333 | 0 | ip6_rthdr0.ip6r0_len = hdr.ip6r0_len(); |
334 | 0 | ip6_rthdr0.ip6r0_type = hdr.ip6r0_type(); |
335 | 0 | ip6_rthdr0.ip6r0_segleft = hdr.ip6r0_segleft(); |
336 | 0 | ip6_rthdr0.ip6r0_reserved = hdr.ip6r0_reserved(); |
337 | 0 | *(uint32_t *)&ip6_rthdr0.ip6r0_slmap[0] = hdr.ip6r0_slmap(); |
338 | |
|
339 | 0 | int i = 0; |
340 | 0 | for (int in6addr : hdr.ip6r0_addr()) { |
341 | 0 | if (i >= 23) { |
342 | 0 | break; |
343 | 0 | } |
344 | | |
345 | 0 | get_in6_addr(&ip6_rthdr0.ip6r0_addr[i], (In6Addr)in6addr); |
346 | |
|
347 | 0 | i++; |
348 | 0 | } |
349 | |
|
350 | 0 | std::string dat((char *)&ip6_rthdr0, |
351 | 0 | (char *)&ip6_rthdr0 + sizeof(ip6_rthdr0)); |
352 | 0 | return dat; |
353 | 0 | } |
354 | | |
355 | 0 | std::string get_ip6_frag_hdr(const Ip6FragHdr &hdr) { |
356 | 0 | struct ip6_frag ip6_frag = { |
357 | 0 | .ip6f_nxt = (uint8_t)hdr.ip6f_nxt(), |
358 | 0 | .ip6f_reserved = (uint8_t)hdr.ip6f_reserved(), |
359 | 0 | .ip6f_offlg = (uint16_t)hdr.ip6f_offlg(), |
360 | 0 | .ip6f_ident = hdr.ip6f_ident(), |
361 | 0 | }; |
362 | |
|
363 | 0 | std::string dat((char *)&ip6_frag, (char *)&ip6_frag + sizeof(ip6_frag)); |
364 | 0 | return dat; |
365 | 0 | } |
366 | | |
367 | 0 | std::string get_ip6_ext(const Ip6Ext &hdr) { |
368 | 0 | struct ip6_ext ip6_ext = { |
369 | 0 | .ip6e_nxt = (uint8_t)hdr.ip6e_nxt(), |
370 | 0 | .ip6e_len = (uint8_t)hdr.ip6e_len(), |
371 | 0 | }; |
372 | |
|
373 | 0 | std::string dat((char *)&ip6_ext, (char *)&ip6_ext + sizeof(ip6_ext)); |
374 | 0 | return dat; |
375 | 0 | } |
376 | | |
377 | 0 | std::string GetNecpClient(const NecpClientId &necp_client_id) { |
378 | 0 | switch (necp_client_id) { |
379 | 0 | case CLIENT_0: { |
380 | 0 | return "0000000000000000"; |
381 | 0 | } |
382 | 0 | case CLIENT_1: { |
383 | 0 | return "1111111111111111"; |
384 | 0 | } |
385 | 0 | case CLIENT_2: { |
386 | 0 | return "2222222222222222"; |
387 | 0 | } |
388 | 0 | } |
389 | 0 | assert(false); |
390 | 0 | return ""; |
391 | 0 | } |
392 | | |
393 | | extern "C" { |
394 | | |
395 | | static FuzzedDataProvider *fdp = nullptr; |
396 | | |
397 | | // These are callbacks to let the C-based backend access the fuzzed input |
398 | | // stream. |
399 | 1.23M | void get_fuzzed_bytes(void *addr, size_t bytes) { |
400 | | // If we didn't initialize the fdp just clear the bytes. |
401 | 1.23M | if (!fdp) { |
402 | 2 | memset(addr, 0, bytes); |
403 | 2 | return; |
404 | 2 | } |
405 | 1.23M | memset(addr, 0, bytes); |
406 | 1.23M | std::vector<uint8_t> dat = fdp->ConsumeBytes<uint8_t>(bytes); |
407 | 1.23M | memcpy(addr, dat.data(), dat.size()); |
408 | 1.23M | } |
409 | | |
410 | 750k | bool get_fuzzed_bool(void) { |
411 | | // If we didn't initialize the fdp just return false. |
412 | 750k | if (!fdp) { |
413 | 0 | return false; |
414 | 0 | } |
415 | 750k | return fdp->ConsumeBool(); |
416 | 750k | } |
417 | | |
418 | 0 | int get_fuzzed_int32(int low, int high) { |
419 | 0 | return fdp->ConsumeIntegralInRange<int>(low, high); |
420 | 0 | } |
421 | | |
422 | 0 | unsigned int get_fuzzed_uint32(unsigned int low, unsigned int high) { |
423 | 0 | return fdp->ConsumeIntegralInRange<unsigned int>(low, high); |
424 | 0 | } |
425 | | |
426 | 0 | unsigned int get_remaining_bytes() { return fdp->remaining_bytes(); } |
427 | | |
428 | | static bool ready = false; |
429 | | |
430 | | bool initialize_network(void); |
431 | | |
432 | | extern unsigned long ioctls[]; |
433 | | extern int num_ioctls; |
434 | | extern const unsigned long siocaifaddr_in6_64; |
435 | | extern const unsigned long siocsifflags; |
436 | | |
437 | | // Enable this when copyout should work. |
438 | | extern bool real_copyout; |
439 | | |
440 | | void get_in6_addrlifetime_64(struct in6_addrlifetime_64 *sai, |
441 | 22.2k | const In6AddrLifetime_64 &msg) { |
442 | 22.2k | sai->ia6t_expire = msg.ia6t_expire(); |
443 | 22.2k | sai->ia6t_preferred = msg.ia6t_preferred(); |
444 | 22.2k | sai->ia6t_vltime = msg.ia6t_vltime(); |
445 | 22.2k | sai->ia6t_pltime = msg.ia6t_pltime(); |
446 | 22.2k | } |
447 | | |
448 | 90.0k | void get_ifr_name(void *dest, const IfrName name) { |
449 | 90.0k | switch (name) { |
450 | 90.0k | case LO0: { |
451 | 90.0k | memcpy(dest, "lo0", sizeof("lo0")); |
452 | 90.0k | break; |
453 | 0 | } |
454 | 0 | case STF0: { |
455 | 0 | memcpy(dest, "stf0", sizeof("stf0")); |
456 | 0 | break; |
457 | 0 | } |
458 | 90.0k | } |
459 | 90.0k | } |
460 | | |
461 | | // NECP client wrappers |
462 | | // TODO(nedwill): move these to their own file |
463 | | void necp_client_add(int fd, NecpClientId client_id, unsigned char *data, |
464 | 0 | size_t size) { |
465 | 0 | std::string client_id_s = GetNecpClient(client_id); |
466 | 0 | int retval = 0; |
467 | 0 | necp_client_action_wrapper(fd, NECP_CLIENT_ACTION_ADD, |
468 | | // parameters |
469 | 0 | (unsigned char *)client_id_s.data(), |
470 | 0 | client_id_s.size(), data, size, &retval); |
471 | 0 | } |
472 | | |
473 | | // TODO(nedwill): support flow_ifnet_stats |
474 | 0 | void necp_client_remove(int fd, NecpClientId client_id) { |
475 | 0 | std::string client_id_s = GetNecpClient(client_id); |
476 | 0 | int retval = 0; |
477 | 0 | necp_client_action_wrapper(fd, NECP_CLIENT_ACTION_REMOVE, |
478 | 0 | (unsigned char *)client_id_s.data(), |
479 | 0 | client_id_s.size(), nullptr, 0, &retval); |
480 | 0 | } |
481 | | |
482 | | void necp_client_copy_parameters(int fd, NecpClientId client_id, |
483 | 0 | uint32_t copyout_size) { |
484 | 0 | std::string client_id_s = GetNecpClient(client_id); |
485 | 0 | copyout_size %= 4096; |
486 | 0 | std::unique_ptr<uint8_t[]> copyout_buffer(new uint8_t[copyout_size]); |
487 | 0 | int retval = 0; |
488 | 0 | necp_client_action_wrapper(fd, NECP_CLIENT_ACTION_COPY_PARAMETERS, |
489 | 0 | (unsigned char *)client_id_s.data(), |
490 | 0 | client_id_s.size(), copyout_buffer.get(), |
491 | 0 | copyout_size, &retval); |
492 | 0 | } |
493 | | |
494 | | void necp_client_agent( |
495 | | int fd, NecpClientId client_id, |
496 | 0 | const ::google::protobuf::RepeatedPtrField<::NecpTlv> &necp_tlv) { |
497 | 0 | std::string client_id_s = GetNecpClient(client_id); |
498 | 0 | std::string parameters; |
499 | 0 | for (const NecpTlv &tlv : necp_tlv) { |
500 | | // std::string dat((char *)&icmp6_hdr, (char *)&icmp6_hdr + |
501 | | // sizeof(icmp6_hdr)); |
502 | 0 | struct necp_tlv_header header = { |
503 | 0 | .type = (uint8_t)tlv.necp_type(), |
504 | 0 | .length = (uint32_t)tlv.data().size(), |
505 | 0 | }; |
506 | 0 | std::string tlv_s((char *)&header, (char *)&header + sizeof(header)); |
507 | 0 | tlv_s += tlv.data(); |
508 | 0 | parameters += tlv_s; |
509 | 0 | } |
510 | 0 | int retval = 0; |
511 | 0 | necp_client_action_wrapper(fd, NECP_CLIENT_ACTION_AGENT, |
512 | 0 | (unsigned char *)client_id_s.data(), |
513 | 0 | client_id_s.size(), (uint8_t *)parameters.data(), |
514 | 0 | parameters.size(), &retval); |
515 | 0 | } |
516 | | |
517 | 0 | void DoNecpClientAction(const NecpClientAction &necp_client_action) { |
518 | 0 | switch (necp_client_action.action_case()) { |
519 | 0 | case NecpClientAction::kAdd: { |
520 | 0 | necp_client_add(necp_client_action.necp_fd(), |
521 | 0 | necp_client_action.client_id(), |
522 | 0 | (unsigned char *)necp_client_action.add().buffer().data(), |
523 | 0 | necp_client_action.add().buffer().size()); |
524 | 0 | break; |
525 | 0 | } |
526 | 0 | case NecpClientAction::kRemove: { |
527 | 0 | necp_client_remove(necp_client_action.necp_fd(), |
528 | 0 | necp_client_action.client_id()); |
529 | 0 | break; |
530 | 0 | } |
531 | 0 | case NecpClientAction::kCopyParameters: { |
532 | 0 | necp_client_copy_parameters( |
533 | 0 | necp_client_action.necp_fd(), necp_client_action.client_id(), |
534 | 0 | necp_client_action.copy_parameters().copyout_size()); |
535 | 0 | break; |
536 | 0 | } |
537 | 0 | case NecpClientAction::kAgent: { |
538 | 0 | necp_client_agent(necp_client_action.necp_fd(), |
539 | 0 | necp_client_action.client_id(), |
540 | 0 | necp_client_action.agent().necp_tlv()); |
541 | 0 | break; |
542 | 0 | } |
543 | 0 | case NecpClientAction::ACTION_NOT_SET: { |
544 | 0 | break; |
545 | 0 | } |
546 | 0 | } |
547 | 0 | } |
548 | | |
549 | 35.1k | void DoTcpInput(const TcpPacket &tcp_packet) { |
550 | 35.1k | std::string packet_s; |
551 | | |
552 | 35.1k | size_t expected_size = |
553 | 35.1k | sizeof(struct ip) + sizeof(struct tcphdr) + tcp_packet.data().size(); |
554 | 35.1k | packet_s += get_ip_hdr(tcp_packet.ip_hdr(), expected_size); |
555 | 35.1k | packet_s += get_tcp_hdr(tcp_packet.tcp_hdr()); |
556 | 35.1k | packet_s += tcp_packet.data(); |
557 | 35.1k | assert(expected_size == packet_s.size()); |
558 | | |
559 | 35.1k | if (packet_s.empty()) { |
560 | 0 | return; |
561 | 0 | } |
562 | | |
563 | | // TODO(nedwill): fuzz structure of mbuf itself |
564 | 35.1k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
565 | 35.1k | if (!mbuf_data) { |
566 | 0 | return; |
567 | 0 | } |
568 | | |
569 | 35.1k | ip_input_wrapper(mbuf_data); |
570 | 35.1k | } |
571 | | |
572 | 36.7k | void DoTcp6Input(const Tcp6Packet &tcp6_packet) { |
573 | 36.7k | std::string packet_s; |
574 | | |
575 | | // TODO(nedwill): support hop-by-hop and other options |
576 | 36.7k | size_t expected_size = sizeof(struct tcphdr) + tcp6_packet.data().size(); |
577 | 36.7k | packet_s += get_ip6_hdr(tcp6_packet.ip6_hdr(), expected_size); |
578 | 36.7k | packet_s += get_tcp_hdr(tcp6_packet.tcp_hdr()); |
579 | 36.7k | packet_s += tcp6_packet.data(); |
580 | | |
581 | 36.7k | if (packet_s.empty()) { |
582 | 0 | return; |
583 | 0 | } |
584 | | |
585 | 36.7k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
586 | 36.7k | if (!mbuf_data) { |
587 | 0 | return; |
588 | 0 | } |
589 | | |
590 | 36.7k | ip6_input_wrapper(mbuf_data); |
591 | 36.7k | } |
592 | | |
593 | 199k | void DoIp4Packet(const Ip4Packet &packet) { |
594 | 199k | size_t expected_size = sizeof(struct ip) + packet.data().size(); |
595 | 199k | std::string packet_s = get_ip_hdr(packet.ip_hdr(), expected_size); |
596 | 199k | packet_s += packet.data(); |
597 | | |
598 | 199k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
599 | 199k | if (!mbuf_data) { |
600 | 0 | return; |
601 | 0 | } |
602 | | |
603 | 199k | ip_input_wrapper(mbuf_data); |
604 | 199k | } |
605 | | |
606 | 279k | void DoIp6Packet(const Ip6Packet &packet) { |
607 | 279k | size_t expected_size = packet.data().size(); |
608 | 279k | std::string packet_s = get_ip6_hdr(packet.ip6_hdr(), expected_size); |
609 | 279k | packet_s += packet.data(); |
610 | | |
611 | 279k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
612 | 279k | if (!mbuf_data) { |
613 | 0 | return; |
614 | 0 | } |
615 | | |
616 | 279k | ip6_input_wrapper(mbuf_data); |
617 | 279k | } |
618 | | |
619 | 1.53M | void DoIpInput(const Packet &packet) { |
620 | 1.53M | switch (packet.packet_case()) { |
621 | 35.1k | case Packet::kTcpPacket: { |
622 | 35.1k | DoTcpInput(packet.tcp_packet()); |
623 | 35.1k | break; |
624 | 0 | } |
625 | 36.7k | case Packet::kTcp6Packet: { |
626 | 36.7k | DoTcp6Input(packet.tcp6_packet()); |
627 | 36.7k | break; |
628 | 0 | } |
629 | 199k | case Packet::kIp4Packet: { |
630 | 199k | DoIp4Packet(packet.ip4_packet()); |
631 | 199k | break; |
632 | 0 | } |
633 | 279k | case Packet::kIp6Packet: { |
634 | 279k | DoIp6Packet(packet.ip6_packet()); |
635 | 279k | break; |
636 | 0 | } |
637 | 212k | case Packet::kRawIp4: { |
638 | 212k | void *mbuf_data = get_mbuf_data(packet.raw_ip4().data(), |
639 | 212k | packet.raw_ip4().size(), PKTF_LOOP); |
640 | 212k | if (!mbuf_data) { |
641 | 0 | return; |
642 | 0 | } |
643 | | |
644 | 212k | ip_input_wrapper(mbuf_data); |
645 | 212k | break; |
646 | 212k | } |
647 | 124k | case Packet::kRawIp6: { |
648 | 124k | void *mbuf_data = get_mbuf_data(packet.raw_ip6().data(), |
649 | 124k | packet.raw_ip6().size(), PKTF_LOOP); |
650 | 124k | if (!mbuf_data) { |
651 | 0 | return; |
652 | 0 | } |
653 | | |
654 | 124k | ip6_input_wrapper(mbuf_data); |
655 | 124k | break; |
656 | 124k | } |
657 | 643k | case Packet::PACKET_NOT_SET: { |
658 | 643k | break; |
659 | 124k | } |
660 | 1.53M | } |
661 | 1.53M | } |
662 | | |
663 | | // TODO(nedwill): make alternative build of this function that runs the |
664 | | // the testcases against the real XNU syscalls, also KCOV-enabled |
665 | 10.0k | DEFINE_BINARY_PROTO_FUZZER(const Session &session) { |
666 | | // std::string str; |
667 | | // google::protobuf::TextFormat::PrintToString(session, &str); |
668 | | // std::cout << str; |
669 | 10.0k | if (!ready) { |
670 | 1 | initialize_network(); |
671 | 1 | init_proc(); |
672 | 1 | ready = true; |
673 | 1 | } |
674 | | |
675 | 10.0k | FuzzedDataProvider dp((const uint8_t *)session.data_provider().data(), |
676 | 10.0k | session.data_provider().size()); |
677 | 10.0k | fdp = &dp; |
678 | | |
679 | | // TODO(nedwill): Make these containers own the references to their |
680 | | // objects so that we can use RAII to avoid leaks. |
681 | 10.0k | std::vector<uint32_t> cids; |
682 | 10.0k | std::set<int> open_fds; |
683 | | |
684 | 17.0M | for (const Command &command : session.commands()) { |
685 | 17.0M | int retval = 0; |
686 | 17.0M | switch (command.command_case()) { |
687 | 86.5k | case Command::kSocket: { |
688 | 86.5k | int fd = 0; |
689 | 86.5k | int err = socket_wrapper(command.socket().domain(), |
690 | 86.5k | command.socket().so_type(), |
691 | 86.5k | command.socket().protocol(), &fd); |
692 | 86.5k | if (err == 0) { |
693 | | // Make sure we're tracking fds properly. |
694 | 2 | if (open_fds.find(fd) != open_fds.end()) { |
695 | 0 | printf("Found existing fd %d\n", fd); |
696 | 0 | assert(false); |
697 | 0 | } |
698 | 2 | open_fds.insert(fd); |
699 | 2 | } |
700 | 86.5k | break; |
701 | 86.5k | } |
702 | 162k | case Command::kClose: { |
703 | 162k | open_fds.erase(command.close().fd()); |
704 | 162k | close_wrapper(command.close().fd(), nullptr); |
705 | 162k | break; |
706 | 86.5k | } |
707 | 172k | case Command::kSetSockOpt: { |
708 | 172k | int s = command.set_sock_opt().fd(); |
709 | 172k | int level = command.set_sock_opt().level(); |
710 | 172k | int name = command.set_sock_opt().name(); |
711 | 172k | size_t size = command.set_sock_opt().val().size(); |
712 | 172k | std::unique_ptr<char[]> val(new char[size]); |
713 | 172k | memcpy(val.get(), command.set_sock_opt().val().data(), size); |
714 | 172k | setsockopt_wrapper(s, level, name, val.get(), size, nullptr); |
715 | 172k | break; |
716 | 86.5k | } |
717 | 371k | case Command::kGetSockOpt: { |
718 | 371k | int s = command.get_sock_opt().fd(); |
719 | 371k | int level = command.get_sock_opt().level(); |
720 | 371k | int name = command.get_sock_opt().name(); |
721 | 371k | socklen_t size = command.get_sock_opt().size(); |
722 | 371k | if (size < 0 || size > 4096) { |
723 | 8.00k | break; |
724 | 8.00k | } |
725 | 363k | std::unique_ptr<char[]> val(new char[size]); |
726 | 363k | getsockopt_wrapper(s, level, name, val.get(), &size, nullptr); |
727 | 363k | break; |
728 | 371k | } |
729 | 95.3k | case Command::kBind: { |
730 | 95.3k | std::string sockaddr_s = get_sockaddr(command.bind().sockaddr()); |
731 | 95.3k | bind_wrapper(command.bind().fd(), (caddr_t)sockaddr_s.data(), |
732 | 95.3k | sockaddr_s.size(), nullptr); |
733 | 95.3k | break; |
734 | 371k | } |
735 | 621k | case Command::kIoctl: { |
736 | | // TODO: pick these values more efficiently |
737 | | // XXX: these mutate global state |
738 | 621k | uint32_t fd = command.ioctl().fd(); |
739 | 621k | uint32_t com = ioctls[command.ioctl().ioctl_idx() - 1]; |
740 | 621k | real_copyout = false; |
741 | 621k | ioctl_wrapper(fd, com, /*data=*/(caddr_t)1, nullptr); |
742 | 621k | real_copyout = true; |
743 | 621k | break; |
744 | 371k | } |
745 | 166k | case Command::kAccept: { |
746 | 166k | std::string sockaddr_s = get_sockaddr(command.accept().sockaddr()); |
747 | 166k | socklen_t size = sockaddr_s.size(); |
748 | 166k | int retval = 0; |
749 | 166k | accept_wrapper(command.accept().fd(), (caddr_t)sockaddr_s.data(), &size, |
750 | 166k | &retval); |
751 | 166k | break; |
752 | 371k | } |
753 | 1.53M | case Command::kIpInput: { |
754 | 1.53M | DoIpInput(command.ip_input()); |
755 | 1.53M | break; |
756 | 371k | } |
757 | 201k | case Command::kIoctlReal: { |
758 | 201k | switch (command.ioctl_real().ioctl_case()) { |
759 | 22.2k | case IoctlReal::kSiocaifaddrIn664: { |
760 | 22.2k | const In6_AliasReq_64 &req = |
761 | 22.2k | command.ioctl_real().siocaifaddr_in6_64(); |
762 | 22.2k | struct in6_aliasreq_64 alias = {}; |
763 | 22.2k | memcpy(alias.ifra_name, req.ifra_name().data(), |
764 | 22.2k | std::min(req.ifra_name().size(), sizeof(alias.ifra_name))); |
765 | 22.2k | get_sockaddr6(&alias.ifra_addr, req.ifra_addr()); |
766 | 22.2k | get_sockaddr6(&alias.ifra_dstaddr, req.ifra_dstaddr()); |
767 | 22.2k | get_sockaddr6(&alias.ifra_prefixmask, req.ifra_prefixmask()); |
768 | 22.2k | for (int flag : req.ifra_flags()) { |
769 | | // make mutations that dupe a flag more useful by xoring |
770 | 5.68k | alias.ifra_flags ^= flag; |
771 | 5.68k | } |
772 | 22.2k | get_in6_addrlifetime_64(&alias.ifra_lifetime, req.ifra_lifetime()); |
773 | 22.2k | ioctl_wrapper(command.ioctl_real().fd(), siocaifaddr_in6_64, |
774 | 22.2k | (caddr_t)&alias, nullptr); |
775 | 22.2k | } |
776 | 90.0k | case IoctlReal::kSiocsifflags: { |
777 | 90.0k | struct ifreq ifreq = {}; |
778 | 90.0k | for (int flag : command.ioctl_real().siocsifflags().flags()) { |
779 | 79.6k | ifreq.ifr_flags |= flag; |
780 | 79.6k | } |
781 | 90.0k | get_ifr_name(ifreq.ifr_name, LO0); |
782 | 90.0k | ioctl_wrapper(command.ioctl_real().fd(), siocsifflags, |
783 | 90.0k | (caddr_t)&ifreq, nullptr); |
784 | 90.0k | break; |
785 | 22.2k | } |
786 | 111k | case IoctlReal::IOCTL_NOT_SET: { |
787 | 111k | break; |
788 | 22.2k | } |
789 | 201k | } |
790 | 201k | } |
791 | 326k | case Command::kConnectx: { |
792 | 326k | bool has_srcaddr = command.connectx().endpoints().has_sae_srcaddr(); |
793 | | |
794 | 326k | std::string srcaddr_s; |
795 | 326k | if (has_srcaddr) { |
796 | 23.8k | srcaddr_s = |
797 | 23.8k | get_sockaddr(command.connectx().endpoints().sae_srcaddr()); |
798 | 23.8k | } |
799 | | |
800 | 326k | std::string dstaddr_s = |
801 | 326k | get_sockaddr(command.connectx().endpoints().sae_dstaddr()); |
802 | | |
803 | 326k | void *srcaddr = (void *)srcaddr_s.data(); |
804 | 326k | uint32_t srcsize = srcaddr_s.size(); |
805 | 326k | if (!has_srcaddr) { |
806 | 303k | srcaddr = nullptr; |
807 | 303k | assert(!srcsize); |
808 | 303k | } |
809 | | |
810 | 326k | void *dstaddr = (void *)dstaddr_s.data(); |
811 | 326k | uint32_t dstsize = dstaddr_s.size(); |
812 | | |
813 | | // We ignore failure here since it's ok to try to send things regardless |
814 | 326k | uint32_t connectx_flags = 0; |
815 | 326k | for (const int flag : command.connectx().flags()) { |
816 | 18.9k | connectx_flags |= flag; |
817 | 18.9k | } |
818 | 326k | uint32_t cid = 0; |
819 | | |
820 | 326k | struct user64_sa_endpoints endpoints = { |
821 | 326k | .sae_srcif = static_cast<unsigned int>(command.connectx().endpoints().sae_srcif()), |
822 | 326k | .sae_srcaddr = (user64_addr_t)srcaddr, |
823 | 326k | .sae_srcaddrlen = srcsize, |
824 | 326k | .sae_dstaddr = (user64_addr_t)dstaddr, |
825 | 326k | .sae_dstaddrlen = dstsize}; |
826 | | |
827 | | // TODO(nedwill): is this a return value? |
828 | 326k | size_t len = 0; |
829 | | // TODO(nedwill): add IOV mocking |
830 | 326k | connectx_wrapper(command.connectx().socket(), &endpoints, |
831 | 326k | command.connectx().associd(), connectx_flags, nullptr, |
832 | 326k | 0, &len, &cid, nullptr); |
833 | 326k | cids.push_back(cid); |
834 | 326k | break; |
835 | 326k | } |
836 | 93.1k | case Command::kConnect: { |
837 | 93.1k | std::string sockaddr_s = get_sockaddr(command.connect().sockaddr()); |
838 | 93.1k | connect_wrapper(command.connect().fd(), (caddr_t)sockaddr_s.data(), |
839 | 93.1k | sockaddr_s.size(), nullptr); |
840 | 93.1k | break; |
841 | 326k | } |
842 | 114k | case Command::kListen: { |
843 | 114k | listen_wrapper(command.listen().socket(), command.listen().backlog(), |
844 | 114k | nullptr); |
845 | 114k | break; |
846 | 326k | } |
847 | 72.7k | case Command::kDisconnectx: { |
848 | 72.7k | uint32_t cid = 0; |
849 | 72.7k | if (!cids.empty()) { |
850 | 70.7k | cid = cids[command.disconnectx().cid() % cids.size()]; |
851 | 70.7k | } else { |
852 | 2.00k | cid = command.disconnectx().cid(); |
853 | 2.00k | } |
854 | 72.7k | disconnectx_wrapper(command.disconnectx().fd(), |
855 | 72.7k | command.disconnectx().associd(), cid, nullptr); |
856 | 72.7k | break; |
857 | 326k | } |
858 | 408k | case Command::kClearAll: { |
859 | | // TODO(nedwill): finer-grained calling of clear_all functions here |
860 | 408k | clear_all(); |
861 | 408k | break; |
862 | 326k | } |
863 | 63.0k | case Command::kNecpMatchPolicy: { |
864 | 63.0k | std::unique_ptr<uint8_t[]> parameters_u8( |
865 | 63.0k | new uint8_t[command.necp_match_policy().parameters().size()]); |
866 | 63.0k | memcpy(parameters_u8.get(), |
867 | 63.0k | command.necp_match_policy().parameters().data(), |
868 | 63.0k | command.necp_match_policy().parameters().size()); |
869 | | // necp_match_policy_wrapper( |
870 | | // parameters_u8.get(), |
871 | | // command.necp_match_policy().parameters().size(), |
872 | | // /*returned_result*/ nullptr, nullptr); |
873 | 63.0k | break; |
874 | 326k | } |
875 | 162k | case Command::kNecpOpen: { |
876 | | // int flags = 0; |
877 | | // for (int flag : command.necp_open().flags()) { |
878 | | // flags |= flag; |
879 | | // } |
880 | | // int fd = 0; |
881 | | // int err = necp_open_wrapper(flags, &fd); |
882 | | // if (err == 0) { |
883 | | // if (open_fds.find(fd) != open_fds.end()) { |
884 | | // printf("fd %d already in open sockets\n", fd); |
885 | | // assert(false); |
886 | | // } |
887 | | // open_fds.insert(fd); |
888 | | // } |
889 | 162k | break; |
890 | 326k | } |
891 | 105k | case Command::kNecpClientAction: { |
892 | | // DoNecpClientAction(command.necp_client_action()); |
893 | 105k | break; |
894 | 326k | } |
895 | 140k | case Command::kNecpSessionOpen: { |
896 | | // int flags = 0; |
897 | | // int fd = 0; |
898 | | // int err = necp_session_open_wrapper(flags, &fd); |
899 | | // if (err == 0) { |
900 | | // if (open_fds.find(fd) != open_fds.end()) { |
901 | | // printf("fd %d already in open sockets\n", fd); |
902 | | // assert(false); |
903 | | // } |
904 | | // open_fds.insert(fd); |
905 | | // } |
906 | 140k | break; |
907 | 326k | } |
908 | 135k | case Command::kNecpSessionAction: { |
909 | 135k | size_t out_buffer_size = |
910 | 135k | command.necp_session_action().out_buffer_size() % 4096; |
911 | 135k | std::unique_ptr<uint8_t[]> out_buffer(new uint8_t[out_buffer_size]); |
912 | | // necp_session_action_wrapper( |
913 | | // command.necp_session_action().necp_fd(), |
914 | | // command.necp_session_action().action(), |
915 | | // // TODO(nedwill): fix const cast |
916 | | // (uint8_t *)command.necp_session_action().in_buffer().data(), |
917 | | // command.necp_session_action().in_buffer().size(), out_buffer.get(), |
918 | | // out_buffer_size, &retval); |
919 | 135k | break; |
920 | 326k | } |
921 | 99.5k | case Command::kAcceptNocancel: { |
922 | 99.5k | std::string sockaddr_s = get_sockaddr(command.accept_nocancel().name()); |
923 | 99.5k | socklen_t size = sockaddr_s.size(); |
924 | 99.5k | accept_nocancel_wrapper(command.accept_nocancel().s(), |
925 | 99.5k | (caddr_t)sockaddr_s.data(), &size, &retval); |
926 | 99.5k | break; |
927 | 326k | } |
928 | 126k | case Command::kConnectNocancel: { |
929 | 126k | std::string sockaddr_s = |
930 | 126k | get_sockaddr(command.connect_nocancel().name()); |
931 | 126k | socklen_t size = sockaddr_s.size(); |
932 | 126k | connect_nocancel_wrapper(command.connect_nocancel().s(), |
933 | 126k | (caddr_t)sockaddr_s.data(), size, &retval); |
934 | 126k | break; |
935 | 326k | } |
936 | 116k | case Command::kGetpeername: { |
937 | 116k | std::string sockaddr_s = get_sockaddr(command.getpeername().asa()); |
938 | 116k | socklen_t size = sockaddr_s.size(); |
939 | 116k | getpeername_wrapper(command.getpeername().fdes(), |
940 | 116k | (caddr_t)sockaddr_s.data(), &size, &retval); |
941 | 116k | break; |
942 | 326k | } |
943 | 92.4k | case Command::kGetsockname: { |
944 | 92.4k | std::string sockaddr_s = get_sockaddr(command.getsockname().asa()); |
945 | 92.4k | socklen_t size = sockaddr_s.size(); |
946 | 92.4k | getsockname_wrapper(command.getsockname().fdes(), |
947 | 92.4k | (caddr_t)sockaddr_s.data(), &size, &retval); |
948 | 92.4k | break; |
949 | 326k | } |
950 | 108k | case Command::kPeeloff: { |
951 | 108k | peeloff_wrapper(command.peeloff().s(), command.peeloff().aid(), |
952 | 108k | &retval); |
953 | 108k | break; |
954 | 326k | } |
955 | 76.7k | case Command::kRecvfrom: { |
956 | 76.7k | std::string sockaddr_s = get_sockaddr(command.recvfrom().from()); |
957 | 76.7k | int size = sockaddr_s.size(); |
958 | | // TODO(nedwill): just specify the size of the buffer, don't store bytes |
959 | | // in the proto message just for them to be overwritten |
960 | 76.7k | recvfrom_wrapper( |
961 | 76.7k | command.recvfrom().s(), (caddr_t)command.recvfrom().buf().data(), |
962 | 76.7k | command.recvfrom().buf().size(), command.recvfrom().flags(), |
963 | 76.7k | (struct sockaddr *)sockaddr_s.data(), &size, &retval); |
964 | 76.7k | break; |
965 | 326k | } |
966 | 79.2k | case Command::kRecvfromNocancel: { |
967 | 79.2k | std::string sockaddr_s = |
968 | 79.2k | get_sockaddr(command.recvfrom_nocancel().from()); |
969 | 79.2k | int size = sockaddr_s.size(); |
970 | 79.2k | recvfrom_nocancel_wrapper( |
971 | 79.2k | command.recvfrom_nocancel().s(), |
972 | 79.2k | (caddr_t)command.recvfrom_nocancel().buf().data(), |
973 | 79.2k | command.recvfrom_nocancel().buf().size(), |
974 | 79.2k | command.recvfrom_nocancel().flags(), |
975 | 79.2k | (struct sockaddr *)sockaddr_s.data(), &size, &retval); |
976 | 79.2k | break; |
977 | 326k | } |
978 | 103k | case Command::kRecvmsg: { |
979 | | // TODO(nedwill): fuzz this msg field |
980 | 103k | user64_msghdr msg = {}; |
981 | 103k | recvmsg_wrapper(command.recvmsg().s(), (struct msghdr *)&msg, |
982 | 103k | command.recvmsg().flags(), &retval); |
983 | 103k | break; |
984 | 326k | } |
985 | 174k | case Command::kSendto: { |
986 | 174k | std::string sockaddr_s = get_sockaddr(command.sendto().to()); |
987 | 174k | socklen_t size = sockaddr_s.size(); |
988 | 174k | sendto_wrapper(command.sendto().s(), |
989 | 174k | (caddr_t)command.sendto().buf().data(), |
990 | 174k | command.sendto().buf().size(), command.sendto().flags(), |
991 | 174k | (caddr_t)sockaddr_s.data(), size, &retval); |
992 | 174k | break; |
993 | 326k | } |
994 | 1.90M | case Command::kSocketpair: { |
995 | 1.90M | int rsv[2] = {}; |
996 | 1.90M | int ret = socketpair_wrapper( |
997 | 1.90M | command.socketpair().domain(), command.socketpair().type(), |
998 | 1.90M | command.socketpair().protocol(), rsv, &retval); |
999 | 1.90M | if (!ret) { |
1000 | 2 | if (open_fds.find(rsv[0]) != open_fds.end()) { |
1001 | 0 | assert(false); |
1002 | 0 | } |
1003 | 2 | open_fds.insert(rsv[0]); |
1004 | 2 | if (open_fds.find(rsv[1]) != open_fds.end()) { |
1005 | 0 | assert(false); |
1006 | 0 | } |
1007 | 2 | open_fds.insert(rsv[1]); |
1008 | 2 | } |
1009 | 1.90M | break; |
1010 | 1.90M | } |
1011 | 1.90M | case Command::kPipe: { |
1012 | 192k | int rsv[2] = {}; |
1013 | 192k | int ret = pipe_wrapper(rsv); |
1014 | 192k | if (!ret) { |
1015 | 2 | if (open_fds.find(rsv[0]) != open_fds.end()) { |
1016 | 0 | assert(false); |
1017 | 0 | } |
1018 | 2 | open_fds.insert(rsv[0]); |
1019 | 2 | if (open_fds.find(rsv[1]) != open_fds.end()) { |
1020 | 0 | assert(false); |
1021 | 0 | } |
1022 | 2 | open_fds.insert(rsv[1]); |
1023 | 2 | } |
1024 | 192k | break; |
1025 | 192k | } |
1026 | 192k | case Command::kShutdown: { |
1027 | 129k | shutdown_wrapper(command.shutdown().s(), command.shutdown().how(), |
1028 | 129k | &retval); |
1029 | 129k | break; |
1030 | 192k | } |
1031 | 9.00M | case Command::COMMAND_NOT_SET: { |
1032 | 9.00M | break; |
1033 | 192k | } |
1034 | 17.0M | } |
1035 | 17.0M | } |
1036 | | |
1037 | 10.0k | for (int fd : open_fds) { |
1038 | 10 | int err = close_wrapper(fd, nullptr); |
1039 | 10 | assert(err != EBADF); |
1040 | 10 | } |
1041 | | |
1042 | | // TODO(nedwill): split up these worker threads and run them as |
1043 | | // part of main loop |
1044 | 10.0k | clear_all(); |
1045 | 10.0k | } |
1046 | | } |