diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 6c74996..2ae8bcc 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -694,10 +694,16 @@ static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) { - if (server) + if (server) { + /* Without MSG_DONTROUTE, the packet was seen routed over + * _other interface_ if server ID is bogus (example: 1.1.1.1). + */ return udhcp_send_kernel_packet(packet, ciaddr, CLIENT_PORT, - server, SERVER_PORT); + server, SERVER_PORT, + /*send_flags: "to hosts only on directly connected networks" */ MSG_DONTROUTE + ); + } return raw_bcast_from_client_config_ifindex(packet, ciaddr); } @@ -735,7 +741,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested) { struct dhcp_packet packet; - struct in_addr addr; + struct in_addr temp_addr; /* * RFC 2131 4.3.2 DHCPREQUEST message @@ -766,8 +772,8 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste */ add_client_options(&packet); - addr.s_addr = requested; - bb_error_msg("sending select for %s", inet_ntoa(addr)); + temp_addr.s_addr = requested; + bb_error_msg("sending select for %s", inet_ntoa(temp_addr)); return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); } @@ -776,6 +782,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) { struct dhcp_packet packet; + struct in_addr temp_addr; /* * RFC 2131 4.3.2 DHCPREQUEST message @@ -806,7 +813,8 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) */ add_client_options(&packet); - bb_error_msg("sending %s", "renew"); + temp_addr.s_addr = server; + bb_error_msg("sending renew to %s", inet_ntoa(temp_addr)); return bcast_or_ucast(&packet, ciaddr, server); } @@ -1524,11 +1532,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) * Anyway, it does recover by eventually failing through * into INIT_SELECTING state. */ - send_renew(xid, server_addr, requested_ip); - timeout >>= 1; - continue; + if (send_renew(xid, server_addr, requested_ip) >= 0) { + timeout >>= 1; + continue; + } + /* else: error sending. + * example: ENETUNREACH seen with server + * which gave us bogus server ID 1.1.1.1 + * which wasn't reachable (and probably did not exist). + */ } - /* Timed out, enter rebinding state */ + /* Timed out or error, enter rebinding state */ log1("entering rebinding state"); state = REBINDING; /* fall right through */ |