Add new Wi-Fi tethering APIs 26/74626/7 accepted/tizen/common/20160627.192104 accepted/tizen/ivi/20160628.014606 accepted/tizen/mobile/20160628.014621 accepted/tizen/tv/20160628.014556 accepted/tizen/wearable/20160628.014613 submit/tizen/20160627.065721
authorSeonah Moon <seonah1.moon@samsung.com>
Wed, 15 Jun 2016 04:06:44 +0000 (13:06 +0900)
committerSeonah Moon <seonah1.moon@samsung.com>
Mon, 27 Jun 2016 06:00:23 +0000 (15:00 +0900)
- control mtu
- change mac
- set/get max connected device
- port forwarding
- port filtering
- vpn passthrough

Change-Id: I76a3768bd5f25925bfaa7395fde89d78d8922d87
Signed-off-by: Seonah Moon <seonah1.moon@samsung.com>
include/tethering.h
include/tethering_private.h
src/tethering.c
test/tethering_test.c

index 8f46946ed90399fb18879549d5fc4d0c18fb8a71..905b843e158c7077a82fda65cfab112fee34370d 100644 (file)
@@ -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
@@ -1055,6 +1061,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);
+
 /**
  * @}
  */
index 3f64d28ad09b637b74e29f8a13ec9f2dadc1ef3c..c56723e5dfb2cf6e152722a967ac132dbc6e258e 100644 (file)
@@ -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;
 
index 627c970f8b66af2ce156e113cd0f0694a1045fbb..fb29c363197b623830712f4a9c7382116970d011 100755 (executable)
 #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;
+}
+
index 3410d306bc8665a30306a293c77dc7a5825fa955..3d69e1c2e8e8bf3933db30e3aa87707b38d05b59 100755 (executable)
@@ -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)