/src/SockFuzzer/fuzz/net_fuzzer.cc
Line | Count | Source (jump to first uncovered line) |
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 | 799k | void get_in6_addr(struct in6_addr *sai, enum In6Addr addr) { |
56 | 799k | memset(sai, 0, sizeof(*sai)); |
57 | 799k | switch (addr) { |
58 | 6.60k | case IN6_ADDR_SELF: { |
59 | 6.60k | sai->__u6_addr.__u6_addr32[0] = 16810238; |
60 | 6.60k | sai->__u6_addr.__u6_addr32[0] = 0; |
61 | 6.60k | sai->__u6_addr.__u6_addr32[0] = 0; |
62 | 6.60k | sai->__u6_addr.__u6_addr32[0] = 16777216; |
63 | | // assert(IN6_IS_ADDR_SELF(sai)); |
64 | 6.60k | break; |
65 | 0 | } |
66 | 3.03k | case IN6_ADDR_LINK_LOCAL: { |
67 | 3.03k | sai->s6_addr[0] = 0xfe; |
68 | 3.03k | sai->s6_addr[1] = 0x80; |
69 | | // TODO(nedwill): set other fields? |
70 | 3.03k | assert(IN6_IS_ADDR_LINKLOCAL(sai)); |
71 | 0 | break; |
72 | 0 | } |
73 | 398k | case IN6_ADDR_LOOPBACK: { |
74 | 398k | *sai = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)addr}; |
75 | 398k | assert(IN6_IS_ADDR_LOOPBACK(sai)); |
76 | 0 | break; |
77 | 0 | } |
78 | 11.2k | 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 | 11.2k | } |
83 | 3.79k | case IN6_ADDR_V4COMPAT: { |
84 | 3.79k | sai->s6_addr[12] = 1; |
85 | 3.79k | assert(IN6_IS_ADDR_V4COMPAT(sai)); |
86 | 0 | break; |
87 | 11.2k | } |
88 | 41.2k | case IN6_ADDR_V4MAPPED: { |
89 | 41.2k | *(uint32_t *)&sai->s6_addr[8] = 0xffff0000; |
90 | 41.2k | assert(IN6_IS_ADDR_V4MAPPED(sai)); |
91 | 0 | break; |
92 | 11.2k | } |
93 | 528 | case IN6_ADDR_6TO4: { |
94 | 528 | sai->s6_addr16[0] = ntohs(0x2002); |
95 | 528 | assert(IN6_IS_ADDR_6TO4(sai)); |
96 | 0 | break; |
97 | 11.2k | } |
98 | 4.50k | case IN6_ADDR_LINKLOCAL: { |
99 | 4.50k | sai->s6_addr[0] = 0xfe; |
100 | 4.50k | sai->s6_addr[1] = 0x80; |
101 | 4.50k | assert(IN6_IS_ADDR_LINKLOCAL(sai)); |
102 | 0 | break; |
103 | 11.2k | } |
104 | 709 | case IN6_ADDR_SITELOCAL: { |
105 | 709 | sai->s6_addr[0] = 0xfe; |
106 | 709 | sai->s6_addr[1] = 0xc0; |
107 | 709 | assert(IN6_IS_ADDR_SITELOCAL(sai)); |
108 | 0 | break; |
109 | 11.2k | } |
110 | 2.10k | case IN6_ADDR_MULTICAST: { |
111 | 2.10k | sai->s6_addr[0] = 0xff; |
112 | 2.10k | assert(IN6_IS_ADDR_MULTICAST(sai)); |
113 | 0 | break; |
114 | 11.2k | } |
115 | 1.71k | case IN6_ADDR_UNIQUE_LOCAL: { |
116 | 1.71k | sai->s6_addr[0] = 0xfc; |
117 | 1.71k | assert(IN6_IS_ADDR_UNIQUE_LOCAL(sai)); |
118 | 0 | break; |
119 | 11.2k | } |
120 | 1.31k | case IN6_ADDR_MC_NODELOCAL: { |
121 | 1.31k | sai->s6_addr[0] = 0xff; |
122 | 1.31k | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_NODELOCAL; |
123 | 1.31k | assert(IN6_IS_ADDR_MC_NODELOCAL(sai)); |
124 | 0 | break; |
125 | 11.2k | } |
126 | 444 | case IN6_ADDR_MC_INTFACELOCAL: { |
127 | 444 | sai->s6_addr[0] = 0xff; |
128 | 444 | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_INTFACELOCAL; |
129 | 444 | assert(IN6_IS_ADDR_MC_INTFACELOCAL(sai)); |
130 | 0 | break; |
131 | 11.2k | } |
132 | 13.4k | case IN6_ADDR_MC_LINKLOCAL: { |
133 | 13.4k | sai->s6_addr[0] = 0xff; |
134 | 13.4k | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_LINKLOCAL; |
135 | 13.4k | assert(IN6_IS_ADDR_MC_LINKLOCAL(sai)); |
136 | 0 | break; |
137 | 11.2k | } |
138 | 2.18k | case IN6_ADDR_MC_SITELOCAL: { |
139 | 2.18k | sai->s6_addr[0] = 0xff; |
140 | 2.18k | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_SITELOCAL; |
141 | 2.18k | assert(IN6_IS_ADDR_MC_SITELOCAL(sai)); |
142 | 0 | break; |
143 | 11.2k | } |
144 | 381 | case IN6_ADDR_MC_ORGLOCAL: { |
145 | 381 | sai->s6_addr[0] = 0xff; |
146 | 381 | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_ORGLOCAL; |
147 | 381 | assert(IN6_IS_ADDR_MC_ORGLOCAL(sai)); |
148 | 0 | break; |
149 | 11.2k | } |
150 | 681 | case IN6_ADDR_MC_GLOBAL: { |
151 | 681 | sai->s6_addr[0] = 0xff; |
152 | 681 | sai->s6_addr[1] = __IPV6_ADDR_SCOPE_GLOBAL; |
153 | 681 | assert(IN6_IS_ADDR_MC_GLOBAL(sai)); |
154 | 0 | break; |
155 | 11.2k | } |
156 | 12.6k | case IN6_ADDR_UNSPECIFIED: |
157 | 305k | case IN6_ADDR_ANY: { |
158 | 305k | assert(IN6_IS_ADDR_UNSPECIFIED(sai)); |
159 | 0 | break; |
160 | 12.6k | } |
161 | 1.63k | case IN6_ADDR_LOCAL_ADDRESS: { |
162 | | // Discovered this address dynamically |
163 | | // fe80:0001:0000:0000:a8aa:aaaa:aaaa:aaaa |
164 | 1.63k | sai->s6_addr16[0] = 0xfe80; |
165 | 1.63k | sai->s6_addr16[1] = 0x0001; |
166 | 1.63k | sai->s6_addr16[4] = 0xa8aa; |
167 | 1.63k | sai->s6_addr16[5] = 0xaaaa; |
168 | 1.63k | sai->s6_addr16[6] = 0xaaaa; |
169 | 1.63k | sai->s6_addr16[7] = 0xaaaa; |
170 | 1.63k | } |
171 | | // *sai = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)addr}; |
172 | 799k | } |
173 | 799k | } |
174 | | |
175 | 109k | void get_sockaddr6(struct sockaddr_in6 *sai, const SockAddr6 &sa6) { |
176 | 109k | sai->sin6_len = sizeof(struct sockaddr_in6); |
177 | 109k | sai->sin6_family = (sa_family_t)AF_INET6; // sa6.family(); |
178 | 109k | sai->sin6_port = (in_port_t)sa6.port(); |
179 | 109k | sai->sin6_flowinfo = sa6.flow_info(); |
180 | 109k | get_in6_addr(&sai->sin6_addr, sa6.sin6_addr()); |
181 | 109k | sai->sin6_scope_id = sa6.sin6_scope_id(); |
182 | 109k | } |
183 | | |
184 | 1.46M | std::string get_sockaddr(const SockAddr &sockaddr) { |
185 | 1.46M | std::string dat; |
186 | 1.46M | switch (sockaddr.sockaddr_case()) { |
187 | 123k | case SockAddr::kSockaddrGeneric: { |
188 | 123k | const SockAddrGeneric &sag = sockaddr.sockaddr_generic(); |
189 | | // data size + sizeof(sa_len) + sizeof(sa_family) |
190 | 123k | struct sockaddr_generic sag_s = { |
191 | 123k | .sa_len = (uint8_t)(sizeof(sockaddr_generic) + sag.sa_data().size()), |
192 | 123k | .sa_family = (uint8_t)sag.sa_family(), |
193 | 123k | }; |
194 | | |
195 | 123k | dat = std::string((char *)&sag_s, (char *)&sag_s + sizeof(sag_s)); |
196 | 123k | dat += sag.sa_data(); |
197 | 123k | break; |
198 | 0 | } |
199 | 83.4k | case SockAddr::kSockaddr4: { |
200 | 83.4k | struct sockaddr_in sai = { |
201 | 83.4k | .sin_len = sizeof(struct sockaddr_in), |
202 | 83.4k | .sin_family = |
203 | 83.4k | AF_INET, // (unsigned char)sockaddr.sockaddr4().sin_family(), |
204 | 83.4k | .sin_port = (unsigned short)sockaddr.sockaddr4().sin_port(), |
205 | 83.4k | .sin_addr = {(unsigned int)sockaddr.sockaddr4().sin_addr()}, |
206 | 83.4k | .sin_zero = {}, |
207 | 83.4k | }; |
208 | 83.4k | dat = std::string((char *)&sai, (char *)&sai + sizeof(sai)); |
209 | 83.4k | break; |
210 | 0 | } |
211 | 47.0k | case SockAddr::kSockaddr6: { |
212 | 47.0k | struct sockaddr_in6 sai = {}; |
213 | 47.0k | get_sockaddr6(&sai, sockaddr.sockaddr6()); |
214 | 47.0k | dat = std::string((char *)&sai, (char *)&sai + sizeof(sai)); |
215 | 47.0k | break; |
216 | 0 | } |
217 | | // case SockAddr::kRawBytes: { |
218 | | // dat = sockaddr.raw_bytes(); |
219 | | // break; |
220 | | // } |
221 | 1.21M | case SockAddr::SOCKADDR_NOT_SET: { |
222 | 1.21M | break; |
223 | 0 | } |
224 | 1.46M | } |
225 | 1.46M | return dat; |
226 | 1.46M | } |
227 | | |
228 | 344k | std::string get_ip6_hdr(const Ip6Hdr &hdr, uint16_t expected_size) { |
229 | 344k | struct ip6_hdr ip6_hdr; |
230 | 344k | memset(&ip6_hdr, 0, sizeof(ip6_hdr)); |
231 | 344k | get_in6_addr(&ip6_hdr.ip6_src, hdr.ip6_src()); |
232 | 344k | get_in6_addr(&ip6_hdr.ip6_dst, hdr.ip6_src()); |
233 | 344k | 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 | 344k | ip6_hdr.ip6_ctlun.ip6_un1.ip6_un1_plen = |
237 | 344k | __builtin_bswap16(expected_size); // hdr.ip6_hdrctl().ip6_un1_plen(); |
238 | 344k | ip6_hdr.ip6_ctlun.ip6_un1.ip6_un1_nxt = hdr.ip6_hdrctl().ip6_un1_nxt(); |
239 | 344k | ip6_hdr.ip6_ctlun.ip6_un1.ip6_un1_hlim = hdr.ip6_hdrctl().ip6_un1_hlim(); |
240 | 344k | std::string dat((char *)&ip6_hdr, (char *)&ip6_hdr + sizeof(ip6_hdr)); |
241 | 344k | return dat; |
242 | 344k | } |
243 | | |
244 | 253k | std::string get_ip_hdr(const IpHdr &hdr, size_t expected_size) { |
245 | 253k | struct in_addr ip_src = {.s_addr = (unsigned int)hdr.ip_src()}; |
246 | 253k | struct in_addr ip_dst = {.s_addr = (unsigned int)hdr.ip_dst()}; |
247 | 253k | struct ip ip_hdr = { |
248 | 253k | .ip_hl = 5, // TODO(nedwill): support options // hdr.ip_hl(), |
249 | 253k | .ip_v = IPV4, // hdr.ip_v(), |
250 | 253k | .ip_tos = (u_char)hdr.ip_tos(), |
251 | 253k | .ip_len = (u_short)__builtin_bswap16(expected_size), |
252 | 253k | .ip_id = (u_short)hdr.ip_id(), |
253 | 253k | .ip_off = (u_short)hdr.ip_off(), |
254 | 253k | .ip_ttl = (u_char)hdr.ip_ttl(), |
255 | 253k | .ip_p = (u_char)hdr.ip_p(), |
256 | 253k | .ip_sum = 0, |
257 | 253k | .ip_src = ip_src, |
258 | 253k | .ip_dst = ip_dst, |
259 | 253k | }; |
260 | 253k | std::string dat((char *)&ip_hdr, (char *)&ip_hdr + sizeof(ip_hdr)); |
261 | 253k | return dat; |
262 | 253k | } |
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 | 75.0k | std::string get_tcp_hdr(const TcpHdr &hdr) { |
277 | 75.0k | struct tcphdr tcphdr = { |
278 | 75.0k | .th_sport = (unsigned short)hdr.th_sport(), |
279 | 75.0k | .th_dport = (unsigned short)hdr.th_dport(), |
280 | 75.0k | .th_seq = __builtin_bswap32(hdr.th_seq()), |
281 | 75.0k | .th_ack = __builtin_bswap32(hdr.th_ack()), |
282 | 75.0k | .th_off = hdr.th_off(), |
283 | 75.0k | .th_flags = 0, |
284 | 75.0k | .th_win = (unsigned short)hdr.th_win(), |
285 | 75.0k | .th_sum = 0, |
286 | 75.0k | .th_urp = (unsigned short)hdr.th_urp(), |
287 | 75.0k | }; |
288 | | |
289 | 75.0k | for (const int flag : hdr.th_flags()) { |
290 | 27.2k | tcphdr.th_flags ^= flag; |
291 | 27.2k | } |
292 | | |
293 | | // Prefer pure syn |
294 | 75.0k | if (hdr.is_pure_syn()) { |
295 | 3.31k | tcphdr.th_flags &= ~(TH_RST | TH_ACK); |
296 | 3.31k | tcphdr.th_flags |= TH_SYN; |
297 | 71.7k | } else if (hdr.is_pure_ack()) { |
298 | 4.47k | tcphdr.th_flags &= ~(TH_RST | TH_SYN); |
299 | 4.47k | tcphdr.th_flags |= TH_ACK; |
300 | 4.47k | } |
301 | | |
302 | 75.0k | std::string dat((char *)&tcphdr, (char *)&tcphdr + sizeof(tcphdr)); |
303 | 75.0k | return dat; |
304 | 75.0k | } |
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.25M | void get_fuzzed_bytes(void *addr, size_t bytes) { |
400 | | // If we didn't initialize the fdp just clear the bytes. |
401 | 1.25M | if (!fdp) { |
402 | 2 | memset(addr, 0, bytes); |
403 | 2 | return; |
404 | 2 | } |
405 | 1.25M | memset(addr, 0, bytes); |
406 | 1.25M | std::vector<uint8_t> dat = fdp->ConsumeBytes<uint8_t>(bytes); |
407 | 1.25M | memcpy(addr, dat.data(), dat.size()); |
408 | 1.25M | } |
409 | | |
410 | 667k | bool get_fuzzed_bool(void) { |
411 | | // If we didn't initialize the fdp just return false. |
412 | 667k | if (!fdp) { |
413 | 0 | return false; |
414 | 0 | } |
415 | 667k | return fdp->ConsumeBool(); |
416 | 667k | } |
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 | 20.7k | const In6AddrLifetime_64 &msg) { |
442 | 20.7k | sai->ia6t_expire = msg.ia6t_expire(); |
443 | 20.7k | sai->ia6t_preferred = msg.ia6t_preferred(); |
444 | 20.7k | sai->ia6t_vltime = msg.ia6t_vltime(); |
445 | 20.7k | sai->ia6t_pltime = msg.ia6t_pltime(); |
446 | 20.7k | } |
447 | | |
448 | 81.3k | void get_ifr_name(void *dest, const IfrName name) { |
449 | 81.3k | switch (name) { |
450 | 81.3k | case LO0: { |
451 | 81.3k | memcpy(dest, "lo0", sizeof("lo0")); |
452 | 81.3k | break; |
453 | 0 | } |
454 | 0 | case STF0: { |
455 | 0 | memcpy(dest, "stf0", sizeof("stf0")); |
456 | 0 | break; |
457 | 0 | } |
458 | 81.3k | } |
459 | 81.3k | } |
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 | 31.5k | void DoTcpInput(const TcpPacket &tcp_packet) { |
550 | 31.5k | std::string packet_s; |
551 | | |
552 | 31.5k | size_t expected_size = |
553 | 31.5k | sizeof(struct ip) + sizeof(struct tcphdr) + tcp_packet.data().size(); |
554 | 31.5k | packet_s += get_ip_hdr(tcp_packet.ip_hdr(), expected_size); |
555 | 31.5k | packet_s += get_tcp_hdr(tcp_packet.tcp_hdr()); |
556 | 31.5k | packet_s += tcp_packet.data(); |
557 | 31.5k | assert(expected_size == packet_s.size()); |
558 | | |
559 | 31.5k | if (packet_s.empty()) { |
560 | 0 | return; |
561 | 0 | } |
562 | | |
563 | | // TODO(nedwill): fuzz structure of mbuf itself |
564 | 31.5k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
565 | 31.5k | if (!mbuf_data) { |
566 | 0 | return; |
567 | 0 | } |
568 | | |
569 | 31.5k | ip_input_wrapper(mbuf_data); |
570 | 31.5k | } |
571 | | |
572 | 43.5k | void DoTcp6Input(const Tcp6Packet &tcp6_packet) { |
573 | 43.5k | std::string packet_s; |
574 | | |
575 | | // TODO(nedwill): support hop-by-hop and other options |
576 | 43.5k | size_t expected_size = sizeof(struct tcphdr) + tcp6_packet.data().size(); |
577 | 43.5k | packet_s += get_ip6_hdr(tcp6_packet.ip6_hdr(), expected_size); |
578 | 43.5k | packet_s += get_tcp_hdr(tcp6_packet.tcp_hdr()); |
579 | 43.5k | packet_s += tcp6_packet.data(); |
580 | | |
581 | 43.5k | if (packet_s.empty()) { |
582 | 0 | return; |
583 | 0 | } |
584 | | |
585 | 43.5k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
586 | 43.5k | if (!mbuf_data) { |
587 | 0 | return; |
588 | 0 | } |
589 | | |
590 | 43.5k | ip6_input_wrapper(mbuf_data); |
591 | 43.5k | } |
592 | | |
593 | 222k | void DoIp4Packet(const Ip4Packet &packet) { |
594 | 222k | size_t expected_size = sizeof(struct ip) + packet.data().size(); |
595 | 222k | std::string packet_s = get_ip_hdr(packet.ip_hdr(), expected_size); |
596 | 222k | packet_s += packet.data(); |
597 | | |
598 | 222k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
599 | 222k | if (!mbuf_data) { |
600 | 0 | return; |
601 | 0 | } |
602 | | |
603 | 222k | ip_input_wrapper(mbuf_data); |
604 | 222k | } |
605 | | |
606 | 301k | void DoIp6Packet(const Ip6Packet &packet) { |
607 | 301k | size_t expected_size = packet.data().size(); |
608 | 301k | std::string packet_s = get_ip6_hdr(packet.ip6_hdr(), expected_size); |
609 | 301k | packet_s += packet.data(); |
610 | | |
611 | 301k | void *mbuf_data = get_mbuf_data(packet_s.data(), packet_s.size(), PKTF_LOOP); |
612 | 301k | if (!mbuf_data) { |
613 | 0 | return; |
614 | 0 | } |
615 | | |
616 | 301k | ip6_input_wrapper(mbuf_data); |
617 | 301k | } |
618 | | |
619 | 1.58M | void DoIpInput(const Packet &packet) { |
620 | 1.58M | switch (packet.packet_case()) { |
621 | 31.5k | case Packet::kTcpPacket: { |
622 | 31.5k | DoTcpInput(packet.tcp_packet()); |
623 | 31.5k | break; |
624 | 0 | } |
625 | 43.5k | case Packet::kTcp6Packet: { |
626 | 43.5k | DoTcp6Input(packet.tcp6_packet()); |
627 | 43.5k | break; |
628 | 0 | } |
629 | 222k | case Packet::kIp4Packet: { |
630 | 222k | DoIp4Packet(packet.ip4_packet()); |
631 | 222k | break; |
632 | 0 | } |
633 | 301k | case Packet::kIp6Packet: { |
634 | 301k | DoIp6Packet(packet.ip6_packet()); |
635 | 301k | break; |
636 | 0 | } |
637 | 216k | case Packet::kRawIp4: { |
638 | 216k | void *mbuf_data = get_mbuf_data(packet.raw_ip4().data(), |
639 | 216k | packet.raw_ip4().size(), PKTF_LOOP); |
640 | 216k | if (!mbuf_data) { |
641 | 0 | return; |
642 | 0 | } |
643 | | |
644 | 216k | ip_input_wrapper(mbuf_data); |
645 | 216k | break; |
646 | 216k | } |
647 | 120k | case Packet::kRawIp6: { |
648 | 120k | void *mbuf_data = get_mbuf_data(packet.raw_ip6().data(), |
649 | 120k | packet.raw_ip6().size(), PKTF_LOOP); |
650 | 120k | if (!mbuf_data) { |
651 | 0 | return; |
652 | 0 | } |
653 | | |
654 | 120k | ip6_input_wrapper(mbuf_data); |
655 | 120k | break; |
656 | 120k | } |
657 | 650k | case Packet::PACKET_NOT_SET: { |
658 | 650k | break; |
659 | 120k | } |
660 | 1.58M | } |
661 | 1.58M | } |
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 | 9.83k | DEFINE_BINARY_PROTO_FUZZER(const Session &session) { |
666 | | // std::string str; |
667 | | // google::protobuf::TextFormat::PrintToString(session, &str); |
668 | | // std::cout << str; |
669 | 9.83k | if (!ready) { |
670 | 1 | initialize_network(); |
671 | 1 | init_proc(); |
672 | 1 | ready = true; |
673 | 1 | } |
674 | | |
675 | 9.83k | FuzzedDataProvider dp((const uint8_t *)session.data_provider().data(), |
676 | 9.83k | session.data_provider().size()); |
677 | 9.83k | 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 | 9.83k | std::vector<uint32_t> cids; |
682 | 9.83k | std::set<int> open_fds; |
683 | | |
684 | 17.6M | for (const Command &command : session.commands()) { |
685 | 17.6M | int retval = 0; |
686 | 17.6M | switch (command.command_case()) { |
687 | 74.9k | case Command::kSocket: { |
688 | 74.9k | int fd = 0; |
689 | 74.9k | int err = socket_wrapper(command.socket().domain(), |
690 | 74.9k | command.socket().so_type(), |
691 | 74.9k | command.socket().protocol(), &fd); |
692 | 74.9k | if (err == 0) { |
693 | | // Make sure we're tracking fds properly. |
694 | 0 | if (open_fds.find(fd) != open_fds.end()) { |
695 | 0 | printf("Found existing fd %d\n", fd); |
696 | 0 | assert(false); |
697 | 0 | } |
698 | 0 | open_fds.insert(fd); |
699 | 0 | } |
700 | 0 | break; |
701 | 0 | } |
702 | 161k | case Command::kClose: { |
703 | 161k | open_fds.erase(command.close().fd()); |
704 | 161k | close_wrapper(command.close().fd(), nullptr); |
705 | 161k | break; |
706 | 0 | } |
707 | 176k | case Command::kSetSockOpt: { |
708 | 176k | int s = command.set_sock_opt().fd(); |
709 | 176k | int level = command.set_sock_opt().level(); |
710 | 176k | int name = command.set_sock_opt().name(); |
711 | 176k | size_t size = command.set_sock_opt().val().size(); |
712 | 176k | std::unique_ptr<char[]> val(new char[size]); |
713 | 176k | memcpy(val.get(), command.set_sock_opt().val().data(), size); |
714 | 176k | setsockopt_wrapper(s, level, name, val.get(), size, nullptr); |
715 | 176k | break; |
716 | 0 | } |
717 | 343k | case Command::kGetSockOpt: { |
718 | 343k | int s = command.get_sock_opt().fd(); |
719 | 343k | int level = command.get_sock_opt().level(); |
720 | 343k | int name = command.get_sock_opt().name(); |
721 | 343k | socklen_t size = command.get_sock_opt().size(); |
722 | 343k | if (size < 0 || size > 4096) { |
723 | 6.33k | break; |
724 | 6.33k | } |
725 | 336k | std::unique_ptr<char[]> val(new char[size]); |
726 | 336k | getsockopt_wrapper(s, level, name, val.get(), &size, nullptr); |
727 | 336k | break; |
728 | 343k | } |
729 | 91.0k | case Command::kBind: { |
730 | 91.0k | std::string sockaddr_s = get_sockaddr(command.bind().sockaddr()); |
731 | 91.0k | bind_wrapper(command.bind().fd(), (caddr_t)sockaddr_s.data(), |
732 | 91.0k | sockaddr_s.size(), nullptr); |
733 | 91.0k | break; |
734 | 343k | } |
735 | 624k | case Command::kIoctl: { |
736 | | // TODO: pick these values more efficiently |
737 | | // XXX: these mutate global state |
738 | 624k | uint32_t fd = command.ioctl().fd(); |
739 | 624k | uint32_t com = ioctls[command.ioctl().ioctl_idx() - 1]; |
740 | 624k | real_copyout = false; |
741 | 624k | ioctl_wrapper(fd, com, /*data=*/(caddr_t)1, nullptr); |
742 | 624k | real_copyout = true; |
743 | 624k | break; |
744 | 343k | } |
745 | 163k | case Command::kAccept: { |
746 | 163k | std::string sockaddr_s = get_sockaddr(command.accept().sockaddr()); |
747 | 163k | socklen_t size = sockaddr_s.size(); |
748 | 163k | int retval = 0; |
749 | 163k | accept_wrapper(command.accept().fd(), (caddr_t)sockaddr_s.data(), &size, |
750 | 163k | &retval); |
751 | 163k | break; |
752 | 343k | } |
753 | 1.58M | case Command::kIpInput: { |
754 | 1.58M | DoIpInput(command.ip_input()); |
755 | 1.58M | break; |
756 | 343k | } |
757 | 190k | case Command::kIoctlReal: { |
758 | 190k | switch (command.ioctl_real().ioctl_case()) { |
759 | 20.7k | case IoctlReal::kSiocaifaddrIn664: { |
760 | 20.7k | const In6_AliasReq_64 &req = |
761 | 20.7k | command.ioctl_real().siocaifaddr_in6_64(); |
762 | 20.7k | struct in6_aliasreq_64 alias = {}; |
763 | 20.7k | memcpy(alias.ifra_name, req.ifra_name().data(), |
764 | 20.7k | std::min(req.ifra_name().size(), sizeof(alias.ifra_name))); |
765 | 20.7k | get_sockaddr6(&alias.ifra_addr, req.ifra_addr()); |
766 | 20.7k | get_sockaddr6(&alias.ifra_dstaddr, req.ifra_dstaddr()); |
767 | 20.7k | get_sockaddr6(&alias.ifra_prefixmask, req.ifra_prefixmask()); |
768 | 20.7k | for (int flag : req.ifra_flags()) { |
769 | | // make mutations that dupe a flag more useful by xoring |
770 | 5.00k | alias.ifra_flags ^= flag; |
771 | 5.00k | } |
772 | 20.7k | get_in6_addrlifetime_64(&alias.ifra_lifetime, req.ifra_lifetime()); |
773 | 20.7k | ioctl_wrapper(command.ioctl_real().fd(), siocaifaddr_in6_64, |
774 | 20.7k | (caddr_t)&alias, nullptr); |
775 | 20.7k | } |
776 | 81.3k | case IoctlReal::kSiocsifflags: { |
777 | 81.3k | struct ifreq ifreq = {}; |
778 | 81.3k | for (int flag : command.ioctl_real().siocsifflags().flags()) { |
779 | 69.7k | ifreq.ifr_flags |= flag; |
780 | 69.7k | } |
781 | 81.3k | get_ifr_name(ifreq.ifr_name, LO0); |
782 | 81.3k | ioctl_wrapper(command.ioctl_real().fd(), siocsifflags, |
783 | 81.3k | (caddr_t)&ifreq, nullptr); |
784 | 81.3k | break; |
785 | 20.7k | } |
786 | 108k | case IoctlReal::IOCTL_NOT_SET: { |
787 | 108k | break; |
788 | 20.7k | } |
789 | 190k | } |
790 | 190k | } |
791 | 310k | case Command::kConnectx: { |
792 | 310k | bool has_srcaddr = command.connectx().endpoints().has_sae_srcaddr(); |
793 | | |
794 | 310k | std::string srcaddr_s; |
795 | 310k | if (has_srcaddr) { |
796 | 24.1k | srcaddr_s = |
797 | 24.1k | get_sockaddr(command.connectx().endpoints().sae_srcaddr()); |
798 | 24.1k | } |
799 | | |
800 | 310k | std::string dstaddr_s = |
801 | 310k | get_sockaddr(command.connectx().endpoints().sae_dstaddr()); |
802 | | |
803 | 310k | void *srcaddr = (void *)srcaddr_s.data(); |
804 | 310k | uint32_t srcsize = srcaddr_s.size(); |
805 | 310k | if (!has_srcaddr) { |
806 | 286k | srcaddr = nullptr; |
807 | 286k | assert(!srcsize); |
808 | 286k | } |
809 | | |
810 | 0 | void *dstaddr = (void *)dstaddr_s.data(); |
811 | 310k | uint32_t dstsize = dstaddr_s.size(); |
812 | | |
813 | | // We ignore failure here since it's ok to try to send things regardless |
814 | 310k | uint32_t connectx_flags = 0; |
815 | 310k | for (const int flag : command.connectx().flags()) { |
816 | 15.1k | connectx_flags |= flag; |
817 | 15.1k | } |
818 | 310k | uint32_t cid = 0; |
819 | | |
820 | 310k | struct user64_sa_endpoints endpoints = { |
821 | 310k | .sae_srcif = static_cast<unsigned int>(command.connectx().endpoints().sae_srcif()), |
822 | 310k | .sae_srcaddr = (user64_addr_t)srcaddr, |
823 | 310k | .sae_srcaddrlen = srcsize, |
824 | 310k | .sae_dstaddr = (user64_addr_t)dstaddr, |
825 | 310k | .sae_dstaddrlen = dstsize}; |
826 | | |
827 | | // TODO(nedwill): is this a return value? |
828 | 310k | size_t len = 0; |
829 | | // TODO(nedwill): add IOV mocking |
830 | 310k | connectx_wrapper(command.connectx().socket(), &endpoints, |
831 | 310k | command.connectx().associd(), connectx_flags, nullptr, |
832 | 310k | 0, &len, &cid, nullptr); |
833 | 310k | cids.push_back(cid); |
834 | 310k | break; |
835 | 190k | } |
836 | 110k | case Command::kConnect: { |
837 | 110k | std::string sockaddr_s = get_sockaddr(command.connect().sockaddr()); |
838 | 110k | connect_wrapper(command.connect().fd(), (caddr_t)sockaddr_s.data(), |
839 | 110k | sockaddr_s.size(), nullptr); |
840 | 110k | break; |
841 | 190k | } |
842 | 114k | case Command::kListen: { |
843 | 114k | listen_wrapper(command.listen().socket(), command.listen().backlog(), |
844 | 114k | nullptr); |
845 | 114k | break; |
846 | 190k | } |
847 | 73.7k | case Command::kDisconnectx: { |
848 | 73.7k | uint32_t cid = 0; |
849 | 73.7k | if (!cids.empty()) { |
850 | 73.1k | cid = cids[command.disconnectx().cid() % cids.size()]; |
851 | 73.1k | } else { |
852 | 608 | cid = command.disconnectx().cid(); |
853 | 608 | } |
854 | 73.7k | disconnectx_wrapper(command.disconnectx().fd(), |
855 | 73.7k | command.disconnectx().associd(), cid, nullptr); |
856 | 73.7k | break; |
857 | 190k | } |
858 | 399k | case Command::kClearAll: { |
859 | | // TODO(nedwill): finer-grained calling of clear_all functions here |
860 | 399k | clear_all(); |
861 | 399k | break; |
862 | 190k | } |
863 | 63.7k | case Command::kNecpMatchPolicy: { |
864 | 63.7k | std::unique_ptr<uint8_t[]> parameters_u8( |
865 | 63.7k | new uint8_t[command.necp_match_policy().parameters().size()]); |
866 | 63.7k | memcpy(parameters_u8.get(), |
867 | 63.7k | command.necp_match_policy().parameters().data(), |
868 | 63.7k | 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.7k | break; |
874 | 190k | } |
875 | 157k | 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 | 157k | break; |
890 | 190k | } |
891 | 102k | case Command::kNecpClientAction: { |
892 | | // DoNecpClientAction(command.necp_client_action()); |
893 | 102k | break; |
894 | 190k | } |
895 | 137k | 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 | 137k | break; |
907 | 190k | } |
908 | 131k | case Command::kNecpSessionAction: { |
909 | 131k | size_t out_buffer_size = |
910 | 131k | command.necp_session_action().out_buffer_size() % 4096; |
911 | 131k | 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 | 131k | break; |
920 | 190k | } |
921 | 110k | case Command::kAcceptNocancel: { |
922 | 110k | std::string sockaddr_s = get_sockaddr(command.accept_nocancel().name()); |
923 | 110k | socklen_t size = sockaddr_s.size(); |
924 | 110k | accept_nocancel_wrapper(command.accept_nocancel().s(), |
925 | 110k | (caddr_t)sockaddr_s.data(), &size, &retval); |
926 | 110k | break; |
927 | 190k | } |
928 | 128k | case Command::kConnectNocancel: { |
929 | 128k | std::string sockaddr_s = |
930 | 128k | get_sockaddr(command.connect_nocancel().name()); |
931 | 128k | socklen_t size = sockaddr_s.size(); |
932 | 128k | connect_nocancel_wrapper(command.connect_nocancel().s(), |
933 | 128k | (caddr_t)sockaddr_s.data(), size, &retval); |
934 | 128k | break; |
935 | 190k | } |
936 | 108k | case Command::kGetpeername: { |
937 | 108k | std::string sockaddr_s = get_sockaddr(command.getpeername().asa()); |
938 | 108k | socklen_t size = sockaddr_s.size(); |
939 | 108k | getpeername_wrapper(command.getpeername().fdes(), |
940 | 108k | (caddr_t)sockaddr_s.data(), &size, &retval); |
941 | 108k | break; |
942 | 190k | } |
943 | 87.7k | case Command::kGetsockname: { |
944 | 87.7k | std::string sockaddr_s = get_sockaddr(command.getsockname().asa()); |
945 | 87.7k | socklen_t size = sockaddr_s.size(); |
946 | 87.7k | getsockname_wrapper(command.getsockname().fdes(), |
947 | 87.7k | (caddr_t)sockaddr_s.data(), &size, &retval); |
948 | 87.7k | break; |
949 | 190k | } |
950 | 104k | case Command::kPeeloff: { |
951 | 104k | peeloff_wrapper(command.peeloff().s(), command.peeloff().aid(), |
952 | 104k | &retval); |
953 | 104k | break; |
954 | 190k | } |
955 | 75.7k | case Command::kRecvfrom: { |
956 | 75.7k | std::string sockaddr_s = get_sockaddr(command.recvfrom().from()); |
957 | 75.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 | 75.7k | recvfrom_wrapper( |
961 | 75.7k | command.recvfrom().s(), (caddr_t)command.recvfrom().buf().data(), |
962 | 75.7k | command.recvfrom().buf().size(), command.recvfrom().flags(), |
963 | 75.7k | (struct sockaddr *)sockaddr_s.data(), &size, &retval); |
964 | 75.7k | break; |
965 | 190k | } |
966 | 73.8k | case Command::kRecvfromNocancel: { |
967 | 73.8k | std::string sockaddr_s = |
968 | 73.8k | get_sockaddr(command.recvfrom_nocancel().from()); |
969 | 73.8k | int size = sockaddr_s.size(); |
970 | 73.8k | recvfrom_nocancel_wrapper( |
971 | 73.8k | command.recvfrom_nocancel().s(), |
972 | 73.8k | (caddr_t)command.recvfrom_nocancel().buf().data(), |
973 | 73.8k | command.recvfrom_nocancel().buf().size(), |
974 | 73.8k | command.recvfrom_nocancel().flags(), |
975 | 73.8k | (struct sockaddr *)sockaddr_s.data(), &size, &retval); |
976 | 73.8k | break; |
977 | 190k | } |
978 | 100k | case Command::kRecvmsg: { |
979 | | // TODO(nedwill): fuzz this msg field |
980 | 100k | user64_msghdr msg = {}; |
981 | 100k | recvmsg_wrapper(command.recvmsg().s(), (struct msghdr *)&msg, |
982 | 100k | command.recvmsg().flags(), &retval); |
983 | 100k | break; |
984 | 190k | } |
985 | 183k | case Command::kSendto: { |
986 | 183k | std::string sockaddr_s = get_sockaddr(command.sendto().to()); |
987 | 183k | socklen_t size = sockaddr_s.size(); |
988 | 183k | sendto_wrapper(command.sendto().s(), |
989 | 183k | (caddr_t)command.sendto().buf().data(), |
990 | 183k | command.sendto().buf().size(), command.sendto().flags(), |
991 | 183k | (caddr_t)sockaddr_s.data(), size, &retval); |
992 | 183k | break; |
993 | 190k | } |
994 | 1.96M | case Command::kSocketpair: { |
995 | 1.96M | int rsv[2] = {}; |
996 | 1.96M | int ret = socketpair_wrapper( |
997 | 1.96M | command.socketpair().domain(), command.socketpair().type(), |
998 | 1.96M | command.socketpair().protocol(), rsv, &retval); |
999 | 1.96M | if (!ret) { |
1000 | 1 | if (open_fds.find(rsv[0]) != open_fds.end()) { |
1001 | 0 | assert(false); |
1002 | 0 | } |
1003 | 0 | open_fds.insert(rsv[0]); |
1004 | 1 | if (open_fds.find(rsv[1]) != open_fds.end()) { |
1005 | 0 | assert(false); |
1006 | 0 | } |
1007 | 0 | open_fds.insert(rsv[1]); |
1008 | 1 | } |
1009 | 0 | break; |
1010 | 190k | } |
1011 | 189k | case Command::kPipe: { |
1012 | 189k | int rsv[2] = {}; |
1013 | 189k | int ret = pipe_wrapper(rsv); |
1014 | 189k | if (!ret) { |
1015 | 4 | if (open_fds.find(rsv[0]) != open_fds.end()) { |
1016 | 0 | assert(false); |
1017 | 0 | } |
1018 | 0 | open_fds.insert(rsv[0]); |
1019 | 4 | if (open_fds.find(rsv[1]) != open_fds.end()) { |
1020 | 0 | assert(false); |
1021 | 0 | } |
1022 | 0 | open_fds.insert(rsv[1]); |
1023 | 4 | } |
1024 | 0 | break; |
1025 | 190k | } |
1026 | 122k | case Command::kShutdown: { |
1027 | 122k | shutdown_wrapper(command.shutdown().s(), command.shutdown().how(), |
1028 | 122k | &retval); |
1029 | 122k | break; |
1030 | 190k | } |
1031 | 9.59M | case Command::COMMAND_NOT_SET: { |
1032 | 9.59M | break; |
1033 | 190k | } |
1034 | 17.6M | } |
1035 | 17.6M | } |
1036 | | |
1037 | 9.83k | 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 | 9.83k | clear_all(); |
1045 | 9.83k | } |
1046 | | } |