From 1aa44c8ddaacf4c2e1377b3c29a0ef6685ab95e4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 29 Apr 2013 12:39:11 +0300 Subject: [PATCH] dhcpv6: Add elapsed time option to sent messages A mandatory elapsed time option was missing from the sent DHCPv6 messages. See RFC 3315 chapter 22.9 for details. --- gdhcp/client.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- gdhcp/gdhcp.h | 1 + 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/gdhcp/client.c b/gdhcp/client.c index 71983ce..b671a8c 100644 --- a/gdhcp/client.c +++ b/gdhcp/client.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -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); diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h index f7a6ede..0820cdd 100644 --- a/gdhcp/gdhcp.h +++ b/gdhcp/gdhcp.h @@ -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 -- 2.7.4