diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2013-04-29 12:39:11 +0300 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2013-04-30 13:43:37 +0300 |
commit | 1aa44c8ddaacf4c2e1377b3c29a0ef6685ab95e4 (patch) | |
tree | 0f0c3719c3afeade58e48201803f69f9e56343ba /gdhcp | |
parent | 16abff229fe782c6a8463a7e3b8df3f9c4a17283 (diff) | |
download | connman-1aa44c8ddaacf4c2e1377b3c29a0ef6685ab95e4.tar.gz connman-1aa44c8ddaacf4c2e1377b3c29a0ef6685ab95e4.tar.bz2 connman-1aa44c8ddaacf4c2e1377b3c29a0ef6685ab95e4.zip |
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.
Diffstat (limited to 'gdhcp')
-rw-r--r-- | gdhcp/client.c | 50 | ||||
-rw-r--r-- | gdhcp/gdhcp.h | 1 |
2 files changed, 48 insertions, 3 deletions
diff --git a/gdhcp/client.c b/gdhcp/client.c index 71983ce8..b671a8ca 100644 --- a/gdhcp/client.c +++ b/gdhcp/client.c @@ -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); diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h index f7a6edeb..0820cdd5 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 |