udhcpc: shrink udhcpc: guard against zero lease time
No binary (build failed)
—
(log yok)
| @@ -135,7 +135,18 @@ | |
| #define SWAP_LE64(x) (x) | |
| #endif | |
| + | /* ---- Unaligned access ------------------------------------ */ |
| + | |
| + | /* parameter is supposed to be an uint32_t* ptr */ |
| + | #if defined(i386) || defined(__x86_64__) /* + other arches? */ |
| + | #define get_unaligned_u32p(u32p) (*(u32p)) |
| + | #else |
| + | /* performs reasonably well (gcc usually inlines memcpy here) */ |
| + | #define get_unaligned_u32p(u32p) ({ uint32_t __t; memcpy(&__t, (u32p), 4); __t; }) |
| + | #endif |
| + | |
| /* ---- Networking ------------------------------------------ */ | |
| + | |
| #ifndef __APPLE__ | |
| # include <arpa/inet.h> | |
| # ifndef __socklen_t_defined | |
| @@ -146,6 +157,7 @@ typedef int socklen_t; | |
| #endif | |
| /* ---- Compiler dependent settings ------------------------- */ | |
| + | |
| #if (defined __digital__ && defined __unix__) || defined __APPLE__ | |
| # undef HAVE_MNTENT_H | |
| # undef HAVE_SYS_STATFS_H | |
| @@ -163,9 +175,10 @@ __extension__ typedef unsigned long long __u64; | |
| #endif | |
| /*----- Kernel versioning ------------------------------------*/ | |
| + | |
| #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) | |
| - | /* ---- miscellaneous --------------------------------------- */ |
| + | /* ---- Miscellaneous --------------------------------------- */ |
| #if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 5 && \ | |
| !defined(__dietlibc__) && \ | |
| @@ -18,9 +18,6 @@ | |
| #include "options.h" | |
| - | static int timeout; /* = 0. Must be signed */ |
| - | static uint32_t requested_ip; /* = 0 */ |
| - | static uint32_t server_addr; |
| static int sockfd = -1; | |
| #define LISTEN_NONE 0 | |
| @@ -28,6 +25,14 @@ static int sockfd = -1; | |
| #define LISTEN_RAW 2 | |
| static smallint listen_mode; | |
| + | #define INIT_SELECTING 0 |
| + | #define REQUESTING 1 |
| + | #define BOUND 2 |
| + | #define RENEWING 3 |
| + | #define REBINDING 4 |
| + | #define INIT_REBOOT 5 |
| + | #define RENEW_REQUESTED 6 |
| + | #define RELEASED 7 |
| static smallint state; | |
| /* struct client_config_t client_config is in bb_common_bufsiz1 */ | |
| @@ -71,7 +76,7 @@ static void perform_renew(void) | |
| /* perform a release */ | |
| - | static void perform_release(void) |
| + | static void perform_release(uint32_t requested_ip, uint32_t server_addr) |
| { | |
| char buffer[sizeof("255.255.255.255")]; | |
| struct in_addr temp_addr; | |
| @@ -90,7 +95,6 @@ static void perform_release(void) | |
| change_listen_mode(LISTEN_NONE); | |
| state = RELEASED; | |
| - | timeout = INT_MAX; |
| } | |
| @@ -140,9 +144,12 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |
| int tryagain_timeout = 20; | |
| int discover_timeout = 3; | |
| int discover_retries = 3; | |
| + | uint32_t server_addr = server_addr; /* for compiler */ |
| + | uint32_t requested_ip = 0; |
| uint32_t xid = 0; | |
| uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */ | |
| int packet_num; | |
| + | int timeout; /* must be signed */ |
| unsigned already_waited_sec; | |
| unsigned opt; | |
| int max_fd; | |
| @@ -332,6 +339,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |
| udhcp_run_script(NULL, "deconfig"); | |
| change_listen_mode(LISTEN_RAW); | |
| packet_num = 0; | |
| + | timeout = 0; |
| already_waited_sec = 0; | |
| /* Main event loop. select() waits on signal pipe and possibly | |
| @@ -510,8 +518,8 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |
| continue; | |
| /* still selecting - this server looks bad */ | |
| } | |
| - | /* can be misaligned, thus memcpy */ |
| - | memcpy(&server_addr, temp, 4); |
| + | /* it IS unaligned sometimes, don't "optimize" */ |
| + | server_addr = get_unaligned_u32p((uint32_t*)temp); |
| xid = packet.xid; | |
| requested_ip = packet.yiaddr; | |
| @@ -535,7 +543,9 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |
| /* can be misaligned, thus memcpy */ | |
| memcpy(&lease_seconds, temp, 4); | |
| lease_seconds = ntohl(lease_seconds); | |
| - | lease_seconds &= 0x0fffffff; /* paranoia: must not be negative */ |
| + | lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */ |
| + | if (lease_seconds < 10) /* and not too small */ |
| + | lease_seconds = 10; |
| } | |
| #if ENABLE_FEATURE_UDHCPC_ARPING | |
| if (opt & OPT_a) { | |
| @@ -576,7 +586,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |
| change_listen_mode(LISTEN_NONE); | |
| if (client_config.quit_after_lease) { | |
| if (client_config.release_on_quit) | |
| - | perform_release(); |
| + | perform_release(requested_ip, server_addr); |
| goto ret0; | |
| } | |
| if (!client_config.foreground) | |
| @@ -618,12 +628,13 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv) | |
| timeout = 0; | |
| break; | |
| case SIGUSR2: | |
| - | perform_release(); |
| + | perform_release(requested_ip, server_addr); |
| + | timeout = INT_MAX; |
| break; | |
| case SIGTERM: | |
| bb_info_msg("Received SIGTERM"); | |
| if (client_config.release_on_quit) | |
| - | perform_release(); |
| + | perform_release(requested_ip, server_addr); |
| goto ret0; | |
| } | |
| } | |
| @@ -8,15 +8,6 @@ | |
| # pragma GCC visibility push(hidden) | |
| #endif | |
| - | #define INIT_SELECTING 0 |
| - | #define REQUESTING 1 |
| - | #define BOUND 2 |
| - | #define RENEWING 3 |
| - | #define REBINDING 4 |
| - | #define INIT_REBOOT 5 |
| - | #define RENEW_REQUESTED 6 |
| - | #define RELEASED 7 |
| - | |
| struct client_config_t { | |
| /* TODO: combine flag fields into single "unsigned opt" */ | |
| /* (can be set directly to the result of getopt32) */ | |