- Return in place of raise an impossible condition when one tries to release
an empty active lease.
+- Timer granularity is now 1/100s in the DHCPv6 client.
+
Changes since 4.0.0b3
- The reverse dns name for PTR updates on IPv6 addresses has been fixed to
int xid;
/* Initialize timers. */
- client->start_time = cur_time;
client->txcount = 0;
client->RT = client->IRT + dhc6_rand(client->IRT);
static void
dhc6_retrans_advance(struct client_state *client)
{
- TIME elapsed;
+ struct timeval elapsed;
- elapsed = cur_time - client->start_time;
+ /* elapsed = cur - start */
+ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
+ elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
+ if (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
/* retrans_advance is called after consuming client->RT. */
- elapsed += client->RT;
+ /* elapsed += RT */
+ elapsed.tv_sec += client->RT / 100;
+ elapsed.tv_usec += (client->RT % 100) * 10000;
+ if (elapsed.tv_usec >= 1000000) {
+ elapsed.tv_sec += 1;
+ elapsed.tv_usec -= 1000000;
+ }
/* RT for each subsequent message transmission is based on the previous
* value of RT:
/* Further, if there's an MRD, we should wake up upon reaching
* the MRD rather than at some point after it.
*/
- if ((client->MRD != 0) && ((elapsed + client->RT) > client->MRD)) {
- client->RT = (client->start_time + client->MRD) - cur_time;
+ if (client->MRD == 0) {
+ /* Done. */
+ client->txcount++;
+ return;
+ }
+ /* elapsed += client->RT */
+ elapsed.tv_sec += client->RT / 100;
+ elapsed.tv_usec += (client->RT % 100) * 10000;
+ if (elapsed.tv_usec >= 1000000) {
+ elapsed.tv_sec += 1;
+ elapsed.tv_usec -= 1000000;
+ }
+ if (elapsed.tv_sec >= client->MRD) {
+ /*
+ * wake at RT + cur = start + MRD
+ */
+ client->RT = client->MRD +
+ (client->start_time.tv_sec - cur_tv.tv_sec);
+ client->RT = client->RT * 100 +
+ (client->start_time.tv_usec - cur_tv.tv_usec) / 10000;
}
-
client->txcount++;
}
void
start_init6(struct client_state *client)
{
+ struct timeval tv;
+
log_debug("PRC: Soliciting for leases (INIT).");
client->state = S_INIT;
/* Initialize timers, RFC3315 section 17.1.2. */
- client->IRT = SOL_TIMEOUT;
- client->MRT = SOL_MAX_RT;
+ client->IRT = SOL_TIMEOUT * 100;
+ client->MRT = SOL_MAX_RT * 100;
client->MRC = 0;
client->MRD = 0;
* Also, the first RT MUST be selected to be strictly greater than IRT
* by choosing RAND to be strictly greater than 0.
*/
+ /* if RAND < 0 then RAND = -RAND */
+ if (client->RT <= client->IRT)
+ client->RT = client->IRT + (client->IRT - client->RT);
+ /* if RAND == 0 then RAND = 1 */
if (client->RT <= client->IRT)
client->RT = client->IRT + 1;
* between 0 and SOL_MAX_DELAY seconds. The good news is
* SOL_MAX_DELAY is 1.
*/
- add_timeout(cur_time + (random() % SOL_MAX_DELAY), do_init6, client,
- NULL, NULL);
+ tv.tv_sec = cur_tv.tv_sec;
+ tv.tv_usec = cur_tv.tv_usec;
+ tv.tv_usec += (random() % (SOL_MAX_DELAY * 100)) * 10000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+ add_timeout(&tv, do_init6, client, NULL, NULL);
if (nowait)
go_daemon();
void
start_confirm6(struct client_state *client)
{
+ struct timeval tv;
+
/* If there is no active lease, there is nothing to check. */
if (client->active_lease == NULL) {
start_init6(client);
client->state = S_REBOOTING;
/* Initialize timers, RFC3315 section 17.1.3. */
- client->IRT = CNF_TIMEOUT;
- client->MRT = CNF_MAX_RT;
+ client->IRT = CNF_TIMEOUT * 100;
+ client->MRT = CNF_MAX_RT * 100;
client->MRC = 0;
client->MRD = CNF_MAX_RD;
client->v6_handler = reply_handler;
- add_timeout(cur_time + (random() % CNF_MAX_DELAY), do_confirm6, client,
- NULL, NULL);
+ /* RFC3315 section 18.1.2 says we MUST start the first packet
+ * between 0 and CNF_MAX_DELAY seconds. The good news is
+ * CNF_MAX_DELAY is 1.
+ */
+ tv.tv_sec = cur_tv.tv_sec;
+ tv.tv_usec = cur_tv.tv_usec;
+ tv.tv_usec += (random() % (CNF_MAX_DELAY * 100)) * 10000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+ add_timeout(&tv, do_confirm6, client, NULL, NULL);
}
/* do_init6() marshals and transmits a solicit.
struct data_string ds;
struct data_string ia;
struct data_string addr;
- TIME elapsed;
+ struct timeval elapsed, tv;
u_int32_t t1, t2;
int idx, len, send_ret;
return;
}
- elapsed = cur_time - client->start_time;
- if ((client->MRD != 0) && (elapsed > client->MRD)) {
+ /*
+ * Start_time starts at the first transmission.
+ */
+ if (client->txcount == 0) {
+ client->start_time.tv_sec = cur_tv.tv_sec;
+ client->start_time.tv_usec = cur_tv.tv_usec;
+ }
+
+ /* elapsed = cur - start */
+ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
+ elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
+ if (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
log_info("Max retransmission duration exceeded.");
return;
}
memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
/* Form an elapsed option. */
- if ((elapsed < 0) || (elapsed > 655))
+ /* Maximum value is 65535 1/100s coded as 0xffff. */
+ if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
+ ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
client->elapsed = 0xffff;
- else
- client->elapsed = elapsed * 100;
+ } else {
+ client->elapsed = elapsed.tv_sec * 100;
+ client->elapsed += elapsed.tv_usec / 10000;
+ }
- log_debug("XMT: Forming Solicit, %u0 ms elapsed.",
- (unsigned)client->elapsed);
+ if (client->elapsed == 0)
+ log_debug("XMT: Forming Solicit, 0 ms elapsed.");
+ else
+ log_debug("XMT: Forming Solicit, %u0 ms elapsed.",
+ (unsigned)client->elapsed);
client->elapsed = htons(client->elapsed);
/* Transmit and wait. */
- log_info("XMT: Solicit on %s, interval %ld",
+ log_info("XMT: Solicit on %s, interval %ld0ms.",
client->name ? client->name : client->interface->name,
(long int)client->RT);
data_string_forget(&ds, MDL);
- add_timeout(cur_time + client->RT, do_init6, client, NULL, NULL);
+ /* Wait RT */
+ tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
+ tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+ add_timeout(&tv, do_init6, client, NULL, NULL);
dhc6_retrans_advance(client);
}
struct client_state *client;
struct data_string ds;
int send_ret;
- TIME elapsed;
+ struct timeval elapsed, tv;
client = input;
return;
}
- elapsed = cur_time - client->start_time;
- if ((client->MRD != 0) && (elapsed > client->MRD)) {
+ /*
+ * Start_time starts at the first transmission.
+ */
+ if (client->txcount == 0) {
+ client->start_time.tv_sec = cur_tv.tv_sec;
+ client->start_time.tv_usec = cur_tv.tv_usec;
+ }
+
+ /* elapsed = cur - start */
+ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
+ elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
+ if (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
log_info("Max retransmission duration exceeded.");
start_bound(client);
return;
memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
/* Form an elapsed option. */
- if ((elapsed < 0) || (elapsed > 655))
+ /* Maximum value is 65535 1/100s coded as 0xffff. */
+ if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
+ ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
client->elapsed = 0xffff;
- else
- client->elapsed = elapsed * 100;
+ } else {
+ client->elapsed = elapsed.tv_sec * 100;
+ client->elapsed += elapsed.tv_usec / 10000;
+ }
- log_debug("XMT: Forming Confirm, %u0 ms elapsed.",
- (unsigned)client->elapsed);
+ if (client->elapsed == 0)
+ log_debug("XMT: Forming Confirm, 0 ms elapsed.");
+ else
+ log_debug("XMT: Forming Confirm, %u0 ms elapsed.",
+ (unsigned)client->elapsed);
client->elapsed = htons(client->elapsed);
/* Transmit and wait. */
- log_info("XMT: Confirm on %s, interval %ld.",
+ log_info("XMT: Confirm on %s, interval %ld0ms.",
client->name ? client->name : client->interface->name,
(long int)client->RT);
data_string_forget(&ds, MDL);
- add_timeout(cur_time + client->RT, do_confirm6, client, NULL, NULL);
+ /* Wait RT */
+ tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
+ tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+ add_timeout(&tv, do_confirm6, client, NULL, NULL);
dhc6_retrans_advance(client);
}
unconfigure6(client, "RELEASE6");
/* Set timers per RFC3315 section 18.1.1. */
- client->IRT = REL_TIMEOUT;
+ client->IRT = REL_TIMEOUT * 100;
client->MRT = 0;
- client->MRC = REL_MAX_RC;
+ client->MRC = REL_MAX_RC * 100;
client->MRD = 0;
dhc6_retrans_init(client);
struct data_string ds;
struct option_cache *oc;
int send_ret;
+ struct timeval tv;
client = input;
return;
}
+ /*
+ * Start_time starts at the first transmission.
+ */
+ if (client->txcount == 0) {
+ client->start_time.tv_sec = cur_tv.tv_sec;
+ client->start_time.tv_usec = cur_tv.tv_usec;
+ }
+
/*
* Check whether the server has sent a unicast option; if so, we can
* use the address it specified.
}
/* Transmit and wait. */
- log_info("XMT: Release on %s, interval %ld.",
+ log_info("XMT: Release on %s, interval %ld0ms.",
client->name ? client->name : client->interface->name,
(long int)client->RT);
data_string_forget(&ds, MDL);
- add_timeout(cur_time + client->RT, do_release6, client, NULL, NULL);
+ /* Wait RT */
+ tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
+ tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+ add_timeout(&tv, do_release6, client, NULL, NULL);
dhc6_retrans_advance(client);
}
client->selected_lease = lease;
/* Set timers per RFC3315 section 18.1.1. */
- client->IRT = REQ_TIMEOUT;
- client->MRT = REQ_MAX_RT;
+ client->IRT = REQ_TIMEOUT * 100;
+ client->MRT = REQ_MAX_RT * 100;
client->MRC = REQ_MAX_RC;
client->MRD = 0;
struct client_state *client;
struct dhc6_lease *lease;
struct data_string ds;
- TIME elapsed;
+ struct timeval elapsed, tv;
int abort = ISC_FALSE;
int send_ret;
abort = ISC_TRUE;
}
- elapsed = cur_time - client->start_time;
- if ((client->MRD != 0) && (elapsed > client->MRD)) {
+ /*
+ * Start_time starts at the first transmission.
+ */
+ if (client->txcount == 0) {
+ client->start_time.tv_sec = cur_tv.tv_sec;
+ client->start_time.tv_usec = cur_tv.tv_usec;
+ }
+
+ /* elapsed = cur - start */
+ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
+ elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
+ if (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
+ if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
log_info("Max retransmission duration exceeded.");
abort = ISC_TRUE;
}
memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
/* Form an elapsed option. */
- if ((elapsed < 0) || (elapsed > 655))
+ /* Maximum value is 65535 1/100s coded as 0xffff. */
+ if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
+ ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
client->elapsed = 0xffff;
- else
- client->elapsed = elapsed * 100;
+ } else {
+ client->elapsed = elapsed.tv_sec * 100;
+ client->elapsed += elapsed.tv_usec / 10000;
+ }
- log_debug("XMT: Forming Request, %u0 ms elapsed.",
- (unsigned)client->elapsed);
+ if (client->elapsed == 0)
+ log_debug("XMT: Forming Request, 0 ms elapsed.");
+ else
+ log_debug("XMT: Forming Request, %u0 ms elapsed.",
+ (unsigned)client->elapsed);
client->elapsed = htons(client->elapsed);
return;
}
- log_info("XMT: Request on %s, interval %ld",
+ log_info("XMT: Request on %s, interval %ld0ms.",
client->name ? client->name : client->interface->name,
(long int)client->RT);
data_string_forget(&ds, MDL);
- add_timeout(cur_time + client->RT, do_select6, client, NULL, NULL);
+ /* Wait RT */
+ tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
+ tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+ add_timeout(&tv, do_select6, client, NULL, NULL);
dhc6_retrans_advance(client);
}
TIME renew=MAX_TIME, rebind=MAX_TIME, depref=MAX_TIME,
lo_expire=MAX_TIME, hi_expire=0, tmp;
int has_addrs = ISC_FALSE;
+ struct timeval tv;
lease = client->active_lease;
"to run for %u seconds.",
(int)(renew - cur_time),
(unsigned)(rebind - renew));
- client->next_MRD = rebind - cur_time;
- add_timeout(renew, start_renew6, client, NULL, NULL);
+ client->next_MRD = rebind;
+ tv.tv_sec = renew;
+ tv.tv_usec = 0;
+ add_timeout(&tv, start_renew6, client, NULL, NULL);
break;
}
"to run for %d seconds.",
(int)(rebind - cur_time),
(int)(hi_expire - rebind));
- client->next_MRD = hi_expire - cur_time;
- add_timeout(rebind, start_rebind6, client, NULL, NULL);
+ client->next_MRD = hi_expire;
+ tv.tv_sec = rebind;
+ tv.tv_usec = 0;
+ add_timeout(&tv, start_rebind6, client, NULL, NULL);
}
break;
if (depref != MAX_TIME) {
log_debug("PRC: Depreference scheduled in %d seconds.",
(int)(depref - cur_time));
- add_timeout(depref, do_depref, client, NULL, NULL);
+ tv.tv_sec = depref;
+ tv.tv_usec = 0;
+ add_timeout(&tv, do_depref, client, NULL, NULL);
}
if (lo_expire != MAX_TIME) {
log_debug("PRC: Expiration scheduled in %d seconds.",
(int)(lo_expire - cur_time));
- add_timeout(lo_expire, do_expire, client, NULL, NULL);
+ tv.tv_sec = lo_expire;
+ tv.tv_usec = 0;
+ add_timeout(&tv, do_expire, client, NULL, NULL);
}
}
}
/* start_renew6() gets us all ready to go to start transmitting Renew packets.
- * Note that client->MRD must be set before entering this function - it must
- * be set to the time at which the client should start Rebinding.
+ * Note that client->next_MRD must be set before entering this function -
+ * it must be set to the time at which the client should start Rebinding.
*/
void
start_renew6(void *input)
client->v6_handler = reply_handler;
/* Times per RFC3315 section 18.1.3. */
- client->IRT = REN_TIMEOUT;
- client->MRT = REN_MAX_RT;
+ client->IRT = REN_TIMEOUT * 100;
+ client->MRT = REN_MAX_RT * 100;
client->MRC = 0;
/* MRD is special in renew - we need to set it by checking timer
* state.
*/
- client->MRD = client->next_MRD;
+ client->MRD = client->next_MRD - cur_time;
dhc6_retrans_init(client);
struct data_string ds;
struct client_state *client;
struct dhc6_lease *lease;
- TIME elapsed;
+ struct timeval elapsed, tv;
int send_ret;
client = (struct client_state *)input;
client->refresh_type, MDL);
}
- elapsed = cur_time - client->start_time;
+ /*
+ * Start_time starts at the first transmission.
+ */
+ if (client->txcount == 0) {
+ client->start_time.tv_sec = cur_tv.tv_sec;
+ client->start_time.tv_usec = cur_tv.tv_usec;
+ }
+
+ /* elapsed = cur - start */
+ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
+ elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
+ if (elapsed.tv_usec < 0) {
+ elapsed.tv_sec -= 1;
+ elapsed.tv_usec += 1000000;
+ }
if (((client->MRC != 0) && (client->txcount > client->MRC)) ||
- ((client->MRD != 0) && (elapsed >= client->MRD))) {
+ ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD))) {
/* We're done. Move on to the next phase, if any. */
dhc6_check_times(client);
return;
ds.buffer->data[0] = client->refresh_type;
memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
- if ((elapsed < 0) || (elapsed > 655))
+ /* Form an elapsed option. */
+ /* Maximum value is 65535 1/100s coded as 0xffff. */
+ if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
+ ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
client->elapsed = 0xffff;
- else
- client->elapsed = elapsed * 100;
+ } else {
+ client->elapsed = elapsed.tv_sec * 100;
+ client->elapsed += elapsed.tv_usec / 10000;
+ }
- log_debug("XMT: Forming %s, %u0 ms elapsed.",
- dhcpv6_type_names[client->refresh_type],
- (unsigned)client->elapsed);
+ if (client->elapsed == 0)
+ log_debug("XMT: Forming %s, 0 ms elapsed.",
+ dhcpv6_type_names[client->refresh_type]);
+ else
+ log_debug("XMT: Forming %s, %u0 ms elapsed.",
+ dhcpv6_type_names[client->refresh_type],
+ (unsigned)client->elapsed);
client->elapsed = htons(client->elapsed);
return;
}
- log_info("XMT: %s on %s, interval %ld",
+ log_info("XMT: %s on %s, interval %ld0ms.",
dhcpv6_type_names[client->refresh_type],
client->name ? client->name : client->interface->name,
(long int)client->RT);
data_string_forget(&ds, MDL);
- add_timeout(cur_time + client->RT, do_refresh6, client, NULL, NULL);
+ /* Wait RT */
+ tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
+ tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+ add_timeout(&tv, do_refresh6, client, NULL, NULL);
dhc6_retrans_advance(client);
}
/* start_rebind6() gets us all set up to go and rebind a lease. Note that
- * client->MRD must be set before entering this function. In this case,
+ * client->next_MRD must be set before entering this function. In this case,
* MRD must be set to the maximum time any address in the packet will
* expire.
*/
client->v6_handler = reply_handler;
/* Times per RFC3315 section 18.1.4. */
- client->IRT = REB_TIMEOUT;
- client->MRT = REB_MAX_RT;
+ client->IRT = REB_TIMEOUT * 100;
+ client->MRT = REB_MAX_RT * 100;
client->MRC = 0;
/* MRD is special in rebind - it's determined by the timer
* state.
*/
- client->MRD = client->next_MRD;
+ client->MRD = client->next_MRD - cur_time;
dhc6_retrans_init(client);
#include <syslog.h>
#include <signal.h>
#include <errno.h>
+#include <sys/time.h>
#include <sys/wait.h>
#include <limits.h>
isc_result_t status;
int exit_mode = 0;
int release_mode = 0;
+ struct timeval tv;
omapi_object_t *listener;
isc_result_t result;
int persist = 0;
}
/* Get the current time... */
- time(&cur_time);
+ gettimeofday(&cur_tv, NULL);
sockaddr_broadcast.sin_family = AF_INET;
sockaddr_broadcast.sin_port = remote_port;
/* Set up a timeout to start the
* initialization process.
*/
- add_timeout(cur_time + random() % 5,
- state_reboot, client, 0, 0);
+ tv.tv_sec = cur_time + random() % 5;
+ tv.tv_usec = 0;
+ add_timeout(&tv, state_reboot,
+ client, 0, 0);
}
}
}
void bind_lease (client)
struct client_state *client;
{
+ struct timeval tv;
+
/* Remember the medium. */
client -> new -> medium = client -> medium;
client -> new = (struct client_lease *)0;
/* Set up a timeout to start the renewal process. */
- add_timeout (client -> active -> renewal,
- state_bound, client, 0, 0);
+ tv . tv_sec = client -> active -> renewal;
+ tv . tv_usec = 0;
+ add_timeout (&tv, state_bound, client, 0, 0);
log_info ("bound to %s -- renewal in %ld seconds.",
piaddr (client -> active -> address),
int stop_selecting;
const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
char obuf [1024];
+ struct timeval tv;
#ifdef DEBUG_PACKET
dump_packet (packet);
if (stop_selecting <= 0)
state_selecting (client);
else {
- add_timeout (stop_selecting, state_selecting, client, 0, 0);
+ tv . tv_sec = stop_selecting;
+ tv . tv_usec = 0;
+ add_timeout (&tv, state_selecting, client, 0, 0);
cancel_timeout (send_discover, client);
}
log_info ("%s", obuf);
int result;
int interval;
int increase = 1;
+ struct timeval tv;
/* Figure out how long it's been since we started transmitting. */
interval = cur_time - client -> first_sending;
inaddr_any, &sockaddr_broadcast,
(struct hardware *)0);
- add_timeout (cur_time + client -> interval,
- send_discover, client, 0, 0);
+ tv . tv_sec = cur_time + client -> interval;
+ tv . tv_usec = 0;
+ add_timeout (&tv, send_discover, client, 0, 0);
}
/* state_panic gets called if we haven't received any offers in a preset
struct client_state *client = cpp;
struct client_lease *loop;
struct client_lease *lp;
+ struct timeval tv;
loop = lp = client -> active;
log_info ("bound: renewal in %ld %s.",
(long)(client -> active -> renewal -
cur_time), "seconds");
- add_timeout (client -> active -> renewal,
- state_bound, client, 0, 0);
+ tv . tv_sec = client -> active -> renewal;
+ tv . tv_usec = 0;
+ add_timeout (&tv, state_bound, client, 0, 0);
} else {
client -> state = S_BOUND;
log_info ("bound: immediate renewal.");
script_write_params (client, "alias_", client -> alias);
script_go (client);
client -> state = S_INIT;
- add_timeout (cur_time +
+ tv . tv_sec = cur_time +
((client -> config -> retry_interval + 1) / 2 +
- (random () % client -> config -> retry_interval)),
- state_init, client, 0, 0);
+ (random () % client -> config -> retry_interval));
+ tv . tv_usec = 0;
+ add_timeout (&tv, state_init, client, 0, 0);
go_daemon ();
}
int interval;
struct sockaddr_in destination;
struct in_addr from;
+ struct timeval tv;
/* Figure out how long it's been since we started transmitting. */
interval = cur_time - client -> first_sending;
from, &destination,
(struct hardware *)0);
- add_timeout (cur_time + client -> interval,
- send_request, client, 0, 0);
+ tv . tv_sec = cur_time + client -> interval;
+ tv . tv_usec = 0;
+ add_timeout (&tv, send_request, client, 0, 0);
}
void send_decline (cpp)
client -> envc = 0;
}
dfree (envp, MDL);
- time(&cur_time);
+ gettimeofday(&cur_tv, NULL);
return (WIFEXITED (wstatus) ?
WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
}
{
struct interface_info *ip;
struct client_state *client;
+ struct timeval tv;
/* This code needs some rethinking. It doesn't test against
a signal name, and it just kind of bulls into doing something
client -> state = S_INIT;
/* Set up a timeout to start the initialization
process. */
- add_timeout (cur_time + random () % 5,
- state_reboot, client, 0, 0);
+ tv . tv_sec = cur_time + random () % 5;
+ tv . tv_usec = 0;
+ add_timeout (&tv, state_reboot, client, 0, 0);
}
}
return ISC_R_SUCCESS;
{
struct interface_info *ip;
struct client_state *client;
+ struct timeval tv;
/* Do the right thing for each interface. */
for (ip = interfaces; ip; ip = ip -> next) {
}
}
- if (newstate == server_shutdown)
- add_timeout (cur_time + 1, shutdown_exit, 0, 0, 0);
+ if (newstate == server_shutdown) {
+ tv . tv_sec = cur_tv . tv_sec + 1;
+ tv . tv_usec = cur_tv . tv_usec;
+ add_timeout (&tv, shutdown_exit, 0, 0, 0);
+ }
return ISC_R_SUCCESS;
}
int offset)
{
struct dns_update_state *ustate;
+ struct timeval tv;
if (!client->config->do_forward_update)
return;
ustate->address = *addr;
ustate->dns_update_timeout = 1;
- add_timeout(cur_time + offset, client_dns_update_timeout,
+ tv.tv_sec = cur_time + offset;
+ tv.tv_usec = 0;
+ add_timeout(&tv, client_dns_update_timeout,
ustate, NULL, NULL);
} else {
log_error("Unable to allocate dns update state for %s.",
{
struct dns_update_state *ustate = cp;
isc_result_t status = ISC_R_FAILURE;
+ struct timeval tv;
/* XXX: DNS TTL is a problem we need to solve properly. Until
* that time, 300 is a placeholder default for something that is
if (status == ISC_R_TIMEDOUT) {
if (ustate->dns_update_timeout < 3600)
ustate->dns_update_timeout *= 10;
- add_timeout(cur_time + ustate->dns_update_timeout,
- client_dns_update_timeout, ustate, NULL, NULL);
+ tv.tv_sec = cur_time + ustate->dns_update_timeout;
+ tv.tv_usec = 0;
+ add_timeout(&tv, client_dns_update_timeout,
+ ustate, NULL, NULL);
} else
dfree(ustate, MDL);
}
void set_time(TIME t)
{
/* Do any outstanding timeouts. */
- if (cur_time != t) {
- cur_time = t;
+ if (cur_tv . tv_sec != t) {
+ cur_tv . tv_sec = t;
+ cur_tv . tv_usec = 0;
process_outstanding_timeouts ((struct timeval *)0);
}
}
another:
if (timeouts) {
struct timeout *t;
- if (timeouts -> when <= cur_time) {
+ if ((timeouts -> when . tv_sec < cur_tv . tv_sec) ||
+ ((timeouts -> when . tv_sec == cur_tv . tv_sec) &&
+ (timeouts -> when . tv_usec <= cur_tv . tv_usec))) {
t = timeouts;
timeouts = timeouts -> next;
(*(t -> func)) (t -> what);
goto another;
}
if (tvp) {
- tvp -> tv_sec = timeouts -> when;
- tvp -> tv_usec = 0;
+ tvp -> tv_sec = timeouts -> when . tv_sec;
+ tvp -> tv_usec = timeouts -> when . tv_usec;
}
return tvp;
} else
}
void add_timeout (when, where, what, ref, unref)
- TIME when;
+ struct timeval *when;
void (*where) PROTO ((void *));
void *what;
tvref_t ref;
q -> what = what;
}
- q -> when = when;
+ q -> when . tv_sec = when -> tv_sec;
+ q -> when . tv_usec = when -> tv_usec;
/* Now sort this timeout into the timeout list. */
/* Beginning of list? */
- if (!timeouts || timeouts -> when > q -> when) {
+ if (!timeouts || (timeouts -> when . tv_sec > q -> when . tv_sec) ||
+ ((timeouts -> when . tv_sec == q -> when . tv_sec) &&
+ (timeouts -> when . tv_usec > q -> when . tv_usec))) {
q -> next = timeouts;
timeouts = q;
return;
/* Middle of list? */
for (t = timeouts; t -> next; t = t -> next) {
- if (t -> next -> when > q -> when) {
+ if ((t -> next -> when . tv_sec > q -> when . tv_sec) ||
+ ((t -> next -> when . tv_sec == q -> when . tv_sec) &&
+ (t -> next -> when . tv_usec > q -> when . tv_usec))) {
q -> next = t -> next;
t -> next = q;
return;
struct dhc6_lease *selected_lease;
struct dhc6_lease *held_leases;
- TIME start_time;
+ struct timeval start_time;
u_int16_t elapsed;
int txcount;
/* See RFC3315 section 14. */
- TIME RT;
- TIME IRT;
- TIME MRC;
- TIME MRT;
- TIME MRD;
- TIME next_MRD;
+ TIME RT; /* In hundredths of seconds. */
+ TIME IRT; /* In hundredths of seconds. */
+ TIME MRC; /* Count. */
+ TIME MRT; /* In hundredths of seconds. */
+ TIME MRD; /* In seconds, relative. */
+ TIME next_MRD; /* In seconds, absolute. */
/* Rather than a state, we use a function that shifts around
* depending what stage of life the v6 state machine is in.
typedef void (*tvunref_t)(void *, const char *, int);
struct timeout {
struct timeout *next;
- TIME when;
+ struct timeval when;
void (*func) PROTO ((void *));
void *what;
tvref_t ref;
unsigned int data_len);
/* dhcpd.c */
-extern TIME cur_time;
+extern struct timeval cur_tv;
+#define cur_time cur_tv.tv_sec
extern int ddns_update_style;
omapi_object_t *,
omapi_object_t *);
-void add_timeout PROTO ((TIME, void (*) PROTO ((void *)), void *,
+void add_timeout PROTO ((struct timeval *, void (*) PROTO ((void *)), void *,
tvref_t, tvunref_t));
void cancel_timeout PROTO ((void (*) PROTO ((void *)), void *));
void cancel_all_timeouts (void);
#define b64_ntop MRb64_ntop
extern const struct res_sym __p_type_syms[];
-extern time_t cur_time;
+extern struct timeval cur_tv;
+#define cur_time cur_tv.tv_sec
int dn_comp (const char *,
unsigned char *, unsigned, unsigned char **, unsigned char **);
#include <sys/time.h>
static omapi_io_object_t omapi_io_states;
-time_t cur_time;
+struct timeval cur_tv;
OMAPI_OBJECT_ALLOC (omapi_io,
omapi_io_object_t, omapi_type_io_object)
/* First, see if the timeout has expired, and if so return. */
if (t) {
gettimeofday (&now, (struct timezone *)0);
- cur_time = now.tv_sec;
+ cur_tv.tv_sec = now.tv_sec;
+ cur_tv.tv_usec = now.tv_usec;
if (now.tv_sec > t -> tv_sec ||
(now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
return ISC_R_TIMEDOUT;
count = select (max + 1, &r, &w, &x, t ? &to : (struct timeval *)0);
/* Get the current time... */
- gettimeofday (&now, (struct timezone *)0);
- cur_time = now.tv_sec;
+ gettimeofday (&cur_tv, (struct timezone *)0);
/* We probably have a bad file descriptor. Figure out which one.
When we find it, call the reaper function on it, which will
#include "dhcpd.h"
#include <syslog.h>
+#include <sys/time.h>
static void usage PROTO ((void));
}
/* Get the current time... */
- time(&cur_time);
+ gettimeofday(&cur_tv, NULL);
/* Discover all the network interfaces. */
discover_interfaces (DISCOVER_RELAY);
unsigned i, j;
int s1;
int ignorep;
+ struct timeval tv;
/* If we're already acking this lease, don't do it again. */
if (lease -> state)
log_debug ("Ping timeout: %ld", (long)ping_timeout);
#endif
- add_timeout (cur_time + ping_timeout, lease_ping_timeout, lease,
+ tv . tv_sec = cur_time + ping_timeout;
+ tv . tv_usec = 0;
+ add_timeout (&tv, lease_ping_timeout, lease,
(tvref_t)lease_reference,
(tvunref_t)lease_dereference);
++outstanding_pings;
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
+#include <sys/time.h>
#include <signal.h>
static void usage(void);
{
omapi_object_t *listener;
isc_result_t result;
+ struct timeval tv;
listener = (omapi_object_t *)0;
result = omapi_generic_new (&listener, MDL);
if (result != ISC_R_SUCCESS) {
log_error ("Can't start OMAPI protocol: %s",
isc_result_totext (result));
- add_timeout (cur_time + 5, omapi_listener_start, 0, 0, 0);
+ tv.tv_sec = cur_time + 5;
+ tv.tv_usec = 0;
+ add_timeout (&tv, omapi_listener_start, 0, 0, 0);
}
omapi_object_dereference (&listener, MDL);
}
}
/* Get the current time... */
- time(&cur_time);
+ gettimeofday(&cur_tv, NULL);
/* Set up the initial dhcp option universe. */
initialize_common_option_spaces ();
#if defined (FAILOVER_PROTOCOL)
int failover_connection_count = 0;
#endif
+ struct timeval tv;
oncemore:
if (shutdown_state == shutdown_listeners ||
shutdown_time = cur_time;
goto oncemore;
}
- add_timeout (cur_time + 1,
+ tv.tv_sec = cur_tv.tv_sec + 1;
+ tv.tv_usec = cur_tv.tv_usec;
+ add_timeout (&tv,
(void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
return ISC_R_SUCCESS;
}
{
dhcp_failover_state_t *state;
isc_result_t status;
+ struct timeval tv;
for (state = failover_states; state; state = state -> next) {
dhcp_failover_state_transition (state, "startup");
#if defined (DEBUG_FAILOVER_TIMING)
log_info ("add_timeout +90 dhcp_failover_reconnect");
#endif
- add_timeout (cur_time + 90,
+ tv . tv_sec = cur_time + 90;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_reconnect, state,
(tvref_t)
dhcp_failover_state_reference,
log_info ("add_timeout +90 %s",
"dhcp_failover_listener_restart");
#endif
- add_timeout (cur_time + 90,
+ tv . tv_sec = cur_time + 90;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_listener_restart,
state,
(tvref_t)omapi_object_reference,
dhcp_failover_state_t *s, *state = (dhcp_failover_state_t *)0;
char *sname;
int slen;
+ struct timeval tv;
if (h -> type != dhcp_type_failover_link) {
/* XXX shouldn't happen. Put an assert here? */
log_info ("add_timeout +15 %s",
"dhcp_failover_link_startup_timeout");
#endif
- add_timeout (cur_time + 15,
+ tv . tv_sec = cur_time + 15;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_link_startup_timeout,
link,
(tvref_t)dhcp_failover_link_reference,
log_info ("add_timeout +5 %s",
"dhcp_failover_reconnect");
#endif
- add_timeout (cur_time + 5, dhcp_failover_reconnect,
+ tv . tv_sec = cur_time + 5;
+ tv . tv_usec = 0;
+ add_timeout (&tv, dhcp_failover_reconnect,
state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
log_info ("add_timeout +5 %s",
"dhcp_failover_reconnect");
#endif
- add_timeout (cur_time + 5, dhcp_failover_reconnect,
+ tv . tv_sec = cur_time + 5;
+ tv . tv_usec = 0;
+ add_timeout (&tv, dhcp_failover_reconnect,
state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
isc_result_t status;
dhcp_failover_state_t *state;
dhcp_failover_link_t *link;
+ struct timeval tv;
if (!o || o -> type != dhcp_type_failover_state)
return ISC_R_INVALIDARG;
log_info ("add_timeout +90 %s",
"dhcp_failover_reconnect");
#endif
- add_timeout (cur_time + 90, dhcp_failover_reconnect,
+ tv . tv_sec = cur_time + 90;
+ tv . tv_usec = 0;
+ add_timeout (&tv, dhcp_failover_reconnect,
state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)
(int)state -> partner.max_response_delay / 3,
"dhcp_failover_send_contact");
#endif
- add_timeout (cur_time +
- (int)state -> partner.max_response_delay / 3,
+ tv . tv_sec = cur_time +
+ (int)state -> partner.max_response_delay / 3;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_send_contact, state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
(int)state -> me.max_response_delay,
"dhcp_failover_timeout");
#endif
- add_timeout (cur_time +
- (int)state -> me.max_response_delay,
+ tv . tv_sec = cur_time +
+ (int)state -> me.max_response_delay;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_timeout, state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
(int)state -> me.max_response_delay,
"dhcp_failover_timeout");
#endif
- add_timeout (cur_time +
- (int)state -> me.max_response_delay,
+ tv . tv_sec = cur_time +
+ (int)state -> me.max_response_delay;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_timeout, state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
struct pool *p;
struct shared_network *s;
struct lease *l;
+ struct timeval tv;
/* If we're in certain states where we're sending updates, and the peer
* state changes, we need to re-schedule any pending updates just to
log_info ("add_timeout +15 %s",
"dhcp_failover_startup_timeout");
#endif
- add_timeout (cur_time + 15,
+ tv . tv_sec = cur_time + 15;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_startup_timeout,
state,
(tvref_t)omapi_object_reference,
state -> me.stos + state -> mclt),
"dhcp_failover_startup_timeout");
#endif
- add_timeout ((int)(state -> me.stos + state -> mclt),
+ tv . tv_sec = (int)(state -> me.stos + state -> mclt);
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_recover_done,
state,
(tvref_t)omapi_object_reference,
(int)(cur_time - p->next_event_time),
"pool_timer");
#endif
- add_timeout(p->next_event_time, pool_timer, p,
+ tv.tv_sec = p->next_event_time;
+ tv.tv_usec = 0;
+ add_timeout(&tv, pool_timer, p,
(tvref_t)pool_reference,
(tvunref_t)pool_dereference);
}
{
dhcp_failover_state_t *peer;
TIME est1, est2;
+ struct timeval tv;
peer = pool->failover_peer;
log_info("add_timeout +%d dhcp_failover_pool_rebalance",
est1 - cur_time);
#endif
- add_timeout(est1, dhcp_failover_pool_rebalance, peer,
+ tv.tv_sec = est1;
+ tv.tv_usec = 0;
+ add_timeout(&tv, dhcp_failover_pool_rebalance, peer,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
}
int dhcp_failover_queue_ack (dhcp_failover_state_t *state,
failover_message_t *msg)
{
+ struct timeval tv;
+
if (state -> toack_queue_head) {
failover_message_reference
(&state -> toack_queue_tail -> next, msg, MDL);
log_info ("add_timeout +2 %s",
"dhcp_failover_toack_queue_timeout");
#endif
- add_timeout (cur_time + 2,
+ tv . tv_sec = cur_time + 2;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_toack_queue_timeout, state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
{
dhcp_failover_state_t *state = vs;
isc_result_t status;
+ struct timeval tv;
#if defined (DEBUG_FAILOVER_TIMING)
log_info ("dhcp_failover_reconnect");
log_info ("add_timeout +90 %s",
"dhcp_failover_listener_restart");
#endif
- add_timeout (cur_time + 90,
+ tv . tv_sec = cur_time + 90;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_listener_restart, state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
{
dhcp_failover_state_t *state = vs;
isc_result_t status;
+ struct timeval tv;
#if defined (DEBUG_FAILOVER_TIMING)
log_info ("dhcp_failover_listener_restart");
log_info ("add_timeout +90 %s",
"dhcp_failover_listener_restart");
#endif
- add_timeout (cur_time + 90,
+ tv . tv_sec = cur_time + 90;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_listener_restart, state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
unsigned char *opbuf;
isc_result_t status = ISC_R_SUCCESS;
unsigned char cbuf;
+ struct timeval tv;
/* Run through the argument list once to compute the length of
the option portion of the message. */
partner.max_response_delay) / 3,
"dhcp_failover_send_contact");
#endif
- add_timeout (cur_time +
- (int)(link -> state_object ->
- partner.max_response_delay) / 3,
+ tv . tv_sec = cur_time +
+ (int)(link -> state_object ->
+ partner.max_response_delay) / 3;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_send_contact, link -> state_object,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
const char *message = "no memory";
u_int32_t pot_expire;
int send_to_backup = ISC_FALSE;
+ struct timeval tv;
ia.len = sizeof msg -> assigned_addr;
memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
succession (e.g., when stealing leases from the
secondary), we do not do an immediate commit for
each one. */
- add_timeout(cur_time + 2,
- commit_leases_timeout, (void *)0, 0, 0);
+ tv.tv_sec = cur_time + 2;
+ tv.tv_usec = 0;
+ add_timeout(&tv, commit_leases_timeout, (void *)0, 0, 0);
}
unqueue:
dhcp_failover_process_update_done (dhcp_failover_state_t *state,
failover_message_t *msg)
{
+ struct timeval tv;
+
log_info ("failover peer %s: peer update completed.",
state -> name);
state -> me.stos + state -> mclt),
"dhcp_failover_recover_done");
#endif
- add_timeout ((int)(state -> me.stos + state -> mclt),
+ tv . tv_sec = (int)(state -> me.stos + state -> mclt);
+ tv . tv_usec = 0;
+ add_timeout (&tv,
dhcp_failover_recover_done,
state,
(tvref_t)omapi_object_reference,
if (pimmediate && !commit)
return 0;
#endif
+ struct timeval tv;
/* If there is no sample lease, just do the move. */
if (!lease)
(comp -> sort_time < comp -> pool -> next_event_time ||
comp -> pool -> next_event_time == MIN_TIME)) {
comp -> pool -> next_event_time = comp -> sort_time;
- add_timeout (comp -> pool -> next_event_time,
+ tv . tv_sec = comp -> pool -> next_event_time;
+ tv . tv_usec = 0;
+ add_timeout (&tv,
pool_timer, comp -> pool,
(tvref_t)pool_reference,
(tvunref_t)pool_dereference);
struct lease **lptr[RESERVED_LEASES+1];
TIME next_expiry = MAX_TIME;
int i;
+ struct timeval tv;
pool = (struct pool *)vpool;
}
if (next_expiry != MAX_TIME) {
pool -> next_event_time = next_expiry;
- add_timeout (pool -> next_event_time, pool_timer, pool,
+ tv . tv_sec = pool -> next_event_time;
+ tv . tv_usec = 0;
+ add_timeout (&tv, pool_timer, pool,
(tvref_t)pool_reference,
(tvunref_t)pool_dereference);
} else
struct iaaddr *tmp;
time_t timeout;
time_t next_timeout;
+ struct timeval tv;
next_timeout = MAX_TIME;
}
if (next_timeout < MAX_TIME) {
- add_timeout(next_timeout, lease_timeout_support, pool,
+ tv.tv_sec = next_timeout;
+ tv.tv_usec = 0;
+ add_timeout(&tv, lease_timeout_support, pool,
(tvref_t)ipv6_pool_reference,
(tvunref_t)ipv6_pool_dereference);
}