"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
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);
void _stop_timeout_cb(mobile_ap_type_e type);
void _deinit_timeout_cb(mobile_ap_type_e type);
+
#endif
#define __MOBILEAP_NETWORK_H__
#include <glib.h>
-#include <net_connection.h>
gboolean _get_network_interface_name(char **if_name);
gboolean _set_masquerade(void);
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
%{_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
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) {
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);
}
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)) {
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, };
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, };
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)
{
{0, NULL, NULL},
{0, __bt_timeout_cb, NULL}};
+
+
static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
{
if (key == NULL) {
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;
}
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);
return;
}
-
static void __handle_device_name_changed_cb(keynode_t *key, void *data)
{
if (key == NULL || data == NULL) {
return;
}
-
-
-
void _register_vconf_cb(void *user_data)
{
if (user_data == NULL) {
}
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},
}
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},
DBG("-\n");
return;
}
+
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;
return TRUE;
}
+
static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
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;
}
* 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)
{
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();
return FALSE;
}
+ DBG("Service type : %d\n", svc_type);
if (svc_type != CONNECTION_CELLULAR_SERVICE_TYPE_TETHERING)
return FALSE;
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;
}
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;
}
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;
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) {
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;
}
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");
__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;
}
connection_profile_destroy(cprof);
cprof = NULL;
+ DBG("-\n");
return TRUE;
}
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;
}
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);
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;
}