From e8d2d73d55676a6528feb6656cd52db18f5dfe30 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Sun, 4 Apr 2021 23:20:30 +0300 Subject: [PATCH] DHCPClient: Store current IP address instead of relaying on the yiaddr Real DHCP servers might decide to send the DHCPAck directly to the specified ciaddr instead of as a unicast or multicast, resulting in the ack being ignored by the network adapter when we are requesting a new IPv4 address instead of renewing an existing lease, as the yiaddr (and as a result the ciaddr) is set to the offered address in that case instead of the current ip address. --- Userland/Services/DHCPClient/DHCPv4Client.cpp | 15 ++++++++------- Userland/Services/DHCPClient/DHCPv4Client.h | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Userland/Services/DHCPClient/DHCPv4Client.cpp b/Userland/Services/DHCPClient/DHCPv4Client.cpp index 73a377deb2..8cefa1e66c 100644 --- a/Userland/Services/DHCPClient/DHCPv4Client.cpp +++ b/Userland/Services/DHCPClient/DHCPv4Client.cpp @@ -172,14 +172,15 @@ void DHCPv4Client::handle_ack(const DHCPv4Packet& packet, const ParsedDHCPv4Opti transaction->has_ip = true; auto& interface = transaction->interface; auto new_ip = packet.yiaddr(); + interface.m_current_ip_address = new_ip; auto lease_time = AK::convert_between_host_and_network_endian(options.get(DHCPOption::IPAddressLeaseTime).value_or(transaction->offered_lease_time)); // set a timer for the duration of the lease, we shall renew if needed Core::Timer::create_single_shot( lease_time * 1000, - [this, transaction, interface = InterfaceDescriptor { interface }, new_ip] { + [this, transaction, interface = InterfaceDescriptor { interface }] { transaction->accepted_offer = false; transaction->has_ip = false; - dhcp_discover(interface, new_ip); + dhcp_discover(interface); }, this); set_params(transaction->interface, new_ip, options.get(DHCPOption::SubnetMask).value(), options.get_many(DHCPOption::Router, 1).first()); @@ -238,14 +239,14 @@ void DHCPv4Client::process_incoming(const DHCPv4Packet& packet) } } -void DHCPv4Client::dhcp_discover(const InterfaceDescriptor& iface, IPv4Address previous) +void DHCPv4Client::dhcp_discover(const InterfaceDescriptor& iface) { auto transaction_id = get_random(); if constexpr (DHCPV4CLIENT_DEBUG) { dbgln("Trying to lease an IP for {} with ID {}", iface.m_ifname, transaction_id); - if (!previous.is_zero()) - dbgln("going to request the server to hand us {}", previous.to_string()); + if (!iface.m_current_ip_address.is_zero()) + dbgln("going to request the server to hand us {}", iface.m_current_ip_address.to_string()); } DHCPv4PacketBuilder builder; @@ -256,7 +257,7 @@ void DHCPv4Client::dhcp_discover(const InterfaceDescriptor& iface, IPv4Address p packet.set_hlen(sizeof(MACAddress)); packet.set_xid(transaction_id); packet.set_flags(DHCPv4Flags::Broadcast); - packet.ciaddr() = previous; + packet.ciaddr() = iface.m_current_ip_address; packet.set_chaddr(iface.m_mac_address); packet.set_secs(65535); // we lie @@ -277,7 +278,7 @@ void DHCPv4Client::dhcp_request(DHCPv4Transaction& transaction, const DHCPv4Pack DHCPv4Packet& packet = builder.peek(); packet.set_op(DHCPv4Op::BootRequest); - packet.ciaddr() = offer.yiaddr(); + packet.ciaddr() = iface.m_current_ip_address; packet.set_htype(1); // 10mb ethernet packet.set_hlen(sizeof(MACAddress)); packet.set_xid(offer.xid()); diff --git a/Userland/Services/DHCPClient/DHCPv4Client.h b/Userland/Services/DHCPClient/DHCPv4Client.h index 60f76a55ef..1c4a9e260e 100644 --- a/Userland/Services/DHCPClient/DHCPv4Client.h +++ b/Userland/Services/DHCPClient/DHCPv4Client.h @@ -40,6 +40,7 @@ struct InterfaceDescriptor { String m_ifname; MACAddress m_mac_address; + IPv4Address m_current_ip_address { 0, 0, 0, 0 }; }; struct DHCPv4Transaction { @@ -61,7 +62,7 @@ public: explicit DHCPv4Client(Vector ifnames); virtual ~DHCPv4Client() override; - void dhcp_discover(const InterfaceDescriptor& ifname, IPv4Address previous = IPv4Address { 0, 0, 0, 0 }); + void dhcp_discover(const InterfaceDescriptor& ifname); void dhcp_request(DHCPv4Transaction& transaction, const DHCPv4Packet& packet); void process_incoming(const DHCPv4Packet& packet);