X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdhcp%2Fclient.c;h=80fdf26588eaf5c0306709363d03da2e0bbc5270;hb=38681c4833c5e1def43efac3afee023abebe3110;hp=9b2de9db4686c0a00b85ef3d500fdde70c7c2710;hpb=74b79a30bb7d74d9b7d3ff0e8dd122f64e847e5f;p=platform%2Fupstream%2Fconnman.git diff --git a/gdhcp/client.c b/gdhcp/client.c index 9b2de9d..80fdf26 100755 --- a/gdhcp/client.c +++ b/gdhcp/client.c @@ -23,7 +23,6 @@ #include #endif -#define _GNU_SOURCE #include #include #include @@ -43,16 +42,38 @@ #include +#include "../src/connman.h" +#include "../src/shared/arp.h" #include "gdhcp.h" #include "common.h" -#include "ipv4ll.h" #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, @@ -65,6 +86,7 @@ typedef enum _dhcp_client_state { REBOOTING, REQUESTING, BOUND, + DECLINED, RENEWING, REBINDING, RELEASED, @@ -109,6 +131,7 @@ struct _GDHCPClient { GList *request_list; GHashTable *code_value_hash; GHashTable *send_value_hash; + GHashTable *secs_bcast_hash; GDHCPClientEventFunc lease_available_cb; gpointer lease_available_data; GDHCPClientEventFunc ipv4ll_available_cb; @@ -157,6 +180,7 @@ struct _GDHCPClient { struct timeval start_time; bool request_bcast; #if defined TIZEN_EXT + uint32_t dhcp_lease_seconds; gboolean init_reboot; #endif }; @@ -467,10 +491,40 @@ static int send_discover(GDHCPClient *dhcp_client, uint32_t requested) * versa. In the receiving side we then find out what kind of packet * the server can send. */ + dhcp_client->request_bcast = dhcp_client->retry_times % 2; + + if (dhcp_client->request_bcast) + g_hash_table_add(dhcp_client->secs_bcast_hash, + GINT_TO_POINTER(packet.secs)); + return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcp_client->ifindex, - dhcp_client->retry_times % 2); + dhcp_client->request_bcast); +} + +int g_dhcp_client_decline(GDHCPClient *dhcp_client, uint32_t requested) +{ + struct dhcp_packet packet; + + dhcp_client->state = DECLINED; + dhcp_client->retry_times = 0; + + debug(dhcp_client, "sending DHCP decline"); + + init_packet(dhcp_client, &packet, DHCPDECLINE); + + packet.xid = dhcp_client->xid; + packet.secs = dhcp_attempt_secs(dhcp_client); + + if (requested) + dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP, requested); + + add_send_options(dhcp_client, &packet); + + return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, + INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, + dhcp_client->ifindex, true); } static int send_request(GDHCPClient *dhcp_client) @@ -508,7 +562,8 @@ static int send_request(GDHCPClient *dhcp_client) if (dhcp_client->state == RENEWING) return dhcp_send_kernel_packet(&packet, dhcp_client->requested_ip, CLIENT_PORT, - dhcp_client->server_ip, SERVER_PORT); + dhcp_client->server_ip, SERVER_PORT, + dhcp_client->interface); return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, @@ -525,14 +580,15 @@ static int send_release(GDHCPClient *dhcp_client, debug(dhcp_client, "sending DHCP release request"); init_packet(dhcp_client, &packet, DHCPRELEASE); - dhcp_get_random(&rand); + __connman_util_get_random(&rand); packet.xid = rand; packet.ciaddr = htonl(ciaddr); dhcp_add_option_uint32(&packet, DHCP_SERVER_ID, server); return dhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, - server, SERVER_PORT); + server, SERVER_PORT, + dhcp_client->interface); } static gboolean ipv4ll_probe_timeout(gpointer dhcp_data); @@ -548,7 +604,7 @@ static gboolean send_probe_packet(gpointer dhcp_data) /* if requested_ip is not valid, pick a new address*/ if (dhcp_client->requested_ip == 0) { debug(dhcp_client, "pick a new random address"); - dhcp_client->requested_ip = ipv4ll_random_ip(); + dhcp_client->requested_ip = arp_random_ip(); } debug(dhcp_client, "sending IPV4LL probe request"); @@ -557,12 +613,12 @@ static gboolean send_probe_packet(gpointer dhcp_data) dhcp_client->state = IPV4LL_PROBE; switch_listening_mode(dhcp_client, L_ARP); } - ipv4ll_send_arp_packet(dhcp_client->mac_address, 0, + arp_send_packet(dhcp_client->mac_address, 0, dhcp_client->requested_ip, dhcp_client->ifindex); if (dhcp_client->retry_times < PROBE_NUM) { /*add a random timeout in range of PROBE_MIN to PROBE_MAX*/ - timeout = ipv4ll_random_delay_ms(PROBE_MAX-PROBE_MIN); + timeout = __connman_util_random_delay_ms(PROBE_MAX-PROBE_MIN); timeout += PROBE_MIN*1000; } else timeout = (ANNOUNCE_WAIT * 1000); @@ -586,7 +642,7 @@ static gboolean send_announce_packet(gpointer dhcp_data) debug(dhcp_client, "sending IPV4LL announce request"); - ipv4ll_send_arp_packet(dhcp_client->mac_address, + arp_send_packet(dhcp_client->mac_address, dhcp_client->requested_ip, dhcp_client->requested_ip, dhcp_client->ifindex); @@ -611,38 +667,6 @@ static gboolean send_announce_packet(gpointer dhcp_data) return TRUE; } -static void get_interface_mac_address(int index, uint8_t *mac_address) -{ - struct ifreq ifr; - int sk, err; - - sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (sk < 0) { - perror("Open socket error"); - return; - } - - 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, SIOCGIFHWADDR, &ifr); - if (err < 0) { - perror("Get mac address error"); - goto done; - } - - memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6); - -done: - close(sk); -} - void g_dhcpv6_client_set_retransmit(GDHCPClient *dhcp_client) { if (!dhcp_client) @@ -673,7 +697,7 @@ int g_dhcpv6_create_duid(GDHCPDuidType duid_type, int index, int type, (*duid)[0] = 0; (*duid)[1] = 1; - get_interface_mac_address(index, &(*duid)[2 + 2 + 4]); + __connman_inet_get_interface_mac_address(index, &(*duid)[2 + 2 + 4]); (*duid)[2] = 0; (*duid)[3] = type; duid_time = time(NULL) - DUID_TIME_EPOCH; @@ -692,7 +716,7 @@ int g_dhcpv6_create_duid(GDHCPDuidType duid_type, int index, int type, (*duid)[0] = 0; (*duid)[1] = 3; - get_interface_mac_address(index, &(*duid)[2 + 2]); + __connman_inet_get_interface_mac_address(index, &(*duid)[2 + 2]); (*duid)[2] = 0; (*duid)[3] = type; break; @@ -817,7 +841,7 @@ void g_dhcpv6_client_create_iaid(GDHCPClient *dhcp_client, int index, { uint8_t buf[6]; - get_interface_mac_address(index, buf); + __connman_inet_get_interface_mac_address(index, buf); memcpy(iaid, &buf[2], 4); dhcp_client->iaid = iaid[0] << 24 | @@ -833,16 +857,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; } @@ -1181,7 +1208,7 @@ GDHCPClient *g_dhcp_client_new(GDHCPType type, goto error; } - get_interface_mac_address(ifindex, dhcp_client->mac_address); + __connman_inet_get_interface_mac_address(ifindex, dhcp_client->mac_address); dhcp_client->listener_sockfd = -1; dhcp_client->listen_mode = L_NONE; @@ -1201,6 +1228,8 @@ GDHCPClient *g_dhcp_client_new(GDHCPType type, g_direct_equal, NULL, remove_option_value); dhcp_client->send_value_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); + dhcp_client->secs_bcast_hash = g_hash_table_new(g_direct_hash, + g_direct_equal); dhcp_client->request_list = NULL; dhcp_client->require_list = NULL; dhcp_client->duid = NULL; @@ -1272,7 +1301,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; @@ -1376,10 +1405,10 @@ static void ipv4ll_start(GDHCPClient *dhcp_client) dhcp_client->retry_times = 0; dhcp_client->requested_ip = 0; - dhcp_client->requested_ip = ipv4ll_random_ip(); + dhcp_client->requested_ip = arp_random_ip(); /*first wait a random delay to avoid storm of arp request on boot*/ - timeout = ipv4ll_random_delay_ms(PROBE_WAIT); + timeout = __connman_util_random_delay_ms(PROBE_WAIT); dhcp_client->retry_times++; dhcp_client->timeout = g_timeout_add_full(G_PRIORITY_HIGH, @@ -1416,6 +1445,7 @@ static int ipv4ll_recv_arp_packet(GDHCPClient *dhcp_client) uint32_t ip_requested; int source_conflict; int target_conflict; + guint timeout_ms; memset(&arp, 0, sizeof(arp)); bytes = read(dhcp_client->listener_sockfd, &arp, sizeof(arp)); @@ -1426,6 +1456,9 @@ static int ipv4ll_recv_arp_packet(GDHCPClient *dhcp_client) arp.arp_op != htons(ARPOP_REQUEST)) return -EINVAL; + if (memcmp(arp.arp_sha, dhcp_client->mac_address, ETH_ALEN) == 0) + return 0; + ip_requested = htonl(dhcp_client->requested_ip); source_conflict = !memcmp(arp.arp_spa, &ip_requested, sizeof(ip_requested)); @@ -1461,23 +1494,20 @@ static int ipv4ll_recv_arp_packet(GDHCPClient *dhcp_client) ipv4ll_stop(dhcp_client); - if (dhcp_client->conflicts < MAX_CONFLICTS) { - /*restart whole state machine*/ - dhcp_client->retry_times++; - dhcp_client->timeout = - g_timeout_add_full(G_PRIORITY_HIGH, - ipv4ll_random_delay_ms(PROBE_WAIT), - send_probe_packet, - dhcp_client, - NULL); - } - /* Here we got a lot of conflicts, RFC3927 states that we have + /* If we got a lot of conflicts, RFC3927 states that we have * to wait RATE_LIMIT_INTERVAL before retrying, - * but we just report failure. */ - else if (dhcp_client->no_lease_cb) - dhcp_client->no_lease_cb(dhcp_client, - dhcp_client->no_lease_data); + if (dhcp_client->conflicts < MAX_CONFLICTS) + timeout_ms = __connman_util_random_delay_ms(PROBE_WAIT); + else + timeout_ms = RATE_LIMIT_INTERVAL * 1000; + dhcp_client->retry_times++; + dhcp_client->timeout = + g_timeout_add_full(G_PRIORITY_HIGH, + timeout_ms, + send_probe_packet, + dhcp_client, + NULL); return 0; } @@ -1544,6 +1574,12 @@ static gboolean request_timeout(gpointer user_data) return FALSE; } +static void listener_watch_destroy(gpointer user_data) +{ + GDHCPClient *dhcp_client = user_data; + g_dhcp_client_unref(dhcp_client); +} + static gboolean listener_event(GIOChannel *channel, GIOCondition condition, gpointer user_data); @@ -1582,7 +1618,7 @@ static int switch_listening_mode(GDHCPClient *dhcp_client, dhcp_client->interface, AF_INET); } else if (listen_mode == L_ARP) - listener_sockfd = ipv4ll_arp_socket(dhcp_client->ifindex); + listener_sockfd = arp_socket(dhcp_client->ifindex); else return -EIO; @@ -1603,8 +1639,8 @@ static int switch_listening_mode(GDHCPClient *dhcp_client, dhcp_client->listener_watch = g_io_add_watch_full(listener_channel, G_PRIORITY_HIGH, G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP, - listener_event, dhcp_client, - NULL); + listener_event, g_dhcp_client_ref(dhcp_client), + listener_watch_destroy); g_io_channel_unref(listener_channel); return 0; @@ -1646,8 +1682,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; @@ -1695,13 +1730,15 @@ 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; if (dhcp_client->T2 > 60) { - dhcp_get_random(&rand); + __connman_util_get_random(&rand); dhcp_client->t2_timeout = g_timeout_add_full(G_PRIORITY_HIGH, dhcp_client->T2 * 1000 + (rand % 2000) - 1000, @@ -1749,7 +1786,7 @@ static gboolean continue_renew (gpointer user_data) dhcp_client->T1 >>= 1; if (dhcp_client->T1 > 60) { - dhcp_get_random(&rand); + __connman_util_get_random(&rand); dhcp_client->t1_timeout = g_timeout_add_full(G_PRIORITY_HIGH, dhcp_client->T1 * 1000 + (rand % 2000) - 1000, continue_renew, @@ -1834,6 +1871,71 @@ static char *get_ip(uint32_t ip) return g_strdup(inet_ntoa(addr)); } +/* get a rough idea of how long an option will be */ +static const uint8_t len_of_option_as_string[] = { + [OPTION_IP] = sizeof("255.255.255.255 "), + [OPTION_STRING] = 1, + [OPTION_U8] = sizeof("255 "), + [OPTION_U16] = sizeof("65535 "), + [OPTION_U32] = sizeof("4294967295 "), +}; + +static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) +{ + return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); +} + +/* Create "opt_value1 option_value2 ..." string */ +static char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type) +{ + unsigned upper_length; + int len, optlen; + char *dest, *ret; + + len = option[OPT_LEN - OPT_DATA]; + type &= OPTION_TYPE_MASK; + optlen = dhcp_option_lengths[type]; + if (optlen == 0) + return NULL; + upper_length = len_of_option_as_string[type] * + ((unsigned)len / (unsigned)optlen); + dest = ret = g_malloc(upper_length + 1); + if (!ret) + return NULL; + + while (len >= optlen) { + switch (type) { + case OPTION_IP: + dest += sprint_nip(dest, "", option); + break; + case OPTION_U16: { + uint16_t val_u16 = get_be16(option); + dest += sprintf(dest, "%u", val_u16); + break; + } + case OPTION_U32: { + uint32_t val_u32 = get_be32(option); + dest += sprintf(dest, "%u", val_u32); + break; + } + case OPTION_STRING: + memcpy(dest, option, len); + dest[len] = '\0'; + return ret; + default: + break; + } + option += optlen; + len -= optlen; + if (len <= 0) + break; + *dest++ = ' '; + *dest = '\0'; + } + + return ret; +} + static GList *get_option_value_list(char *value, GDHCPOptionType type) { char *pos = value; @@ -2224,6 +2326,14 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { dhcp_client->listener_watch = 0; +#if defined TIZEN_EXT + /* re-register event listener when socket failed */ + int retry_count = 0; + int ret = -1; + while (retry_count++ < GIO_SOCKET_RETRY_COUNT && ret < 0) + ret = switch_listening_mode(dhcp_client, + dhcp_client->type); +#endif /* defined TIZEN_EXT */ return FALSE; } @@ -2243,6 +2353,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 | @@ -2305,10 +2417,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); @@ -2327,14 +2435,28 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, dhcp_client->state = REQUESTING; - if (dst_addr.sin_addr.s_addr == INADDR_BROADCAST) - dhcp_client->request_bcast = true; - else - dhcp_client->request_bcast = false; + /* + * RFC2131: + * + * If unicasting is not possible, the message MAY be + * sent as an IP broadcast using an IP broadcast address + * (preferably 0xffffffff) as the IP destination address + * and the link-layer broadcast address as the link-layer + * destination address. + * + * For interoperability reasons, if the response is an IP + * broadcast, let's reuse broadcast flag from DHCPDISCOVER + * to which the server has responded. Some servers are picky + * about this flag. + */ + dhcp_client->request_bcast = + dst_addr.sin_addr.s_addr == INADDR_BROADCAST && + g_hash_table_contains(dhcp_client->secs_bcast_hash, + GINT_TO_POINTER(packet.secs)); - debug(dhcp_client, "init ip %s -> %sadding broadcast flag", - inet_ntoa(dst_addr.sin_addr), - dhcp_client->request_bcast ? "" : "not "); + debug(dhcp_client, "init ip %s secs %hu -> broadcast flag %s", + inet_ntoa(dst_addr.sin_addr), packet.secs, + dhcp_client->request_bcast ? "on" : "off"); start_request(dhcp_client); @@ -2359,6 +2481,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); @@ -2687,6 +2813,12 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) int re; uint32_t addr; uint64_t rand; + ClientState oldstate = dhcp_client->state; + +#if defined TIZEN_EXT + int discover_retry = 0; + int timeout = 0; +#endif remove_timeouts(dhcp_client); @@ -2774,13 +2906,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 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); @@ -2797,12 +2948,13 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) if (re != 0) return re; - dhcp_get_random(&rand); + __connman_util_get_random(&rand); dhcp_client->xid = rand; dhcp_client->start = time(NULL); + g_hash_table_remove_all(dhcp_client->secs_bcast_hash); } - if (!last_address) { + if (!last_address || oldstate == DECLINED) { addr = 0; } else { addr = ntohl(inet_addr(last_address)); @@ -2823,7 +2975,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); @@ -2832,7 +2988,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); @@ -2973,9 +3133,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); @@ -3002,6 +3173,7 @@ char *g_dhcp_client_get_netmask(GDHCPClient *dhcp_client) case REBOOTING: case REQUESTING: case RELEASED: + case DECLINED: case IPV4LL_PROBE: case IPV4LL_ANNOUNCE: case INFORMATION_REQ: @@ -3088,13 +3260,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) @@ -3198,6 +3371,7 @@ void g_dhcp_client_unref(GDHCPClient *dhcp_client) g_hash_table_destroy(dhcp_client->code_value_hash); g_hash_table_destroy(dhcp_client->send_value_hash); + g_hash_table_destroy(dhcp_client->secs_bcast_hash); g_free(dhcp_client); #if defined TIZEN_EXT