1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:27:35 +00:00

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.
This commit is contained in:
Idan Horowitz 2021-04-04 23:20:30 +03:00 committed by Andreas Kling
parent 6b360834f2
commit e8d2d73d55
2 changed files with 10 additions and 8 deletions

View file

@ -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<u32>(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<IPv4Address>(DHCPOption::SubnetMask).value(), options.get_many<IPv4Address>(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<u32>();
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());

View file

@ -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<InterfaceDescriptor> 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);