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, | |||
308 | 308 | ||
309 | int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 309 | int 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 | ||
313 | void udhcp_sp_setup(void) FAST_FUNC; | 315 | void udhcp_sp_setup(void) FAST_FUNC; |
314 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; | 316 | 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 | |||
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 | ||
695 | static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) | 695 | static 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) | |||
735 | static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested) | 741 | static 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 | |||
776 | static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | 782 | static 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 | ||
594 | static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) | 596 | 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, | |||
191 | /* Let the kernel do all the work for packet generation */ | 191 | /* Let the kernel do all the work for packet generation */ |
192 | int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | 192 | int 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) { |