wifi: Add support for autoscan request
[framework/connectivity/connman.git] / gdhcp / common.c
index 46cf5f6..8d5c284 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  DHCP library with GLib integration
  *
- *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -36,8 +36,6 @@
 #include <net/ethernet.h>
 #include <arpa/inet.h>
 
-#include <inet.h>
-
 #include "gdhcp.h"
 #include "common.h"
 
@@ -157,14 +155,16 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
        rem = pkt_len - 1 - 3;
 
        if (rem <= 0)
-               /* Bad packet */
-               return NULL;
+               goto bad_packet;
 
        while (1) {
                opt_code = optionptr[0] << 8 | optionptr[1];
                opt_len = len = optionptr[2] << 8 | optionptr[3];
                len += 2 + 2; /* skip code and len */
 
+               if (len < 4)
+                       goto bad_packet;
+
                rem -= len;
                if (rem < 0)
                        break;
@@ -172,7 +172,10 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
                if (opt_code == code) {
                        if (option_len != NULL)
                                *option_len = opt_len;
-                       found = optionptr + 2 + 2;
+                       if (rem == 0)
+                               found = NULL;
+                       else
+                               found = optionptr + 2 + 2;
                        count++;
                }
 
@@ -186,6 +189,38 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
                *option_count = count;
 
        return found;
+
+bad_packet:
+       if (option_len != NULL)
+               *option_len = 0;
+       if (option_count != NULL)
+               *option_count = 0;
+       return NULL;
+}
+
+uint8_t *dhcpv6_get_sub_option(unsigned char *option, uint16_t max_len,
+                       uint16_t *option_code, uint16_t *option_len)
+{
+       int rem;
+       uint16_t code, len;
+
+       rem = max_len - 2 - 2;
+
+       if (rem <= 0)
+               /* Bad option */
+               return NULL;
+
+       code = option[0] << 8 | option[1];
+       len = option[2] << 8 | option[3];
+
+       rem -= len;
+       if (rem < 0)
+               return NULL;
+
+       *option_code = code;
+       *option_len = len;
+
+       return &option[4];
 }
 
 /*
@@ -249,7 +284,7 @@ void dhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code,
        data <<= 8 * (4 - len);
 #endif
 
-       dhcp_put_unaligned(data, (uint32_t *) &option[OPT_DATA]);
+       dhcp_put_unaligned(data, (uint32_t *)(option + OPT_DATA));
        dhcp_add_binary_option(packet, option);
 
        return;