Updated connman to version 1.35
[platform/upstream/connman.git] / gdhcp / client.c
index 106c777..5a455f0 100755 (executable)
 #define DISCOVER_TIMEOUT 5
 #define DISCOVER_RETRIES 6
 
+#if defined TIZEN_EXT
+#define REQUEST_TIMEOUT 1
+#else
 #define REQUEST_TIMEOUT 5
+#endif
 #define REQUEST_RETRIES 3
 
+#if defined TIZEN_EXT
+#define DISCOVER_TIMEOUT_WIFI 1
+#define DISCOVER_RETRIES_WIFI 10
+static int dhcp_discover_timeout = DISCOVER_TIMEOUT_WIFI;
+static int dhcp_discover_max_retry = DISCOVER_RETRIES_WIFI;
+
+void set_dhcp_discover_timeout(int timeout_value)
+{
+       dhcp_discover_timeout = timeout_value;
+}
+
+void set_dhcp_discover_retry_count(int retry_count)
+{
+       dhcp_discover_max_retry = retry_count;
+}
+#endif
+
 typedef enum _listen_mode {
        L_NONE,
        L2,
@@ -156,6 +177,10 @@ struct _GDHCPClient {
        bool retransmit;
        struct timeval start_time;
        bool request_bcast;
+#if defined TIZEN_EXT
+       uint32_t dhcp_lease_seconds;
+       gboolean init_reboot;
+#endif
 };
 
 static inline void debug(GDHCPClient *client, const char *format, ...)
@@ -480,6 +505,9 @@ static int send_request(GDHCPClient *dhcp_client)
        init_packet(dhcp_client, &packet, DHCPREQUEST);
 
        packet.xid = dhcp_client->xid;
+#if defined TIZEN_EXT
+       if (dhcp_client->init_reboot != TRUE)
+#endif
        packet.secs = dhcp_attempt_secs(dhcp_client);
 
        if (dhcp_client->state == REQUESTING || dhcp_client->state == REBOOTING)
@@ -827,16 +855,19 @@ int g_dhcpv6_client_get_timeouts(GDHCPClient *dhcp_client,
                return -EINVAL;
 
        if (T1)
-               *T1 = dhcp_client->T1;
+               *T1 = (dhcp_client->expire == 0xffffffff) ? 0xffffffff:
+                       dhcp_client->T1;
 
        if (T2)
-               *T2 = dhcp_client->T2;
+               *T2 = (dhcp_client->expire == 0xffffffff) ? 0xffffffff:
+                       dhcp_client->T2;
 
        if (started)
                *started = dhcp_client->last_request;
 
        if (expire)
-               *expire = dhcp_client->last_request + dhcp_client->expire;
+               *expire = (dhcp_client->expire == 0xffffffff) ? 0xffffffff:
+                       dhcp_client->last_request + dhcp_client->expire;
 
        return 0;
 }
@@ -1266,7 +1297,7 @@ static int dhcp_l2_socket(int ifindex)
                .filter = (struct sock_filter *) filter_instr,
        };
 
-       fd = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_IP));
+       fd = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
        if (fd < 0)
                return -errno;
 
@@ -1513,6 +1544,21 @@ static gboolean request_timeout(gpointer user_data)
 {
        GDHCPClient *dhcp_client = user_data;
 
+#if defined TIZEN_EXT
+       if (dhcp_client->init_reboot) {
+               debug(dhcp_client, "DHCPREQUEST of INIT-REBOOT has failed");
+
+               /* Start DHCPDISCOVERY when DHCPREQUEST of INIT-REBOOT has failed */
+               g_dhcp_client_set_address_known(dhcp_client, FALSE);
+
+               dhcp_client->retry_times = 0;
+               dhcp_client->requested_ip = 0;
+
+               g_dhcp_client_start(dhcp_client, dhcp_client->last_address);
+
+               return FALSE;
+       }
+#endif
        debug(dhcp_client, "request timeout (retries %d)",
                                        dhcp_client->retry_times);
 
@@ -1625,8 +1671,7 @@ static uint32_t get_lease(struct dhcp_packet *packet)
                return 3600;
 
        lease_seconds = get_be32(option);
-       /* paranoia: must not be prone to overflows */
-       lease_seconds &= 0x0fffffff;
+
        if (lease_seconds < 10)
                lease_seconds = 10;
 
@@ -1674,8 +1719,10 @@ static gboolean continue_rebound(gpointer user_data)
        switch_listening_mode(dhcp_client, L2);
        send_request(dhcp_client);
 
-       if (dhcp_client->t2_timeout> 0)
+       if (dhcp_client->t2_timeout> 0) {
                g_source_remove(dhcp_client->t2_timeout);
+               dhcp_client->t2_timeout = 0;
+       }
 
        /*recalculate remaining rebind time*/
        dhcp_client->T2 >>= 1;
@@ -2222,6 +2269,8 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                if (dhcp_client->type == G_DHCP_IPV6) {
                        re = dhcpv6_recv_l3_packet(&packet6, buf, sizeof(buf),
                                                dhcp_client->listener_sockfd);
+                       if (re < 0)
+                           return TRUE;
                        pkt_len = re;
                        pkt = packet6;
                        xid = packet6->transaction_id[0] << 16 |
@@ -2284,10 +2333,6 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                        return TRUE;
        }
 
-       if (!message_type && !client_id)
-               /* No message type / client id option, ignore package */
-               return TRUE;
-
        debug(dhcp_client, "received DHCP packet xid 0x%04x "
                "(current state %d)", ntohl(xid), dhcp_client->state);
 
@@ -2338,6 +2383,10 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
 
                        dhcp_client->lease_seconds = get_lease(&packet);
 
+#if defined TIZEN_EXT
+                       dhcp_client->dhcp_lease_seconds = dhcp_client->lease_seconds;
+#endif
+
                        get_request(dhcp_client, &packet);
 
                        switch_listening_mode(dhcp_client, L_NONE);
@@ -2362,6 +2411,18 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
 
                        remove_timeouts(dhcp_client);
 
+#if defined TIZEN_EXT
+                       if (dhcp_client->init_reboot) {
+                               g_dhcp_client_set_address_known(dhcp_client, FALSE);
+                               dhcp_client->timeout = g_idle_add_full(
+                                                               G_PRIORITY_HIGH,
+                                                               restart_dhcp_timeout,
+                                                               dhcp_client,
+                                                               NULL);
+
+                               break;
+                       }
+#endif
                        dhcp_client->timeout = g_timeout_add_seconds_full(
                                                        G_PRIORITY_HIGH, 3,
                                                        restart_dhcp_timeout,
@@ -2655,6 +2716,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
        uint32_t addr;
        uint64_t rand;
 
+#if defined TIZEN_EXT
+       int discover_retry = 0;
+       int timeout = 0;
+#endif
+
        remove_timeouts(dhcp_client);
 
        if (dhcp_client->type == G_DHCP_IPV6) {
@@ -2741,13 +2807,32 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
                return 0;
        }
 
+#if defined TIZEN_EXT
+       if (g_ascii_strncasecmp(dhcp_client->interface, "wlan", 4)
+                       == 0) {
+               discover_retry = DISCOVER_RETRIES_WIFI;
+               timeout = DISCOVER_TIMEOUT_WIFI;
+       } else {
+               discover_retry = DISCOVER_RETRIES;
+               timeout = DISCOVER_TIMEOUT;
+       }
+
+       debug(dhcp_client, "[DHCPC] Discover retry/total : [%d]/[%d] timeout [%d]",
+                       dhcp_client->retry_times, discover_retry, timeout);
+#endif
+
+
        if (dhcp_client->type == G_DHCP_IPV4LL) {
                dhcp_client->state = INIT_SELECTING;
                ipv4ll_start(dhcp_client);
                return 0;
        }
 
-       if (dhcp_client->retry_times == DISCOVER_RETRIES) {
+#if defined TIZEN_EXT
+               if (dhcp_client->retry_times == discover_retry) {
+#else
+               if (dhcp_client->retry_times == DISCOVER_RETRIES) {
+#endif
                if (dhcp_client->no_lease_cb)
                        dhcp_client->no_lease_cb(dhcp_client,
                                                dhcp_client->no_lease_data);
@@ -2776,7 +2861,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
                if (addr == 0xFFFFFFFF || ((addr & LINKLOCAL_ADDR) ==
                                        LINKLOCAL_ADDR)) {
                        addr = 0;
-               } else {
+               } else if (dhcp_client->last_address != last_address) {
                        g_free(dhcp_client->last_address);
                        dhcp_client->last_address = g_strdup(last_address);
                }
@@ -2790,7 +2875,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
 
                dhcp_client->timeout = g_timeout_add_seconds_full(
                                                                G_PRIORITY_HIGH,
+#if defined TIZEN_EXT
+                                                               timeout,
+#else
                                                                REQUEST_TIMEOUT,
+#endif
                                                                reboot_timeout,
                                                                dhcp_client,
                                                                NULL);
@@ -2799,7 +2888,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
        send_discover(dhcp_client, addr);
 
        dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
+#if defined TIZEN_EXT
+                                                       timeout,
+#else
                                                        DISCOVER_TIMEOUT,
+#endif
                                                        discover_timeout,
                                                        dhcp_client,
                                                        NULL);
@@ -2940,9 +3033,20 @@ char *g_dhcp_client_get_server_address(GDHCPClient *dhcp_client)
        if (!dhcp_client)
                return NULL;
 
+#if defined TIZEN_EXT
+       return get_ip(htonl(dhcp_client->server_ip));
+#else
        return get_ip(dhcp_client->server_ip);
+#endif
 }
 
+#if defined TIZEN_EXT
+int g_dhcp_client_get_dhcp_lease_duration(GDHCPClient *dhcp_client)
+{
+       return dhcp_client->dhcp_lease_seconds;
+}
+#endif
+
 char *g_dhcp_client_get_address(GDHCPClient *dhcp_client)
 {
        return g_strdup(dhcp_client->assigned_ip);
@@ -3055,13 +3159,14 @@ GDHCPClientError g_dhcp_client_set_id(GDHCPClient *dhcp_client)
        return G_DHCP_CLIENT_ERROR_NONE;
 }
 
-/* Now only support send hostname */
+/* Now only support send hostname and vendor class ID */
 GDHCPClientError g_dhcp_client_set_send(GDHCPClient *dhcp_client,
                unsigned char option_code, const char *option_value)
 {
        uint8_t *binary_option;
 
-       if (option_code == G_DHCP_HOST_NAME && option_value) {
+       if ((option_code == G_DHCP_HOST_NAME ||
+               option_code == G_DHCP_VENDOR_CLASS_ID) && option_value) {
                binary_option = alloc_dhcp_string_option(option_code,
                                                        option_value);
                if (!binary_option)
@@ -3205,3 +3310,19 @@ GSList *g_dhcpv6_copy_prefixes(GSList *prefixes)
 
        return copy;
 }
+
+#if defined TIZEN_EXT
+void g_dhcp_client_set_address_known(GDHCPClient *dhcp_client, gboolean known)
+{
+       /* DHCPREQUEST during INIT-REBOOT state (rfc2131)
+        * 4.4.3 Initialization with known network address
+        * 4.3.2 DHCPREQUEST generated during INIT-REBOOT state
+        */
+       debug(dhcp_client, "known network address (%d)", known);
+
+       if (dhcp_client->init_reboot == known)
+               return;
+
+       dhcp_client->init_reboot = known;
+}
+#endif