summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/common.h4
-rw-r--r--networking/udhcp/d6_dhcpc.c4
-rw-r--r--networking/udhcp/dhcpc.c34
-rw-r--r--networking/udhcp/dhcpd.c4
-rw-r--r--networking/udhcp/packet.c7
5 files changed, 37 insertions, 16 deletions
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index a9c23a1..04939e7 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 d4bb350..c13f235 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 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 */
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 05ddc86..57d8b36 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 44d9cee..ad0028b 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) {