diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-05-21 07:02:16 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-05-21 07:02:16 +0000 |
commit | b23429198eedc77763d05e3c6fcf319721800b32 (patch) | |
tree | 9d3d608d130aac3e14910f225773f4206d997ff8 /networking/udhcp/dhcpc.c | |
parent | 54b90b598858297186582ab89ac98ecc918afa92 (diff) |
udhcpc: properly reduce timeout if bogus packets were received
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index fb328cb03..eeef435de 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -343,8 +343,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) * "continue" statements in code below jump to the top of the loop. */ for (;;) { - tv.tv_sec = timeout; - tv.tv_usec = 0; + unsigned timestamp_before_wait; if (listen_mode != LISTEN_NONE && sockfd < 0) { if (listen_mode == LISTEN_KERNEL) @@ -354,19 +353,20 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) } max_fd = udhcp_sp_fd_set(&rfds, sockfd); + tv.tv_sec = timeout; + tv.tv_usec = 0; retval = 0; /* If we already timed out, fall through, else... */ if (tv.tv_sec > 0) { + timestamp_before_wait = (unsigned)monotonic_sec(); DEBUG("Waiting on select..."); retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); - } - - if (retval < 0) { - /* EINTR? signal was caught, don't panic */ - if (errno != EINTR) { + if (retval < 0) { + /* EINTR? A signal was caught, don't panic */ + if (errno == EINTR) + continue; /* Else: an error occured, panic! */ bb_perror_msg_and_die("select"); } - continue; } /* If timeout dropped to zero, time to become active: @@ -431,7 +431,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) /* send a request packet */ send_renew(xid, server_addr, requested_ip); /* unicast */ t1 += (t2 - t1) / 2; - timeout = t1 - ((int)monotonic_sec() - timestamp_got_lease); + timeout = t1 - ((unsigned)monotonic_sec() - timestamp_got_lease); continue; } /* Timed out, enter rebinding state */ @@ -446,7 +446,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) /* send a request packet */ send_renew(xid, 0, requested_ip); /* broadcast */ t2 += (lease_seconds - t2) / 2; - timeout = t2 - ((int)monotonic_sec() - timestamp_got_lease); + timeout = t2 - ((unsigned)monotonic_sec() - timestamp_got_lease); continue; } /* Timed out, enter init state */ @@ -474,6 +474,11 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) else len = get_raw_packet(&packet, sockfd); + /* If this packet will turn out to be unrelated/bogus, + * we will go back and wait for next one. + * Be sure timeout is properly decreased. */ + timeout -= (unsigned)monotonic_sec() - timestamp_before_wait; + if (len == -1) { /* error is severe, reopen socket */ DEBUG("error on read, %s, reopening socket", strerror(errno)); change_listen_mode(listen_mode); /* just close and reopen */ @@ -628,7 +633,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) ret0: retval = 0; ret: - /*if (client_config.pidfile) - remove_pidfile has it's own check */ + /*if (client_config.pidfile) - remove_pidfile has its own check */ remove_pidfile(client_config.pidfile); return retval; } |