dhcpv6: Add elapsed time option to sent messages
authorJukka Rissanen <jukka.rissanen@linux.intel.com>
Mon, 29 Apr 2013 09:39:11 +0000 (12:39 +0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Tue, 30 Apr 2013 10:43:37 +0000 (13:43 +0300)
A mandatory elapsed time option was missing from the sent
DHCPv6 messages. See RFC 3315 chapter 22.9 for details.

gdhcp/client.c
gdhcp/gdhcp.h

index 71983ce..b671a8c 100644 (file)
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
+#include <sys/time.h>
 
 #include <netpacket/packet.h>
 #include <netinet/if_ether.h>
@@ -144,6 +145,7 @@ struct _GDHCPClient {
        time_t last_rebind;
        time_t expire;
        gboolean retransmit;
+       struct timeval start_time;
 };
 
 static inline void debug(GDHCPClient *client, const char *format, ...)
@@ -250,13 +252,27 @@ static void copy_option(uint8_t *buf, uint16_t code, uint16_t len,
                memcpy(&buf[4], msg, len);
 }
 
+static int32_t get_time_diff(struct timeval *tv)
+{
+       struct timeval now;
+       int32_t hsec;
+
+       gettimeofday(&now, NULL);
+
+       hsec = (now.tv_sec - tv->tv_sec) * 100;
+       hsec += (now.tv_usec - tv->tv_usec) / 10000;
+
+       return hsec;
+}
+
 static void add_dhcpv6_request_options(GDHCPClient *dhcp_client,
                                struct dhcpv6_packet *packet,
                                unsigned char *buf, int max_buf,
                                unsigned char **ptr_buf)
 {
        GList *list;
-       uint16_t code;
+       uint16_t code, value;
+       int32_t diff;
        int len;
 
        if (dhcp_client->type == G_DHCP_IPV4)
@@ -314,6 +330,31 @@ static void add_dhcpv6_request_options(GDHCPClient *dhcp_client,
                case G_DHCPV6_ORO:
                        break;
 
+               case G_DHCPV6_ELAPSED_TIME:
+                       if (dhcp_client->retransmit == FALSE) {
+                               /*
+                                * Initial message, elapsed time is 0.
+                                */
+                               diff = 0;
+                       } else {
+                               diff = get_time_diff(&dhcp_client->start_time);
+                               if (diff < 0 || diff > 0xffff)
+                                       diff = 0xffff;
+                       }
+
+                       len = 2 + 2 + 2;
+                       if ((*ptr_buf + len) > (buf + max_buf)) {
+                               debug(dhcp_client, "Too long dhcpv6 message "
+                                       "when writing elapsed time option");
+                               return;
+                       }
+
+                       value = htons((uint16_t)diff);
+                       copy_option(*ptr_buf, G_DHCPV6_ELAPSED_TIME,
+                               2, (uint8_t *)&value);
+                       (*ptr_buf) += len;
+                       break;
+
                case G_DHCPV6_DNS_SERVERS:
                        break;
 
@@ -816,16 +857,19 @@ static int send_dhcpv6_msg(GDHCPClient *dhcp_client, int type, char *msg)
 
        init_packet(dhcp_client, packet, type);
 
-       if (dhcp_client->retransmit == FALSE)
+       if (dhcp_client->retransmit == FALSE) {
                dhcp_client->xid = packet->transaction_id[0] << 16 |
                                packet->transaction_id[1] << 8 |
                                packet->transaction_id[2];
-       else {
+               gettimeofday(&dhcp_client->start_time, NULL);
+       } else {
                packet->transaction_id[0] = dhcp_client->xid >> 16;
                packet->transaction_id[1] = dhcp_client->xid >> 8 ;
                packet->transaction_id[2] = dhcp_client->xid;
        }
 
+       g_dhcp_client_set_request(dhcp_client, G_DHCPV6_ELAPSED_TIME);
+
        debug(dhcp_client, "sending DHCPv6 %s message xid 0x%04x", msg,
                                                        dhcp_client->xid);
 
index f7a6ede..0820cdd 100644 (file)
@@ -82,6 +82,7 @@ typedef enum {
 #define G_DHCPV6_IA_TA         4
 #define G_DHCPV6_IAADDR                5
 #define G_DHCPV6_ORO           6
+#define G_DHCPV6_ELAPSED_TIME   8
 #define G_DHCPV6_STATUS_CODE   13
 #define G_DHCPV6_RAPID_COMMIT  14
 #define G_DHCPV6_DNS_SERVERS   23