From 905d0ea7b0080dd17db46460e6c962220dc8eeaf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Nov 2023 13:49:03 +0900 Subject: [PATCH] sd-dhcp-client,-server: set timestamp based on the time when received a packet It seems that RFC does not say anything about the timestamp of lease we should use: time that the client sent a request or received a reply. In DHCPv6 client and NDisc, we use a timestamp that we receive a packet, rather than we sent something. So, let's consistently use the same logic for DHCPv4 client. By using the logic, we will hopefully not forget to set timestamp again, which is fixed by 089362976c2a653a77f942bfeb3f61d0e180f078. --- src/libsystemd-network/dhcp-lease-internal.h | 2 +- src/libsystemd-network/dhcp-network.c | 8 ++ src/libsystemd-network/dhcp-server-internal.h | 3 +- src/libsystemd-network/fuzz-dhcp-client.c | 2 +- src/libsystemd-network/fuzz-dhcp-server.c | 2 +- src/libsystemd-network/sd-dhcp-client.c | 85 ++++++++++++------- src/libsystemd-network/sd-dhcp-lease.c | 9 ++ src/libsystemd-network/sd-dhcp-server.c | 55 +++++++++--- src/libsystemd-network/test-dhcp-server.c | 46 +++++----- 9 files changed, 144 insertions(+), 68 deletions(-) diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index 0b72813733b..a3d8bb45b39 100644 --- a/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -90,8 +90,8 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains); int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len); +void dhcp_lease_set_timestamp(sd_dhcp_lease *lease, const triple_timestamp *timestamp); int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease); - int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len); #define dhcp_lease_unref_and_replace(a, b) \ diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c index 3d3809c96b3..1f4ad095d5d 100644 --- a/src/libsystemd-network/dhcp-network.c +++ b/src/libsystemd-network/dhcp-network.c @@ -115,6 +115,10 @@ static int _bind_raw_socket( if (r < 0) return -errno; + r = setsockopt_int(s, SOL_SOCKET, SO_TIMESTAMP, true); + if (r < 0) + return r; + if (so_priority_set) { r = setsockopt_int(s, SOL_SOCKET, SO_PRIORITY, so_priority); if (r < 0) @@ -206,6 +210,10 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int if (r < 0) return r; + r = setsockopt_int(s, SOL_SOCKET, SO_TIMESTAMP, true); + if (r < 0) + return r; + if (ifindex > 0) { r = socket_bind_to_ifindex(s, ifindex); if (r < 0) diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 8db517293f8..da9e56b943f 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -110,12 +110,13 @@ typedef struct DHCPRequest { const uint8_t *parameter_request_list; size_t parameter_request_list_len; bool rapid_commit; + triple_timestamp timestamp; } DHCPRequest; extern const struct hash_ops dhcp_lease_hash_ops; int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, - size_t length); + size_t length, const triple_timestamp *timestamp); int dhcp_server_send_packet(sd_dhcp_server *server, DHCPRequest *req, DHCPPacket *packet, int type, size_t optoffset); diff --git a/src/libsystemd-network/fuzz-dhcp-client.c b/src/libsystemd-network/fuzz-dhcp-client.c index cbdeb42eff8..384972f1a0a 100644 --- a/src/libsystemd-network/fuzz-dhcp-client.c +++ b/src/libsystemd-network/fuzz-dhcp-client.c @@ -75,7 +75,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { client->xid = 2; client->state = DHCP_STATE_SELECTING; - (void) client_handle_offer_or_rapid_ack(client, (DHCPMessage*) data, size); + (void) client_handle_offer_or_rapid_ack(client, (DHCPMessage*) data, size, NULL); assert_se(sd_dhcp_client_stop(client) >= 0); diff --git a/src/libsystemd-network/fuzz-dhcp-server.c b/src/libsystemd-network/fuzz-dhcp-server.c index 6be2f4b02ab..fddb3a59ebe 100644 --- a/src/libsystemd-network/fuzz-dhcp-server.c +++ b/src/libsystemd-network/fuzz-dhcp-server.c @@ -96,7 +96,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { assert_se(add_static_lease(server, 3) >= 0); assert_se(add_static_lease(server, 4) >= 0); - (void) dhcp_server_handle_message(server, (DHCPMessage*) duped, size); + (void) dhcp_server_handle_message(server, (DHCPMessage*) duped, size, NULL); return 0; } diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 2a0d7bf853b..bf19226d4ff 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -116,7 +116,6 @@ struct sd_dhcp_client { uint64_t max_attempts; OrderedHashmap *extra_options; OrderedHashmap *vendor_options; - usec_t request_sent; sd_event_source *timeout_t1; sd_event_source *timeout_t2; sd_event_source *timeout_expire; @@ -1366,16 +1365,12 @@ static int client_timeout_resend( client->attempt = 0; } else if (client->attempt >= client->max_attempts) goto error; - - client->request_sent = time_now; break; case DHCP_STATE_SELECTING: r = client_send_discover(client); if (r < 0 && client->attempt >= client->max_attempts) goto error; - - client->request_sent = time_now; break; case DHCP_STATE_INIT_REBOOT: @@ -1388,8 +1383,6 @@ static int client_timeout_resend( if (client->state == DHCP_STATE_INIT_REBOOT) client_set_state(client, DHCP_STATE_REBOOTING); - - client->request_sent = time_now; break; case DHCP_STATE_REBOOTING: @@ -1672,7 +1665,7 @@ static int client_parse_message( return 0; } -static int client_handle_offer_or_rapid_ack(sd_dhcp_client *client, DHCPMessage *message, size_t len) { +static int client_handle_offer_or_rapid_ack(sd_dhcp_client *client, DHCPMessage *message, size_t len, const triple_timestamp *timestamp) { _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; int r; @@ -1683,6 +1676,8 @@ static int client_handle_offer_or_rapid_ack(sd_dhcp_client *client, DHCPMessage if (r < 0) return r; + dhcp_lease_set_timestamp(lease, timestamp); + dhcp_lease_unref_and_replace(client->lease, lease); if (client->lease->rapid_commit) { @@ -1786,7 +1781,7 @@ static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) { return true; } -static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *message, size_t len) { +static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *message, size_t len, const triple_timestamp *timestamp) { _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; int r; @@ -1797,6 +1792,8 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *message, size_ if (r < 0) return r; + dhcp_lease_set_timestamp(lease, timestamp); + if (!client->lease) r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE; else if (lease_equal(client->lease, lease)) @@ -1818,8 +1815,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { assert(client->event); assert(client->lease); assert(client->lease->lifetime > 0); - - triple_timestamp_from_boottime(&client->lease->timestamp, client->request_sent); + assert(triple_timestamp_is_set(&client->lease->timestamp)); /* don't set timers for infinite leases */ if (client->lease->lifetime == USEC_INFINITY) { @@ -1833,7 +1829,6 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { r = sd_event_now(client->event, CLOCK_BOOTTIME, &time_now); if (r < 0) return r; - assert(client->request_sent <= time_now); /* verify that 0 < t2 < lifetime */ if (client->lease->t2 == 0 || client->lease->t2 >= client->lease->lifetime) @@ -1851,9 +1846,15 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { assert(client->lease->t1 < client->lease->t2); assert(client->lease->t2 < client->lease->lifetime); - client->expire_time = usec_add(client->request_sent, client->lease->lifetime); - client->t1_time = usec_add(client->request_sent, client->lease->t1); - client->t2_time = usec_add(client->request_sent, client->lease->t2); + r = sd_dhcp_lease_get_lifetime_timestamp(client->lease, CLOCK_BOOTTIME, &client->expire_time); + if (r < 0) + return r; + r = sd_dhcp_lease_get_t1_timestamp(client->lease, CLOCK_BOOTTIME, &client->t1_time); + if (r < 0) + return r; + r = sd_dhcp_lease_get_t2_timestamp(client->lease, CLOCK_BOOTTIME, &client->t2_time); + if (r < 0) + return r; /* RFC2131 section 4.4.5: * Times T1 and T2 SHOULD be chosen with some random "fuzz". @@ -2060,7 +2061,7 @@ static int client_verify_message_header(sd_dhcp_client *client, DHCPMessage *mes return 0; } -static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, size_t len) { +static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, size_t len, const triple_timestamp *timestamp) { DHCP_CLIENT_DONT_DESTROY(client); int r; @@ -2073,7 +2074,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, s switch (client->state) { case DHCP_STATE_SELECTING: - r = client_handle_offer_or_rapid_ack(client, message, len); + r = client_handle_offer_or_rapid_ack(client, message, len, timestamp); if (ERRNO_IS_NEG_RESOURCE(r)) return r; if (r == -EADDRNOTAVAIL) @@ -2093,7 +2094,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, s case DHCP_STATE_RENEWING: case DHCP_STATE_REBINDING: - r = client_handle_ack(client, message, len); + r = client_handle_ack(client, message, len, timestamp); if (ERRNO_IS_NEG_RESOURCE(r)) return r; if (r == -EADDRNOTAVAIL) @@ -2134,6 +2135,16 @@ static int client_receive_message_udp( sd_dhcp_client *client = ASSERT_PTR(userdata); _cleanup_free_ DHCPMessage *message = NULL; ssize_t len, buflen; + /* This needs to be initialized with zero. See #20741. */ + CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL) control = {}; + struct iovec iov; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + triple_timestamp t = {}; int r; assert(s); @@ -2150,17 +2161,22 @@ static int client_receive_message_udp( if (!message) return -ENOMEM; - len = recv(fd, message, buflen, 0); - if (len < 0) { - if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno)) - return 0; + iov = IOVEC_MAKE(message, buflen); - log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket, ignoring: %m"); + len = recvmsg_safe(fd, &msg, MSG_DONTWAIT); + if (ERRNO_IS_NEG_TRANSIENT(len) || ERRNO_IS_NEG_DISCONNECT(len)) + return 0; + if (len < 0) { + log_dhcp_client_errno(client, len, "Could not receive message from UDP socket, ignoring: %m"); return 0; } + struct timeval *tv = CMSG_FIND_AND_COPY_DATA(&msg, SOL_SOCKET, SCM_TIMESTAMP, struct timeval); + if (tv) + triple_timestamp_from_realtime(&t, timeval_load(tv)); + log_dhcp_client(client, "Received message from UDP socket, processing."); - r = client_handle_message(client, message, len); + r = client_handle_message(client, message, len, &t); if (r < 0) client_stop(client, r); @@ -2175,7 +2191,9 @@ static int client_receive_message_raw( sd_dhcp_client *client = ASSERT_PTR(userdata); _cleanup_free_ DHCPPacket *packet = NULL; - CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata))) control; + /* This needs to be initialized with zero. See #20741. */ + CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL + + CMSG_SPACE(sizeof(struct tpacket_auxdata))) control = {}; struct iovec iov = {}; struct msghdr msg = { .msg_iov = &iov, @@ -2185,6 +2203,7 @@ static int client_receive_message_raw( }; struct cmsghdr *cmsg; bool checksum = true; + triple_timestamp t = {}; ssize_t buflen, len; int r; @@ -2212,11 +2231,15 @@ static int client_receive_message_raw( return 0; } - cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata))); - if (cmsg) { - struct tpacket_auxdata *aux = CMSG_TYPED_DATA(cmsg, struct tpacket_auxdata); - checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); - } + CMSG_FOREACH(cmsg, &msg) + if (cmsg->cmsg_level == SOL_PACKET && cmsg->cmsg_type == PACKET_AUXDATA) { + struct tpacket_auxdata *aux = CMSG_TYPED_DATA(cmsg, struct tpacket_auxdata); + checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); + + } else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP) { + struct timeval *tv = CMSG_TYPED_DATA(cmsg, struct timeval); + triple_timestamp_from_realtime(&t, timeval_load(tv)); + } if (dhcp_packet_verify_headers(packet, len, checksum, client->port) < 0) return 0; @@ -2224,7 +2247,7 @@ static int client_receive_message_raw( len -= DHCP_IP_UDP_SIZE; log_dhcp_client(client, "Received message from RAW socket, processing."); - r = client_handle_message(client, &packet->dhcp, len); + r = client_handle_message(client, &packet->dhcp, len, &t); if (r < 0) client_stop(client, r); diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index a8e5c683b88..a6e78dd0719 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -33,6 +33,15 @@ #include "tmpfile-util.h" #include "unaligned.h" +void dhcp_lease_set_timestamp(sd_dhcp_lease *lease, const triple_timestamp *timestamp) { + assert(lease); + + if (timestamp && triple_timestamp_is_set(timestamp)) + lease->timestamp = *timestamp; + else + triple_timestamp_get(&lease->timestamp); +} + int sd_dhcp_lease_get_timestamp(sd_dhcp_lease *lease, clockid_t clock, uint64_t *ret) { assert_return(lease, -EINVAL); assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 437028800d0..45c0f14d2cf 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -897,6 +897,31 @@ static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMes return 0; } +static void request_set_timestamp(DHCPRequest *req, const triple_timestamp *timestamp) { + assert(req); + + if (timestamp && triple_timestamp_is_set(timestamp)) + req->timestamp = *timestamp; + else + triple_timestamp_get(&req->timestamp); +} + +static int request_get_lifetime_timestamp(DHCPRequest *req, clockid_t clock, usec_t *ret) { + assert(req); + assert(TRIPLE_TIMESTAMP_HAS_CLOCK(clock)); + assert(clock_supported(clock)); + assert(ret); + + if (req->lifetime <= 0) + return -ENODATA; + + if (!triple_timestamp_is_set(&req->timestamp)) + return -ENODATA; + + *ret = usec_add(triple_timestamp_by_clock(&req->timestamp, clock), req->lifetime); + return 0; +} + static bool address_is_in_pool(sd_dhcp_server *server, be32_t address) { assert(server); @@ -1031,19 +1056,17 @@ static int prepare_new_lease(DHCPLease **ret_lease, be32_t address, DHCPRequest } static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, DHCPLease *existing_lease, be32_t address) { - usec_t time_now, expiration; + usec_t expiration; int r; assert(server); assert(req); assert(address != 0); - r = sd_event_now(server->event, CLOCK_BOOTTIME, &time_now); + r = request_get_lifetime_timestamp(req, CLOCK_BOOTTIME, &expiration); if (r < 0) return r; - expiration = usec_add(req->lifetime, time_now); - if (existing_lease) { assert(existing_lease->server); assert(existing_lease->address == address); @@ -1148,7 +1171,7 @@ static int server_get_static_lease(sd_dhcp_server *server, const DHCPRequest *re #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30) -int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length) { +int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length, const triple_timestamp *timestamp) { _cleanup_(dhcp_request_freep) DHCPRequest *req = NULL; _cleanup_free_ char *error_message = NULL; DHCPLease *existing_lease, *static_lease; @@ -1172,6 +1195,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz if (r < 0) return r; + request_set_timestamp(req, timestamp); + r = dhcp_server_cleanup_expired_leases(server); if (r < 0) return r; @@ -1354,7 +1379,9 @@ static size_t relay_agent_information_length(const char* agent_circuit_id, const static int server_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_free_ DHCPMessage *message = NULL; - CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control; + /* This needs to be initialized with zero. See #20741. */ + CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL + + CMSG_SPACE(sizeof(struct in_pktinfo))) control = {}; sd_dhcp_server *server = ASSERT_PTR(userdata); struct iovec iov = {}; struct msghdr msg = { @@ -1364,6 +1391,8 @@ static int server_receive_message(sd_event_source *s, int fd, .msg_controllen = sizeof(control), }; ssize_t datagram_size, len; + struct cmsghdr *cmsg; + triple_timestamp t = {}; int r; datagram_size = next_datagram_size_fd(fd); @@ -1397,16 +1426,22 @@ static int server_receive_message(sd_event_source *s, int fd, return 0; /* TODO figure out if this can be done as a filter on the socket, like for IPv6 */ - struct in_pktinfo *info = CMSG_FIND_DATA(&msg, IPPROTO_IP, IP_PKTINFO, struct in_pktinfo); - if (info && info->ipi_ifindex != server->ifindex) - return 0; + CMSG_FOREACH(cmsg, &msg) + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { + struct in_pktinfo *info = CMSG_TYPED_DATA(cmsg, struct in_pktinfo); + if (info->ipi_ifindex != server->ifindex) + return 0; + } else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP) { + struct timeval *tv = CMSG_TYPED_DATA(cmsg, struct timeval); + triple_timestamp_from_realtime(&t, timeval_load(tv)); + } if (sd_dhcp_server_is_in_relay_mode(server)) { r = dhcp_server_relay_message(server, message, len - sizeof(DHCPMessage), buflen); if (r < 0) log_dhcp_server_errno(server, r, "Couldn't relay message, ignoring: %m"); } else { - r = dhcp_server_handle_message(server, message, (size_t) len); + r = dhcp_server_handle_message(server, message, (size_t) len, &t); if (r < 0) log_dhcp_server_errno(server, r, "Couldn't process incoming message, ignoring: %m"); } diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index a2b46b99627..b2e6034b420 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -135,58 +135,58 @@ static void test_message_handler(void) { assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); assert_se(sd_dhcp_server_start(server) >= 0); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.end = 0; /* TODO, shouldn't this fail? */ - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.end = SD_DHCP_OPTION_END; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.option_type.code = 0; test.option_type.length = 0; test.option_type.type = 0; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == -ENOMSG); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == -ENOMSG); test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE; test.option_type.length = 1; test.option_type.type = DHCP_DISCOVER; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.message.op = 0; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0); test.message.op = BOOTREQUEST; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.message.htype = 0; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.message.htype = ARPHRD_ETHER; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.message.hlen = 0; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == -EBADMSG); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == -EBADMSG); test.message.hlen = ETHER_ADDR_LEN; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); test.option_type.type = DHCP_REQUEST; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0); test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS; test.option_requested_ip.length = 4; test.option_requested_ip.address = htobe32(0x12345678); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_NAK); test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER; test.option_server_id.length = 4; test.option_server_id.address = htobe32(INADDR_LOOPBACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK); test.option_server_id.address = htobe32(0x12345678); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0); test.option_server_id.address = htobe32(INADDR_LOOPBACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK); test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER; test.option_client_id.length = 7; @@ -197,30 +197,30 @@ static void test_message_handler(void) { test.option_client_id.id[4] = 'D'; test.option_client_id.id[5] = 'E'; test.option_client_id.id[6] = 'F'; - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0); /* request address reserved for static lease (unmatching client ID) */ test.option_client_id.id[6] = 'H'; test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0); /* request unmatching address */ test.option_client_id.id[6] = 'G'; test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 41); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0); /* request matching address */ test.option_client_id.id[6] = 'G'; test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK); /* try again */ test.option_client_id.id[6] = 'G'; test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK); } static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) { -- 2.47.3