gdhcp: Fix spelling mistake
[framework/connectivity/connman.git] / gdhcp / client.c
index 7be3d3d..55810d5 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <netpacket/packet.h>
 #include <net/ethernet.h>
-#include <net/if_arp.h>
 
 #include <linux/if.h>
 #include <linux/filter.h>
 #include "common.h"
 
 #define DISCOVER_TIMEOUT 3
-#define DISCOVER_RETRIES 3
+#define DISCOVER_RETRIES 10
 
 #define REQUEST_TIMEOUT 3
-#define REQUEST_RETRIES 3
+#define REQUEST_RETRIES 5
 
 typedef enum _listen_mode {
        L_NONE,
@@ -99,7 +98,21 @@ struct _GDHCPClient {
        gpointer debug_data;
 };
 
-static GTimer *timer = NULL;
+static inline void debug(GDHCPClient *client, const char *format, ...)
+{
+       char str[256];
+       va_list ap;
+
+       if (client->debug_func == NULL)
+               return;
+
+       va_start(ap, format);
+
+       if (vsnprintf(str, sizeof(str), format, ap) > 0)
+               client->debug_func(str, client->debug_data);
+
+       va_end(ap);
+}
 
 /* Initialize the packet with the proper defaults */
 static void init_packet(GDHCPClient *dhcp_client,
@@ -151,6 +164,8 @@ static int send_discover(GDHCPClient *dhcp_client, uint32_t requested)
 {
        struct dhcp_packet packet;
 
+       debug(dhcp_client, "sending DHCP discover request");
+
        init_packet(dhcp_client, &packet, DHCPDISCOVER);
 
        packet.xid = dhcp_client->xid;
@@ -176,6 +191,8 @@ static int send_select(GDHCPClient *dhcp_client)
        struct dhcp_packet packet;
        struct in_addr addr;
 
+       debug(dhcp_client, "sending DHCP select request");
+
        init_packet(dhcp_client, &packet, DHCPREQUEST);
 
        packet.xid = dhcp_client->xid;
@@ -199,6 +216,8 @@ static int send_renew(GDHCPClient *dhcp_client)
 {
        struct dhcp_packet packet;
 
+       debug(dhcp_client, "sending DHCP renew request");
+
        init_packet(dhcp_client , &packet, DHCPREQUEST);
        packet.xid = dhcp_client->xid;
        packet.ciaddr = dhcp_client->requested_ip;
@@ -216,6 +235,8 @@ static int send_rebound(GDHCPClient *dhcp_client)
 {
        struct dhcp_packet packet;
 
+       debug(dhcp_client, "sending DHCP rebound request");
+
        init_packet(dhcp_client , &packet, DHCPREQUEST);
        packet.xid = dhcp_client->xid;
        packet.ciaddr = dhcp_client->requested_ip;
@@ -234,6 +255,8 @@ static int send_release(GDHCPClient *dhcp_client,
 {
        struct dhcp_packet packet;
 
+       debug(dhcp_client, "sending DHCP release request");
+
        init_packet(dhcp_client, &packet, DHCPRELEASE);
        packet.xid = rand();
        packet.ciaddr = ciaddr;
@@ -244,70 +267,7 @@ static int send_release(GDHCPClient *dhcp_client,
                                                server, SERVER_PORT);
 }
 
-static gboolean interface_is_up(int index)
-{
-       int sk, err;
-       struct ifreq ifr;
-       gboolean ret = FALSE;
-
-       sk = socket(PF_INET, SOCK_DGRAM, 0);
-       if (sk < 0) {
-               perror("Open socket error");
-               return FALSE;
-       }
-
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_ifindex = index;
-
-       err = ioctl(sk, SIOCGIFNAME, &ifr);
-       if (err < 0) {
-               perror("Get interface name error");
-               goto done;
-       }
-
-       err = ioctl(sk, SIOCGIFFLAGS, &ifr);
-       if (err < 0) {
-               perror("Get interface flags error");
-               goto done;
-       }
-
-       if (ifr.ifr_flags & IFF_UP)
-               ret = TRUE;
-
-done:
-       close(sk);
-
-       return ret;
-}
-
-static char *get_interface_name(int index)
-{
-       struct ifreq ifr;
-       int sk, err;
-
-       if (index < 0)
-               return NULL;
-
-       sk = socket(PF_INET, SOCK_DGRAM, 0);
-       if (sk < 0) {
-               perror("Open socket error");
-               return NULL;
-       }
-
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_ifindex = index;
 
-       err = ioctl(sk, SIOCGIFNAME, &ifr);
-       if (err < 0) {
-               perror("Get interface name error");
-               close(sk);
-               return NULL;
-       }
-
-       close(sk);
-
-       return g_strdup(ifr.ifr_name);
-}
 
 static void get_interface_mac_address(int index, uint8_t *mac_address)
 {
@@ -475,6 +435,7 @@ static int dhcp_l2_socket(int ifindex)
                setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
                                                        sizeof(filter_prog));
 
+       memset(&sock, 0, sizeof(sock));
        sock.sll_family = AF_PACKET;
        sock.sll_protocol = htons(ETH_P_IP);
        sock.sll_ifindex = ifindex;
@@ -576,6 +537,9 @@ static gboolean request_timeout(gpointer user_data)
 {
        GDHCPClient *dhcp_client = user_data;
 
+       debug(dhcp_client, "request timeout (retries %d)",
+                                       dhcp_client->retry_times);
+
        dhcp_client->retry_times++;
 
        start_request(dhcp_client);
@@ -592,6 +556,9 @@ static int switch_listening_mode(GDHCPClient *dhcp_client,
        GIOChannel *listener_channel;
        int listener_sockfd;
 
+       debug(dhcp_client, "switch listening mode (%d ==> %d)",
+                               dhcp_client->listen_mode, listen_mode);
+
        if (dhcp_client->listen_mode == listen_mode)
                return 0;
 
@@ -641,6 +608,9 @@ static int switch_listening_mode(GDHCPClient *dhcp_client,
 
 static void start_request(GDHCPClient *dhcp_client)
 {
+       debug(dhcp_client, "start request (retries %d)",
+                                       dhcp_client->retry_times);
+
        if (dhcp_client->retry_times == REQUEST_RETRIES) {
                dhcp_client->state = INIT_SELECTING;
 
@@ -686,6 +656,8 @@ static uint32_t get_lease(struct dhcp_packet *packet)
 
 static void restart_dhcp(GDHCPClient *dhcp_client, int retry_times)
 {
+       debug(dhcp_client, "restart DHCP (retries %d)", retry_times);
+
        if (dhcp_client->timeout > 0) {
                g_source_remove(dhcp_client->timeout);
                dhcp_client->timeout = 0;
@@ -702,6 +674,8 @@ static gboolean start_rebound_timeout(gpointer user_data)
 {
        GDHCPClient *dhcp_client = user_data;
 
+       debug(dhcp_client, "start rebound timeout");
+
        switch_listening_mode(dhcp_client, L2);
 
        dhcp_client->lease_seconds >>= 1;
@@ -731,6 +705,8 @@ static gboolean start_rebound_timeout(gpointer user_data)
 
 static void start_rebound(GDHCPClient *dhcp_client)
 {
+       debug(dhcp_client, "start rebound");
+
        dhcp_client->state = REBINDING;
 
        dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
@@ -743,12 +719,8 @@ static void start_rebound(GDHCPClient *dhcp_client)
 static gboolean start_renew_timeout(gpointer user_data)
 {
        GDHCPClient *dhcp_client = user_data;
-       gdouble elapse;
-       gulong microseconds;
 
-       elapse = g_timer_elapsed(timer, &microseconds);
-
-       g_timer_start(timer);
+       debug(dhcp_client, "start renew timeout");
 
        dhcp_client->state = RENEWING;
 
@@ -773,13 +745,11 @@ static gboolean start_renew_timeout(gpointer user_data)
 
 static void start_bound(GDHCPClient *dhcp_client)
 {
-       dhcp_client->state = BOUND;
+       debug(dhcp_client, "start bound");
 
-       if (timer == NULL)
-               timer = g_timer_new();
+       dhcp_client->state = BOUND;
 
-       dhcp_client->timeout =
-                       g_timeout_add_seconds_full(G_PRIORITY_HIGH,
+       dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
                                        dhcp_client->lease_seconds >> 1,
                                        start_renew_timeout, dhcp_client,
                                                        NULL);
@@ -789,6 +759,8 @@ static gboolean restart_dhcp_timeout(gpointer user_data)
 {
        GDHCPClient *dhcp_client = user_data;
 
+       debug(dhcp_client, "restart DHCP timeout");
+
        dhcp_client->ack_retry_times++;
 
        restart_dhcp(dhcp_client, dhcp_client->ack_retry_times);
@@ -873,20 +845,26 @@ static char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type)
        return ret;
 }
 
-static GList *get_option_value_list(char *value)
+static GList *get_option_value_list(char *value, GDHCPOptionType type)
 {
        char *pos = value;
        GList *list = NULL;
 
+       if (pos == NULL)
+               return NULL;
+
+       if (type == OPTION_STRING)
+               return g_list_append(list, g_strdup(value));
+
        while ((pos = strchr(pos, ' ')) != NULL) {
                *pos = '\0';
 
-               list =  g_list_append(list, g_strdup(value));
+               list = g_list_append(list, g_strdup(value));
 
                value = ++pos;
        }
 
-       list =  g_list_append(list, g_strdup(value));
+       list = g_list_append(list, g_strdup(value));
 
        return list;
 }
@@ -916,7 +894,7 @@ static void get_request(GDHCPClient *dhcp_client, struct dhcp_packet *packet)
                        g_hash_table_remove(dhcp_client->code_value_hash,
                                                GINT_TO_POINTER((int) code));
 
-               value_list = get_option_value_list(option_value);
+               value_list = get_option_value_list(option_value, type);
 
                g_free(option_value);
 
@@ -960,9 +938,12 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
 
        message_type = dhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
        if (message_type == NULL)
-               /* No message type option, ignore pakcage */
+               /* No message type option, ignore package */
                return TRUE;
 
+       debug(dhcp_client, "received DHCP packet (current state %d)",
+                                                       dhcp_client->state);
+
        switch (dhcp_client->state) {
        case INIT_SELECTING:
                if (*message_type != DHCPOFFER)
@@ -1025,6 +1006,9 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                break;
        }
 
+       debug(dhcp_client, "processed DHCP packet (new state %d)",
+                                                       dhcp_client->state);
+
        return TRUE;
 }
 
@@ -1170,32 +1154,15 @@ static uint8_t *alloc_dhcp_option(int code, const char *str, int extra)
        return storage;
 }
 
-static const char *get_hostname(const char *host)
-{
-       char local_host_name[HOST_NAME_MAX + 1];
-
-       if (g_strcmp0("<hostname>", host) != 0)
-               return g_strdup(host);
-
-       if (gethostname(local_host_name, HOST_NAME_MAX) != 0)
-               return NULL;
-
-       local_host_name[HOST_NAME_MAX] = 0;
-
-       return g_strdup(local_host_name);
-}
-
 /* Now only support send hostname */
 GDHCPClientError g_dhcp_client_set_send(GDHCPClient *dhcp_client,
                unsigned char option_code, const char *option_value)
 {
        uint8_t *binary_option;
-       const char *hostname;
 
-       if (option_code == G_DHCP_HOST_NAME) {
-               hostname = get_hostname(option_value);
-
-               binary_option = alloc_dhcp_option(option_code, hostname, 0);
+       if (option_code == G_DHCP_HOST_NAME && option_value != NULL) {
+               binary_option = alloc_dhcp_option(option_code,
+                                                       option_value, 0);
 
                g_hash_table_insert(dhcp_client->send_value_hash,
                        GINT_TO_POINTER((int) option_code), binary_option);
@@ -1204,13 +1171,21 @@ GDHCPClientError g_dhcp_client_set_send(GDHCPClient *dhcp_client,
        return G_DHCP_CLIENT_ERROR_NONE;
 }
 
-void g_dhcp_client_ref(GDHCPClient *dhcp_client)
+GDHCPClient *g_dhcp_client_ref(GDHCPClient *dhcp_client)
 {
+       if (dhcp_client == NULL)
+               return NULL;
+
        g_atomic_int_inc(&dhcp_client->ref_count);
+
+       return dhcp_client;
 }
 
 void g_dhcp_client_unref(GDHCPClient *dhcp_client)
 {
+       if (dhcp_client == NULL)
+               return;
+
        if (g_atomic_int_dec_and_test(&dhcp_client->ref_count) == FALSE)
                return;
 
@@ -1229,8 +1204,11 @@ void g_dhcp_client_unref(GDHCPClient *dhcp_client)
 }
 
 void g_dhcp_client_set_debug(GDHCPClient *dhcp_client,
-                               GDHCPDebugFunc func, gpointer data)
+                               GDHCPDebugFunc func, gpointer user_data)
 {
+       if (dhcp_client == NULL)
+               return;
+
        dhcp_client->debug_func = func;
-       dhcp_client->debug_data = data;
+       dhcp_client->debug_data = user_data;
 }