aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/platform.h15
-rw-r--r--networking/udhcp/dhcpc.c33
-rw-r--r--networking/udhcp/dhcpc.h9
3 files changed, 36 insertions, 21 deletions
diff --git a/include/platform.h b/include/platform.h
index 0e0ccaf90..21224fabf 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -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__) && \
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index fef8632f6..f1aa36fe6 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -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;
}
}
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h
index 9331466e1..97d3b3c9d 100644
--- a/networking/udhcp/dhcpc.h
+++ b/networking/udhcp/dhcpc.h
@@ -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) */