From 208d67025799aeff74877b7c5416e14e19408424 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Wed, 15 Jun 2016 13:06:44 +0900 Subject: [PATCH] Add new Wi-Fi tethering APIs - control mtu - change mac - set/get max connected device - port forwarding - port filtering - vpn passthrough Change-Id: I76a3768bd5f25925bfaa7395fde89d78d8922d87 Signed-off-by: Seonah Moon --- include/tethering.h | 267 ++++++++++++++++++++++- include/tethering_private.h | 5 + src/tethering.c | 509 +++++++++++++++++++++++++++++++++++++++++++- test/tethering_test.c | 319 ++++++++++++++++++++++++++- 4 files changed, 1090 insertions(+), 10 deletions(-) diff --git a/include/tethering.h b/include/tethering.h index 8f46946..905b843 100644 --- a/include/tethering.h +++ b/include/tethering.h @@ -114,6 +114,12 @@ typedef enum { TETHERING_WIFI_MODE_TYPE_AD, /**< mode ad */ } tethering_wifi_mode_type_e; +typedef enum { + TETHERING_TYPE_IPSEC_PASSTHROUGH = 0, /**< IPSEC */ + TETHERING_TYPE_PPTP_PASSTHROUGH, /**< PPTP type */ + TETHERING_TYPE_L2TP_PASSTHROUGH, /**< L2TP type */ +} tethering_vpn_passthrough_type_e; + /** * @} */ @@ -1015,7 +1021,7 @@ int tethering_wifi_set_mode(tethering_h tethering, tethering_wifi_mode_type_e ty * @privilege %http://tizen.org/privilege/tethering.admin * @remarks @a mode must be released using free(). * @param[in] tethering The tethering handle - * @param[out] type The mode of Wi-Fi AP + * @param[out] type The mode of Wi-Fi tethering * @return 0 on success, otherwise negative error value * @retval #TETHERING_ERROR_NONE Successful * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter @@ -1056,6 +1062,265 @@ int tethering_wifi_set_txpower(tethering_h tethering, unsigned int txpower); int tethering_wifi_get_txpower(tethering_h tethering, unsigned int *txpower); /** + * @brief Sets mtu for Wi-Fi tethering. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The tethering handle + * @param[in] mtu value of mtu to be set + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_set_mtu(tethering_h tethering, unsigned int mtu); + +/** + * @brief Changes mac address for Wi-Fi tethering. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The client handle + * @param[in] mac The mac address + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_change_mac(tethering_h tethering, char *mac); + +/** + * @brief Sets max connected devices for Wi-Fi tethering. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The client handle + * @param[in] max_device value of max_device to be set + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + * @see tethering_wifi_get_max_connected_device() + */ +int tethering_wifi_set_max_connected_device(tethering_h tethering, int max_device); + +/** + * @brief Gets max connected devices for Wi-Fi tethering. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The client handle + * @param[out] max_device value of max_device + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + * @see tethering_wifi_set_max_connected_device() + */ +int tethering_wifi_get_max_connected_device(tethering_h tethering, int *max_device); + +/** + * @brief Enables port forwarding feature. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @details enable/disable port forwarding feature. + * @param[in] tethering The handle of tethering + * @param[in] enable Enable/Disable port forwarding + * @return 0 on success, otherwise negative error value. + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_enable_port_forwarding(tethering_h tethering, bool enable); + +/** + * @brief Sets port forwarding rule. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @details Set port forwarding rule. + * @param[in] tethering The handle of tethering + * @param[in] ifname interface name + * @param[in] protocol protocol (tcp/udp) + * @param[in] org_ip original destination ip where packet was meant to sent + * @param[in] org_port original destination port where packet was meant to sent + * @param[in] final_ip new destination ip where packet will be forwarded + * @param[in] final_port new destination port where packet will be forwarded + * @return 0 on success, otherwise negative error value. + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_add_port_forwarding_rule(tethering_h tethering, char *ifname, char *protocol, char *org_ip, int org_port, char *final_ip, int final_port); + +/** + * @brief Resets port forwarding rule. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @details Reset port forwarding rule. + * @param[in] tethering The handle of tethering + * @return 0 on success, otherwise negative error value. + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_reset_port_forwarding_rule(tethering_h tethering); + +/** + * @brief Checks whether the port forwarding is enabled or not. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The tethering handle + * @param[out] forwarding_enabled @c true if port forwarding is enabled, \n @c false if port forwarding is disabled + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_is_port_forwarding_enabled(tethering_h tethering, bool* forwarding_enabled); + +/** + * @brief Gets the port forwarding rule for Wi-Fi tethering. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The client handle + * @param[out] port_forwarding_list list of port forwarding rules + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_get_port_forwarding_rule(tethering_h tethering, void **port_forwarding_list); + +/** + * @brief Enables port filtering feature. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @details enable/disable port filtering feature. + * @param[in] tethering The handle of tethering + * @param[in] enable Enable/Disable port filtering + * @return 0 on success, otherwise negative error value. + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_enable_port_filtering(tethering_h tethering, bool enable); + +/** + * @brief Sets port filtering rule. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @details Set port filtering rule. + * @param[in] tethering The handle of tethering + * @param[in] port to be filtered + * @param[in] protocol protocol (tcp/udp) + * @param[in] allow allow/disallow port filtering + * @return 0 on success, otherwise negative error value. + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_add_port_filtering_rule(tethering_h tethering, int port, char *protocol, bool allow); + +/** + * @brief Sets custom port filtering rule. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @details Set custom port filtering rule. + * @param[in] tethering The handle of tethering + * @param[in] port1 to be filtered + * @param[in] port2 to be filtered + * @param[in] protocol protocol (tcp/udp) + * @param[in] allow allow/disallow port filtering + * @return 0 on success, otherwise negative error value. + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_add_custom_port_filtering_rule(tethering_h tethering, int port1, int port2, char *protocol, bool allow); + +/** + * @brief Gets the port filtering rule for Wi-Fi tethering. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The client handle + * @param[out] port_filtering_list list of port filtering rules + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_get_port_filtering_rule(tethering_h tethering, void **port_filtering_list); + +/** + * @brief Gets the custom port filtering rule for Wi-Fi tethering. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The client handle + * @param[out] custom_port_filtering_list list of custom port filtering rules + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_get_custom_port_filtering_rule(tethering_h tethering, void **custom_port_filtering_list); + +/** + * @brief Checks whether the port filtering is enabled or not. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @param[in] tethering The tethering handle + * @param[out] filtering_enabled @c true if port filtering is enabled, \n @c false if port filtering is disabled + * @return 0 on success, otherwise a negative error value + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_is_port_filtering_enabled(tethering_h tethering, bool* filtering_enabled); + +/** + * @brief Sets vpn passthrough rule. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/tethering.admin + * @details Set vpn passthrough rule. + * @param[in] tethering The handle of tethering + * @param[in] type vpn passthrough type + * @param[in] enable @c true if vpn passthrough is enabled, \n @c false if vpn passthrough is disabled + * @return 0 on success, otherwise negative error value. + * @retval #TETHERING_ERROR_NONE Successful + * @retval #TETHERING_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TETHERING_ERROR_NOT_SUPPORT_API API not supported + * @retval #TETHERING_ERROR_PERMISSION_DENIED Permission Denied + */ +int tethering_wifi_set_vpn_passthrough_rule(tethering_h tethering, tethering_vpn_passthrough_type_e type, bool enable); + +/** * @} */ diff --git a/include/tethering_private.h b/include/tethering_private.h index 3f64d28..c56723e 100644 --- a/include/tethering_private.h +++ b/include/tethering_private.h @@ -230,6 +230,7 @@ typedef enum { #define TETHERING_WIFI_KEY_MIN_LEN 8 /**< Minimum length of wifi key */ #define TETHERING_WIFI_KEY_MAX_LEN 64 /**< Maximum length of wifi key */ #define TETHERING_WIFI_HASH_KEY_MAX_LEN 64 +#define TETHERING_WIFI_MAX_STA 10 /**< Maximum Wi-Fi tethering station */ #define TETHERING_WIFI_MODE_MAX_LEN 10 /**< Maximum length of mode */ @@ -286,8 +287,11 @@ typedef struct { tethering_wifi_mode_type_e mode_type; bool visibility; bool mac_filter; + bool port_forwarding; + bool port_filtering; bool dhcp_enabled; int channel; + int wifi_max_connected; } __tethering_h; typedef struct { @@ -313,6 +317,7 @@ typedef struct { tethering_wifi_security_type_e sec_type; bool visibility; bool mac_filter; + int max_connected; int channel; } _softap_settings_t; diff --git a/src/tethering.c b/src/tethering.c index 627c970..fb29c36 100755 --- a/src/tethering.c +++ b/src/tethering.c @@ -38,8 +38,22 @@ #define MAC_ADDR_LEN 18 #define MAX_BUF_SIZE 80 +#define IPTABLES "/usr/sbin/iptables" +#define TABLE_NAT "nat" +#define TETH_NAT_PRE "teth_nat_pre" +#define TABLE_FILTER "filter" +#define TETH_FILTER_FW "teth_filter_fw" +#define ACTION_DROP "DROP" +#define ACTION_ACCEPT "ACCEPT" +#define PORT_FORWARD_RULE_STR "-t %s -A %s -i %s -p %s -d %s --dport %d -j DNAT --to %s:%d" +#define FILTERING_MULTIPORT_RULE_STR "-t %s -A %s -p %s -m multiport --dport %d,%d -j %s" +#define FILTERING_RULE_STR "-t %s -A %s -p %s --dport %d -j %s" + static GSList *allowed_list = NULL; static GSList *blocked_list = NULL; +static GSList *port_forwarding = NULL; +static GSList *port_filtering = NULL; +static GSList *custom_port_filtering = NULL; static void __handle_wifi_tether_on(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, @@ -155,7 +169,7 @@ static tethering_error_e __set_security_type(const tethering_wifi_security_type_ } if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, security_type) < 0) { - ERR("vconf_set_int is failed\n"); + ERR("vconf_set_int is failed\n"); return TETHERING_ERROR_OPERATION_FAILED; } @@ -304,7 +318,7 @@ static tethering_error_e __get_error(int agent_error) err = TETHERING_ERROR_PERMISSION_DENIED; break; //LCOV_EXCL_STOP - default: + default : ERR("Not defined error : %d\n", agent_error); err = TETHERING_ERROR_OPERATION_FAILED; break; @@ -1235,6 +1249,7 @@ static int __prepare_wifi_settings(tethering_h tethering, _softap_settings_t *se set->visibility = th->visibility; set->mac_filter = th->mac_filter; + set->max_connected = th->wifi_max_connected; set->channel = th->channel; __get_wifi_mode_type(th->mode_type, &ptr); @@ -1350,6 +1365,7 @@ API int tethering_create(tethering_h *tethering) th->mac_filter = false; th->channel = 6; th->mode_type = TETHERING_WIFI_MODE_TYPE_G; + th->wifi_max_connected = TETHERING_WIFI_MAX_STA; if (__generate_initial_passphrase(th->passphrase, sizeof(th->passphrase)) == 0) { @@ -1506,7 +1522,7 @@ API int tethering_enable(tethering_h tethering, tethering_type_e type) sigs[E_SIGNAL_WIFI_TETHER_ON].sig_id); g_dbus_proxy_call(proxy, "enable_wifi_tethering", - g_variant_new("(sssiiii)", set.ssid, set.key, set.mode, set.channel, set.visibility, set.mac_filter, set.sec_type), + g_variant_new("(sssiiiii)", set.ssid, set.key, set.mode, set.channel, set.visibility, set.mac_filter, set.max_connected, set.sec_type), G_DBUS_CALL_FLAGS_NONE, -1, th->cancellable, (GAsyncReadyCallback) __wifi_enabled_cfm_cb, (gpointer)tethering); break; @@ -3004,7 +3020,7 @@ API int tethering_wifi_reload_settings(tethering_h tethering, tethering_wifi_set th->settings_reloaded_user_data = user_data; g_dbus_proxy_call(proxy, "reload_wifi_settings", - g_variant_new("(sssiiii)", set.ssid, set.key, set.mode, set.channel, set.visibility, set.mac_filter, set.sec_type), + g_variant_new("(sssiiii)", set.ssid, set.key, set.mode, set.channel, set.visibility, set.mac_filter, set.max_connected, set.sec_type), G_DBUS_CALL_FLAGS_NONE, -1, th->cancellable, (GAsyncReadyCallback) __settings_reloaded_cb, (gpointer)tethering); @@ -3361,3 +3377,488 @@ API int tethering_wifi_get_txpower(tethering_h tethering, unsigned int *txpower) return TETHERING_ERROR_NONE; } +API int tethering_wifi_set_mtu(tethering_h tethering, unsigned int mtu) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "set_mtu", + g_variant_new("(u)", mtu), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + + g_variant_unref(parameters); + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_change_mac(tethering_h tethering, char *mac) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(mac == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(mac) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "change_mac", + g_variant_new("(s)", mac), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + + g_variant_unref(parameters); + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_set_max_connected_device(tethering_h tethering, int max_device) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + + __tethering_h *th = (__tethering_h *)tethering; + + th->wifi_max_connected = max_device; + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_get_max_connected_device(tethering_h tethering, int *max_device) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(max_device == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(max_device) is NULL\n"); + + __tethering_h *th = (__tethering_h *)tethering; + + *max_device = th->wifi_max_connected; + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_enable_port_forwarding(tethering_h tethering, bool enable) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "enable_port_forwarding", + g_variant_new("(b)", enable), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + g_variant_unref(parameters); + + th->port_forwarding = true; + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_add_port_forwarding_rule(tethering_h tethering, char *ifname, char *protocol, char *org_ip, int org_port, char *final_ip, int final_port) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(protocol == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(protocol) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + char cmd[MAX_BUF_SIZE] = { 0, }; + char *list = NULL; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "add_port_forwarding_rule", + g_variant_new("(sssisi)", ifname, protocol, org_ip, org_port, final_ip, final_port), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + g_variant_unref(parameters); + + snprintf(cmd, sizeof(cmd), "%s "PORT_FORWARD_RULE_STR, IPTABLES, TABLE_NAT, TETH_NAT_PRE, ifname, protocol, org_ip, org_port, final_ip, final_port); + + list = strdup(cmd); + if (list == NULL) { + ERR("strdup failed\n"); + return TETHERING_ERROR_OUT_OF_MEMORY; + } + + port_forwarding = g_slist_append(port_forwarding, list); + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_reset_port_forwarding_rule(tethering_h tethering) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "reset_port_forwarding_rule", + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + + g_variant_unref(parameters); + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_is_port_forwarding_enabled(tethering_h tethering, bool* forwarding_enabled) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(forwarding_enabled == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(forwarding_enabled) is NULL\n"); + + __tethering_h *th = (__tethering_h *)tethering; + + *forwarding_enabled = th->port_forwarding; + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_get_port_forwarding_rule(tethering_h tethering, void **port_forwarding_list) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(port_forwarding_list == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(port_forwarding_list) is NULL\n"); + + *port_forwarding_list = g_slist_copy(port_forwarding); + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_enable_port_filtering(tethering_h tethering, bool enable) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "enable_port_filtering", + g_variant_new("(b)", enable), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + g_variant_unref(parameters); + + th->port_filtering = true; + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_add_port_filtering_rule(tethering_h tethering, int port, char *protocol, bool allow) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(protocol == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(protocol) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + char cmd[MAX_BUF_SIZE] = { 0, }; + char *list = NULL; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "add_port_filtering_rule", + g_variant_new("(isb)", port, protocol, allow), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + g_variant_unref(parameters); + + if (allow) + snprintf(cmd, sizeof(cmd), "%s "FILTERING_RULE_STR, IPTABLES, TABLE_FILTER, TETH_FILTER_FW, protocol, port, ACTION_ACCEPT); + else + snprintf(cmd, sizeof(cmd), "%s "FILTERING_RULE_STR, IPTABLES, TABLE_FILTER, TETH_FILTER_FW, protocol, port, ACTION_DROP); + + DBG("cmd:%s", cmd); + + list = strdup(cmd); + if (list == NULL) { + ERR("strdup failed\n"); + return TETHERING_ERROR_OUT_OF_MEMORY; + } + + port_filtering = g_slist_append(port_filtering, list); + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_add_custom_port_filtering_rule(tethering_h tethering, int port1, int port2, char *protocol, bool allow) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(protocol == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(protocol) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + char cmd[MAX_BUF_SIZE] = { 0, }; + char *list = NULL; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "add_custom_port_filtering_rule", + g_variant_new("(iisb)", port1, port2, protocol, allow), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + g_variant_unref(parameters); + + if (allow) + snprintf(cmd, sizeof(cmd), "%s "FILTERING_MULTIPORT_RULE_STR, IPTABLES, TABLE_FILTER, TETH_FILTER_FW, protocol, port1, port2, ACTION_ACCEPT); + else + snprintf(cmd, sizeof(cmd), "%s "FILTERING_MULTIPORT_RULE_STR, IPTABLES, TABLE_FILTER, TETH_FILTER_FW, protocol, port1, port2, ACTION_DROP); + + DBG("cmd:%s", cmd); + + list = strdup(cmd); + if (list == NULL) { + ERR("strdup failed\n"); + return TETHERING_ERROR_OUT_OF_MEMORY; + } + + custom_port_filtering = g_slist_append(custom_port_filtering, list); + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_get_port_filtering_rule(tethering_h tethering, void **port_filtering_list) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(port_filtering_list == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(port_filtering_list) is NULL\n"); + + *port_filtering_list = g_slist_copy(port_filtering); + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_get_custom_port_filtering_rule(tethering_h tethering, void **custom_port_filtering_list) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(custom_port_filtering_list == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(custom_port_filtering_list) is NULL\n"); + + *custom_port_filtering_list = g_slist_copy(custom_port_filtering); + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_is_port_filtering_enabled(tethering_h tethering, bool* filtering_enabled) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + _retvm_if(filtering_enabled == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(filtering_enabled) is NULL\n"); + + __tethering_h *th = (__tethering_h *)tethering; + + *filtering_enabled = th->port_filtering; + + return TETHERING_ERROR_NONE; +} + +API int tethering_wifi_set_vpn_passthrough_rule(tethering_h tethering, tethering_vpn_passthrough_type_e type, bool enable) +{ + CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE, TETHERING_WIFI_FEATURE); + + _retvm_if(tethering == NULL, TETHERING_ERROR_INVALID_PARAMETER, + "parameter(tethering) is NULL\n"); + + GVariant *parameters; + GError *error = NULL; + guint result; + + __tethering_h *th = (__tethering_h *)tethering; + + GDBusProxy *proxy = th->client_bus_proxy; + + parameters = g_dbus_proxy_call_sync(proxy, "set_vpn_passthrough_rule", + g_variant_new("(ib)", type, enable), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERR("g_dbus_proxy_call_sync failed because %s\n", error->message); + + if (error->code == G_DBUS_ERROR_ACCESS_DENIED) + result = TETHERING_ERROR_PERMISSION_DENIED; + else + result = TETHERING_ERROR_OPERATION_FAILED; + + g_error_free(error); + return result; + } + + g_variant_get(parameters, "(u)", &result); + + g_variant_unref(parameters); + + return TETHERING_ERROR_NONE; +} + diff --git a/test/tethering_test.c b/test/tethering_test.c index 3410d30..3d69e1c 100755 --- a/test/tethering_test.c +++ b/test/tethering_test.c @@ -457,7 +457,10 @@ static void __print_wifi_tethering_setting(tethering_h th) char *passphrase = NULL; bool visibility = false; bool mac_filter = 0; + bool forwarding_enabled = false; + bool filtering_enabled = false; int channel = 0; + int max_connected = 0; tethering_wifi_security_type_e security_type = TETHERING_WIFI_SECURITY_TYPE_NONE; tethering_wifi_mode_type_e hw_mode = TETHERING_WIFI_MODE_TYPE_G; @@ -491,6 +494,24 @@ static void __print_wifi_tethering_setting(tethering_h th) TETHERING_WIFI_SECURITY_TYPE_NONE ? "open" : "wpa2-psk"); + error = tethering_wifi_get_mode(th, &hw_mode); + if (error != TETHERING_ERROR_NONE) + __is_err(error); + else + g_print("\t** WiFi tethering mode : %d\n", hw_mode); + + error = tethering_wifi_get_channel(th, &channel); + if (error != TETHERING_ERROR_NONE) + __is_err(error); + else + g_print("\t** WiFi tethering channel : %d\n", channel); + + error = tethering_wifi_get_max_connected_device(th, &max_connected); + if (error != TETHERING_ERROR_NONE) + __is_err(error); + else + g_print("\t** WiFi tethering max connected device : %d\n", max_connected); + error = tethering_wifi_get_mac_filter(th, &mac_filter); if (error != TETHERING_ERROR_NONE) __is_err(error); @@ -498,17 +519,19 @@ static void __print_wifi_tethering_setting(tethering_h th) g_print("\t** WiFi tethering mac filter : %s\n", mac_filter ? "enable" : "disable"); - error = tethering_wifi_get_mode(th, &hw_mode); + error = tethering_wifi_is_port_filtering_enabled(th, &filtering_enabled); if (error != TETHERING_ERROR_NONE) __is_err(error); else - g_print("\t** WiFi tethering mode : %d\n", hw_mode); + g_print("\t** WiFi tethering port filtering : %s\n", + filtering_enabled ? "enable" : "disable"); - error = tethering_wifi_get_channel(th, &channel); + error = tethering_wifi_is_port_forwarding_enabled(th, &forwarding_enabled); if (error != TETHERING_ERROR_NONE) __is_err(error); else - g_print("\t** WiFi tethering channel : %d\n", channel); + g_print("\t** WiFi tethering port forwarding : %s\n", + forwarding_enabled ? "enable" : "disable"); if (ssid) free(ssid); @@ -954,6 +977,7 @@ static int test_tethering_wifi_get_txpower(void) g_print("tethering_hostapd_get_txpower received [%d]\n",txpower); return 1; } + static int test_tethering_wifi_set_txpower(void) { int ret; @@ -971,6 +995,239 @@ static int test_tethering_wifi_set_txpower(void) return 1; } +static int test_tethering_wifi_set_mtu(void) +{ + int ret; + unsigned int mtu = 0; + + printf("Input mtu for Wi-Fi tethering: "); + ret = scanf("%d", &mtu); + + ret = tethering_wifi_set_mtu(th, mtu); + if (__is_err(ret) == true) { + printf("Fail to set mtu!!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_change_mac(void) +{ + int ret; + char mac[18]; + + printf("Input mac address: "); + ret = scanf("%17s", mac); + + ret = tethering_wifi_change_mac(th, mac); + if (__is_err(ret) == true) { + printf("Fail to change mac!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_set_max_connected_device(void) +{ + int ret; + int max_connected; + + printf("Input max connected device: "); + ret = scanf("%d", &max_connected); + + ret = tethering_wifi_set_max_connected_device(th, max_connected); + if (__is_err(ret) == true) { + printf("Fail to set max connected device!\n"); + return -1; + } + + return 1; + +} + +static int test_tethering_wifi_enable_port_forwarding(void) +{ + int ret; + int enable = false; + + printf("Wi-Fi tethring port forwarding(0:disable 1:enable): "); + ret = scanf("%d", &enable); + + ret =tethering_wifi_enable_port_forwarding(th, enable); + if (__is_err(ret) == true) { + printf("Fail to enable port forwarding!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_add_port_forwarding_rule(void) +{ + int ret; + char ifname[20]; + char proto[20]; + char org_ip[16]; + char final_ip[16]; + int org_port, final_port; + + printf("Input ifname, protocol, original ip/port, final ip/port: "); + ret = scanf("%19s", ifname); + ret = scanf("%19s", proto); + ret = scanf("%15s", org_ip); + ret = scanf("%d", &org_port); + ret = scanf("%15s", final_ip); + ret = scanf("%d", &final_port); + + ret = tethering_wifi_add_port_forwarding_rule(th, ifname, proto, org_ip, org_port, final_ip, final_port); + if (__is_err(ret) == true) { + printf("Fail to add port forwarding rule!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_reset_port_forwarding_rule(void) +{ + int ret; + + ret = tethering_wifi_reset_port_forwarding_rule(th); + if (__is_err(ret) == true) { + printf("Fail to reset port forwarding rule!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_get_port_forwarding_rule(void) +{ + int ret = 0; + void *pf_list = NULL; + + ret = tethering_wifi_get_port_forwarding_rule(th, &pf_list); + if (__is_err(ret) == true) { + printf("Fail to get port forwarding rule!\n"); + return -1; + } + + __display_list(pf_list); + + return 1; +} + +static int test_tethering_wifi_enable_port_filtering(void) +{ + int ret; + int enable = false; + + printf("Wi-Fi tethring port filtering(0:disable 1:enable): "); + ret = scanf("%d", &enable); + + ret =tethering_wifi_enable_port_filtering(th, enable); + if (__is_err(ret) == true) { + printf("Fail to enable port filtering!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_add_port_filtering_rule(void) +{ + int ret; + char proto[20]; + int port; + int allow; + + printf("Input protocol, port, allow: "); + ret = scanf("%19s", proto); + ret = scanf("%d", &port); + ret = scanf("%d", &allow); + + ret = tethering_wifi_add_port_filtering_rule(th, port, proto, allow); + if (__is_err(ret) == true) { + printf("Fail to add port forwarding rule!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_add_custom_port_filtering_rule(void) +{ + int ret; + char proto[20]; + int port1, port2; + int allow; + + printf("Input protocol, port1, port2, allow: "); + ret = scanf("%19s", proto); + ret = scanf("%d", &port1); + ret = scanf("%d", &port2); + ret = scanf("%d", &allow); + + ret = tethering_wifi_add_custom_port_filtering_rule(th, port1, port2, proto, allow); + if (__is_err(ret) == true) { + printf("Fail to add custom port forwarding rule!\n"); + return -1; + } + + return 1; +} + +static int test_tethering_wifi_get_port_filtering_rule(void) +{ + int ret = 0; + void *pf_list = NULL; + + ret = tethering_wifi_get_port_filtering_rule(th, &pf_list); + if (__is_err(ret) == true) { + printf("Fail to get port filtering rule!\n"); + return -1; + } + + __display_list(pf_list); + + return 1; +} + +static int test_tethering_wifi_get_custom_port_filtering_rule(void) +{ + int ret = 0; + void *pf_list = NULL; + + ret = tethering_wifi_get_custom_port_filtering_rule(th, &pf_list); + if (__is_err(ret) == true) { + printf("Fail to get port filtering rule!\n"); + return -1; + } + + __display_list(pf_list); + + return 1; +} + +static int test_tethering_wifi_set_vpn_passthrough_rule(void) +{ + int ret = 0; + int type; + + printf("Select vpn passthrough type (0:IPSEC 1:PPTP 2:L2TP): "); + ret = scanf("%d", &type); + + ret = tethering_wifi_set_vpn_passthrough_rule(th, (tethering_vpn_passthrough_type_e)type, true); + if (__is_err(ret) == true) { + printf("Fail to get port filtering rule!\n"); + return -1; + } + + return 1; +} + int main(int argc, char **argv) { GMainLoop *mainloop; @@ -1026,7 +1283,20 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) printf("q - Is dhcp server enabled?\n"); printf("r - Get Wi-Fi txpower\n"); printf("s - Set Wi-Fi txpower\n"); - printf("0 - Exit \n"); + printf("t - Set Wi-Fi mtu\n"); + printf("u - Change mac address\n"); + printf("v - Set max connected device(Wi-Fi tethering)\n"); + printf("w - Enable port forwarding\n"); + printf("x - Add port forwarding rule\n"); + printf("y - Reset port forwarding rule\n"); + printf("z - Get port forwarding rule\n"); + printf("A - Enable port filtering\n"); + printf("B - Add port filtering rule\n"); + printf("C - Add custom port filtering rule\n"); + printf("D - Get port filtering rule\n"); + printf("E - Get custom port filtering rule\n"); + printf("F - Set vpn passthrough rule\n"); + printf("0 - \n"); printf("ENTER - Show options menu.......\n"); } @@ -1100,6 +1370,45 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) case 's': rv = test_tethering_wifi_set_txpower(); break; + case 't': + rv = test_tethering_wifi_set_mtu(); + break; + case 'u': + rv = test_tethering_wifi_change_mac(); + break; + case 'v': + rv = test_tethering_wifi_set_max_connected_device(); + break; + case 'w': + rv = test_tethering_wifi_enable_port_forwarding(); + break; + case 'x': + rv = test_tethering_wifi_add_port_forwarding_rule(); + break; + case 'y': + rv = test_tethering_wifi_reset_port_forwarding_rule(); + break; + case 'z': + rv = test_tethering_wifi_get_port_forwarding_rule(); + break; + case 'A': + rv = test_tethering_wifi_enable_port_filtering(); + break; + case 'B': + rv = test_tethering_wifi_add_port_filtering_rule(); + break; + case 'C': + rv = test_tethering_wifi_add_custom_port_filtering_rule(); + break; + case 'D': + rv = test_tethering_wifi_get_port_filtering_rule(); + break; + case 'E': + rv = test_tethering_wifi_get_custom_port_filtering_rule(); + break; + case 'F': + rv = test_tethering_wifi_set_vpn_passthrough_rule(); + break; } if (rv == 1) -- 2.7.4