]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/fuzz-dhcp6-client.c
dhcp6-network: constify arguments
[thirdparty/systemd.git] / src / libsystemd-network / fuzz-dhcp6-client.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
d89a400e
EV
2
3#include <unistd.h>
4
5#include "sd-dhcp6-client.h"
6#include "sd-event.h"
7
8#include "dhcp6-internal.h"
013c6904 9#include "event-util.h"
d89a400e
EV
10#include "fd-util.h"
11#include "fuzz.h"
12
71136404 13static int test_dhcp_fd[2] = EBADF_PAIR;
d89a400e 14
dea17a08 15int dhcp6_network_send_udp_socket(int s, const struct in6_addr *server_address, const void *packet, size_t len) {
d89a400e
EV
16 return len;
17}
18
dea17a08 19int dhcp6_network_bind_udp_socket(int index, const struct in6_addr *local_address) {
804a6a17 20 assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_dhcp_fd) >= 0);
013c6904 21 return TAKE_FD(test_dhcp_fd[0]);
d89a400e
EV
22}
23
013c6904
YW
24static void fuzz_client(sd_dhcp6_client *client, const uint8_t *data, size_t size, DHCP6State state) {
25 assert_se(sd_dhcp6_client_set_information_request(client, state == DHCP6_STATE_INFORMATION_REQUEST) >= 0);
d89a400e
EV
26 assert_se(sd_dhcp6_client_start(client) >= 0);
27
013c6904
YW
28 client->state = state;
29
d89a400e 30 if (size >= sizeof(DHCP6Message))
6f3fc861 31 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message *) data)->transaction_id) == 0);
d89a400e 32
7b53d3ea
YW
33 /* These states does not require lease to send message. */
34 if (IN_SET(client->state, DHCP6_STATE_INFORMATION_REQUEST, DHCP6_STATE_SOLICITATION))
35 assert_se(dhcp6_client_send_message(client) >= 0);
36
d89a400e
EV
37 assert_se(write(test_dhcp_fd[1], data, size) == (ssize_t) size);
38
013c6904
YW
39 assert_se(sd_event_run(sd_dhcp6_client_get_event(client), UINT64_MAX) > 0);
40
41 /* Check the state transition. */
42 if (client->state != state)
43 switch (state) {
44 case DHCP6_STATE_INFORMATION_REQUEST:
45 assert_se(client->state == DHCP6_STATE_STOPPED);
46 break;
47 case DHCP6_STATE_SOLICITATION:
48 assert_se(IN_SET(client->state, DHCP6_STATE_REQUEST, DHCP6_STATE_BOUND));
49 break;
50 case DHCP6_STATE_REQUEST:
1929c1fc 51 assert_se(IN_SET(client->state, DHCP6_STATE_BOUND, DHCP6_STATE_SOLICITATION));
013c6904
YW
52 break;
53 default:
54 assert_not_reached();
55 }
d89a400e 56
7b53d3ea
YW
57 /* Send message if the client has a lease. */
58 if (state != DHCP6_STATE_INFORMATION_REQUEST && sd_dhcp6_client_get_lease(client, NULL) >= 0) {
59 client->state = DHCP6_STATE_REQUEST;
60 dhcp6_client_send_message(client);
61 }
62
d89a400e
EV
63 assert_se(sd_dhcp6_client_stop(client) >= 0);
64
65 test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]);
66}
67
68int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
013c6904
YW
69 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
70 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
bccb8fc6 71 _cleanup_(sd_dhcp6_option_unrefp) sd_dhcp6_option *v1 = NULL, *v2 = NULL;
013c6904 72 struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
bccb8fc6
YW
73 struct in6_addr hint = { { { 0x3f, 0xfe, 0x05, 0x01, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } };
74 static const char *v1_data = "hogehoge", *v2_data = "foobar";
013c6904 75
8b50b319
YW
76 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
77
4820c9d4 78 fuzz_setup_logging();
042c9145 79
c4f883b7 80 if (outside_size_range(size, 0, 65536))
55ac7b63
YW
81 return 0;
82
013c6904
YW
83 assert_se(sd_event_new(&e) >= 0);
84 assert_se(sd_dhcp6_client_new(&client) >= 0);
85 assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
86 assert_se(sd_dhcp6_client_set_ifindex(client, 42) >= 0);
87 assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
013c6904 88
7b53d3ea
YW
89 /* Used when sending message. */
90 assert_se(sd_dhcp6_client_set_fqdn(client, "example.com") == 1);
91 assert_se(sd_dhcp6_client_set_request_mud_url(client, "https://www.example.com/mudfile.json") >= 0);
92 assert_se(sd_dhcp6_client_set_request_user_class(client, STRV_MAKE("u1", "u2", "u3")) >= 0);
93 assert_se(sd_dhcp6_client_set_request_vendor_class(client, STRV_MAKE("v1", "v2", "v3")) >= 0);
bccb8fc6
YW
94 assert_se(sd_dhcp6_client_set_prefix_delegation_hint(client, 48, &hint) >= 0);
95 assert_se(sd_dhcp6_option_new(123, v1_data, strlen(v1_data), 12345, &v1) >= 0);
96 assert_se(sd_dhcp6_option_new(456, v2_data, strlen(v2_data), 45678, &v2) >= 0);
97 assert_se(sd_dhcp6_client_add_vendor_option(client, v1) >= 0);
98 assert_se(sd_dhcp6_client_add_vendor_option(client, v2) >= 0);
7b53d3ea 99
013c6904
YW
100 fuzz_client(client, data, size, DHCP6_STATE_INFORMATION_REQUEST);
101 fuzz_client(client, data, size, DHCP6_STATE_SOLICITATION);
102
103 /* If size is zero, then the resend timer will be triggered at first,
104 * but in the REQUEST state the client must have a lease. */
105 if (size == 0)
106 return 0;
d89a400e 107
013c6904 108 fuzz_client(client, data, size, DHCP6_STATE_REQUEST);
d89a400e
EV
109
110 return 0;
111}