dhcp.c: Remove temporary default route properly
DHCP is implemented in propagator in a rather lazy way: to dynamically configure a network interface, say `eno1', instead of slinging raw Ethernet frames around like everyone else, it sets up a (temporary) default null route through that interface and throws UDP messages with actual bootp payload. `ip' utility describes such a route as `default dev eno1 scope link' The idea behind this presumably was to avoid generating IP and UDP headers manually while the null route is sufficient to send a couple of link-wide (maybe broadcast) messages and generic enough to work anywhere. To this date propagator didn't bother to remove that route, so *in some networks* it had persisted even after the initramfs (and propagator itself) was long gone, and in other networks did not, having been luckily replaced by the default route to DHCP gateway. In the cases where it did the real problem showed itself after the real userspace (for example, in a live distro) eventually tried to reconfigure the network (because why not?). The pesky null route was most often left untouched by the DHCP client (ALT live distros mostly use dhcpcd), managing to squeeze its way up the routing table and effectively preventing the host from network access beyond a router. If the NFS root is behind a couple routers, any attempt to access the file system gets stuck — the system keeps tirelessly looking for the NFS host via ARP.
This commit is contained in:
parent
dfa3713d0f
commit
6ce39ab483
32
dhcp.c
32
dhcp.c
@ -212,6 +212,37 @@ static int initial_setup_interface(char * device, int s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int interface_cleanup(char * device, int s) {
|
||||||
|
/*
|
||||||
|
* Removing the auxiliary route
|
||||||
|
* made by initial_setup_interface()
|
||||||
|
*/
|
||||||
|
struct rtentry route;
|
||||||
|
struct sockaddr_in* address;
|
||||||
|
|
||||||
|
memset(&route, 0, sizeof(route));
|
||||||
|
|
||||||
|
route.rt_dev = device;
|
||||||
|
route.rt_flags = RTF_UP | RTF_GATEWAY;
|
||||||
|
route.rt_metric = 0;
|
||||||
|
|
||||||
|
address = (struct sockaddr_in*) &route.rt_dst;
|
||||||
|
address->sin_family = AF_INET;
|
||||||
|
|
||||||
|
address = (struct sockaddr_in*) &route.rt_gateway;
|
||||||
|
address->sin_family = AF_INET;
|
||||||
|
|
||||||
|
address = (struct sockaddr_in*) &route.rt_genmask;
|
||||||
|
address->sin_family = AF_INET;
|
||||||
|
|
||||||
|
if (ioctl(s, SIOCDELRT, &route)) {
|
||||||
|
close(s);
|
||||||
|
log_perror("SIOCDELRT");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void set_missing_ip_info(struct interface_info * intf)
|
void set_missing_ip_info(struct interface_info * intf)
|
||||||
{
|
{
|
||||||
@ -665,6 +696,7 @@ enum return_type perform_dhcp(struct interface_info * intf)
|
|||||||
}
|
}
|
||||||
lease = ntohl(lease);
|
lease = ntohl(lease);
|
||||||
|
|
||||||
|
interface_cleanup(intf->device, s);
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
intf->netmask.s_addr = 0;
|
intf->netmask.s_addr = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user