Below changes are applied
authorSeungyoun Ju <sy39.ju@samsung.com>
Mon, 14 Jan 2013 12:13:21 +0000 (21:13 +0900)
committerSeungyoun Ju <sy39.ju@samsung.com>
Tue, 15 Jan 2013 07:18:03 +0000 (16:18 +0900)
- dhcp lease delete is handled based on IP Address
- DNS Forward by netfilter is implemented
- Vconf key for flight mode is changed

Change-Id: I57695d7def889bd036a94bffcc18ac6600644a8f

include/mobileap_agent.h
include/mobileap_common.h
include/mobileap_handler.h
include/mobileap_network.h
packaging/mobileap-agent.spec
src/mobileap_agent.c
src/mobileap_common.c
src/mobileap_handler.c
src/mobileap_main.c
src/mobileap_network.c
src/mobileap_notification.c

index bc6429b..bf9dc9b 100644 (file)
@@ -77,7 +77,6 @@
                        "dhcp-range=192.168.136.2,192.168.136.150,255.255.255.0\n" \
                        "dhcp-range=192.168.137.2,192.168.137.150,255.255.255.0\n" \
                        "dhcp-range=set:blue,192.168.129.4,192.168.129.150,255.255.255.0\n"\
-                       "dhcp-option=option:dns-server,%s\n" \
                        "enable-dbus\n" \
                        "dhcp-option=tag:blue,option:router,192.168.129.3\n"
 #define DNSMASQ_CONF_FILE      "/tmp/dnsmasq.conf"
 #define AWK            "/usr/bin/awk"
 #define DATA_USAGE_FILE        "/tmp/tethering_data_usage.txt"
 #define MASQUERADE_RULE                "-o %s -j MASQUERADE"
-#define DNS_FORWARD_RULE       "-p udp -i %s --dport 53 -j DNAT --to %s"
+#define DNS_ORDER              1
+#define TCP_DNS_FORWARD_RULE   "-i %s -p tcp --dport 53 -j DNAT --to %s:53"
+#define UDP_DNS_FORWARD_RULE   "-i %s -p udp --dport 53 -j DNAT --to %s:53"
 #define FORWARD_RULE           "-i %s -o %s"
-#ifndef __USE_CONNMAN_DNS_ADDR__
-#define GOOGLE_PUBLIC_DNS      "8.8.8.8"
-#endif /* __USE_CONNMAN_DNS_ADDR__ */
 
 #define MOBILE_AP_STATE_NONE   0
 #define MOBILE_AP_STATE_WIFI   1
index 7716242..137b79c 100644 (file)
@@ -28,6 +28,7 @@
 
 gint _slist_find_station_by_interface(gconstpointer a, gconstpointer b);
 gint _slist_find_station_by_mac(gconstpointer a, gconstpointer b);
+gint _slist_find_station_by_ip_addr(gconstpointer a, gconstpointer b);
 
 void _emit_mobileap_dbus_signal(MobileAPObject *obj,
                mobile_ap_sig_e num, const gchar *message);
index ee640a4..c1bc03b 100644 (file)
@@ -26,4 +26,5 @@ void _start_timeout_cb(mobile_ap_type_e type);
 void _stop_timeout_cb(mobile_ap_type_e type);
 void _deinit_timeout_cb(mobile_ap_type_e type);
 
+
 #endif
index c63847d..985797f 100644 (file)
@@ -19,7 +19,6 @@
 #define __MOBILEAP_NETWORK_H__
 
 #include <glib.h>
-#include <net_connection.h>
 
 gboolean _get_network_interface_name(char **if_name);
 gboolean _set_masquerade(void);
index 4b97ee4..356d8a4 100644 (file)
@@ -1,6 +1,6 @@
 Name:       mobileap-agent
 Summary:    Mobile AP daemon for setting tethering environments
-Version:    0.1.80
+Version:    0.1.81
 Release:    1
 Group:      TO_BE/FILLED_IN
 License:    Apache License Version 2.0
@@ -48,6 +48,11 @@ rm -rf %{buildroot}
 %{_bindir}/mobileap-agent
 
 %changelog
+* Mon Jan 14 2013 Seungyoun Ju <sy39.ju@samsung.com> 0.1.81-1
+- dhcp lease delete is handled based on IP Address
+- DNS Forward by netfilter is implemented
+- Vconf key for flight mode is changed
+
 * Fri Dec 07 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.80-1
 - Notification API's usage is changed
 - Duplicated station information issue is fixed
index 7bcca53..68f1c67 100644 (file)
@@ -73,138 +73,6 @@ static int __issue_ioctl(int sock_fd, char *if_name, char *cmd, char *buf)
        return ret_val;
 }
 
-static int __get_dns_server(char *dns_server, int len)
-{
-#ifndef __USE_CONNMAN_DNS_ADDR__
-       g_strlcpy(dns_server, GOOGLE_PUBLIC_DNS, len);
-       DBG("DNS server [%s]\n", dns_server);
-
-       return EXIT_SUCCESS;
-#else
-       int ret = EXIT_FAILURE;
-       GError *error = NULL;
-       DBusGConnection *bus = NULL;
-       DBusGProxy *manager_proxy = NULL;
-       DBusGProxy *service_proxy = NULL;
-       gchar *service_object_path = NULL;
-
-       GHashTable *hash = NULL;
-       GValue *value;
-       const gchar *state;
-       gchar **dns_server_list = NULL;
-       GPtrArray *service_list = NULL;
-
-       bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-       if (error) {
-               ERR("Couldn't connect to the System bus[%s]", error->message);
-               g_error_free(error);
-               return ret;
-       }
-
-       manager_proxy = dbus_g_proxy_new_for_name(bus, "net.connman",
-                                               "/",
-                                               "net.connman.Manager");
-       if (!manager_proxy) {
-               ERR("Couldn't create the proxy object");
-               goto done;
-       }
-
-       dbus_g_proxy_call(manager_proxy, "GetProperties", &error, G_TYPE_INVALID,
-               dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
-               &hash, G_TYPE_INVALID);
-       if (error) {
-               ERR("GetProperties failed[%s]", error->message);
-               g_error_free(error);
-               goto done;
-       }
-
-       /*
-       dict entry(
-               string "Services"
-               variant         array [
-                       object path "/profile/default/cellular_45001_cellular_Samsung3G_1"
-                       object path "/profile/default/cellular_45001_cellular_Samsung3G_MMS_2"
-               ]
-       )
-       */
-       value = g_hash_table_lookup(hash, "Services");
-
-       service_list = g_value_get_boxed(value);
-       if (!service_list) {
-               ERR("No service available");
-               goto done;
-       }
-
-       service_object_path = g_ptr_array_index(service_list, 0);
-       DBG("service object path : %s\n", service_object_path);
-
-       service_proxy = dbus_g_proxy_new_for_name(bus, "net.connman",
-                                               service_object_path,
-                                               "net.connman.Service");
-       if (!service_proxy) {
-               ERR("Couldn't create the proxy object");
-               goto done;
-       }
-
-       dbus_g_proxy_call(service_proxy, "GetProperties", &error, G_TYPE_INVALID,
-               dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
-               &hash, G_TYPE_INVALID);
-       if (error) {
-               ERR("GetProperties failed[%s]", error->message);
-               g_error_free(error);
-               goto done;
-       }
-
-       /*
-       dict entry(
-               string "State"
-               variant         string "online"
-       )
-
-       dict entry(
-               string "Nameservers"
-               variant         array [
-                       string "165.213.73.226"
-                       string "10.32.192.11"
-               ]
-       )
-       */
-       value = g_hash_table_lookup(hash, "State");
-       state = value ? g_value_get_string(value) : NULL;
-       DBG("Network state : %s\n", state);
-
-       if (g_strcmp0(state, "ready") != 0 && g_strcmp0(state, "online") != 0) {
-               ERR("Network is not connected\n");
-               goto done;
-       }
-
-       value = g_hash_table_lookup(hash, "Nameservers");
-
-       dns_server_list = g_value_get_boxed(value);
-       if (!dns_server_list) {
-               ERR("No Nameserver exist");
-               goto done;
-       }
-       g_strlcpy(dns_server, *dns_server_list, len);
-       DBG("DNS server [%s]\n", dns_server);
-
-       ret = EXIT_SUCCESS;
-done:
-       if (dns_server_list)
-               g_strfreev(dns_server_list);
-       if (service_list)
-               g_ptr_array_free(service_list, TRUE);
-       if (manager_proxy)
-               g_object_unref(manager_proxy);
-       if (service_proxy)
-               g_object_unref(service_proxy);
-       if (bus)
-               dbus_g_connection_unref(bus);
-
-       return ret;
-#endif
-}
-
 static int __get_psk_hexascii(const char *pass, const unsigned char *salt, char *psk, unsigned int psk_len)
 {
        if (pass == NULL || salt == NULL || psk == NULL || psk_len == 0) {
@@ -951,21 +819,15 @@ int _mh_core_get_device_info(softap_device_info_t *di)
 int _mh_core_execute_dhcp_server(void)
 {
        char buf[DNSMASQ_CONF_LEN] = "";
-       char dns_server[MOBILE_AP_STR_INFO_LEN] = {0, };
        FILE *fp = NULL;
        pid_t pid;
 
-       if (__get_dns_server(dns_server, sizeof(dns_server))) {
-               ERR("Getting DNS server failed\n");
-               return MOBILE_AP_ERROR_INTERNAL;
-       }
-
        fp = fopen(DNSMASQ_CONF_FILE, "w");
        if (NULL == fp) {
                ERR("Could not create the file.\n");
                return MOBILE_AP_ERROR_RESOURCE;
        }
-       snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF, dns_server);
+       snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF);
        fputs(buf, fp);
        fclose(fp);
 
@@ -976,6 +838,10 @@ int _mh_core_execute_dhcp_server(void)
        }
 
        if (pid == 0) {
+               /* -d : Debug mode
+                * -p 0 : DNS off
+                * -C file : Configuration file path
+                */
                if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
                                        "-p", "0", "-C", DNSMASQ_CONF_FILE,
                                        (char *)NULL)) {
@@ -1007,6 +873,11 @@ int _mh_core_terminate_dhcp_server(void)
 
 int _mh_core_enable_masquerade(const char *ext_if)
 {
+       if (ext_if == NULL || strlen(ext_if) == 0) {
+               ERR("ext_if[%s] is invalid\n", ext_if);
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
+
        int fd = -1;
        char cmd[MAX_BUF_SIZE] = {0, };
 
@@ -1039,6 +910,11 @@ int _mh_core_enable_masquerade(const char *ext_if)
 
 int _mh_core_disable_masquerade(const char *ext_if)
 {
+       if (ext_if == NULL || strlen(ext_if) == 0) {
+               ERR("ext_if[%s] is invalid\n", ext_if);
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
+
        int fd = -1;
        char cmd[MAX_BUF_SIZE] = {0, };
 
index edba972..ef54323 100644 (file)
@@ -57,6 +57,14 @@ gint _slist_find_station_by_mac(gconstpointer a, gconstpointer b)
        return g_ascii_strcasecmp(si->mac, mac);
 }
 
+gint _slist_find_station_by_ip_addr(gconstpointer a, gconstpointer b)
+{
+       mobile_ap_station_info_t *si = (mobile_ap_station_info_t *)a;
+       const char *ip_addr = (const char *)b;
+
+       return g_ascii_strcasecmp(si->ip, ip_addr);
+}
+
 void _emit_mobileap_dbus_signal(MobileAPObject *obj,
                                mobile_ap_sig_e num, const gchar *message)
 {
index 461d951..425b12c 100644 (file)
@@ -45,6 +45,8 @@ static sp_timeout_handler_t sp_timeout_handler[MOBILE_AP_TYPE_MAX] = {
        {0, NULL, NULL},
        {0, __bt_timeout_cb, NULL}};
 
+
+
 static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
 {
        if (key == NULL) {
@@ -55,8 +57,8 @@ static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
        MobileAPObject *obj = (MobileAPObject *)data;
        int vconf_key = 0;
 
-       if (_mobileap_is_disabled()) {
-               DBG("Tethering is not enabled\n");
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
+               DBG("Wi-Fi tethering is not enabled\n");
                return;
        }
 
@@ -69,10 +71,8 @@ static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
        DBG("key = %s, value = %d(bool)\n",
                        vconf_keynode_get_name(key), vconf_key);
 
-       if (vconf_key == FALSE) {
-               DBG("Flight mode is turned off\n");
+       if (vconf_key == FALSE)
                return;
-       }
 
        DBG("Flight mode\n");
        _disable_wifi_tethering(obj);
@@ -81,7 +81,6 @@ static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
        return;
 }
 
-
 static void __handle_device_name_changed_cb(keynode_t *key, void *data)
 {
        if (key == NULL || data == NULL) {
@@ -116,9 +115,6 @@ static void __handle_device_name_changed_cb(keynode_t *key, void *data)
        return;
 }
 
-
-
-
 void _register_vconf_cb(void *user_data)
 {
        if (user_data == NULL) {
@@ -127,7 +123,7 @@ void _register_vconf_cb(void *user_data)
        }
 
        vconf_reg_t vconf_reg[] = {
-               {VCONFKEY_SETAPPL_FLIGHT_MODE_BOOL,
+               {VCONFKEY_TELEPHONY_FLIGHT_MODE,
                        __handle_flight_mode_changed_cb, NULL},
                {VCONFKEY_SETAPPL_DEVICE_NAME_STR,
                        __handle_device_name_changed_cb, NULL},
@@ -167,7 +163,7 @@ void _unregister_vconf_cb(void *user_data)
        }
 
        vconf_reg_t vconf_reg[] = {
-               {VCONFKEY_SETAPPL_FLIGHT_MODE_BOOL,
+               {VCONFKEY_TELEPHONY_FLIGHT_MODE,
                        __handle_flight_mode_changed_cb, NULL},
                {VCONFKEY_SETAPPL_DEVICE_NAME_STR,
                        __handle_device_name_changed_cb, NULL},
@@ -325,3 +321,4 @@ void _deinit_timeout_cb(mobile_ap_type_e type) {
        DBG("-\n");
        return;
 }
+
index 9a639f9..118839d 100644 (file)
@@ -233,11 +233,12 @@ gboolean _init_tethering(MobileAPObject *obj)
 
        obj->init_count++;
 
-       DBG("Set masquerading / Run DHCP\n");
        __block_device_sleep();
 
+       DBG("Open network\n");
        _open_network();
 
+       DBG("Run DHCP server\n");
        _mh_core_execute_dhcp_server();
 
        return TRUE;
@@ -367,6 +368,7 @@ gboolean mobileap_get_data_packet_usage(MobileAPObject *obj,
        return TRUE;
 }
 
+
 static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
                DBusMessage *msg, void *user_data)
 {
@@ -462,9 +464,9 @@ static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
                        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
                }
 
-               DBG("DhcpLeaseDeleted signal : %s  %s %s\n", ip_addr, mac, name);
+               DBG("DhcpLeaseDeleted signal : %s %s %s\n", ip_addr, mac, name);
 
-               _remove_station_info(mac, _slist_find_station_by_mac);
+               _remove_station_info(ip_addr, _slist_find_station_by_ip_addr);
 
                return DBUS_HANDLER_RESULT_HANDLED;
        }
index 1b78f59..a472c35 100644 (file)
  * limitations under the License.
  */
 
+#include <stdio.h>
 #include <stdlib.h>
+#include <net_connection.h>
 
 #include "mobileap_agent.h"
+#include "mobileap_common.h"
 #include "mobileap_network.h"
 
 static connection_h connection = NULL;
 static connection_profile_h cprof = NULL;
+static char *dns_addr = NULL;
+
+static gboolean __set_dns_forward(void);
+static gboolean __unset_dns_forward(void);
 
 static void __print_profile(connection_profile_h profile)
 {
@@ -92,12 +99,15 @@ static void __connection_opened_cb(connection_error_e result, void *user_data)
                cprof = NULL;
                return;
        }
+       DBG("connection is opened\n");
 
        if (_mobileap_is_disabled()) {
+               DBG("Tethering is disabled\n");
                _close_network();
                return;
        }
 
+       DBG("Set masquerading\n");
        if (_set_masquerade() == FALSE) {
                ERR("_set_masquerade is failed\n");
                _close_network();
@@ -156,6 +166,7 @@ static gboolean __is_tethering_cellular_prof(connection_profile_h profile)
                return FALSE;
        }
 
+       DBG("Service type : %d\n", svc_type);
        if (svc_type != CONNECTION_CELLULAR_SERVICE_TYPE_TETHERING)
                return FALSE;
 
@@ -180,11 +191,16 @@ static gboolean __get_tethering_cellular_prof(connection_profile_h *profile, gbo
                connection_profile_destroy(*profile);
                return FALSE;
        }
+       DBG("Tethering cellular service profile\n");
+       __print_profile(*profile);
 
-       if (pstat != CONNECTION_PROFILE_STATE_CONNECTED)
+       if (pstat != CONNECTION_PROFILE_STATE_CONNECTED) {
+               DBG("Tethering profile is not connected\n");
                *is_connected = FALSE;
-       else
+       } else {
+               DBG("Tethering profile is connected\n");
                *is_connected = TRUE;
+       }
 
        return TRUE;
 }
@@ -200,16 +216,20 @@ static gboolean __get_network_prof(connection_profile_h *r_prof, gboolean *is_co
                return FALSE;
        }
 
+       DBG("Current connected net_type : %d\n", net_type);
        if (net_type == CONNECTION_PROFILE_TYPE_CELLULAR) {
+               DBG("Cellular profile\n");
+               __print_profile(profile);
+
                if (__is_tethering_cellular_prof(profile) == TRUE)
                        goto DONE;
 
-               if (__get_tethering_cellular_prof(&tether_prof, is_connected) == FALSE) {
-                       DBG("There is no tethering service cellular\n");
+               if (__get_tethering_cellular_prof(&tether_prof, is_connected) == FALSE)
                        goto DONE;
-               }
                connection_profile_destroy(profile);
 
+               DBG("Getting tethering profile is successful\n");
+
                *r_prof = tether_prof;
                return TRUE;
        }
@@ -290,12 +310,90 @@ gboolean _unset_masquerade(void)
        return TRUE;
 }
 
+static gboolean __set_dns_forward(void)
+{
+       if (cprof == NULL) {
+               ERR("There is no connected network profile\n");
+               return FALSE;
+       }
+
+       char cmd[MAX_BUF_SIZE] = {0, };
+       char *interface[] = {WIFI_IF, BT_IF_ALL, USB_IF, NULL};
+       int conn_ret;
+       int i;
+
+       if (dns_addr)
+               __unset_dns_forward();
+
+       conn_ret = connection_profile_get_dns_address(cprof, DNS_ORDER,
+                       CONNECTION_ADDRESS_FAMILY_IPV4, &dns_addr);
+       if (conn_ret != CONNECTION_ERROR_NONE || dns_addr == NULL) {
+               ERR("connection_profile_get_dns_address is failed : 0x%X, 0x%p\n",
+                               conn_ret, dns_addr);
+               return FALSE;
+       }
+
+       if (strlen(dns_addr) == 0) {
+               ERR("DNS Address has zero length\n");
+               free(dns_addr);
+               dns_addr = NULL;
+               return FALSE;
+       }
+
+       DBG("DNS Address : %s\n", dns_addr);
+       for (i = 0; interface[i] != NULL; i++) {
+               snprintf(cmd, sizeof(cmd),
+                               "%s -t nat -A PREROUTING "TCP_DNS_FORWARD_RULE,
+                               IPTABLES, interface[i], dns_addr);
+               _execute_command(cmd);
+
+               snprintf(cmd, sizeof(cmd),
+                               "%s -t nat -A PREROUTING "UDP_DNS_FORWARD_RULE,
+                               IPTABLES, interface[i], dns_addr);
+               _execute_command(cmd);
+       }
+
+       return TRUE;
+}
+
+static gboolean __unset_dns_forward(void)
+{
+       if (dns_addr == NULL) {
+               DBG("There is no configured dns forward\n");
+               return TRUE;
+       }
+
+       char cmd[MAX_BUF_SIZE] = {0, };
+       char *interface[] = {WIFI_IF, BT_IF_ALL, USB_IF, NULL};
+       int i;
+
+       DBG("DNS Address : %s\n", dns_addr);
+       for (i = 0; interface[i] != NULL; i++) {
+               snprintf(cmd, sizeof(cmd),
+                               "%s -t nat -D PREROUTING "TCP_DNS_FORWARD_RULE,
+                               IPTABLES, interface[i], dns_addr);
+               _execute_command(cmd);
+
+               snprintf(cmd, sizeof(cmd),
+                               "%s -t nat -D PREROUTING "UDP_DNS_FORWARD_RULE,
+                               IPTABLES, interface[i], dns_addr);
+               _execute_command(cmd);
+       }
+
+       free(dns_addr);
+       dns_addr = NULL;
+
+       return TRUE;
+}
+
 gboolean _open_network(void)
 {
        connection_profile_h profile = NULL;
        gboolean is_connected = FALSE;
        int conn_ret;
 
+       DBG("+\n");
+
        if (__get_network_prof(&profile, &is_connected) == FALSE) {
                ERR("__get_network_prof is failed\n");
                return FALSE;
@@ -303,6 +401,7 @@ gboolean _open_network(void)
        cprof = profile;
 
        if (is_connected == FALSE) {
+               DBG("Profile is not connected\n");
                conn_ret = connection_open_profile(connection, cprof,
                                __connection_opened_cb, NULL);
                if (conn_ret != CONNECTION_ERROR_NONE) {
@@ -315,12 +414,23 @@ gboolean _open_network(void)
                return TRUE;
        }
 
+       DBG("Set masquerading\n");
        if (_set_masquerade() == FALSE) {
                ERR("_set_masquerade is failed\n");
                _close_network();
                return FALSE;
        }
 
+       DBG("Set dns forwarding\n");
+       if (__set_dns_forward() == FALSE) {
+               ERR("_set_dns_forward is failed\n");
+               _unset_masquerade();
+               _close_network();
+               return FALSE;
+       }
+
+       DBG("-\n");
+
        return TRUE;
 }
 
@@ -331,6 +441,11 @@ gboolean _close_network(void)
        if (cprof == NULL)
                return TRUE;
 
+       DBG("+\n");
+
+       if (__unset_dns_forward() == FALSE)
+               ERR("__unset_dns_forward is failed\n");
+
        if (_unset_masquerade() == FALSE)
                ERR("_unset_masquerade is failed\n");
 
@@ -339,6 +454,8 @@ gboolean _close_network(void)
                                __connection_closed_cb, NULL);
                if (conn_ret != CONNECTION_ERROR_NONE) {
                        ERR("connection_close_profile is failed : 0x%X\n", conn_ret);
+                       connection_profile_destroy(cprof);
+                       cprof = NULL;
                        return FALSE;
                }
 
@@ -348,6 +465,7 @@ gboolean _close_network(void)
        connection_profile_destroy(cprof);
        cprof = NULL;
 
+       DBG("-\n");
        return TRUE;
 }
 
index c6f81ce..ec53043 100644 (file)
@@ -43,6 +43,10 @@ int _create_timeout_noti(const char *content, const char *title,
                        ret = notification_delete(noti);
                        if (ret != NOTIFICATION_ERROR_NONE) {
                                ERR("Fail to notification_delete [%d]\n", ret);
+
+                               ret = notification_free(noti);
+                               if (ret != NOTIFICATION_ERROR_NONE)
+                                       ERR("Fail to notification_free [%d]\n", ret);
                                return MOBILE_AP_ERROR_INTERNAL;
                        }
 
@@ -243,12 +247,17 @@ int _update_connected_noti(const char *content)
                        content, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_text [%d]\n", ret);
+
+               ret = notification_free(noti);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       ERR("Fail to notification_free [%d]\n", ret);
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
        ret = notification_update(noti);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_update [%d]\n", ret);
+
                ret = notification_free(noti);
                if (ret != NOTIFICATION_ERROR_NONE)
                        ERR("Fail to notification_free [%d]\n", ret);
@@ -282,6 +291,10 @@ int _delete_connected_noti(void)
        ret = notification_delete(noti);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_delete [%d]\n", ret);
+
+               ret = notification_free(noti);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       ERR("Fail to notification_free [%d]\n", ret);
                return MOBILE_AP_ERROR_INTERNAL;
        }