diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-01 17:05:57 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-01 17:05:57 +0000 |
commit | c82b5108e1a40f3b299043770e01d7d7db35de04 (patch) | |
tree | 35039a36868df644b8e5ffc766c1b0c921c88ab5 | |
parent | dc7a5eae36d31f5cfc301de2499329b8a03ea660 (diff) | |
download | busybox-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.h | 5 | ||||
-rw-r--r-- | networking/udhcp/Config.in | 10 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 3 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.h | 6 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 21 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.h | 18 | ||||
-rw-r--r-- | networking/udhcp/files.c | 161 | ||||
-rw-r--r-- | networking/udhcp/leases.c | 4 | ||||
-rw-r--r-- | networking/udhcp/serverpacket.c | 31 | ||||
-rw-r--r-- | networking/udhcp/socket.c | 7 |
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 | ||
35 | config 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 | |||
35 | config APP_UDHCPC | 45 | config 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 | ||
28 | struct server_config_t { | 28 | struct 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 | ||
98 | struct config_keyword { | ||
99 | const char *keyword; | ||
100 | int (* const handler)(const char *line, void *var); | ||
101 | void *var; | ||
102 | const char *def; | ||
103 | }; | ||
104 | |||
105 | int read_config(const char *file); | 99 | int read_config(const char *file); |
106 | void write_leases(void); | 100 | void write_leases(void); |
107 | void read_leases(const char *file); | 101 | void 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 */ | ||
22 | static int read_ip(const char *line, void *arg) | 15 | static 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 | ||
36 | static int read_mac(const char *line, void *arg) | 28 | static 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 | ||
64 | static int read_u32(const char *line, void *arg) | 51 | static 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) | |||
71 | static int read_yn(const char *line, void *arg) | 58 | static 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 | ||
280 | struct config_keyword { | ||
281 | const char *keyword; | ||
282 | int (*handler)(const char *line, void *var); | ||
283 | void *var; | ||
284 | const char *def; | ||
285 | }; | ||
286 | |||
278 | static const struct config_keyword keywords[] = { | 287 | static 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 | |||
304 | int read_config(const char *file) | 321 | int 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 | } |