]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
0f0a1dad | 2 | |
0f0a1dad | 3 | #include <arpa/inet.h> |
ef118d00 YW |
4 | #include <netinet/icmp6.h> |
5 | #include <unistd.h> | |
0f0a1dad | 6 | |
f26c38ed | 7 | #include "sd-ndisc.h" |
54a4ffc0 | 8 | #include "sd-radv.h" |
f26c38ed | 9 | |
0f0a1dad | 10 | #include "alloc-util.h" |
19ee48a6 | 11 | #include "fd-util.h" |
0f0a1dad | 12 | #include "fuzz.h" |
cdb88ae4 | 13 | #include "icmp6-packet.h" |
8e41e460 | 14 | #include "icmp6-test-util.h" |
0f0a1dad | 15 | #include "ndisc-internal.h" |
cdb88ae4 | 16 | #include "ndisc-option.h" |
f26c38ed | 17 | #include "socket-util.h" |
0f0a1dad | 18 | |
cdb88ae4 | 19 | static void test_with_sd_ndisc(const uint8_t *data, size_t size) { |
0f0a1dad EV |
20 | struct ether_addr mac_addr = { |
21 | .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} | |
22 | }; | |
23 | _cleanup_(sd_event_unrefp) sd_event *e = NULL; | |
24 | _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL; | |
25 | ||
26 | assert_se(sd_event_new(&e) >= 0); | |
27 | assert_se(sd_ndisc_new(&nd) >= 0); | |
28 | assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0); | |
29 | assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); | |
30 | assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); | |
31 | assert_se(sd_ndisc_start(nd) >= 0); | |
32 | assert_se(write(test_fd[1], data, size) == (ssize_t) size); | |
f5fbe71d | 33 | (void) sd_event_run(e, UINT64_MAX); |
0f0a1dad | 34 | assert_se(sd_ndisc_stop(nd) >= 0); |
54a4ffc0 YW |
35 | test_fd[1] = safe_close(test_fd[1]); |
36 | TAKE_FD(test_fd[0]); /* It should be already closed by sd_ndisc_stop(). */ | |
37 | } | |
38 | ||
39 | static void test_with_sd_radv(const uint8_t *data, size_t size) { | |
40 | struct ether_addr mac_addr = { | |
41 | .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} | |
42 | }; | |
43 | _cleanup_(sd_event_unrefp) sd_event *e = NULL; | |
44 | _cleanup_(sd_radv_unrefp) sd_radv *ra = NULL; | |
45 | ||
46 | assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0); | |
47 | ||
48 | assert_se(sd_event_new(&e) >= 0); | |
49 | assert_se(sd_radv_new(&ra) >= 0); | |
50 | assert_se(sd_radv_attach_event(ra, e, 0) >= 0); | |
51 | assert_se(sd_radv_set_ifindex(ra, 42) >= 0); | |
52 | assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0); | |
53 | assert_se(sd_radv_start(ra) >= 0); | |
54 | assert_se(write(test_fd[0], data, size) == (ssize_t) size); | |
55 | (void) sd_event_run(e, UINT64_MAX); | |
56 | assert_se(sd_radv_stop(ra) >= 0); | |
57 | test_fd[0] = safe_close(test_fd[0]); | |
58 | TAKE_FD(test_fd[1]); /* It should be already closed by sd_radv_stop(). */ | |
cdb88ae4 YW |
59 | } |
60 | ||
61 | static void test_with_icmp6_packet(const uint8_t *data, size_t size) { | |
cdb88ae4 YW |
62 | _cleanup_close_pair_ int fd_pair[2] = EBADF_PAIR; |
63 | _cleanup_(icmp6_packet_unrefp) ICMP6Packet *packet = NULL; | |
64 | _cleanup_set_free_ Set *options = NULL; | |
65 | ||
66 | assert_se(socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, fd_pair) >= 0); | |
67 | assert_se(write(fd_pair[1], data, size) == (ssize_t) size); | |
68 | ||
69 | if (icmp6_packet_receive(fd_pair[0], &packet) < 0) | |
70 | return; | |
71 | ||
72 | if (ndisc_parse_options(packet, &options) < 0) | |
73 | return; | |
74 | ||
ac336e75 YW |
75 | if (ndisc_send(fd_pair[1], &IN6_ADDR_ALL_ROUTERS_MULTICAST, |
76 | icmp6_packet_get_header(packet), options, /* timestamp = */ 0) < 0) | |
cdb88ae4 YW |
77 | return; |
78 | ||
79 | packet = icmp6_packet_unref(packet); | |
80 | options = set_free(options); | |
81 | ||
82 | if (icmp6_packet_receive(fd_pair[0], &packet) < 0) | |
83 | return; | |
84 | ||
a33a636b | 85 | assert_se(ndisc_parse_options(packet, &options) >= 0); |
cdb88ae4 YW |
86 | } |
87 | ||
88 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | |
89 | if (outside_size_range(size, 0, 2048)) | |
90 | return 0; | |
91 | ||
92 | fuzz_setup_logging(); | |
0f0a1dad | 93 | |
cdb88ae4 | 94 | test_with_sd_ndisc(data, size); |
54a4ffc0 | 95 | test_with_sd_radv(data, size); |
cdb88ae4 | 96 | test_with_icmp6_packet(data, size); |
0f0a1dad EV |
97 | return 0; |
98 | } |