]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Add an elapsed time option to the release message and refactor the
authorShawn Routhier <sar@isc.org>
Fri, 10 Sep 2010 20:21:03 +0000 (20:21 +0000)
committerShawn Routhier <sar@isc.org>
Fri, 10 Sep 2010 20:21:03 +0000 (20:21 +0000)
  code to move most of the common code to a single routine.
  [ISC-Bugs #21171].

RELNOTES
client/dhc6.c

index bc1a82501b998e4c3b3f6e9ca1548ead707ba60c..230d275014ec01d92c3cc0c779bba9ccbf5a5142 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -96,6 +96,10 @@ work on other platforms. Please report any problems and suggested fixes to
 - When parsing a domain name free the memory for the name after we are
   done with it.  [ISC-Bugs #20824]
 
+- Add an elapsed time option to the release message and refactor the
+  code to move most of the common code to a single routine.
+  [ISC-Bugs #21171].
+
                        Changes since 4.2.0b2
 
 - Add declaration for variable in debug code in alloc.c.  [ISC-Bugs #21472]
index cafe12212ce795143a90b0b255a6a60d43fab909..633f9b1a661697f8b6e9de02672307893e66d0bf 100644 (file)
@@ -1,7 +1,7 @@
 /* dhc6.c - DHCPv6 client routines. */
 
 /*
- * Copyright (c) 2006-2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -110,6 +110,10 @@ static void script_write_params6(struct client_state *client,
                                 struct option_state *options);
 static isc_boolean_t active_prefix(struct client_state *client);
 
+static int check_timing6(struct client_state *client, u_int8_t msg_type, 
+                        char *msg_str, struct dhc6_lease *lease,
+                        struct data_string *ds);
+
 extern int onetry;
 extern int stateless;
 
@@ -1456,36 +1460,20 @@ start_confirm6(struct client_state *client)
 }
 
 /*
- * do_init6() marshals and transmits a solicit.
+ * check_timing6() check on the timing for sending a v6 message
+ * and then do the basic initialization for a v6 message.
  */
-void
-do_init6(void *input)
+#define CHK_TIM_SUCCESS                0
+#define CHK_TIM_MRC_EXCEEDED   1
+#define CHK_TIM_MRD_EXCEEDED   2
+#define CHK_TIM_ALLOC_FAILURE  3
+
+int
+check_timing6 (struct client_state *client, u_int8_t msg_type, 
+              char *msg_str, struct dhc6_lease *lease,
+              struct data_string *ds)
 {
-       struct client_state *client;
-       struct dhc6_ia *old_ia;
-       struct dhc6_addr *old_addr;
-       struct data_string ds;
-       struct data_string ia;
-       struct data_string addr;
-       struct timeval elapsed, tv;
-       u_int32_t t1, t2;
-       int i, idx, len, send_ret;
-
-       client = input;
-
-       /*
-        * In RFC3315 section 17.1.2, the retransmission timer is
-        * used as the selecting timer.
-        */
-       if (client->advertised_leases != NULL) {
-               start_selecting6(client);
-               return;
-       }
-
-       if ((client->MRC != 0) && (client->txcount > client->MRC)) {
-               log_info("Max retransmission count exceeded.");
-               return;
-       }
+       struct timeval elapsed;
 
        /*
         * Start_time starts at the first transmission.
@@ -1493,6 +1481,9 @@ do_init6(void *input)
        if (client->txcount == 0) {
                client->start_time.tv_sec = cur_tv.tv_sec;
                client->start_time.tv_usec = cur_tv.tv_usec;
+       } else if ((client->MRC != 0) && (client->txcount > client->MRC)) {
+               log_info("Max retransmission count exceeded.");
+               return(CHK_TIM_MRC_EXCEEDED);
        }
 
        /* elapsed = cur - start */
@@ -1502,30 +1493,23 @@ do_init6(void *input)
                elapsed.tv_sec -= 1;
                elapsed.tv_usec += 1000000;
        }
+
        /* Check if finished (-1 argument). */
        if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
                log_info("Max retransmission duration exceeded.");
-               client->state = S_STOPPED;
-               if (client->active_lease != NULL) {
-                       dhc6_lease_destroy(&client->active_lease, MDL);
-                       client->active_lease = NULL;
-               }
-               /* Stop if and only if this is the last client. */
-               if (stopping_finished())
-                       exit(2);
-               return;
+               return(CHK_TIM_MRD_EXCEEDED);
        }
 
-       memset(&ds, 0, sizeof(ds));
-       if (!buffer_allocate(&ds.buffer, 4, MDL)) {
-               log_error("Unable to allocate memory for SOLICIT.");
-               return;
+       memset(ds, 0, sizeof(*ds));
+       if (!buffer_allocate(&(ds->buffer), 4, MDL)) {
+               log_error("Unable to allocate memory for %s.", msg_str);
+               return(CHK_TIM_ALLOC_FAILURE);
        }
-       ds.data = ds.buffer->data;
-       ds.len = 4;
+       ds->data = ds->buffer->data;
+       ds->len = 4;
 
-       ds.buffer->data[0] = DHCPV6_SOLICIT;
-       memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
+       ds->buffer->data[0] = msg_type;
+       memcpy(ds->buffer->data + 1, client->dhcpv6_transaction_id, 3);
 
        /* Form an elapsed option. */
        /* Maximum value is 65535 1/100s coded as 0xffff. */
@@ -1538,15 +1522,60 @@ do_init6(void *input)
        }
 
        if (client->elapsed == 0)
-               log_debug("XMT: Forming Solicit, 0 ms elapsed.");
+               log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str);
        else
-               log_debug("XMT: Forming Solicit, %u0 ms elapsed.",
+               log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str,
                          (unsigned)client->elapsed);
 
        client->elapsed = htons(client->elapsed);
 
-       make_client6_options(client, &client->sent_options, NULL,
-                            DHCPV6_SOLICIT);
+       make_client6_options(client, &client->sent_options, lease, msg_type);
+
+       return(CHK_TIM_SUCCESS);
+}
+
+/*
+ * do_init6() marshals and transmits a solicit.
+ */
+void
+do_init6(void *input)
+{
+       struct client_state *client;
+       struct dhc6_ia *old_ia;
+       struct dhc6_addr *old_addr;
+       struct data_string ds;
+       struct data_string ia;
+       struct data_string addr;
+       struct timeval tv;
+       u_int32_t t1, t2;
+       int i, idx, len, send_ret;
+
+       client = input;
+
+       /*
+        * In RFC3315 section 17.1.2, the retransmission timer is
+        * used as the selecting timer.
+        */
+       if (client->advertised_leases != NULL) {
+               start_selecting6(client);
+               return;
+       }
+
+       switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) {
+             case CHK_TIM_MRC_EXCEEDED:
+             case CHK_TIM_ALLOC_FAILURE:
+               return;
+             case CHK_TIM_MRD_EXCEEDED:
+               client->state = S_STOPPED;
+               if (client->active_lease != NULL) {
+                       dhc6_lease_destroy(&client->active_lease, MDL);
+                       client->active_lease = NULL;
+               }
+               /* Stop if and only if this is the last client. */
+               if (stopping_finished())
+                       exit(2);
+               return;
+       }
 
        /*
         * Fetch any configured 'sent' options (includes DUID) in wire format.
@@ -1897,69 +1926,22 @@ do_info_request6(void *input)
 {
        struct client_state *client;
        struct data_string ds;
-       struct timeval elapsed, tv;
+       struct timeval tv;
        int send_ret;
 
        client = input;
 
-       if ((client->MRC != 0) && (client->txcount > client->MRC)) {
-               log_info("Max retransmission count exceeded.");
+       switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST,
+                            "Info-Request", NULL, &ds)) {
+             case CHK_TIM_MRC_EXCEEDED:
+             case CHK_TIM_ALLOC_FAILURE:
                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;
-       }
-
-       /* 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;
-       }
-       /* Check if finished (-1 argument). */
-       if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
-               log_info("Max retransmission duration exceeded.");
+             case CHK_TIM_MRD_EXCEEDED:
                exit(2);
+             case CHK_TIM_SUCCESS:
+               break;
        }
 
-       memset(&ds, 0, sizeof(ds));
-       if (!buffer_allocate(&ds.buffer, 4, MDL)) {
-               log_error("Unable to allocate memory for INFO-REQUEST.");
-               return;
-       }
-       ds.data = ds.buffer->data;
-       ds.len = 4;
-
-       ds.buffer->data[0] = DHCPV6_INFORMATION_REQUEST;
-       memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
-
-       /* 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.tv_sec * 100;
-               client->elapsed += elapsed.tv_usec / 10000;
-       }
-
-       if (client->elapsed == 0)
-               log_debug("XMT: Forming Info-Request, 0 ms elapsed.");
-       else
-               log_debug("XMT: Forming Info-Request, %u0 ms elapsed.",
-                         (unsigned)client->elapsed);
-
-       client->elapsed = htons(client->elapsed);
-
-       make_client6_options(client, &client->sent_options, NULL,
-                            DHCPV6_INFORMATION_REQUEST);
-
        /* Fetch any configured 'sent' options (includes DUID) in wire format.
         */
        dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
@@ -2002,7 +1984,7 @@ do_confirm6(void *input)
        struct client_state *client;
        struct data_string ds;
        int send_ret;
-       struct timeval elapsed, tv;
+       struct timeval tv;
 
        client = input;
 
@@ -2023,65 +2005,18 @@ do_confirm6(void *input)
         * stick there until we get a reply?
         */
 
-       if ((client->MRC != 0) && (client->txcount > client->MRC))  {
-               log_info("Max retransmission count exceeded.");
+       switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm",
+                            client->active_lease, &ds)) {
+             case CHK_TIM_MRC_EXCEEDED:
+             case CHK_TIM_MRD_EXCEEDED:
                start_bound(client);
                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;
-       }
-
-       /* 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);
+             case CHK_TIM_ALLOC_FAILURE:
                return;
+             case CHK_TIM_SUCCESS:
+               break;
        }
 
-       memset(&ds, 0, sizeof(ds));
-       if (!buffer_allocate(&ds.buffer, 4, MDL)) {
-               log_error("Unable to allocate memory for Confirm.");
-               return;
-       }
-       ds.data = ds.buffer->data;
-       ds.len = 4;
-
-       ds.buffer->data[0] = DHCPV6_CONFIRM;
-       memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
-
-       /* 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.tv_sec * 100;
-               client->elapsed += elapsed.tv_usec / 10000;
-       }
-
-       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);
-
-       make_client6_options(client, &client->sent_options,
-                            client->active_lease, DHCPV6_CONFIRM);
-
        /* Fetch any configured 'sent' options (includes DUID') in wire format.
         */
        dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
@@ -2182,17 +2117,14 @@ do_release6(void *input)
        if ((client->active_lease == NULL) || !active_prefix(client))
                return;
 
-       if ((client->MRC != 0) && (client->txcount > client->MRC))  {
-               log_info("Max retransmission count exceeded.");
+       switch(check_timing6(client, DHCPV6_RELEASE, "Release", 
+                            client->active_lease, &ds)) {
+             case CHK_TIM_MRC_EXCEEDED:
+             case CHK_TIM_ALLOC_FAILURE:
+             case CHK_TIM_MRD_EXCEEDED:
                goto release_done;
-       }
-
-       /*
-        * 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;
+             case CHK_TIM_SUCCESS:
+               break;
        }
 
        /*
@@ -2200,20 +2132,6 @@ do_release6(void *input)
         * available address with enough scope.
         */
 
-       memset(&ds, 0, sizeof(ds));
-       if (!buffer_allocate(&ds.buffer, 4, MDL)) {
-               log_error("Unable to allocate memory for Release.");
-               goto release_done;
-       }
-
-       ds.data = ds.buffer->data;
-       ds.len = 4;
-       ds.buffer->data[0] = DHCPV6_RELEASE;
-       memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
-
-       log_debug("XMT: Forming Release.");
-       make_client6_options(client, &client->sent_options,
-                            client->active_lease, DHCPV6_RELEASE);
        dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
                                    client->sent_options, &global_scope,
                                    &dhcpv6_universe);
@@ -3254,8 +3172,7 @@ do_select6(void *input)
        struct client_state *client;
        struct dhc6_lease *lease;
        struct data_string ds;
-       struct timeval elapsed, tv;
-       int abort = ISC_FALSE;
+       struct timeval tv;
        int send_ret;
 
        client = input;
@@ -3268,32 +3185,9 @@ do_select6(void *input)
                return;
        }
 
-       if ((client->MRC != 0) && (client->txcount > client->MRC)) {
-               log_info("Max retransmission count exceeded.");
-               abort = ISC_TRUE;
-       }
-
-       /*
-        * 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;
-       }
-
-       if (abort) {
+       switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) {
+             case CHK_TIM_MRC_EXCEEDED:
+             case CHK_TIM_MRD_EXCEEDED:
                log_debug("PRC: Lease %s failed.",
                          print_hex_1(lease->server_id.len,
                                      lease->server_id.data, 56));
@@ -3307,8 +3201,11 @@ do_select6(void *input)
                        start_selecting6(client);
                else
                        start_init6(client);
-
                return;
+             case CHK_TIM_ALLOC_FAILURE:
+               return;
+             case CHK_TIM_SUCCESS:
+               break;
        }
 
        /* Now make a packet that looks suspiciously like the one we
@@ -3321,37 +3218,6 @@ do_select6(void *input)
         * construct for the iaid, then we can delve into this matter
         * more properly.  In the time being, this will work.
         */
-       memset(&ds, 0, sizeof(ds));
-       if (!buffer_allocate(&ds.buffer, 4, MDL)) {
-               log_error("Unable to allocate memory for REQUEST.");
-               return;
-       }
-       ds.data = ds.buffer->data;
-       ds.len = 4;
-
-       ds.buffer->data[0] = DHCPV6_REQUEST;
-       memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
-
-       /* 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.tv_sec * 100;
-               client->elapsed += elapsed.tv_usec / 10000;
-       }
-
-       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);
-
-       make_client6_options(client, &client->sent_options, lease,
-                            DHCPV6_REQUEST);
 
        /* Fetch any configured 'sent' options (includes DUID) in wire format.
         */