diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index 0b72813733..a3d8bb45b3 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 3d3809c96b..1f4ad095d5 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 8db517293f..da9e56b943 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 cbdeb42eff..384972f1a0 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 6be2f4b02a..fddb3a59eb 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 2a0d7bf853..bf19226d4f 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 a8e5c683b8..a6e78dd071 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 437028800d..45c0f14d2c 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 a2b46b9962..b2e6034b42 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]) {