diff options
-rw-r--r-- | networking/udhcp/common.h | 4 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 4 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 34 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 4 | ||||
-rw-r--r-- | networking/udhcp/packet.c | 7 |
5 files changed, 37 insertions, 16 deletions
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index a9c23a186..04939e707 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -308,7 +308,9 @@ int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port) FAST_FUNC; + uint32_t dest_nip, int dest_port, + int send_flags +) FAST_FUNC; void udhcp_sp_setup(void) FAST_FUNC; void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index d4bb3507b..c13f23505 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -702,13 +702,15 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st opt_ptr = add_d6_client_options(opt_ptr); bb_error_msg("sending %s", "renew"); - if (server_ipv6) + if (server_ipv6) { return d6_send_kernel_packet( &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, server_ipv6, SERVER_PORT6, client_config.ifindex + /* TODO? send_flags: MSG_DONTROUTE (see IPv4 code for reason why) */ ); + } return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); } diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 6c74996ef..2ae8bcc4d 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 */ diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 05ddc8649..57d8b36c5 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -588,7 +588,9 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) udhcp_send_kernel_packet(dhcp_pkt, server_config.server_nip, SERVER_PORT, - dhcp_pkt->gateway_nip, SERVER_PORT); + dhcp_pkt->gateway_nip, SERVER_PORT, + /*send_flags:*/ 0 + ); } static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 44d9ceec7..ad0028bd0 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -191,7 +191,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, /* Let the kernel do all the work for packet generation */ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port) + uint32_t dest_nip, int dest_port, + int send_flags) { struct sockaddr_in sa; unsigned padding; @@ -228,8 +229,8 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); if (padding > DHCP_SIZE - 300) padding = DHCP_SIZE - 300; - result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding); - msg = "write"; + result = send(fd, dhcp_pkt, DHCP_SIZE - padding, send_flags); + msg = "send"; ret_close: close(fd); if (result < 0) { |