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
This commit is contained in:
Denis Vlasenko 2007-07-01 17:05:57 +00:00
parent dc7a5eae36
commit c82b5108e1
10 changed files with 153 additions and 117 deletions

View File

@ -3575,7 +3575,8 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when
"Adjust filesystem options on ext[23] filesystems" "Adjust filesystem options on ext[23] filesystems"
#define udhcpc_trivial_usage \ #define udhcpc_trivial_usage \
"[-Cfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n[-p pidfile] [-r IP] [-s script]" "[-Cfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n" \
" [-p pidfile] [-r IP] [-s script]"
#define udhcpc_full_usage \ #define udhcpc_full_usage \
" -V,--vendorclass=CLASSID Set vendor class identifier\n" \ " -V,--vendorclass=CLASSID Set vendor class identifier\n" \
" -i,--interface=INTERFACE Interface to use (default: eth0)\n" \ " -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
" -v,--version Display version" \ " -v,--version Display version" \
#define udhcpd_trivial_usage \ #define udhcpd_trivial_usage \
"[configfile]\n" \ "[configfile]" \
#define udhcpd_full_usage \ #define udhcpd_full_usage \
"" ""

View File

@ -32,6 +32,16 @@ config APP_DUMPLEASES
See http://udhcp.busybox.net for further details. See http://udhcp.busybox.net for further details.
config FEATURE_UDHCPD_WRITE_LEASES_EARLY
bool "Rewrite the lease file at every new acknowledge"
default n
depends on APP_UDHCPD
help
If selected, udhcpd will write a new file with leases every
time a new lease has been accepted, thus eleminating the need
to send SIGUSR1 for the initial writing, or updating. Any timed
rewriting remains undisturbed
config APP_UDHCPC config APP_UDHCPC
bool "udhcp Client (udhcpc)" bool "udhcp Client (udhcpc)"
default n default n

View File

@ -114,8 +114,7 @@ static void client_background(void)
* If that will be properly disabled for NOMMU, client_background() * If that will be properly disabled for NOMMU, client_background()
* will work on NOMMU too */ * will work on NOMMU too */
#else #else
// chdir(/) is problematic. Imagine that e.g. pidfile name is RELATIVE! what will unlink do then, eh? bb_daemonize(0);
bb_daemonize(DAEMON_CHDIR_ROOT);
/* rewrite pidfile, as our pid is different now */ /* rewrite pidfile, as our pid is different now */
if (client_config.pidfile) if (client_config.pidfile)
write_pidfile(client_config.pidfile); write_pidfile(client_config.pidfile);

View File

@ -17,12 +17,12 @@ struct client_config_t {
/* (can be set directly to the result of getopt32) */ /* (can be set directly to the result of getopt32) */
char foreground; /* Do not fork */ char foreground; /* Do not fork */
char quit_after_lease; /* Quit after obtaining lease */ char quit_after_lease; /* Quit after obtaining lease */
char release_on_quit; /* perform release on quit */ char release_on_quit; /* Perform release on quit */
char abort_if_no_lease; /* Abort if no lease */ char abort_if_no_lease; /* Abort if no lease */
char background_if_no_lease; /* Fork to background if no lease */ char background_if_no_lease; /* Fork to background if no lease */
const char *interface; /* The name of the interface to use */ const char *interface; /* The name of the interface to use */
char *pidfile; /* Optionally store the process ID */ char *pidfile; /* Optionally store the process ID */
const char *script; /* User script to run at dhcp events */ const char *script; /* User script to run at dhcp events */
uint8_t *clientid; /* Optional client id to use */ uint8_t *clientid; /* Optional client id to use */
uint8_t *vendorclass; /* Optional vendor class-id to use */ uint8_t *vendorclass; /* Optional vendor class-id to use */
uint8_t *hostname; /* Optional hostname to use */ uint8_t *hostname; /* Optional hostname to use */

View File

@ -37,7 +37,7 @@ int udhcpd_main(int argc, char **argv)
//Huh, dhcpd don't have --foreground, --syslog options?? TODO //Huh, dhcpd don't have --foreground, --syslog options?? TODO
if (!ENABLE_FEATURE_UDHCP_DEBUG) { if (!ENABLE_FEATURE_UDHCP_DEBUG) {
bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); bb_daemonize_or_rexec(0, argv);
logmode &= ~LOGMODE_STDIO; logmode &= ~LOGMODE_STDIO;
} }
@ -60,15 +60,15 @@ int udhcpd_main(int argc, char **argv)
} }
/* Sanity check */ /* Sanity check */
num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1; num_ips = server_config.end_ip - server_config.start_ip + 1;
if (server_config.max_leases > num_ips) { if (server_config.max_leases > num_ips) {
bb_error_msg("max_leases value (%lu) not sane, " bb_error_msg("max_leases=%lu is too big, "
"setting to %lu instead", "setting to %lu",
server_config.max_leases, num_ips); server_config.max_leases, num_ips);
server_config.max_leases = num_ips; server_config.max_leases = num_ips;
} }
leases = xzalloc(server_config.max_leases * sizeof(struct dhcpOfferedAddr)); leases = xzalloc(server_config.max_leases * sizeof(*leases));
read_leases(server_config.lease_file); read_leases(server_config.lease_file);
if (read_interface(server_config.interface, &server_config.ifindex, if (read_interface(server_config.interface, &server_config.ifindex,
@ -207,10 +207,13 @@ int udhcpd_main(int argc, char **argv)
/* make some contention for this address */ /* make some contention for this address */
} else } else
sendNAK(&packet); sendNAK(&packet);
} else if (requested_align < server_config.start } else {
|| requested_align > server_config.end uint32_t r = ntohl(requested_align);
) { if (r < server_config.start_ip
sendNAK(&packet); || r > server_config.end_ip
) {
sendNAK(&packet);
}
} /* else remain silent */ } /* else remain silent */
} else { } else {

View File

@ -27,23 +27,24 @@ struct static_lease {
struct server_config_t { struct server_config_t {
uint32_t server; /* Our IP, in network order */ uint32_t server; /* Our IP, in network order */
uint32_t start; /* Start address of leases, network order */ /* start,end are in host order: we need to compare start <= ip <= end */
uint32_t end; /* End of leases, network order */ uint32_t start_ip; /* Start address of leases, in host order */
uint32_t end_ip; /* End of leases, in host order */
struct option_set *options; /* List of DHCP options loaded from the config file */ struct option_set *options; /* List of DHCP options loaded from the config file */
char *interface; /* The name of the interface to use */ char *interface; /* The name of the interface to use */
int ifindex; /* Index number of the interface to use */ int ifindex; /* Index number of the interface to use */
uint8_t arp[6]; /* Our arp address */ uint8_t arp[6]; /* Our arp address */
unsigned long lease; /* lease time in seconds (host order) */
unsigned long max_leases; /* maximum number of leases (including reserved address) */
char remaining; /* should the lease file be interpreted as lease time remaining, or char remaining; /* should the lease file be interpreted as lease time remaining, or
* as the time the lease expires */ * as the time the lease expires */
unsigned long lease; /* lease time in seconds (host order) */
unsigned long max_leases; /* maximum number of leases (including reserved address) */
unsigned long auto_time; /* how long should udhcpd wait before writing a config file. unsigned long auto_time; /* how long should udhcpd wait before writing a config file.
* if this is zero, it will only write one on SIGUSR1 */ * if this is zero, it will only write one on SIGUSR1 */
unsigned long decline_time; /* how long an address is reserved if a client returns a unsigned long decline_time; /* how long an address is reserved if a client returns a
* decline message */ * decline message */
unsigned long conflict_time; /* how long an arp conflict offender is leased for */ unsigned long conflict_time; /* how long an arp conflict offender is leased for */
unsigned long offer_time; /* how long an offered address is reserved */ unsigned long offer_time; /* how long an offered address is reserved */
unsigned long min_lease; /* minimum lease a client can request*/ unsigned long min_lease; /* minimum lease a client can request */
char *lease_file; char *lease_file;
char *pidfile; char *pidfile;
char *notify_file; /* What to run whenever leases are written */ char *notify_file; /* What to run whenever leases are written */
@ -95,13 +96,6 @@ int send_inform(struct dhcpMessage *oldpacket);
/*** files.h ***/ /*** files.h ***/
struct config_keyword {
const char *keyword;
int (* const handler)(const char *line, void *var);
void *var;
const char *def;
};
int read_config(const char *file); int read_config(const char *file);
void write_leases(void); void write_leases(void);
void read_leases(const char *file); void read_leases(const char *file);

View File

@ -11,42 +11,30 @@
#include "options.h" #include "options.h"
/* /* on these functions, make sure your datatype matches */
* Domain names may have 254 chars, and string options can be 254
* chars long. However, 80 bytes will be enough for most, and won't
* hog up memory. If you have a special application, change it
*/
#define READ_CONFIG_BUF_SIZE 80
/* on these functions, make sure you datatype matches */
static int read_ip(const char *line, void *arg) static int read_ip(const char *line, void *arg)
{ {
len_and_sockaddr *lsa; len_and_sockaddr *lsa;
int retval = 0;
lsa = host_and_af2sockaddr(line, 0, AF_INET); lsa = host_and_af2sockaddr(line, 0, AF_INET);
if (lsa) { if (lsa) {
*(struct in_addr*)arg = lsa->sin.sin_addr; *(uint32_t*)arg = lsa->sin.sin_addr.s_addr;
free(lsa); free(lsa);
retval = 1; return 1;
} }
return retval; return 0;
} }
static int read_mac(const char *line, void *arg) static int read_mac(const char *line, void *arg)
{ {
uint8_t *mac_bytes = arg; uint8_t *mac_bytes = arg;
struct ether_addr *temp_ether_addr; struct ether_addr *temp_ether_addr;
int retval = 1;
temp_ether_addr = ether_aton(line); temp_ether_addr = ether_aton(line);
if (temp_ether_addr == NULL) if (temp_ether_addr == NULL)
retval = 0; return 0;
else memcpy(mac_bytes, temp_ether_addr, 6);
memcpy(mac_bytes, temp_ether_addr, 6); return 1;
return retval;
} }
@ -56,14 +44,13 @@ static int read_str(const char *line, void *arg)
free(*dest); free(*dest);
*dest = xstrdup(line); *dest = xstrdup(line);
return 1; return 1;
} }
static int read_u32(const char *line, void *arg) static int read_u32(const char *line, void *arg)
{ {
*((uint32_t*)arg) = bb_strtou32(line, NULL, 10); *(uint32_t*)arg = bb_strtou32(line, NULL, 10);
return errno == 0; return errno == 0;
} }
@ -71,15 +58,16 @@ static int read_u32(const char *line, void *arg)
static int read_yn(const char *line, void *arg) static int read_yn(const char *line, void *arg)
{ {
char *dest = arg; char *dest = arg;
int retval = 1;
if (!strcasecmp("yes", line)) if (!strcasecmp("yes", line)) {
*dest = 1; *dest = 1;
else if (!strcasecmp("no", line)) return 1;
}
if (!strcasecmp("no", line)) {
*dest = 0; *dest = 0;
else retval = 0; return 1;
}
return retval; return 0;
} }
@ -89,8 +77,9 @@ struct option_set *find_option(struct option_set *opt_list, char code)
while (opt_list && opt_list->data[OPT_CODE] < code) while (opt_list && opt_list->data[OPT_CODE] < code)
opt_list = opt_list->next; opt_list = opt_list->next;
if (opt_list && opt_list->data[OPT_CODE] == code) return opt_list; if (opt_list && opt_list->data[OPT_CODE] == code)
else return NULL; return opt_list;
return NULL;
} }
@ -111,7 +100,7 @@ static void attach_option(struct option_set **opt_list,
#endif #endif
/* make a new option */ /* make a new option */
new = xmalloc(sizeof(struct option_set)); new = xmalloc(sizeof(*new));
new->data = xmalloc(length + 2); new->data = xmalloc(length + 2);
new->data[OPT_CODE] = option->code; new->data[OPT_CODE] = option->code;
new->data[OPT_LEN] = length; new->data[OPT_LEN] = length;
@ -184,7 +173,7 @@ static int read_opt(const char *const_line, void *arg)
return 0; return 0;
if (!strcasecmp(option->name, opt)) if (!strcasecmp(option->name, opt))
break; break;
option++; option++;
} }
do { do {
@ -199,8 +188,11 @@ static int read_opt(const char *const_line, void *arg)
break; break;
case OPTION_IP_PAIR: case OPTION_IP_PAIR:
retval = read_ip(val, buffer); retval = read_ip(val, buffer);
if (!(val = strtok(NULL, ", \t/-"))) retval = 0; val = strtok(NULL, ", \t/-");
if (retval) retval = read_ip(val, buffer + 4); if (!val)
retval = 0;
if (retval)
retval = read_ip(val, buffer + 4);
break; break;
case OPTION_STRING: case OPTION_STRING:
#if ENABLE_FEATURE_RFC3397 #if ENABLE_FEATURE_RFC3397
@ -220,22 +212,33 @@ static int read_opt(const char *const_line, void *arg)
buffer[0] = strtoul(val, &endptr, 0); buffer[0] = strtoul(val, &endptr, 0);
retval = (endptr[0] == '\0'); retval = (endptr[0] == '\0');
break; break;
case OPTION_U16: /* htonX are macros in older libc's, using temp var
*result_u16 = htons(strtoul(val, &endptr, 0)); * in code below for safety */
/* TODO: use bb_strtoX? */
case OPTION_U16: {
unsigned long tmp = strtoul(val, &endptr, 0);
*result_u16 = htons(tmp);
retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/);
break;
}
case OPTION_S16: {
long tmp = strtol(val, &endptr, 0);
*result_u16 = htons(tmp);
retval = (endptr[0] == '\0'); retval = (endptr[0] == '\0');
break; break;
case OPTION_S16: }
*result_u16 = htons(strtol(val, &endptr, 0)); case OPTION_U32: {
unsigned long tmp = strtoul(val, &endptr, 0);
*result_u32 = htonl(tmp);
retval = (endptr[0] == '\0'); retval = (endptr[0] == '\0');
break; break;
case OPTION_U32: }
*result_u32 = htonl(strtoul(val, &endptr, 0)); case OPTION_S32: {
retval = (endptr[0] == '\0'); long tmp = strtol(val, &endptr, 0);
break; *result_u32 = htonl(tmp);
case OPTION_S32:
*result_u32 = htonl(strtol(val, &endptr, 0));
retval = (endptr[0] == '\0'); retval = (endptr[0] == '\0');
break; break;
}
default: default:
break; break;
} }
@ -253,7 +256,6 @@ static int read_staticlease(const char *const_line, void *arg)
uint8_t *mac_bytes; uint8_t *mac_bytes;
uint32_t *ip; uint32_t *ip;
/* Allocate memory for addresses */ /* Allocate memory for addresses */
mac_bytes = xmalloc(sizeof(unsigned char) * 8); mac_bytes = xmalloc(sizeof(unsigned char) * 8);
ip = xmalloc(sizeof(uint32_t)); ip = xmalloc(sizeof(uint32_t));
@ -275,31 +277,46 @@ static int read_staticlease(const char *const_line, void *arg)
} }
static const struct config_keyword keywords[] = { struct config_keyword {
/* keyword handler variable address default */ const char *keyword;
{"start", read_ip, &(server_config.start), "192.168.0.20"}, int (*handler)(const char *line, void *var);
{"end", read_ip, &(server_config.end), "192.168.0.254"}, void *var;
{"interface", read_str, &(server_config.interface), "eth0"}, const char *def;
{"option", read_opt, &(server_config.options), ""},
{"opt", read_opt, &(server_config.options), ""},
{"max_leases", read_u32, &(server_config.max_leases), "254"},
{"remaining", read_yn, &(server_config.remaining), "yes"},
{"auto_time", read_u32, &(server_config.auto_time), "7200"},
{"decline_time",read_u32, &(server_config.decline_time),"3600"},
{"conflict_time",read_u32,&(server_config.conflict_time),"3600"},
{"offer_time", read_u32, &(server_config.offer_time), "60"},
{"min_lease", read_u32, &(server_config.min_lease), "60"},
{"lease_file", read_str, &(server_config.lease_file), LEASES_FILE},
{"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"},
{"notify_file", read_str, &(server_config.notify_file), ""},
{"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"},
{"sname", read_str, &(server_config.sname), ""},
{"boot_file", read_str, &(server_config.boot_file), ""},
{"static_lease",read_staticlease, &(server_config.static_leases), ""},
/*ADDME: static lease */
{"", NULL, NULL, ""}
}; };
static const struct config_keyword keywords[] = {
/* keyword handler variable address default */
{"start", read_ip, &(server_config.start_ip), "192.168.0.20"},
{"end", read_ip, &(server_config.end_ip), "192.168.0.254"},
{"interface", read_str, &(server_config.interface), "eth0"},
{"option", read_opt, &(server_config.options), ""},
{"opt", read_opt, &(server_config.options), ""},
/* Avoid "max_leases value not sane" warning by setting default
* to default_end_ip - default_start_ip + 1: */
{"max_leases", read_u32, &(server_config.max_leases), "235"},
{"remaining", read_yn, &(server_config.remaining), "yes"},
{"auto_time", read_u32, &(server_config.auto_time), "7200"},
{"decline_time", read_u32, &(server_config.decline_time), "3600"},
{"conflict_time",read_u32, &(server_config.conflict_time),"3600"},
{"offer_time", read_u32, &(server_config.offer_time), "60"},
{"min_lease", read_u32, &(server_config.min_lease), "60"},
{"lease_file", read_str, &(server_config.lease_file), LEASES_FILE},
{"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"},
{"notify_file", read_str, &(server_config.notify_file), ""},
{"siaddr", read_ip, &(server_config.siaddr), "0.0.0.0"},
{"sname", read_str, &(server_config.sname), ""},
{"boot_file", read_str, &(server_config.boot_file), ""},
{"static_lease", read_staticlease, &(server_config.static_leases), ""},
/* ADDME: static lease */
};
/*
* Domain names may have 254 chars, and string options can be 254
* chars long. However, 80 bytes will be enough for most, and won't
* hog up memory. If you have a special application, change it
*/
#define READ_CONFIG_BUF_SIZE 80
int read_config(const char *file) int read_config(const char *file)
{ {
@ -307,7 +324,7 @@ int read_config(const char *file)
char buffer[READ_CONFIG_BUF_SIZE], *token, *line; char buffer[READ_CONFIG_BUF_SIZE], *token, *line;
int i, lm = 0; int i, lm = 0;
for (i = 0; keywords[i].keyword[0]; i++) for (i = 0; i < ARRAY_SIZE(keywords); i++)
if (keywords[i].def[0]) if (keywords[i].def[0])
keywords[i].handler(keywords[i].def, keywords[i].var); keywords[i].handler(keywords[i].def, keywords[i].var);
@ -337,7 +354,7 @@ int read_config(const char *file)
while (i >= 0 && isspace(line[i])) while (i >= 0 && isspace(line[i]))
line[i--] = '\0'; line[i--] = '\0';
for (i = 0; keywords[i].keyword[0]; i++) for (i = 0; i < ARRAY_SIZE(keywords); i++)
if (!strcasecmp(token, keywords[i].keyword)) if (!strcasecmp(token, keywords[i].keyword))
if (!keywords[i].handler(line, keywords[i].var)) { if (!keywords[i].handler(line, keywords[i].var)) {
bb_error_msg("cannot parse line %d of %s", lm, file); bb_error_msg("cannot parse line %d of %s", lm, file);
@ -348,6 +365,10 @@ int read_config(const char *file)
} }
} }
fclose(in); fclose(in);
server_config.start_ip = ntohl(server_config.start_ip);
server_config.end_ip = ntohl(server_config.end_ip);
return 1; return 1;
} }
@ -408,9 +429,11 @@ void read_leases(const char *file)
&& full_read(fp, &lease, sizeof(lease)) == sizeof(lease) && full_read(fp, &lease, sizeof(lease)) == sizeof(lease)
) { ) {
/* ADDME: is it a static lease */ /* ADDME: is it a static lease */
if (lease.yiaddr >= server_config.start && lease.yiaddr <= server_config.end) { uint32_t y = ntohl(lease.yiaddr);
if (y >= server_config.start_ip && y <= server_config.end_ip) {
lease.expires = ntohl(lease.expires); lease.expires = ntohl(lease.expires);
if (!server_config.remaining) lease.expires -= time(0); if (!server_config.remaining)
lease.expires -= time(0);
if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires))) { if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires))) {
bb_error_msg("too many leases while loading %s", file); bb_error_msg("too many leases while loading %s", file);
break; break;

View File

@ -119,8 +119,8 @@ uint32_t find_address(int check_expired)
uint32_t addr, ret; uint32_t addr, ret;
struct dhcpOfferedAddr *lease = NULL; struct dhcpOfferedAddr *lease = NULL;
addr = ntohl(server_config.start); /* addr is in host order here */ addr = server_config.start_ip; /* addr is in host order here */
for (;addr <= ntohl(server_config.end); addr++) { for (;addr <= server_config.end_ip; addr++) {
/* ie, 192.168.55.0 */ /* ie, 192.168.55.0 */
if (!(addr & 0xFF)) continue; if (!(addr & 0xFF)) continue;

View File

@ -122,19 +122,18 @@ int sendOffer(struct dhcpMessage *oldpacket)
if (!lease_expired(lease)) if (!lease_expired(lease))
lease_time_align = lease->expires - time(0); lease_time_align = lease->expires - time(0);
packet.yiaddr = lease->yiaddr; packet.yiaddr = lease->yiaddr;
/* Or the client has a requested ip */ /* Or the client has a requested ip */
} else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP))
/* Don't look here (ugly hackish thing to do) */ /* Don't look here (ugly hackish thing to do) */
&& memcpy(&req_align, req, 4) && memcpy(&req_align, req, 4)
/* and the ip is in the lease range */ /* and the ip is in the lease range */
&& ntohl(req_align) >= ntohl(server_config.start) && ntohl(req_align) >= server_config.start_ip
&& ntohl(req_align) <= ntohl(server_config.end) && ntohl(req_align) <= server_config.end_ip
&& !static_lease_ip /* Check that its not a static lease */ && !static_lease_ip /* Check that its not a static lease */
/* and is not already taken/offered */ /* and is not already taken/offered */
&& (!(lease = find_lease_by_yiaddr(req_align)) && (!(lease = find_lease_by_yiaddr(req_align))
/* or its taken, but expired */ /* ADDME: or maybe in here */ /* or its taken, but expired */ /* ADDME: or maybe in here */
|| lease_expired(lease)) || lease_expired(lease))
) { ) {
packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */ packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */
/* otherwise, find a free IP */ /* otherwise, find a free IP */
@ -142,7 +141,8 @@ int sendOffer(struct dhcpMessage *oldpacket)
/* Is it a static lease? (No, because find_address skips static lease) */ /* Is it a static lease? (No, because find_address skips static lease) */
packet.yiaddr = find_address(0); packet.yiaddr = find_address(0);
/* try for an expired lease */ /* try for an expired lease */
if (!packet.yiaddr) packet.yiaddr = find_address(1); if (!packet.yiaddr)
packet.yiaddr = find_address(1);
} }
if (!packet.yiaddr) { if (!packet.yiaddr) {
@ -209,7 +209,8 @@ int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr)
init_packet(&packet, oldpacket, DHCPACK); init_packet(&packet, oldpacket, DHCPACK);
packet.yiaddr = yiaddr; packet.yiaddr = yiaddr;
if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) { lease_time = get_option(oldpacket, DHCP_LEASE_TIME);
if (lease_time) {
memcpy(&lease_time_align, lease_time, 4); memcpy(&lease_time_align, lease_time, 4);
lease_time_align = ntohl(lease_time_align); lease_time_align = ntohl(lease_time_align);
if (lease_time_align > server_config.lease) if (lease_time_align > server_config.lease)
@ -236,6 +237,10 @@ int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr)
return -1; return -1;
add_lease(packet.chaddr, packet.yiaddr, lease_time_align); add_lease(packet.chaddr, packet.yiaddr, lease_time_align);
if (ENABLE_FEATURE_UDHCPD_WRITE_LEASES_EARLY) {
/* rewrite the file with leases at every new acceptance */
write_leases();
}
return 0; return 0;
} }

View File

@ -43,7 +43,7 @@ int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t
struct ifreq ifr; struct ifreq ifr;
struct sockaddr_in *our_ip; struct sockaddr_in *our_ip;
memset(&ifr, 0, sizeof(struct ifreq)); memset(&ifr, 0, sizeof(ifr));
fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (fd < 0) { if (fd < 0) {
bb_perror_msg("socket failed"); bb_perror_msg("socket failed");
@ -54,7 +54,8 @@ int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t
strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
if (addr) { if (addr) {
if (ioctl(fd, SIOCGIFADDR, &ifr) != 0) { if (ioctl(fd, SIOCGIFADDR, &ifr) != 0) {
bb_perror_msg("SIOCGIFADDR failed, is the interface up and configured?"); bb_perror_msg("SIOCGIFADDR failed (is interface %s "
"up and configured?)", interface);
close(fd); close(fd);
return -1; return -1;
} }
@ -117,7 +118,7 @@ int listen_socket(uint32_t ip, int port, const char *inf)
return -1; return -1;
} }
if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) { if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
close(fd); close(fd);
return -1; return -1;
} }