aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-07-01 17:05:57 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-07-01 17:05:57 +0000
commitc82b5108e1a40f3b299043770e01d7d7db35de04 (patch)
tree35039a36868df644b8e5ffc766c1b0c921c88ab5
parentdc7a5eae36d31f5cfc301de2499329b8a03ea660 (diff)
downloadbusybox-w32-c82b5108e1a40f3b299043770e01d7d7db35de04.tar.gz
busybox-w32-c82b5108e1a40f3b299043770e01d7d7db35de04.tar.bz2
busybox-w32-c82b5108e1a40f3b299043770e01d7d7db35de04.zip
udhcp: new config option "Rewrite the lease file at every new acknowledge"
(Mats Erik Andersson <mats@blue2net.com> (Blue2Net AB)) udhcp: consistently treat server_config.start/end IPs as host-order fix IP parsing for 64bit machines fix unsafe hton macro usage in read_opt() do not chdir("/") when daemonizing fix help text
-rw-r--r--include/usage.h5
-rw-r--r--networking/udhcp/Config.in10
-rw-r--r--networking/udhcp/dhcpc.c3
-rw-r--r--networking/udhcp/dhcpc.h6
-rw-r--r--networking/udhcp/dhcpd.c21
-rw-r--r--networking/udhcp/dhcpd.h18
-rw-r--r--networking/udhcp/files.c161
-rw-r--r--networking/udhcp/leases.c4
-rw-r--r--networking/udhcp/serverpacket.c31
-rw-r--r--networking/udhcp/socket.c7
10 files changed, 151 insertions, 115 deletions
diff --git a/include/usage.h b/include/usage.h
index 6d02c8bbf..68325046f 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -3575,7 +3575,8 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when
3575 "Adjust filesystem options on ext[23] filesystems" 3575 "Adjust filesystem options on ext[23] filesystems"
3576 3576
3577#define udhcpc_trivial_usage \ 3577#define udhcpc_trivial_usage \
3578 "[-Cfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n[-p pidfile] [-r IP] [-s script]" 3578 "[-Cfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n" \
3579 " [-p pidfile] [-r IP] [-s script]"
3579#define udhcpc_full_usage \ 3580#define udhcpc_full_usage \
3580 " -V,--vendorclass=CLASSID Set vendor class identifier\n" \ 3581 " -V,--vendorclass=CLASSID Set vendor class identifier\n" \
3581 " -i,--interface=INTERFACE Interface to use (default: eth0)\n" \ 3582 " -i,--interface=INTERFACE Interface to use (default: eth0)\n" \
@@ -3594,7 +3595,7 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when
3594 " -v,--version Display version" \ 3595 " -v,--version Display version" \
3595 3596
3596#define udhcpd_trivial_usage \ 3597#define udhcpd_trivial_usage \
3597 "[configfile]\n" \ 3598 "[configfile]" \
3598 3599
3599#define udhcpd_full_usage \ 3600#define udhcpd_full_usage \
3600 "" 3601 ""
diff --git a/networking/udhcp/Config.in b/networking/udhcp/Config.in
index 9dd02c497..7a3eda9cc 100644
--- a/networking/udhcp/Config.in
+++ b/networking/udhcp/Config.in
@@ -32,6 +32,16 @@ config APP_DUMPLEASES
32 32
33 See http://udhcp.busybox.net for further details. 33 See http://udhcp.busybox.net for further details.
34 34
35config FEATURE_UDHCPD_WRITE_LEASES_EARLY
36 bool "Rewrite the lease file at every new acknowledge"
37 default n
38 depends on APP_UDHCPD
39 help
40 If selected, udhcpd will write a new file with leases every
41 time a new lease has been accepted, thus eleminating the need
42 to send SIGUSR1 for the initial writing, or updating. Any timed
43 rewriting remains undisturbed
44
35config APP_UDHCPC 45config APP_UDHCPC
36 bool "udhcp Client (udhcpc)" 46 bool "udhcp Client (udhcpc)"
37 default n 47 default n
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 06806ec66..50ac31e61 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -114,8 +114,7 @@ static void client_background(void)
114 * If that will be properly disabled for NOMMU, client_background() 114 * If that will be properly disabled for NOMMU, client_background()
115 * will work on NOMMU too */ 115 * will work on NOMMU too */
116#else 116#else
117// chdir(/) is problematic. Imagine that e.g. pidfile name is RELATIVE! what will unlink do then, eh? 117 bb_daemonize(0);
118 bb_daemonize(DAEMON_CHDIR_ROOT);
119 /* rewrite pidfile, as our pid is different now */ 118 /* rewrite pidfile, as our pid is different now */
120 if (client_config.pidfile) 119 if (client_config.pidfile)
121 write_pidfile(client_config.pidfile); 120 write_pidfile(client_config.pidfile);
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h
index fa091bf72..09b014239 100644
--- a/networking/udhcp/dhcpc.h
+++ b/networking/udhcp/dhcpc.h
@@ -17,12 +17,12 @@ struct client_config_t {
17 /* (can be set directly to the result of getopt32) */ 17 /* (can be set directly to the result of getopt32) */
18 char foreground; /* Do not fork */ 18 char foreground; /* Do not fork */
19 char quit_after_lease; /* Quit after obtaining lease */ 19 char quit_after_lease; /* Quit after obtaining lease */
20 char release_on_quit; /* perform release on quit */ 20 char release_on_quit; /* Perform release on quit */
21 char abort_if_no_lease; /* Abort if no lease */ 21 char abort_if_no_lease; /* Abort if no lease */
22 char background_if_no_lease; /* Fork to background if no lease */ 22 char background_if_no_lease; /* Fork to background if no lease */
23 const char *interface; /* The name of the interface to use */ 23 const char *interface; /* The name of the interface to use */
24 char *pidfile; /* Optionally store the process ID */ 24 char *pidfile; /* Optionally store the process ID */
25 const char *script; /* User script to run at dhcp events */ 25 const char *script; /* User script to run at dhcp events */
26 uint8_t *clientid; /* Optional client id to use */ 26 uint8_t *clientid; /* Optional client id to use */
27 uint8_t *vendorclass; /* Optional vendor class-id to use */ 27 uint8_t *vendorclass; /* Optional vendor class-id to use */
28 uint8_t *hostname; /* Optional hostname to use */ 28 uint8_t *hostname; /* Optional hostname to use */
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 778121b61..6be3c0e2e 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -37,7 +37,7 @@ int udhcpd_main(int argc, char **argv)
37//Huh, dhcpd don't have --foreground, --syslog options?? TODO 37//Huh, dhcpd don't have --foreground, --syslog options?? TODO
38 38
39 if (!ENABLE_FEATURE_UDHCP_DEBUG) { 39 if (!ENABLE_FEATURE_UDHCP_DEBUG) {
40 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 40 bb_daemonize_or_rexec(0, argv);
41 logmode &= ~LOGMODE_STDIO; 41 logmode &= ~LOGMODE_STDIO;
42 } 42 }
43 43
@@ -60,15 +60,15 @@ int udhcpd_main(int argc, char **argv)
60 } 60 }
61 61
62 /* Sanity check */ 62 /* Sanity check */
63 num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1; 63 num_ips = server_config.end_ip - server_config.start_ip + 1;
64 if (server_config.max_leases > num_ips) { 64 if (server_config.max_leases > num_ips) {
65 bb_error_msg("max_leases value (%lu) not sane, " 65 bb_error_msg("max_leases=%lu is too big, "
66 "setting to %lu instead", 66 "setting to %lu",
67 server_config.max_leases, num_ips); 67 server_config.max_leases, num_ips);
68 server_config.max_leases = num_ips; 68 server_config.max_leases = num_ips;
69 } 69 }
70 70
71 leases = xzalloc(server_config.max_leases * sizeof(struct dhcpOfferedAddr)); 71 leases = xzalloc(server_config.max_leases * sizeof(*leases));
72 read_leases(server_config.lease_file); 72 read_leases(server_config.lease_file);
73 73
74 if (read_interface(server_config.interface, &server_config.ifindex, 74 if (read_interface(server_config.interface, &server_config.ifindex,
@@ -207,10 +207,13 @@ int udhcpd_main(int argc, char **argv)
207 /* make some contention for this address */ 207 /* make some contention for this address */
208 } else 208 } else
209 sendNAK(&packet); 209 sendNAK(&packet);
210 } else if (requested_align < server_config.start 210 } else {
211 || requested_align > server_config.end 211 uint32_t r = ntohl(requested_align);
212 ) { 212 if (r < server_config.start_ip
213 sendNAK(&packet); 213 || r > server_config.end_ip
214 ) {
215 sendNAK(&packet);
216 }
214 } /* else remain silent */ 217 } /* else remain silent */
215 218
216 } else { 219 } else {
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h
index 7c4fe695a..05e3cf004 100644
--- a/networking/udhcp/dhcpd.h
+++ b/networking/udhcp/dhcpd.h
@@ -27,23 +27,24 @@ struct static_lease {
27 27
28struct server_config_t { 28struct server_config_t {
29 uint32_t server; /* Our IP, in network order */ 29 uint32_t server; /* Our IP, in network order */
30 uint32_t start; /* Start address of leases, network order */ 30 /* start,end are in host order: we need to compare start <= ip <= end */
31 uint32_t end; /* End of leases, network order */ 31 uint32_t start_ip; /* Start address of leases, in host order */
32 uint32_t end_ip; /* End of leases, in host order */
32 struct option_set *options; /* List of DHCP options loaded from the config file */ 33 struct option_set *options; /* List of DHCP options loaded from the config file */
33 char *interface; /* The name of the interface to use */ 34 char *interface; /* The name of the interface to use */
34 int ifindex; /* Index number of the interface to use */ 35 int ifindex; /* Index number of the interface to use */
35 uint8_t arp[6]; /* Our arp address */ 36 uint8_t arp[6]; /* Our arp address */
36 unsigned long lease; /* lease time in seconds (host order) */
37 unsigned long max_leases; /* maximum number of leases (including reserved address) */
38 char remaining; /* should the lease file be interpreted as lease time remaining, or 37 char remaining; /* should the lease file be interpreted as lease time remaining, or
39 * as the time the lease expires */ 38 * as the time the lease expires */
39 unsigned long lease; /* lease time in seconds (host order) */
40 unsigned long max_leases; /* maximum number of leases (including reserved address) */
40 unsigned long auto_time; /* how long should udhcpd wait before writing a config file. 41 unsigned long auto_time; /* how long should udhcpd wait before writing a config file.
41 * if this is zero, it will only write one on SIGUSR1 */ 42 * if this is zero, it will only write one on SIGUSR1 */
42 unsigned long decline_time; /* how long an address is reserved if a client returns a 43 unsigned long decline_time; /* how long an address is reserved if a client returns a
43 * decline message */ 44 * decline message */
44 unsigned long conflict_time; /* how long an arp conflict offender is leased for */ 45 unsigned long conflict_time; /* how long an arp conflict offender is leased for */
45 unsigned long offer_time; /* how long an offered address is reserved */ 46 unsigned long offer_time; /* how long an offered address is reserved */
46 unsigned long min_lease; /* minimum lease a client can request*/ 47 unsigned long min_lease; /* minimum lease a client can request */
47 char *lease_file; 48 char *lease_file;
48 char *pidfile; 49 char *pidfile;
49 char *notify_file; /* What to run whenever leases are written */ 50 char *notify_file; /* What to run whenever leases are written */
@@ -95,13 +96,6 @@ int send_inform(struct dhcpMessage *oldpacket);
95 96
96/*** files.h ***/ 97/*** files.h ***/
97 98
98struct config_keyword {
99 const char *keyword;
100 int (* const handler)(const char *line, void *var);
101 void *var;
102 const char *def;
103};
104
105int read_config(const char *file); 99int read_config(const char *file);
106void write_leases(void); 100void write_leases(void);
107void read_leases(const char *file); 101void read_leases(const char *file);
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c
index 41c8717cd..7fc734889 100644
--- a/networking/udhcp/files.c
+++ b/networking/udhcp/files.c
@@ -11,42 +11,30 @@
11#include "options.h" 11#include "options.h"
12 12
13 13
14/* 14/* on these functions, make sure your datatype matches */
15 * Domain names may have 254 chars, and string options can be 254
16 * chars long. However, 80 bytes will be enough for most, and won't
17 * hog up memory. If you have a special application, change it
18 */
19#define READ_CONFIG_BUF_SIZE 80
20
21/* on these functions, make sure you datatype matches */
22static int read_ip(const char *line, void *arg) 15static int read_ip(const char *line, void *arg)
23{ 16{
24 len_and_sockaddr *lsa; 17 len_and_sockaddr *lsa;
25 int retval = 0;
26 18
27 lsa = host_and_af2sockaddr(line, 0, AF_INET); 19 lsa = host_and_af2sockaddr(line, 0, AF_INET);
28 if (lsa) { 20 if (lsa) {
29 *(struct in_addr*)arg = lsa->sin.sin_addr; 21 *(uint32_t*)arg = lsa->sin.sin_addr.s_addr;
30 free(lsa); 22 free(lsa);
31 retval = 1; 23 return 1;
32 } 24 }
33 return retval; 25 return 0;
34} 26}
35 27
36static int read_mac(const char *line, void *arg) 28static int read_mac(const char *line, void *arg)
37{ 29{
38 uint8_t *mac_bytes = arg; 30 uint8_t *mac_bytes = arg;
39 struct ether_addr *temp_ether_addr; 31 struct ether_addr *temp_ether_addr;
40 int retval = 1;
41 32
42 temp_ether_addr = ether_aton(line); 33 temp_ether_addr = ether_aton(line);
43
44 if (temp_ether_addr == NULL) 34 if (temp_ether_addr == NULL)
45 retval = 0; 35 return 0;
46 else 36 memcpy(mac_bytes, temp_ether_addr, 6);
47 memcpy(mac_bytes, temp_ether_addr, 6); 37 return 1;
48
49 return retval;
50} 38}
51 39
52 40
@@ -56,14 +44,13 @@ static int read_str(const char *line, void *arg)
56 44
57 free(*dest); 45 free(*dest);
58 *dest = xstrdup(line); 46 *dest = xstrdup(line);
59
60 return 1; 47 return 1;
61} 48}
62 49
63 50
64static int read_u32(const char *line, void *arg) 51static int read_u32(const char *line, void *arg)
65{ 52{
66 *((uint32_t*)arg) = bb_strtou32(line, NULL, 10); 53 *(uint32_t*)arg = bb_strtou32(line, NULL, 10);
67 return errno == 0; 54 return errno == 0;
68} 55}
69 56
@@ -71,15 +58,16 @@ static int read_u32(const char *line, void *arg)
71static int read_yn(const char *line, void *arg) 58static int read_yn(const char *line, void *arg)
72{ 59{
73 char *dest = arg; 60 char *dest = arg;
74 int retval = 1;
75 61
76 if (!strcasecmp("yes", line)) 62 if (!strcasecmp("yes", line)) {
77 *dest = 1; 63 *dest = 1;
78 else if (!strcasecmp("no", line)) 64 return 1;
65 }
66 if (!strcasecmp("no", line)) {
79 *dest = 0; 67 *dest = 0;
80 else retval = 0; 68 return 1;
81 69 }
82 return retval; 70 return 0;
83} 71}
84 72
85 73
@@ -89,8 +77,9 @@ struct option_set *find_option(struct option_set *opt_list, char code)
89 while (opt_list && opt_list->data[OPT_CODE] < code) 77 while (opt_list && opt_list->data[OPT_CODE] < code)
90 opt_list = opt_list->next; 78 opt_list = opt_list->next;
91 79
92 if (opt_list && opt_list->data[OPT_CODE] == code) return opt_list; 80 if (opt_list && opt_list->data[OPT_CODE] == code)
93 else return NULL; 81 return opt_list;
82 return NULL;
94} 83}
95 84
96 85
@@ -111,7 +100,7 @@ static void attach_option(struct option_set **opt_list,
111#endif 100#endif
112 101
113 /* make a new option */ 102 /* make a new option */
114 new = xmalloc(sizeof(struct option_set)); 103 new = xmalloc(sizeof(*new));
115 new->data = xmalloc(length + 2); 104 new->data = xmalloc(length + 2);
116 new->data[OPT_CODE] = option->code; 105 new->data[OPT_CODE] = option->code;
117 new->data[OPT_LEN] = length; 106 new->data[OPT_LEN] = length;
@@ -184,7 +173,7 @@ static int read_opt(const char *const_line, void *arg)
184 return 0; 173 return 0;
185 if (!strcasecmp(option->name, opt)) 174 if (!strcasecmp(option->name, opt))
186 break; 175 break;
187 option++; 176 option++;
188 } 177 }
189 178
190 do { 179 do {
@@ -199,8 +188,11 @@ static int read_opt(const char *const_line, void *arg)
199 break; 188 break;
200 case OPTION_IP_PAIR: 189 case OPTION_IP_PAIR:
201 retval = read_ip(val, buffer); 190 retval = read_ip(val, buffer);
202 if (!(val = strtok(NULL, ", \t/-"))) retval = 0; 191 val = strtok(NULL, ", \t/-");
203 if (retval) retval = read_ip(val, buffer + 4); 192 if (!val)
193 retval = 0;
194 if (retval)
195 retval = read_ip(val, buffer + 4);
204 break; 196 break;
205 case OPTION_STRING: 197 case OPTION_STRING:
206#if ENABLE_FEATURE_RFC3397 198#if ENABLE_FEATURE_RFC3397
@@ -220,22 +212,33 @@ static int read_opt(const char *const_line, void *arg)
220 buffer[0] = strtoul(val, &endptr, 0); 212 buffer[0] = strtoul(val, &endptr, 0);
221 retval = (endptr[0] == '\0'); 213 retval = (endptr[0] == '\0');
222 break; 214 break;
223 case OPTION_U16: 215 /* htonX are macros in older libc's, using temp var
224 *result_u16 = htons(strtoul(val, &endptr, 0)); 216 * in code below for safety */
225 retval = (endptr[0] == '\0'); 217 /* TODO: use bb_strtoX? */
218 case OPTION_U16: {
219 unsigned long tmp = strtoul(val, &endptr, 0);
220 *result_u16 = htons(tmp);
221 retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/);
226 break; 222 break;
227 case OPTION_S16: 223 }
228 *result_u16 = htons(strtol(val, &endptr, 0)); 224 case OPTION_S16: {
225 long tmp = strtol(val, &endptr, 0);
226 *result_u16 = htons(tmp);
229 retval = (endptr[0] == '\0'); 227 retval = (endptr[0] == '\0');
230 break; 228 break;
231 case OPTION_U32: 229 }
232 *result_u32 = htonl(strtoul(val, &endptr, 0)); 230 case OPTION_U32: {
231 unsigned long tmp = strtoul(val, &endptr, 0);
232 *result_u32 = htonl(tmp);
233 retval = (endptr[0] == '\0'); 233 retval = (endptr[0] == '\0');
234 break; 234 break;
235 case OPTION_S32: 235 }
236 *result_u32 = htonl(strtol(val, &endptr, 0)); 236 case OPTION_S32: {
237 long tmp = strtol(val, &endptr, 0);
238 *result_u32 = htonl(tmp);
237 retval = (endptr[0] == '\0'); 239 retval = (endptr[0] == '\0');
238 break; 240 break;
241 }
239 default: 242 default:
240 break; 243 break;
241 } 244 }
@@ -253,7 +256,6 @@ static int read_staticlease(const char *const_line, void *arg)
253 uint8_t *mac_bytes; 256 uint8_t *mac_bytes;
254 uint32_t *ip; 257 uint32_t *ip;
255 258
256
257 /* Allocate memory for addresses */ 259 /* Allocate memory for addresses */
258 mac_bytes = xmalloc(sizeof(unsigned char) * 8); 260 mac_bytes = xmalloc(sizeof(unsigned char) * 8);
259 ip = xmalloc(sizeof(uint32_t)); 261 ip = xmalloc(sizeof(uint32_t));
@@ -275,39 +277,54 @@ static int read_staticlease(const char *const_line, void *arg)
275} 277}
276 278
277 279
280struct config_keyword {
281 const char *keyword;
282 int (*handler)(const char *line, void *var);
283 void *var;
284 const char *def;
285};
286
278static const struct config_keyword keywords[] = { 287static const struct config_keyword keywords[] = {
279 /* keyword handler variable address default */ 288 /* keyword handler variable address default */
280 {"start", read_ip, &(server_config.start), "192.168.0.20"}, 289 {"start", read_ip, &(server_config.start_ip), "192.168.0.20"},
281 {"end", read_ip, &(server_config.end), "192.168.0.254"}, 290 {"end", read_ip, &(server_config.end_ip), "192.168.0.254"},
282 {"interface", read_str, &(server_config.interface), "eth0"}, 291 {"interface", read_str, &(server_config.interface), "eth0"},
283 {"option", read_opt, &(server_config.options), ""}, 292 {"option", read_opt, &(server_config.options), ""},
284 {"opt", read_opt, &(server_config.options), ""}, 293 {"opt", read_opt, &(server_config.options), ""},
285 {"max_leases", read_u32, &(server_config.max_leases), "254"}, 294 /* Avoid "max_leases value not sane" warning by setting default
286 {"remaining", read_yn, &(server_config.remaining), "yes"}, 295 * to default_end_ip - default_start_ip + 1: */
287 {"auto_time", read_u32, &(server_config.auto_time), "7200"}, 296 {"max_leases", read_u32, &(server_config.max_leases), "235"},
288 {"decline_time",read_u32, &(server_config.decline_time),"3600"}, 297 {"remaining", read_yn, &(server_config.remaining), "yes"},
289 {"conflict_time",read_u32,&(server_config.conflict_time),"3600"}, 298 {"auto_time", read_u32, &(server_config.auto_time), "7200"},
290 {"offer_time", read_u32, &(server_config.offer_time), "60"}, 299 {"decline_time", read_u32, &(server_config.decline_time), "3600"},
291 {"min_lease", read_u32, &(server_config.min_lease), "60"}, 300 {"conflict_time",read_u32, &(server_config.conflict_time),"3600"},
292 {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE}, 301 {"offer_time", read_u32, &(server_config.offer_time), "60"},
293 {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"}, 302 {"min_lease", read_u32, &(server_config.min_lease), "60"},
294 {"notify_file", read_str, &(server_config.notify_file), ""}, 303 {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE},
295 {"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"}, 304 {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"},
296 {"sname", read_str, &(server_config.sname), ""}, 305 {"notify_file", read_str, &(server_config.notify_file), ""},
297 {"boot_file", read_str, &(server_config.boot_file), ""}, 306 {"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"},
298 {"static_lease",read_staticlease, &(server_config.static_leases), ""}, 307 {"sname", read_str, &(server_config.sname), ""},
299 /*ADDME: static lease */ 308 {"boot_file", read_str, &(server_config.boot_file), ""},
300 {"", NULL, NULL, ""} 309 {"static_lease", read_staticlease, &(server_config.static_leases), ""},
310 /* ADDME: static lease */
301}; 311};
302 312
303 313
314/*
315 * Domain names may have 254 chars, and string options can be 254
316 * chars long. However, 80 bytes will be enough for most, and won't
317 * hog up memory. If you have a special application, change it
318 */
319#define READ_CONFIG_BUF_SIZE 80
320
304int read_config(const char *file) 321int read_config(const char *file)
305{ 322{
306 FILE *in; 323 FILE *in;
307 char buffer[READ_CONFIG_BUF_SIZE], *token, *line; 324 char buffer[READ_CONFIG_BUF_SIZE], *token, *line;
308 int i, lm = 0; 325 int i, lm = 0;
309 326
310 for (i = 0; keywords[i].keyword[0]; i++) 327 for (i = 0; i < ARRAY_SIZE(keywords); i++)
311 if (keywords[i].def[0]) 328 if (keywords[i].def[0])
312 keywords[i].handler(keywords[i].def, keywords[i].var); 329 keywords[i].handler(keywords[i].def, keywords[i].var);
313 330
@@ -337,7 +354,7 @@ int read_config(const char *file)
337 while (i >= 0 && isspace(line[i])) 354 while (i >= 0 && isspace(line[i]))
338 line[i--] = '\0'; 355 line[i--] = '\0';
339 356
340 for (i = 0; keywords[i].keyword[0]; i++) 357 for (i = 0; i < ARRAY_SIZE(keywords); i++)
341 if (!strcasecmp(token, keywords[i].keyword)) 358 if (!strcasecmp(token, keywords[i].keyword))
342 if (!keywords[i].handler(line, keywords[i].var)) { 359 if (!keywords[i].handler(line, keywords[i].var)) {
343 bb_error_msg("cannot parse line %d of %s", lm, file); 360 bb_error_msg("cannot parse line %d of %s", lm, file);
@@ -348,6 +365,10 @@ int read_config(const char *file)
348 } 365 }
349 } 366 }
350 fclose(in); 367 fclose(in);
368
369 server_config.start_ip = ntohl(server_config.start_ip);
370 server_config.end_ip = ntohl(server_config.end_ip);
371
351 return 1; 372 return 1;
352} 373}
353 374
@@ -408,9 +429,11 @@ void read_leases(const char *file)
408 && full_read(fp, &lease, sizeof(lease)) == sizeof(lease) 429 && full_read(fp, &lease, sizeof(lease)) == sizeof(lease)
409 ) { 430 ) {
410 /* ADDME: is it a static lease */ 431 /* ADDME: is it a static lease */
411 if (lease.yiaddr >= server_config.start && lease.yiaddr <= server_config.end) { 432 uint32_t y = ntohl(lease.yiaddr);
433 if (y >= server_config.start_ip && y <= server_config.end_ip) {
412 lease.expires = ntohl(lease.expires); 434 lease.expires = ntohl(lease.expires);
413 if (!server_config.remaining) lease.expires -= time(0); 435 if (!server_config.remaining)
436 lease.expires -= time(0);
414 if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires))) { 437 if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires))) {
415 bb_error_msg("too many leases while loading %s", file); 438 bb_error_msg("too many leases while loading %s", file);
416 break; 439 break;
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
index 5d8775f63..ceec07345 100644
--- a/networking/udhcp/leases.c
+++ b/networking/udhcp/leases.c
@@ -119,8 +119,8 @@ uint32_t find_address(int check_expired)
119 uint32_t addr, ret; 119 uint32_t addr, ret;
120 struct dhcpOfferedAddr *lease = NULL; 120 struct dhcpOfferedAddr *lease = NULL;
121 121
122 addr = ntohl(server_config.start); /* addr is in host order here */ 122 addr = server_config.start_ip; /* addr is in host order here */
123 for (;addr <= ntohl(server_config.end); addr++) { 123 for (;addr <= server_config.end_ip; addr++) {
124 124
125 /* ie, 192.168.55.0 */ 125 /* ie, 192.168.55.0 */
126 if (!(addr & 0xFF)) continue; 126 if (!(addr & 0xFF)) continue;
diff --git a/networking/udhcp/serverpacket.c b/networking/udhcp/serverpacket.c
index e1a88addd..ecbf50a14 100644
--- a/networking/udhcp/serverpacket.c
+++ b/networking/udhcp/serverpacket.c
@@ -122,19 +122,18 @@ int sendOffer(struct dhcpMessage *oldpacket)
122 if (!lease_expired(lease)) 122 if (!lease_expired(lease))
123 lease_time_align = lease->expires - time(0); 123 lease_time_align = lease->expires - time(0);
124 packet.yiaddr = lease->yiaddr; 124 packet.yiaddr = lease->yiaddr;
125
126 /* Or the client has a requested ip */ 125 /* Or the client has a requested ip */
127 } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) 126 } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP))
128 /* Don't look here (ugly hackish thing to do) */ 127 /* Don't look here (ugly hackish thing to do) */
129 && memcpy(&req_align, req, 4) 128 && memcpy(&req_align, req, 4)
130 /* and the ip is in the lease range */ 129 /* and the ip is in the lease range */
131 && ntohl(req_align) >= ntohl(server_config.start) 130 && ntohl(req_align) >= server_config.start_ip
132 && ntohl(req_align) <= ntohl(server_config.end) 131 && ntohl(req_align) <= server_config.end_ip
133 && !static_lease_ip /* Check that its not a static lease */ 132 && !static_lease_ip /* Check that its not a static lease */
134 /* and is not already taken/offered */ 133 /* and is not already taken/offered */
135 && (!(lease = find_lease_by_yiaddr(req_align)) 134 && (!(lease = find_lease_by_yiaddr(req_align))
136 /* or its taken, but expired */ /* ADDME: or maybe in here */ 135 /* or its taken, but expired */ /* ADDME: or maybe in here */
137 || lease_expired(lease)) 136 || lease_expired(lease))
138 ) { 137 ) {
139 packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */ 138 packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */
140 /* otherwise, find a free IP */ 139 /* otherwise, find a free IP */
@@ -142,7 +141,8 @@ int sendOffer(struct dhcpMessage *oldpacket)
142 /* Is it a static lease? (No, because find_address skips static lease) */ 141 /* Is it a static lease? (No, because find_address skips static lease) */
143 packet.yiaddr = find_address(0); 142 packet.yiaddr = find_address(0);
144 /* try for an expired lease */ 143 /* try for an expired lease */
145 if (!packet.yiaddr) packet.yiaddr = find_address(1); 144 if (!packet.yiaddr)
145 packet.yiaddr = find_address(1);
146 } 146 }
147 147
148 if (!packet.yiaddr) { 148 if (!packet.yiaddr) {
@@ -209,7 +209,8 @@ int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr)
209 init_packet(&packet, oldpacket, DHCPACK); 209 init_packet(&packet, oldpacket, DHCPACK);
210 packet.yiaddr = yiaddr; 210 packet.yiaddr = yiaddr;
211 211
212 if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) { 212 lease_time = get_option(oldpacket, DHCP_LEASE_TIME);
213 if (lease_time) {
213 memcpy(&lease_time_align, lease_time, 4); 214 memcpy(&lease_time_align, lease_time, 4);
214 lease_time_align = ntohl(lease_time_align); 215 lease_time_align = ntohl(lease_time_align);
215 if (lease_time_align > server_config.lease) 216 if (lease_time_align > server_config.lease)
@@ -236,6 +237,10 @@ int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr)
236 return -1; 237 return -1;
237 238
238 add_lease(packet.chaddr, packet.yiaddr, lease_time_align); 239 add_lease(packet.chaddr, packet.yiaddr, lease_time_align);
240 if (ENABLE_FEATURE_UDHCPD_WRITE_LEASES_EARLY) {
241 /* rewrite the file with leases at every new acceptance */
242 write_leases();
243 }
239 244
240 return 0; 245 return 0;
241} 246}
diff --git a/networking/udhcp/socket.c b/networking/udhcp/socket.c
index d294fb259..be5985f88 100644
--- a/networking/udhcp/socket.c
+++ b/networking/udhcp/socket.c
@@ -43,7 +43,7 @@ int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t
43 struct ifreq ifr; 43 struct ifreq ifr;
44 struct sockaddr_in *our_ip; 44 struct sockaddr_in *our_ip;
45 45
46 memset(&ifr, 0, sizeof(struct ifreq)); 46 memset(&ifr, 0, sizeof(ifr));
47 fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 47 fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
48 if (fd < 0) { 48 if (fd < 0) {
49 bb_perror_msg("socket failed"); 49 bb_perror_msg("socket failed");
@@ -54,7 +54,8 @@ int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t
54 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); 54 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
55 if (addr) { 55 if (addr) {
56 if (ioctl(fd, SIOCGIFADDR, &ifr) != 0) { 56 if (ioctl(fd, SIOCGIFADDR, &ifr) != 0) {
57 bb_perror_msg("SIOCGIFADDR failed, is the interface up and configured?"); 57 bb_perror_msg("SIOCGIFADDR failed (is interface %s "
58 "up and configured?)", interface);
58 close(fd); 59 close(fd);
59 return -1; 60 return -1;
60 } 61 }
@@ -117,7 +118,7 @@ int listen_socket(uint32_t ip, int port, const char *inf)
117 return -1; 118 return -1;
118 } 119 }
119 120
120 if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) { 121 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
121 close(fd); 122 close(fd);
122 return -1; 123 return -1;
123 } 124 }