From 8502ca9a9dff612b067f9df7fe5497a6a6e8647c Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Mon, 20 Mar 2017 15:19:17 +0900 Subject: [PATCH] Implement API to get IPv6 addresses Change-Id: Id7760ec2d038d4492704c92fc7159f6524b46268 Signed-off-by: Seonah Moon --- include/network_interface.h | 6 +++-- src/network_interface.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ src/wifi_ap.c | 38 ++++++++++++++++++++++++++ test/wifi_manager_test.c | 13 ++++++++- 4 files changed, 119 insertions(+), 3 deletions(-) diff --git a/include/network_interface.h b/include/network_interface.h index 3a13463..cd8a47c 100755 --- a/include/network_interface.h +++ b/include/network_interface.h @@ -25,6 +25,9 @@ extern "C" { #endif +#define NET_IPV6_ADDRESS_FILE "/proc/net/if_inet6" +#define NET_IPV6_ADDRESS_FILE_LEN 100 + #define WIFI_INFO 1 #define WIFI_ERROR 2 #define WIFI_WARN 3 @@ -248,8 +251,7 @@ int net_wifi_set_autoscan(gboolean autoscan); int net_wifi_set_background_scan_mode(net_wifi_background_scan_mode_e scan_mode); int net_wifi_get_autoscan(gboolean *autoscan); int net_wifi_get_autoscanmode(unsigned int *autoscanmode); - - +int net_foreach_ipv6_address(GSList **ipv6_address_list); int net_config_get_id_list(GSList **list); int net_config_set_field(const gchar *config_id, const gchar *key, const gchar *value); diff --git a/src/network_interface.c b/src/network_interface.c index 32c2680..e7fffab 100755 --- a/src/network_interface.c +++ b/src/network_interface.c @@ -2806,3 +2806,68 @@ int net_wifi_get_autoscanmode(unsigned int *autoscanmode) __NETWORK_FUNC_EXIT__; return Error; } + +static int __net_convert_string_to_ipv6_string(char *str, char **ip_address) +{ + int i = 1; + int pos = 0; + struct sockaddr_in6 sa; + + *ip_address = (char *)malloc(INET6_ADDRSTRLEN); + if (NULL == *ip_address) { + WIFI_LOG(WIFI_ERROR, "Malloc Failed\n"); + return NET_ERR_INVALID_OPERATION; + } + + /* Convert String without : to string with : */ + for (i = 1; i < 8; i++) { + pos = 4 * i + i; + memmove(str + pos, str + pos - 1, + strlen(str) - pos + 2 * i); + str[pos - 1] = ':'; + } + + /* + * Convert "fe80:0000:0000:0000:0a00:27ff:fe7a:65ea" to fe80::a00:27ff:fe7a:65ea + */ + inet_pton(AF_INET6, str, &(sa.sin6_addr)); + inet_ntop(AF_INET6, &(sa.sin6_addr), *ip_address, INET6_ADDRSTRLEN); + + return NET_ERR_NONE; +} + +int net_foreach_ipv6_address(GSList **ipv6_address_list) +{ + __NETWORK_FUNC_ENTER__; + + FILE *fp = NULL; + char *ip_address = NULL; + char *if_name = NULL; + + char buf[NET_IPV6_ADDRESS_FILE_LEN] = {0, }; + char str[NET_IPV6_ADDRESS_FILE_LEN] = {0, }; + + net_err_e Error = NET_ERR_NONE; + + fp = fopen(NET_IPV6_ADDRESS_FILE, "r"); + if (fp == NULL) { + WIFI_LOG(WIFI_ERROR, "Failed to open file"); + __NETWORK_FUNC_EXIT__; + return NET_ERR_INVALID_OPERATION; + } + + while (fgets(buf, sizeof(buf), fp) != NULL) { + sscanf(buf, "%s", str); + if_name = strstr(buf, "wlan"); + if (if_name != NULL) { + Error = __net_convert_string_to_ipv6_string(str, &ip_address); + if (Error == NET_ERR_NONE) + *ipv6_address_list = g_slist_append(*ipv6_address_list, ip_address); + } + } + + fclose(fp); + + __NETWORK_FUNC_EXIT__; + return Error; +} diff --git a/src/wifi_ap.c b/src/wifi_ap.c index 00e23d5..59a707d 100755 --- a/src/wifi_ap.c +++ b/src/wifi_ap.c @@ -1698,3 +1698,41 @@ EXPORT_API int wifi_manager_ap_get_disconnect_reason(wifi_manager_ap_h ap, return WIFI_MANAGER_ERROR_NONE; } + +EXPORT_API int wifi_manager_ap_foreach_ipv6_address(wifi_manager_ap_h ap, + wifi_manager_ap_ipv6_address_cb callback, void *user_data) +{ + CHECK_FEATURE_SUPPORTED(WIFI_FEATURE); + + GSList *ipv6_address_list = NULL; + int rv = WIFI_MANAGER_ERROR_NONE; + + if (_wifi_check_ap_validity(ap) == false || callback == NULL) { + WIFI_LOG(WIFI_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE + return WIFI_MANAGER_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE + } + + net_profile_info_s *profile_info = ap; + net_state_type_e state = profile_info->ProfileState; + + if (state != NET_STATE_TYPE_READY && state != NET_STATE_TYPE_ONLINE) { + callback(__ap_convert_ip_to_string(&profile_info->net_info.IpAddr, + WIFI_MANAGER_ADDRESS_FAMILY_IPV6), user_data); + return WIFI_MANAGER_ERROR_NONE; + } + + if (net_foreach_ipv6_address(&ipv6_address_list) != NET_ERR_NONE) + return WIFI_MANAGER_ERROR_OPERATION_FAILED; + + GSList *list; + for (list = ipv6_address_list; list; list = list->next) { + rv = callback((char *)list->data, user_data); + if (rv == false) + break; + } + + g_slist_free_full(ipv6_address_list, g_free); + ipv6_address_list = NULL; + + return WIFI_MANAGER_ERROR_NONE; +} diff --git a/test/wifi_manager_test.c b/test/wifi_manager_test.c index 660ab0f..3d53e33 100755 --- a/test/wifi_manager_test.c +++ b/test/wifi_manager_test.c @@ -824,6 +824,12 @@ static bool __test_found_change_proxy_method_callback(wifi_manager_ap_h ap, void return true; } +static bool __test_ipv6_address_callback(char *ipv6_address, void *user_data) +{ + printf("IPv6 address: %s\n", ipv6_address); + return true; +} + static bool __test_found_print_ap_info_callback(wifi_manager_ap_h ap, void *user_data) { int rv, address_type = 0; @@ -909,6 +915,12 @@ static bool __test_found_print_ap_info_callback(wifi_manager_ap_h ap, void *user } else printf("Fail to get IP\n"); + if (address_type == WIFI_MANAGER_ADDRESS_FAMILY_IPV6) { + if (wifi_manager_ap_foreach_ipv6_address(ap, __test_ipv6_address_callback, NULL) + != WIFI_MANAGER_ERROR_NONE) + printf("Fail to get multiple IPv6 address\n"); + } + if (wifi_manager_ap_get_subnet_mask(ap, address_type, &str_value) == WIFI_MANAGER_ERROR_NONE) { printf("Subnet mask : %s\n", str_value); g_free(str_value); @@ -2176,7 +2188,6 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) case 'x': rv = test_wifi_manager_get_autoscan_mode(); break; - default: break; } -- 2.7.4