summaryrefslogtreecommitdiff
path: root/gdhcp/client.c
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2013-04-29 12:39:11 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2013-04-30 13:43:37 +0300
commit1aa44c8ddaacf4c2e1377b3c29a0ef6685ab95e4 (patch)
tree0f0c3719c3afeade58e48201803f69f9e56343ba /gdhcp/client.c
parent16abff229fe782c6a8463a7e3b8df3f9c4a17283 (diff)
downloadconnman-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/client.c')
-rw-r--r--gdhcp/client.c50
1 files changed, 47 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);