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 | |
parent | 54b90b598858297186582ab89ac98ecc918afa92 (diff) | |
download | busybox-w32-b23429198eedc77763d05e3c6fcf319721800b32.tar.gz busybox-w32-b23429198eedc77763d05e3c6fcf319721800b32.tar.bz2 busybox-w32-b23429198eedc77763d05e3c6fcf319721800b32.zip |
udhcpc: properly reduce timeout if bogus packets were received
-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) | |||
343 | * "continue" statements in code below jump to the top of the loop. | 343 | * "continue" statements in code below jump to the top of the loop. |
344 | */ | 344 | */ |
345 | for (;;) { | 345 | for (;;) { |
346 | tv.tv_sec = timeout; | 346 | unsigned timestamp_before_wait; |
347 | tv.tv_usec = 0; | ||
348 | 347 | ||
349 | if (listen_mode != LISTEN_NONE && sockfd < 0) { | 348 | if (listen_mode != LISTEN_NONE && sockfd < 0) { |
350 | if (listen_mode == LISTEN_KERNEL) | 349 | if (listen_mode == LISTEN_KERNEL) |
@@ -354,19 +353,20 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
354 | } | 353 | } |
355 | max_fd = udhcp_sp_fd_set(&rfds, sockfd); | 354 | max_fd = udhcp_sp_fd_set(&rfds, sockfd); |
356 | 355 | ||
356 | tv.tv_sec = timeout; | ||
357 | tv.tv_usec = 0; | ||
357 | retval = 0; /* If we already timed out, fall through, else... */ | 358 | retval = 0; /* If we already timed out, fall through, else... */ |
358 | if (tv.tv_sec > 0) { | 359 | if (tv.tv_sec > 0) { |
360 | timestamp_before_wait = (unsigned)monotonic_sec(); | ||
359 | DEBUG("Waiting on select..."); | 361 | DEBUG("Waiting on select..."); |
360 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); | 362 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); |
361 | } | 363 | if (retval < 0) { |
362 | 364 | /* EINTR? A signal was caught, don't panic */ | |
363 | if (retval < 0) { | 365 | if (errno == EINTR) |
364 | /* EINTR? signal was caught, don't panic */ | 366 | continue; |
365 | if (errno != EINTR) { | ||
366 | /* Else: an error occured, panic! */ | 367 | /* Else: an error occured, panic! */ |
367 | bb_perror_msg_and_die("select"); | 368 | bb_perror_msg_and_die("select"); |
368 | } | 369 | } |
369 | continue; | ||
370 | } | 370 | } |
371 | 371 | ||
372 | /* If timeout dropped to zero, time to become active: | 372 | /* If timeout dropped to zero, time to become active: |
@@ -431,7 +431,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
431 | /* send a request packet */ | 431 | /* send a request packet */ |
432 | send_renew(xid, server_addr, requested_ip); /* unicast */ | 432 | send_renew(xid, server_addr, requested_ip); /* unicast */ |
433 | t1 += (t2 - t1) / 2; | 433 | t1 += (t2 - t1) / 2; |
434 | timeout = t1 - ((int)monotonic_sec() - timestamp_got_lease); | 434 | timeout = t1 - ((unsigned)monotonic_sec() - timestamp_got_lease); |
435 | continue; | 435 | continue; |
436 | } | 436 | } |
437 | /* Timed out, enter rebinding state */ | 437 | /* Timed out, enter rebinding state */ |
@@ -446,7 +446,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
446 | /* send a request packet */ | 446 | /* send a request packet */ |
447 | send_renew(xid, 0, requested_ip); /* broadcast */ | 447 | send_renew(xid, 0, requested_ip); /* broadcast */ |
448 | t2 += (lease_seconds - t2) / 2; | 448 | t2 += (lease_seconds - t2) / 2; |
449 | timeout = t2 - ((int)monotonic_sec() - timestamp_got_lease); | 449 | timeout = t2 - ((unsigned)monotonic_sec() - timestamp_got_lease); |
450 | continue; | 450 | continue; |
451 | } | 451 | } |
452 | /* Timed out, enter init state */ | 452 | /* Timed out, enter init state */ |
@@ -474,6 +474,11 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
474 | else | 474 | else |
475 | len = get_raw_packet(&packet, sockfd); | 475 | len = get_raw_packet(&packet, sockfd); |
476 | 476 | ||
477 | /* If this packet will turn out to be unrelated/bogus, | ||
478 | * we will go back and wait for next one. | ||
479 | * Be sure timeout is properly decreased. */ | ||
480 | timeout -= (unsigned)monotonic_sec() - timestamp_before_wait; | ||
481 | |||
477 | if (len == -1) { /* error is severe, reopen socket */ | 482 | if (len == -1) { /* error is severe, reopen socket */ |
478 | DEBUG("error on read, %s, reopening socket", strerror(errno)); | 483 | DEBUG("error on read, %s, reopening socket", strerror(errno)); |
479 | change_listen_mode(listen_mode); /* just close and reopen */ | 484 | change_listen_mode(listen_mode); /* just close and reopen */ |
@@ -628,7 +633,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
628 | ret0: | 633 | ret0: |
629 | retval = 0; | 634 | retval = 0; |
630 | ret: | 635 | ret: |
631 | /*if (client_config.pidfile) - remove_pidfile has it's own check */ | 636 | /*if (client_config.pidfile) - remove_pidfile has its own check */ |
632 | remove_pidfile(client_config.pidfile); | 637 | remove_pidfile(client_config.pidfile); |
633 | return retval; | 638 | return retval; |
634 | } | 639 | } |