aboutsummaryrefslogtreecommitdiff
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 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,
308 308
309int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, 309int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
310 uint32_t source_nip, int source_port, 310 uint32_t source_nip, int source_port,
311 uint32_t dest_nip, int dest_port) FAST_FUNC; 311 uint32_t dest_nip, int dest_port,
312 int send_flags
313) FAST_FUNC;
312 314
313void udhcp_sp_setup(void) FAST_FUNC; 315void udhcp_sp_setup(void) FAST_FUNC;
314void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; 316void 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
702 opt_ptr = add_d6_client_options(opt_ptr); 702 opt_ptr = add_d6_client_options(opt_ptr);
703 703
704 bb_error_msg("sending %s", "renew"); 704 bb_error_msg("sending %s", "renew");
705 if (server_ipv6) 705 if (server_ipv6) {
706 return d6_send_kernel_packet( 706 return d6_send_kernel_packet(
707 &packet, (opt_ptr - (uint8_t*) &packet), 707 &packet, (opt_ptr - (uint8_t*) &packet),
708 our_cur_ipv6, CLIENT_PORT6, 708 our_cur_ipv6, CLIENT_PORT6,
709 server_ipv6, SERVER_PORT6, 709 server_ipv6, SERVER_PORT6,
710 client_config.ifindex 710 client_config.ifindex
711 /* TODO? send_flags: MSG_DONTROUTE (see IPv4 code for reason why) */
711 ); 712 );
713 }
712 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); 714 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
713} 715}
714 716
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
694 694
695static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) 695static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server)
696{ 696{
697 if (server) 697 if (server) {
698 /* Without MSG_DONTROUTE, the packet was seen routed over
699 * _other interface_ if server ID is bogus (example: 1.1.1.1).
700 */
698 return udhcp_send_kernel_packet(packet, 701 return udhcp_send_kernel_packet(packet,
699 ciaddr, CLIENT_PORT, 702 ciaddr, CLIENT_PORT,
700 server, SERVER_PORT); 703 server, SERVER_PORT,
704 /*send_flags: "to hosts only on directly connected networks" */ MSG_DONTROUTE
705 );
706 }
701 return raw_bcast_from_client_config_ifindex(packet, ciaddr); 707 return raw_bcast_from_client_config_ifindex(packet, ciaddr);
702} 708}
703 709
@@ -735,7 +741,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
735static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested) 741static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested)
736{ 742{
737 struct dhcp_packet packet; 743 struct dhcp_packet packet;
738 struct in_addr addr; 744 struct in_addr temp_addr;
739 745
740/* 746/*
741 * RFC 2131 4.3.2 DHCPREQUEST message 747 * 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
766 */ 772 */
767 add_client_options(&packet); 773 add_client_options(&packet);
768 774
769 addr.s_addr = requested; 775 temp_addr.s_addr = requested;
770 bb_error_msg("sending select for %s", inet_ntoa(addr)); 776 bb_error_msg("sending select for %s", inet_ntoa(temp_addr));
771 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); 777 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
772} 778}
773 779
@@ -776,6 +782,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
776static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) 782static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
777{ 783{
778 struct dhcp_packet packet; 784 struct dhcp_packet packet;
785 struct in_addr temp_addr;
779 786
780/* 787/*
781 * RFC 2131 4.3.2 DHCPREQUEST message 788 * 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)
806 */ 813 */
807 add_client_options(&packet); 814 add_client_options(&packet);
808 815
809 bb_error_msg("sending %s", "renew"); 816 temp_addr.s_addr = server;
817 bb_error_msg("sending renew to %s", inet_ntoa(temp_addr));
810 return bcast_or_ucast(&packet, ciaddr, server); 818 return bcast_or_ucast(&packet, ciaddr, server);
811} 819}
812 820
@@ -1524,11 +1532,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1524 * Anyway, it does recover by eventually failing through 1532 * Anyway, it does recover by eventually failing through
1525 * into INIT_SELECTING state. 1533 * into INIT_SELECTING state.
1526 */ 1534 */
1527 send_renew(xid, server_addr, requested_ip); 1535 if (send_renew(xid, server_addr, requested_ip) >= 0) {
1528 timeout >>= 1; 1536 timeout >>= 1;
1529 continue; 1537 continue;
1538 }
1539 /* else: error sending.
1540 * example: ENETUNREACH seen with server
1541 * which gave us bogus server ID 1.1.1.1
1542 * which wasn't reachable (and probably did not exist).
1543 */
1530 } 1544 }
1531 /* Timed out, enter rebinding state */ 1545 /* Timed out or error, enter rebinding state */
1532 log1("entering rebinding state"); 1546 log1("entering rebinding state");
1533 state = REBINDING; 1547 state = REBINDING;
1534 /* fall right through */ 1548 /* 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)
588 588
589 udhcp_send_kernel_packet(dhcp_pkt, 589 udhcp_send_kernel_packet(dhcp_pkt,
590 server_config.server_nip, SERVER_PORT, 590 server_config.server_nip, SERVER_PORT,
591 dhcp_pkt->gateway_nip, SERVER_PORT); 591 dhcp_pkt->gateway_nip, SERVER_PORT,
592 /*send_flags:*/ 0
593 );
592} 594}
593 595
594static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) 596static 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,
191/* Let the kernel do all the work for packet generation */ 191/* Let the kernel do all the work for packet generation */
192int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, 192int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
193 uint32_t source_nip, int source_port, 193 uint32_t source_nip, int source_port,
194 uint32_t dest_nip, int dest_port) 194 uint32_t dest_nip, int dest_port,
195 int send_flags)
195{ 196{
196 struct sockaddr_in sa; 197 struct sockaddr_in sa;
197 unsigned padding; 198 unsigned padding;
@@ -228,8 +229,8 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
228 padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); 229 padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options);
229 if (padding > DHCP_SIZE - 300) 230 if (padding > DHCP_SIZE - 300)
230 padding = DHCP_SIZE - 300; 231 padding = DHCP_SIZE - 300;
231 result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding); 232 result = send(fd, dhcp_pkt, DHCP_SIZE - padding, send_flags);
232 msg = "write"; 233 msg = "send";
233 ret_close: 234 ret_close:
234 close(fd); 235 close(fd);
235 if (result < 0) { 236 if (result < 0) {