From: Yu Watanabe Date: Wed, 8 Nov 2023 04:04:59 +0000 (+0900) Subject: sd-dhcp-client: split out client_verify_message_header() X-Git-Tag: v255-rc2~81^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7f42c66015d694aa44f0965109d7a341e36ee674;p=thirdparty%2Fsystemd.git sd-dhcp-client: split out client_verify_message_header() This is not necessary to be called when a packet is received through the RAW socket, but should not hurt anything. --- diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 24711ee77e2..3f2e0e3ded3 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -2012,6 +2012,54 @@ static int client_restart(sd_dhcp_client *client) { return 0; } +static int client_verify_message_header(sd_dhcp_client *client, DHCPMessage *message, size_t len) { + const uint8_t *expected_chaddr = NULL; + uint8_t expected_hlen = 0; + + assert(client); + assert(message); + + if (len < sizeof(DHCPMessage)) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG), + "Too small to be a DHCP message, ignoring."); + + if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG), + "Not a DHCP message, ignoring."); + + if (message->op != BOOTREPLY) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG), + "Not a BOOTREPLY message, ignoring."); + + if (message->htype != client->arp_type) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG), + "Packet type does not match client type, ignoring."); + + if (client->arp_type == ARPHRD_ETHER) { + expected_hlen = ETH_ALEN; + expected_chaddr = client->hw_addr.bytes; + } + + if (message->hlen != expected_hlen) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG), + "Received packet hlen (%u) does not match expected (%u), ignoring.", + message->hlen, expected_hlen); + + if (memcmp_safe(message->chaddr, expected_chaddr, expected_hlen)) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG), + "Received chaddr does not match expected, ignoring."); + + if (client->state != DHCP_STATE_BOUND && + be32toh(message->xid) != client->xid) + /* in BOUND state, we may receive FORCERENEW with xid set by server, + so ignore the xid in this case */ + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG), + "Received xid (%u) does not match expected (%u), ignoring.", + be32toh(message->xid), client->xid); + + return 0; +} + static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, size_t len) { DHCP_CLIENT_DONT_DESTROY(client); int r; @@ -2019,6 +2067,9 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, s assert(client); assert(message); + if (client_verify_message_header(client, message, len) < 0) + return 0; + switch (client->state) { case DHCP_STATE_SELECTING: @@ -2082,8 +2133,6 @@ static int client_receive_message_udp( sd_dhcp_client *client = ASSERT_PTR(userdata); _cleanup_free_ DHCPMessage *message = NULL; - const uint8_t *expected_chaddr = NULL; - uint8_t expected_hlen = 0; ssize_t len, buflen; int r; @@ -2109,49 +2158,6 @@ static int client_receive_message_udp( log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket, ignoring: %m"); return 0; } - if ((size_t) len < sizeof(DHCPMessage)) { - log_dhcp_client(client, "Too small to be a DHCP message: ignoring"); - return 0; - } - - if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) { - log_dhcp_client(client, "Not a DHCP message: ignoring"); - return 0; - } - - if (message->op != BOOTREPLY) { - log_dhcp_client(client, "Not a BOOTREPLY message: ignoring"); - return 0; - } - - if (message->htype != client->arp_type) { - log_dhcp_client(client, "Packet type does not match client type"); - return 0; - } - - if (client->arp_type == ARPHRD_ETHER) { - expected_hlen = ETH_ALEN; - expected_chaddr = client->hw_addr.bytes; - } - - if (message->hlen != expected_hlen) { - log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen); - return 0; - } - - if (expected_hlen > 0 && memcmp(&message->chaddr[0], expected_chaddr, expected_hlen)) { - log_dhcp_client(client, "Received chaddr does not match expected: ignoring"); - return 0; - } - - if (client->state != DHCP_STATE_BOUND && - be32toh(message->xid) != client->xid) { - /* in BOUND state, we may receive FORCERENEW with xid set by server, - so ignore the xid in this case */ - log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring", - be32toh(message->xid), client->xid); - return 0; - } log_dhcp_client(client, "Received message from UDP socket, processing."); r = client_handle_message(client, message, len);