aboutsummaryrefslogtreecommitdiff
path: root/networking/udhcp/dhcpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp/dhcpd.c')
-rw-r--r--networking/udhcp/dhcpd.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 093239536..19f94a2d7 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -853,6 +853,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
853 /* Would rather not do read_config before daemonization - 853 /* Would rather not do read_config before daemonization -
854 * otherwise NOMMU machines will parse config twice */ 854 * otherwise NOMMU machines will parse config twice */
855 read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); 855 read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE);
856 /* prevent poll timeout overflow */
857 if (server_config.auto_time > INT_MAX / 1000)
858 server_config.auto_time = INT_MAX / 1000;
856 859
857 /* Make sure fd 0,1,2 are open */ 860 /* Make sure fd 0,1,2 are open */
858 bb_sanitize_stdio(); 861 bb_sanitize_stdio();
@@ -914,21 +917,31 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
914 } 917 }
915 918
916 udhcp_sp_fd_set(pfds, server_socket); 919 udhcp_sp_fd_set(pfds, server_socket);
917 tv = timeout_end - monotonic_sec(); 920
918 retval = 0; 921 new_tv:
919 if (!server_config.auto_time || tv > 0) { 922 tv = -1;
920 retval = poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); 923 if (server_config.auto_time) {
921 } 924 tv = timeout_end - monotonic_sec();
922 if (retval == 0) { 925 if (tv <= 0) {
923 write_leases(); 926 write_leases:
924 goto continue_with_autotime; 927 write_leases();
928 goto continue_with_autotime;
929 }
930 tv *= 1000;
925 } 931 }
926 if (retval < 0 && errno != EINTR) { 932
927 log1("error on select"); 933 /* Block here waiting for either signal or packet */
928 continue; 934 retval = poll(pfds, 2, tv);
935 if (retval <= 0) {
936 if (retval == 0)
937 goto write_leases;
938 if (errno == EINTR)
939 goto new_tv;
940 /* < 0 and not EINTR: should not happen */
941 bb_perror_msg_and_die("poll");
929 } 942 }
930 943
931 switch (udhcp_sp_read(pfds)) { 944 if (pfds[0].revents) switch (udhcp_sp_read()) {
932 case SIGUSR1: 945 case SIGUSR1:
933 bb_error_msg("received %s", "SIGUSR1"); 946 bb_error_msg("received %s", "SIGUSR1");
934 write_leases(); 947 write_leases();
@@ -938,12 +951,16 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
938 bb_error_msg("received %s", "SIGTERM"); 951 bb_error_msg("received %s", "SIGTERM");
939 write_leases(); 952 write_leases();
940 goto ret0; 953 goto ret0;
941 case 0: /* no signal: read a packet */
942 break;
943 default: /* signal or error (probably EINTR): back to select */
944 continue;
945 } 954 }
946 955
956 /* Is it a packet? */
957 if (!pfds[1].revents)
958 continue; /* no */
959
960 /* Note: we do not block here, we block on poll() instead.
961 * Blocking here would prevent SIGTERM from working:
962 * socket read inside this call is restarted on caught signals.
963 */
947 bytes = udhcp_recv_kernel_packet(&packet, server_socket); 964 bytes = udhcp_recv_kernel_packet(&packet, server_socket);
948 if (bytes < 0) { 965 if (bytes < 0) {
949 /* bytes can also be -2 ("bad packet data") */ 966 /* bytes can also be -2 ("bad packet data") */