Add APIs to support DHCP state changes 14/293814/4
authorJaehyun Kim <jeik01.kim@samsung.com>
Mon, 5 Jun 2023 11:39:16 +0000 (20:39 +0900)
committerJaehyun Kim <jeik01.kim@samsung.com>
Mon, 19 Jun 2023 07:39:43 +0000 (16:39 +0900)
Change-Id: I8ee7c017cb8e54ebf9b686f1af4be4d4726d8bf0
Signed-off-by: Jaehyun Kim <jeik01.kim@samsung.com>
include/net_connection.h
include/net_connection_private.h
packaging/capi-network-connection.spec
src/connection.c
src/libnetwork.c
test/connection_test.c

index bac6d31..941af40 100755 (executable)
@@ -151,6 +151,15 @@ typedef enum {
        CONNECTION_ETHERNET_CABLE_ATTACHED = 1,   /**< Ethernet cable is attached */
 } connection_ethernet_cable_state_e;
 
+/**
+ * @brief Enumeration for the DHCP state.
+ * @since_tizen 8.0
+ */
+typedef enum {
+       CONNECTION_DHCP_STATE_UNKNOWN = 0,  /**< Unknown state */
+       CONNECTION_DHCP_STATE_STARTED = 1,  /**< DHCP is running */
+       CONNECTION_DHCP_STATE_FINISHED = 2, /**< DHCP is finished */
+} connection_dhcp_state_e;
 
 /**
  * @brief Enumeration for connection errors.
@@ -375,6 +384,19 @@ typedef void(*connection_set_default_cb)(connection_error_e result, void* user_d
 typedef bool(*connection_ipv6_address_cb)(char *ipv6_address, void *user_data);
 
 /**
+ * @brief Called when the DHCP state is changed.
+ * @since_tizen 8.0
+ * @param[in]  state            The DHCP state
+ * @param[in]  interface_name   The interface name with DHCP state change
+ * @param[in]  result           The result of DHCP operation
+ * @param[in]  user_data        The user data passed from the callback registration function
+ * @see  connection_set_dhcp_state_changed_cb()
+ * @see  connection_unset_dhcp_state_changed_cb()
+ */
+typedef void(*connection_dhcp_state_changed_cb)(connection_dhcp_state_e state,
+            const char *interface_name, connection_error_e result, void *user_data);
+
+/**
  * @brief Gets the type of the current profile for data connection.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @param[in] connection        The connection handle
@@ -526,6 +548,7 @@ int connection_get_wifi_state(connection_h connection, connection_wifi_state_e*
  */
 int connection_get_ethernet_state(connection_h connection, connection_ethernet_state_e* state);
 
+
 /**
  * @brief Called when the Internet state of the current connection is changed.
  * @since_tizen 5.5
@@ -589,6 +612,26 @@ int connection_get_ethernet_cable_state(connection_h connection,
 
 
 /**
+ * @brief Gets the DHCP state of the interface.
+ * @since_tizen 8.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/network.get
+ * @param[in] connection        The connection handle
+ * @param[in] interface_name    The interface name
+ * @param[out] state            The DHCP state of the interface
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #CONNECTION_ERROR_NONE                  Successful
+ * @retval #CONNECTION_ERROR_INVALID_PARAMETER     Invalid parameter
+ * @retval #CONNECTION_ERROR_OPERATION_FAILED      Operation failed
+ * @retval #CONNECTION_ERROR_PERMISSION_DENIED     Permission denied
+ * @retval #CONNECTION_ERROR_NOT_SUPPORTED         Not supported
+ */
+int connection_get_dhcp_state(connection_h connection,
+               const char *interface_name, connection_dhcp_state_e *state);
+
+
+/**
  * @deprecated Deprecated since 4.0. Use connection_ethernet_cable_state_changed_cb() instead.
  * @brief Called when ethernet cable is plugged [in/out].
  * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
@@ -796,6 +839,39 @@ int connection_unset_proxy_address_changed_cb(connection_h connection);
 
 
 /**
+ * @brief Sets the callback that is called when the DHCP state is changed.
+ * @since_tizen 8.0
+ * @param[in] connection        The connection handle
+ * @param[in] callback          The callback function to be called
+ * @param[in] user_data         The user data passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #CONNECTION_ERROR_NONE                  Successful
+ * @retval #CONNECTION_ERROR_NOT_INITIALIZED       Not initialized
+ * @retval #CONNECTION_ERROR_INVALID_PARAMETER     Invalid parameter
+ * @retval #CONNECTION_ERROR_OPERATION_FAILED      Operation failed
+ * @retval #CONNECTION_ERROR_NOT_SUPPORTED         Not supported
+ */
+int connection_set_dhcp_state_changed_cb(connection_h connection,
+               connection_dhcp_state_changed_cb callback, void *user_data);
+
+
+/**
+ * @brief Unsets the callback that is called when the DHCP state is changed.
+ * @since_tizen 8.0
+ * @param[in] connection        The connection handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #CONNECTION_ERROR_NONE                  Successful
+ * @retval #CONNECTION_ERROR_NOT_INITIALIZED       Not initialized
+ * @retval #CONNECTION_ERROR_INVALID_PARAMETER     Invalid parameter
+ * @retval #CONNECTION_ERROR_OPERATION_FAILED      Operation failed
+ * @retval #CONNECTION_ERROR_NOT_SUPPORTED         Not supported
+ */
+int connection_unset_dhcp_state_changed_cb(connection_h connection);
+
+
+/**
  * @brief Adds a new profile which is created by connection_profile_create().
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @privlevel public
index 1b2c74f..8085f31 100755 (executable)
@@ -120,6 +120,7 @@ typedef struct _connection_handle_s {
        connection_address_changed_cb proxy_changed_callback;
        connection_internet_state_changed_cb internet_state_changed_callback;
        connection_ethernet_cable_state_changed_cb ethernet_cable_state_changed_callback;
+       connection_dhcp_state_changed_cb dhcp_state_changed_callback;
        connection_set_default_cb set_default_callback;
        connection_opened_cb opened_callback;
        connection_closed_cb closed_callback;
@@ -129,6 +130,7 @@ typedef struct _connection_handle_s {
        void *proxy_changed_user_data;
        void *internet_state_changed_user_data;
        void *ethernet_cable_state_changed_user_data;
+       void *dhcp_state_changed_user_data;
        void *set_default_user_data;
        void *opened_user_data;
        void *closed_user_data;
@@ -152,6 +154,8 @@ int _connection_libnet_get_ethernet_state(connection_handle_s *conn_handle,
                        connection_ethernet_state_e *state);
 int _connection_libnet_get_ethernet_cable_state(connection_handle_s *conn_handle,
                        connection_ethernet_cable_state_e* state);
+int _connection_libnet_get_dhcp_state(connection_handle_s *conn_handle,
+                       const char *interface_name, connection_dhcp_state_e *state);
 int _connection_libnet_get_bluetooth_state(connection_handle_s *conn_handle, connection_bt_state_e* state);
 bool _connection_libnet_check_profile_validity(connection_profile_h profile);
 int _connection_libnet_get_profile_iterator(connection_handle_s *conn_handle,
index a53cc23..ba2906b 100755 (executable)
@@ -1,6 +1,6 @@
 Name:          capi-network-connection
 Summary:       Network Connection library in TIZEN C API
-Version:       1.0.125
+Version:       1.0.126
 Release:       0
 Group:         System/Network
 License:       Apache-2.0
index 0d33571..898b574 100755 (executable)
@@ -153,6 +153,22 @@ static void __connection_set_proxy_changed_callback(connection_handle_s *conn_ha
                conn_handle->proxy_changed_callback = __connection_dummy_address_changed_cb;
 }
 
+static void __connection_dummy_dhcp_state_changed_cb(connection_dhcp_state_e state,
+            const char *interface_name, connection_error_e result, void *user_data)
+{
+       CONNECTION_LOG(CONNECTION_INFO, "Dummy callback");
+}
+
+static void __connection_set_dhcp_state_changed_callback(connection_handle_s *conn_handle,
+                       void *callback, void *user_data)
+{
+       conn_handle->dhcp_state_changed_user_data = user_data;
+       if (callback != NULL)
+               conn_handle->dhcp_state_changed_callback = callback;
+       else
+               conn_handle->dhcp_state_changed_callback = __connection_dummy_dhcp_state_changed_cb;
+}
+
 static void __connection_dummy_internet_state_changed_cb(connection_internet_state_e state,
                        void* user_data)
 {
@@ -305,6 +321,7 @@ EXPORT_API int connection_destroy(connection_h connection)
        __connection_set_proxy_changed_callback(connection, NULL, NULL);
        __connection_set_internet_state_changed_callback(connection, NULL, NULL);
        __connection_set_ethernet_cable_state_changed_cb(connection, NULL, NULL);
+       __connection_set_dhcp_state_changed_callback(connection, NULL, NULL);
 
        _connection_handle_unref(connection);
 
@@ -718,6 +735,31 @@ EXPORT_API int connection_get_ethernet_cable_state(connection_h connection, conn
        return CONNECTION_ERROR_NONE;
 }
 
+EXPORT_API int connection_get_dhcp_state(connection_h connection,
+               const char *interface_name, connection_dhcp_state_e *state)
+{
+       CONN_LOCK;
+
+       CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
+
+       if (interface_name == NULL || state == NULL ||
+                       !(__connection_check_handle_validity(connection))) {
+               CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
+               CONN_UNLOCK;
+               return CONNECTION_ERROR_INVALID_PARAMETER;
+       }
+
+       int rv = _connection_libnet_get_dhcp_state(connection, interface_name, state);
+       if (rv != CONNECTION_ERROR_NONE) {
+               CONNECTION_LOG(CONNECTION_ERROR, "Fail to get DHCP  state[%d]", rv); //LCOV_EXCL_LINE
+               CONN_UNLOCK; //LCOV_EXCL_LINE
+               return rv; //LCOV_EXCL_LINE
+       }
+
+       CONN_UNLOCK;
+       return CONNECTION_ERROR_NONE;
+}
+
 EXPORT_API int connection_set_ethernet_cable_state_chaged_cb(connection_h connection,
                          connection_ethernet_cable_state_chaged_cb callback, void *user_data)
 {
@@ -933,6 +975,43 @@ EXPORT_API int connection_unset_proxy_address_changed_cb(connection_h connection
        return CONNECTION_ERROR_NONE;
 }
 
+EXPORT_API int connection_set_dhcp_state_changed_cb(connection_h connection,
+               connection_dhcp_state_changed_cb callback, void *user_data)
+{
+       CONN_LOCK;
+
+       CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
+
+       if (callback == NULL || !(__connection_check_handle_validity(connection))) {
+               CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
+               CONN_UNLOCK;
+               return CONNECTION_ERROR_INVALID_PARAMETER;
+       }
+
+       __connection_set_dhcp_state_changed_callback(connection, callback, user_data);
+
+       CONN_UNLOCK;
+       return CONNECTION_ERROR_NONE;
+}
+
+EXPORT_API int connection_unset_dhcp_state_changed_cb(connection_h connection)
+{
+       CONN_LOCK;
+
+       CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
+
+       if (!(__connection_check_handle_validity(connection))) {
+               CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
+               CONN_UNLOCK;
+               return CONNECTION_ERROR_INVALID_PARAMETER;
+       }
+
+       __connection_set_dhcp_state_changed_callback(connection, NULL, NULL);
+
+       CONN_UNLOCK;
+       return CONNECTION_ERROR_NONE;
+}
+
 EXPORT_API int connection_set_internet_state_changed_cb(connection_h connection,
                connection_internet_state_changed_cb callback, void *user_data)
 {
index 5ed4ddb..c357e3c 100755 (executable)
@@ -576,6 +576,48 @@ static void __libnet_evt_cb(net_event_info_t *event_cb, void *user_data)
                        return;
                }
                break;
+       case NET_EVENT_DHCP_STATE_CHANGED:
+               CONNECTION_LOG(CONNECTION_INFO, "Got DHCP Changed Indication");
+               net_dhcp_state_info_t *dhcp_state_info = (net_dhcp_state_info_t*)event_cb->data;
+               connection_dhcp_state_e dhcp_state = CONNECTION_DHCP_STATE_UNKNOWN;
+               connection_error_e result = CONNECTION_ERROR_NONE;
+
+               if (!dhcp_state_info || !dhcp_state_info->ifname || !dhcp_state_info->state) {
+                       CONN_UNLOCK;
+                       return;
+               }
+
+               if (conn_handle->dhcp_state_changed_callback) {
+                       if (g_strcmp0(dhcp_state_info->state, "DHCP_STARTED") == 0) {
+                               result = CONNECTION_ERROR_NONE;
+                               dhcp_state = CONNECTION_DHCP_STATE_STARTED;
+                       } else if (g_strcmp0(dhcp_state_info->state, "DHCP_SUCCESS") == 0) {
+                               result = CONNECTION_ERROR_NONE;
+                               dhcp_state = CONNECTION_DHCP_STATE_FINISHED;
+                       } else if (g_strcmp0(dhcp_state_info->state, "DHCP_FAIL") == 0) {
+                               result = CONNECTION_ERROR_DHCP_FAILED;
+                               dhcp_state = CONNECTION_DHCP_STATE_FINISHED;
+                       } else {
+                               result = CONNECTION_ERROR_NONE;
+                               dhcp_state = CONNECTION_DHCP_STATE_UNKNOWN;
+                       }
+
+                       _connection_handle_ref(conn_handle);
+                       CONN_UNLOCK;
+
+                       conn_handle->dhcp_state_changed_callback(
+                                       dhcp_state,
+                                       dhcp_state_info->ifname,
+                                       result,
+                                       conn_handle->dhcp_state_changed_user_data);
+
+                       CONN_LOCK;
+                       _connection_handle_unref(conn_handle);
+                       CONN_UNLOCK;
+
+                       return;
+               }
+               break;
        case NET_EVENT_INTERNET_ONLINE_IND:
        case NET_EVENT_INTERNET_OFFLINE_IND:
                CONNECTION_LOG(CONNECTION_INFO, "Got Internet State Changed Indication: %s",
@@ -911,6 +953,35 @@ int _connection_libnet_get_ethernet_cable_state(connection_handle_s *conn_handle
                *state = CONNECTION_ETHERNET_CABLE_DETACHED;
        return CONNECTION_ERROR_NONE;
 }
+
+int _connection_libnet_get_dhcp_state(connection_handle_s *conn_handle,
+                       const char *interface_name, connection_dhcp_state_e *state)
+{
+       int rv = 0;
+       char *status_str = NULL;
+
+       rv = net_get_dhcp_state(conn_handle->network_info_handle, interface_name, &status_str);
+       if (rv == NET_ERR_ACCESS_DENIED) {
+               CONNECTION_LOG(CONNECTION_ERROR, "Access denied");
+               return CONNECTION_ERROR_PERMISSION_DENIED;
+       } else if (rv != NET_ERR_NONE) {
+               CONNECTION_LOG(CONNECTION_ERROR, "Failed to get DHCP state[%d]", rv);
+               return CONNECTION_ERROR_OPERATION_FAILED;
+       }
+
+       if (g_strcmp0(status_str, "DHCP_STARTED") == 0)
+               *state = CONNECTION_DHCP_STATE_STARTED;
+       else if (g_strcmp0(status_str, "DHCP_SUCCESS") == 0)
+               *state = CONNECTION_DHCP_STATE_FINISHED;
+       else if (g_strcmp0(status_str, "DHCP_FAIL") == 0)
+               *state = CONNECTION_DHCP_STATE_FINISHED;
+       else
+               *state = CONNECTION_DHCP_STATE_UNKNOWN;
+
+       g_free(status_str);
+
+       return CONNECTION_ERROR_NONE;
+}
 //LCOV_EXCL_STOP
 
 int _connection_libnet_get_bluetooth_state(connection_handle_s *conn_handle, connection_bt_state_e *state)
index 3db86eb..ecbfd3d 100755 (executable)
@@ -290,6 +290,13 @@ static void test_internet_state_changed_callback(connection_internet_state_e sta
        printf("Internet state changed callback, state : %d\n", state);
 }
 
+static void test_dhcp_state_changed_callback(connection_dhcp_state_e state,
+               const char *interface_name, connection_error_e result, void *user_data)
+{
+       printf("DHCP state changed callback, ifname: %s, state: %d, result: %d\n",
+                       interface_name, state, result);
+}
+
 static void test_profile_state_callback(connection_profile_state_e state, void* user_data)
 {
        char *profile_name;
@@ -1098,6 +1105,7 @@ int test_register_client(void)
                connection_set_ethernet_cable_state_changed_cb(connection,
                                        test_get_ethernet_cable_state_callback, NULL);
                connection_set_internet_state_changed_cb(connection, test_internet_state_changed_callback, NULL);
+               connection_set_dhcp_state_changed_cb(connection, test_dhcp_state_changed_callback, NULL);
        } else {
                printf("Client registration failed [%s]\n", test_print_error(err));
                return -1;
@@ -2271,6 +2279,29 @@ int test_get_ethernet_cable_state(void)
        return 1;
 }
 
+int test_get_dhcp_state(void)
+{
+       int rv = 0;
+       connection_dhcp_state_e dhcp_state;
+       char if_name[40] = {0};
+
+       if (test_get_user_string("Input Interface name: ", if_name, 40) == false)
+               return -1;
+
+       g_strstrip(if_name);
+
+       rv = connection_get_dhcp_state(connection, if_name, &dhcp_state);
+
+       if (rv != CONNECTION_ERROR_NONE) {
+               printf("Fail to get DHCP state [%s]\n", test_print_error(rv));
+               return -1;
+       }
+
+       printf("Retval = [%s], DHCP state [%d]\n", test_print_error(rv), dhcp_state);
+
+       return 1;
+}
+
 int test_reset_profile(void)
 {
        int type, sim_id, rv;
@@ -3061,6 +3092,7 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data)
                printf("v   - Get all cellular default profiles\n");
                printf("w   - Get mac address\n");
                printf("x   - Get ethernet cable state\n");
+               printf("y   - Get DHCP state\n");
                printf("B   - Add IPv6 new route\n");
                printf("C   - Remove IPv6 route\n");
                printf("D   - Add new route entry\n");
@@ -3188,6 +3220,9 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data)
        case 'x':
                rv = test_get_ethernet_cable_state();
                break;
+       case 'y':
+               rv = test_get_dhcp_state();
+               break;
        case 'B':
                rv = test_add_route_ipv6();
                break;