dhclient - Have only one timeout at once.
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Wed, 15 Aug 2012 01:15:12 +0000 (03:15 +0200)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Sun, 19 Aug 2012 14:31:00 +0000 (16:31 +0200)
- Terminate with extreme prejudice the multiple timeout queuing
  mechanism that was a holdover from when dhclient handled multiple
  interfaces at once.

- Also move calculation of current time to just before check to see
  if the timeout has expired.

Taken-from: OpenBSD

sbin/dhclient/dhclient.c
sbin/dhclient/dhcpd.h
sbin/dhclient/dispatch.c

index ff1a326..159e956 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/dhclient.c,v 1.145 2012/06/24 16:01:18 krw Exp $    */
+/*     $OpenBSD: src/sbin/dhclient/dhclient.c,v 1.146 2012/07/09 16:21:21 krw Exp $    */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -454,11 +454,7 @@ state_reboot(void)
 {
        /* Cancel all timeouts, since a link state change gets us here
           and can happen anytime. */
-       cancel_timeout(state_init);
-       cancel_timeout(state_selecting);
-       cancel_timeout(state_bound);
-       cancel_timeout(send_discover);
-       cancel_timeout(send_request);
+       cancel_timeout();
 
        /* If we don't remember an active lease, go straight to INIT. */
        if (!client->active || client->active->is_bootp) {
@@ -515,8 +511,7 @@ state_selecting(void)
 
        /* Cancel state_selecting and send_discover timeouts, since either
           one could have got us here. */
-       cancel_timeout(state_selecting);
-       cancel_timeout(send_discover);
+       cancel_timeout();
 
        /* We have received one or more DHCPOFFER packets.   Currently,
           the only criterion by which we judge leases is whether or
@@ -600,7 +595,7 @@ dhcpack(struct iaddr client_addr, struct option_data *options)
        client->new = lease;
 
        /* Stop resending DHCPREQUEST. */
-       cancel_timeout(send_request);
+       cancel_timeout();
 
        /* Figure out the lease time. */
        if (client->new->options[DHO_DHCP_LEASE_TIME].data)
@@ -667,8 +662,8 @@ bind_lease(void)
        /* Write out new leases file. */
        rewrite_client_leases();
 
-       /* Set up a timeout to start the renewal process. */
-       add_timeout(client->active->renewal, state_bound);
+       /* Set timeout to start the renewal process. */
+       set_timeout(client->active->renewal, state_bound);
 
        note("bound to %s -- renewal in %ld seconds.",
            piaddr(client->active->address),
@@ -781,8 +776,7 @@ dhcpoffer(struct iaddr client_addr, struct option_data *options)
        if (stop_selecting <= cur_time)
                state_selecting();
        else {
-               add_timeout(stop_selecting, state_selecting);
-               cancel_timeout(send_discover);
+               set_timeout(stop_selecting, state_selecting);
        }
 }
 
@@ -880,7 +874,7 @@ dhcpnak(struct iaddr client_addr, struct option_data *options)
        client->active = NULL;
 
        /* Stop sending DHCPREQUEST packets... */
-       cancel_timeout(send_request);
+       cancel_timeout();
 
        client->state = S_INIT;
        state_init();
@@ -950,7 +944,7 @@ send_discover(void)
        /* Send out a packet. */
        send_packet(inaddr_any, &sockaddr_broadcast, NULL);
 
-       add_timeout(cur_time + client->interval, send_discover);
+       set_timeout(cur_time + client->interval, send_discover);
 }
 
 /*
@@ -992,7 +986,7 @@ state_panic(void)
                                        note("bound: renewal in %ld seconds.",
                                            client->active->renewal -
                                            cur_time);
-                                       add_timeout(client->active->renewal,
+                                       set_timeout(client->active->renewal,
                                            state_bound);
                                } else {
                                        client->state = S_BOUND;
@@ -1039,7 +1033,7 @@ activate_next:
        script_init("FAIL");
        script_go();
        client->state = S_INIT;
-       add_timeout(cur_time + config->retry_interval, state_init);
+       set_timeout(cur_time + config->retry_interval, state_init);
        go_daemon();
 }
 
@@ -1067,7 +1061,7 @@ send_request(void)
            client->state == S_REQUESTING) &&
            interval > config->reboot_timeout) {
                client->state = S_INIT;
-               cancel_timeout(send_request);
+               cancel_timeout();
                state_init();
                return;
        }
@@ -1139,7 +1133,7 @@ send_request(void)
        /* Send out a packet. */
        send_packet(from, &destination, NULL);
 
-       add_timeout(cur_time + client->interval, send_request);
+       set_timeout(cur_time + client->interval, send_request);
 }
 
 void
index 2705556..6b208c9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/dhcpd.h,v 1.75 2012/06/24 16:01:18 krw Exp $        */
+/*     $OpenBSD: src/sbin/dhclient/dhcpd.h,v 1.76 2012/07/09 16:21:21 krw Exp $        */
 
 /*
  * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -249,8 +249,8 @@ void discover_interface(void);
 void reinitialize_interface(void);
 void dispatch(void);
 void got_one(void);
-void add_timeout(time_t, void (*)(void));
-void cancel_timeout(void (*)(void));
+void set_timeout(time_t, void (*)(void));
+void cancel_timeout(void);
 int interface_status(char *);
 int interface_link_forceup(char *);
 
index 16a94cb..e199159 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/dispatch.c,v 1.51 2012/06/24 16:01:18 krw Exp $     */
+/*     $OpenBSD: src/sbin/dhclient/dispatch.c,v 1.52 2012/07/09 16:21:21 krw Exp $     */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -48,8 +48,7 @@
 
 #include "dhcpd.h"
 
-struct timeout *timeouts;
-static struct timeout *free_timeouts;
+struct timeout timeout;
 static int interfaces_invalidated;
 
 /*
@@ -125,10 +124,11 @@ dispatch(void)
        int count, to_msec;
        struct pollfd fds[2];
        time_t howlong;
+       void (*func)(void);
 
        do {
                /*
-                * Call any expired timeouts, and then if there's still
+                * Call expired timeout, and then if there's still
                 * a timeout registered, time out the select call then.
                 */
 another:
@@ -138,25 +138,21 @@ another:
                if (!ifi->linkstat)
                        interfaces_invalidated = 0;
 
-               if (timeouts) {
-                       struct timeout *t;
-
-                       if (timeouts->when <= cur_time) {
-                               t = timeouts;
-                               timeouts = timeouts->next;
-                               (*(t->func))();
-                               t->next = free_timeouts;
-                               free_timeouts = t;
+               if (timeout.func) {
+                       time(&cur_time);
+                       if (timeout.when <= cur_time) {
+                               func = timeout.func;
+                               cancel_timeout();
+                               (*(func))();
                                goto another;
                        }
-
                        /*
                         * Figure timeout in milliseconds, and check for
                         * potential overflow, so we can cram into an
                         * int for poll, while not polling with a
                         * negative timeout and blocking indefinitely.
                         */
-                       howlong = timeouts->when - cur_time;
+                       howlong = timeout.when - cur_time;
                        if (howlong > INT_MAX / 1000)
                                howlong = INT_MAX / 1000;
                        to_msec = howlong * 1000;
@@ -174,9 +170,6 @@ another:
                /* Wait for a packet or a timeout... XXX */
                count = poll(fds, 2, to_msec);
 
-               /* Get the current time... */
-               time(&cur_time);
-
                /* Not likely to be transitory... */
                if (count == -1) {
                        if (errno == EAGAIN || errno == EINTR) {
@@ -312,84 +305,15 @@ active:
 }
 
 void
-add_timeout(time_t when, void (*where)(void))
+set_timeout(time_t when, void (*where)(void))
 {
-       struct timeout *t, *q;
-
-       /* See if this timeout supersedes an existing timeout. */
-       t = NULL;
-       for (q = timeouts; q; q = q->next) {
-               if (q->func == where) {
-                       if (t)
-                               t->next = q->next;
-                       else
-                               timeouts = q->next;
-                       break;
-               }
-               t = q;
-       }
-
-       /* If we didn't supersede a timeout, allocate a timeout
-          structure now. */
-       if (!q) {
-               if (free_timeouts) {
-                       q = free_timeouts;
-                       free_timeouts = q->next;
-                       q->func = where;
-               } else {
-                       q = malloc(sizeof(struct timeout));
-                       if (!q)
-                               error("Can't allocate timeout structure!");
-                       q->func = where;
-               }
-       }
-
-       q->when = when;
-
-       /* Now sort this timeout into the timeout list. */
-
-       /* Beginning of list? */
-       if (!timeouts || timeouts->when > q->when) {
-               q->next = timeouts;
-               timeouts = q;
-               return;
-       }
-
-       /* Middle of list? */
-       for (t = timeouts; t->next; t = t->next) {
-               if (t->next->when > q->when) {
-                       q->next = t->next;
-                       t->next = q;
-                       return;
-               }
-       }
-
-       /* End of list. */
-       t->next = q;
-       q->next = NULL;
+       timeout.when = when;
+       timeout.func = where;
 }
 
 void
-cancel_timeout(void (*where)(void))
+cancel_timeout(void)
 {
-       struct timeout *t, *q;
-
-       /* Look for this timeout on the list, and unlink it if we find it. */
-       t = NULL;
-       for (q = timeouts; q; q = q->next) {
-               if (q->func == where) {
-                       if (t)
-                               t->next = q->next;
-                       else
-                               timeouts = q->next;
-                       break;
-               }
-               t = q;
-       }
-
-       /* If we found the timeout, put it on the free list. */
-       if (q) {
-               q->next = free_timeouts;
-               free_timeouts = q;
-       }
+       timeout.when = 0;
+       timeout.func = NULL;
 }