3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 #include <dbus/dbus.h>
22 #include <dbus/dbus-glib.h>
23 #include <dbus/dbus-glib-lowlevel.h>
29 #include <net_connection.h>
30 #include <appcore-common.h>
32 #include "mobileap_agent.h"
33 #include "mobileap_handler.h"
34 #include "mobileap_common.h"
35 #include "mobileap_bluetooth.h"
36 #include "mobileap_wifi.h"
37 #include "mobileap_usb.h"
38 #include "mobileap_network.h"
39 #include "mobileap_notification.h"
41 GType tethering_object_get_type(void);
42 #define TETHERING_TYPE_OBJECT (tethering_object_get_type())
43 G_DEFINE_TYPE(TetheringObject, tethering_object, G_TYPE_OBJECT)
45 GMainLoop *mainloop = NULL;
46 int mobileap_state = MOBILE_AP_STATE_NONE;
47 DBusConnection *tethering_conn = NULL;
49 gboolean tethering_init(TetheringObject *obj, GError **error);
50 gboolean tethering_deinit(TetheringObject *obj, GError **error);
51 gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context);
52 gboolean tethering_get_station_info(TetheringObject *obj,
53 DBusGMethodInvocation *context);
54 gboolean tethering_get_data_packet_usage(TetheringObject *obj,
55 DBusGMethodInvocation *context);
56 gboolean tethering_set_ip_forward_status(TetheringObject *obj,
57 gint forward_mode, DBusGMethodInvocation *context);
58 gboolean tethering_get_ip_forward_status(TetheringObject *obj, gint *forward_mode);
60 #include "tethering-server-stub.h"
64 static void tethering_object_init(TetheringObject *obj)
67 g_assert(obj != NULL);
69 obj->bt_context = NULL;
70 obj->usb_context = NULL;
71 obj->bt_device = NULL;
74 obj->transfer_check_count = 0;
77 static void tethering_object_finalize(GObject *obj)
81 G_OBJECT_CLASS(tethering_object_parent_class)->finalize(obj);
84 static void tethering_object_class_init(TetheringObjectClass *klass)
86 GObjectClass *object_class = (GObjectClass *)klass;
87 const gchar *signalNames[E_SIGNAL_MAX] = {
88 SIGNAL_NAME_NET_CLOSED,
89 SIGNAL_NAME_STA_CONNECT,
90 SIGNAL_NAME_STA_DISCONNECT,
91 SIGNAL_NAME_WIFI_TETHER_ON,
92 SIGNAL_NAME_WIFI_TETHER_OFF,
93 SIGNAL_NAME_USB_TETHER_ON,
94 SIGNAL_NAME_USB_TETHER_OFF,
95 SIGNAL_NAME_BT_TETHER_ON,
96 SIGNAL_NAME_BT_TETHER_OFF,
97 SIGNAL_NAME_NO_DATA_TIMEOUT,
98 SIGNAL_NAME_LOW_BATTERY_MODE,
99 SIGNAL_NAME_FLIGHT_MODE,
100 SIGNAL_NAME_SECURITY_TYPE_CHANGED,
101 SIGNAL_NAME_SSID_VISIBILITY_CHANGED,
102 SIGNAL_NAME_PASSPHRASE_CHANGED
107 g_assert(klass != NULL);
109 object_class->finalize = tethering_object_finalize;
111 DBG("Creating signals\n");
113 for (i = 0; i < E_SIGNAL_MAX; i++) {
116 signalId = g_signal_new(signalNames[i],
117 G_OBJECT_CLASS_TYPE(klass),
120 g_cclosure_marshal_VOID__STRING,
121 G_TYPE_NONE, 1, G_TYPE_STRING);
122 klass->signals[i] = signalId;
125 DBG("Binding to GLib/D-Bus\n");
127 dbus_g_object_type_install_info(TETHERING_TYPE_OBJECT,
128 &dbus_glib_tethering_object_info);
131 static void __add_station_info_to_array(gpointer data, gpointer user_data)
133 mobile_ap_station_info_t *si = (mobile_ap_station_info_t *)data;
134 GPtrArray *array = (GPtrArray *)user_data;
135 GValue value = {0, {{0}}};
137 g_value_init(&value, DBUS_STRUCT_STATIONS);
138 g_value_take_boxed(&value,
139 dbus_g_type_specialized_construct(DBUS_STRUCT_STATIONS));
140 dbus_g_type_struct_set(&value, 0, si->interface, 1, si->ip,
141 2, si->mac, 3, si->hostname, 4, (guint)(si->tm), G_MAXUINT);
142 g_ptr_array_add(array, g_value_get_boxed(&value));
145 gboolean _mobileap_set_state(int state)
149 DBG("Before mobileap_state : %d\n", mobileap_state);
150 mobileap_state |= state;
151 DBG("After mobileap_state : %d\n", mobileap_state);
153 vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
154 if (vconf_ret != 0) {
155 ERR("vconf_set_int is failed : %d\n", vconf_ret);
162 gboolean _mobileap_is_disabled(void)
164 return mobileap_state ? FALSE : TRUE;
167 gboolean _mobileap_is_enabled(int state)
169 return (mobileap_state & state) ? TRUE : FALSE;
172 gboolean _mobileap_is_enabled_by_type(mobile_ap_type_e type)
175 case MOBILE_AP_TYPE_WIFI:
176 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
180 case MOBILE_AP_TYPE_BT:
181 if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
185 case MOBILE_AP_TYPE_USB:
186 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
191 ERR("Unknow type : %d\n", type);
198 gboolean _mobileap_clear_state(int state)
202 DBG("Before mobileap_state : %d\n", mobileap_state);
203 mobileap_state &= (~state);
204 DBG("After mobileap_state : %d\n", mobileap_state);
206 vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
207 if (vconf_ret != 0) {
208 ERR("vconf_set_int is failed : %d\n", vconf_ret);
215 static void __block_device_sleep(void)
219 ret = pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
221 ERR("PM control [ERROR] result = %d\n", ret);
223 DBG("PM control [SUCCESS]\n");
226 static void __unblock_device_sleep(void)
230 ret = pm_unlock_state(LCD_OFF, PM_SLEEP_MARGIN);
232 ERR("PM control [ERROR] result = %d\n", ret);
234 DBG("PM control [SUCCESS]\n");
237 gboolean _init_tethering(TetheringObject *obj)
239 DBG("obj->init_count: %d\n", obj->init_count);
241 if (obj->init_count > 0) {
242 DBG("Already env. is initialized for tethering: %d\n",
250 __block_device_sleep();
252 DBG("Open network\n");
255 DBG("Run DHCP server\n");
256 _mh_core_execute_dhcp_server();
261 gboolean _deinit_tethering(TetheringObject *obj)
263 DBG("obj->init_count: %d\n", obj->init_count);
265 if (obj->init_count > 1) {
266 DBG("Already deinitialized\n");
269 } else if (obj->init_count <= 0) {
270 ERR("Already deinitialized\n");
277 DBG("Terminate DHCP / IPTABLES\n");
278 _mh_core_terminate_dhcp_server();
280 __unblock_device_sleep();
285 gboolean tethering_init(TetheringObject *obj, GError **error)
287 DBG("There are [%d] references\n", ++ref_agent);
292 gboolean tethering_deinit(TetheringObject *obj, GError **error)
294 if (--ref_agent <= 0 && _mobileap_is_disabled() &&
295 !_is_trying_network_operation()) {
296 DBG("Terminate mobileap-agent\n");
297 g_main_loop_quit(mainloop);
300 DBG("There are [%d] references\n", ref_agent);
305 gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context)
307 int ret = MOBILE_AP_ERROR_NONE;
310 g_assert(obj != NULL);
311 g_assert(context != NULL);
313 if (_mobileap_is_disabled()) {
314 ERR("Mobile hotspot has not been enabled\n");
315 ret = MOBILE_AP_ERROR_NOT_ENABLED;
316 dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
320 _disable_wifi_tethering(obj);
321 _disable_bt_tethering(obj);
322 _disable_usb_tethering(obj);
324 dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
329 gboolean tethering_get_station_info(TetheringObject *obj,
330 DBusGMethodInvocation *context)
334 GPtrArray *array = g_ptr_array_new();
336 g_assert(obj != NULL);
337 g_assert(context != NULL);
339 _station_info_foreach(__add_station_info_to_array, array);
341 dbus_g_method_return(context, MOBILE_AP_GET_STATION_INFO_CFM, array);
342 g_ptr_array_free(array, TRUE);
349 gboolean tethering_get_data_packet_usage(TetheringObject *obj,
350 DBusGMethodInvocation *context)
352 char *if_name = NULL;
353 unsigned long long wifi_tx_bytes = 0;
354 unsigned long long wifi_rx_bytes = 0;
355 unsigned long long bt_tx_bytes = 0;
356 unsigned long long bt_rx_bytes = 0;
357 unsigned long long usb_tx_bytes = 0;
358 unsigned long long usb_rx_bytes = 0;
359 unsigned long long tx_bytes = 0;
360 unsigned long long rx_bytes = 0;
362 if (_get_network_interface_name(&if_name) == FALSE) {
363 ERR("No network interface\n");
364 dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
369 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
370 _get_data_usage(WIFI_IF, if_name,
371 &wifi_tx_bytes, &wifi_rx_bytes);
373 if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
374 _get_data_usage(BT_IF_ALL, if_name,
375 &bt_tx_bytes, &bt_rx_bytes);
377 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
378 _get_data_usage(USB_IF, if_name,
379 &usb_tx_bytes, &usb_rx_bytes);
382 tx_bytes = wifi_tx_bytes + bt_tx_bytes + usb_tx_bytes;
383 rx_bytes = wifi_rx_bytes + bt_rx_bytes + usb_rx_bytes;
385 dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
391 gboolean tethering_set_ip_forward_status(TetheringObject *obj,
392 gint forward_mode, DBusGMethodInvocation *context)
394 g_assert(obj != NULL);
398 if (forward_mode == 0) {
399 ret = _unset_masquerade();
401 ret = _set_masquerade();
404 dbus_g_method_return(context, ret);
409 gboolean tethering_get_ip_forward_status(TetheringObject *obj, gint *forward_mode)
411 g_assert(obj != NULL);
415 char value[2] = {0, };
417 fd = open(IP_FORWARD, O_RDONLY);
419 ERR("open failed\n");
423 ret = read(fd, value, sizeof(value));
425 ERR("read is failed\n");
431 *forward_mode = atoi(value);
437 static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
438 DBusMessage *msg, void *user_data)
441 ERR("Invalid param\n");
442 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
445 char *ip_addr = NULL;
448 char *bt_remote_device_name = NULL;
450 mobile_ap_type_e type = MOBILE_AP_TYPE_MAX;
451 TetheringObject *obj = (TetheringObject *)user_data;
452 mobile_ap_station_info_t *info = NULL;
456 dbus_error_init(&error);
457 if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
459 if (!dbus_message_get_args(msg, &error,
460 DBUS_TYPE_STRING, &ip_addr,
461 DBUS_TYPE_STRING, &mac,
462 DBUS_TYPE_STRING, &name,
463 DBUS_TYPE_INVALID)) {
464 ERR("Cannot read message, cause: %s\n", error.message);
465 dbus_error_free(&error);
466 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
468 DBG("DhcpConnected signal : %s %s %s\n", ip_addr, mac, name);
470 if (_get_tethering_type_from_ip(ip_addr, &type) != MOBILE_AP_ERROR_NONE)
471 return DBUS_HANDLER_RESULT_HANDLED;
473 if (_mobileap_is_enabled_by_type(type) == FALSE) {
474 DBG("Tethering[%d] is disabled. Ignore ACK\n", type);
475 return DBUS_HANDLER_RESULT_HANDLED;
478 info = (mobile_ap_station_info_t *)malloc(sizeof(mobile_ap_station_info_t));
480 ERR("malloc failed\n");
481 return DBUS_HANDLER_RESULT_HANDLED;
484 info->interface = type;
485 g_strlcpy(info->ip, ip_addr, sizeof(info->ip));
486 g_strlcpy(info->mac, mac, sizeof(info->mac));
487 if (type == MOBILE_AP_TYPE_WIFI || type == MOBILE_AP_TYPE_USB) {
489 g_strlcpy(info->hostname,
490 MOBILE_AP_NAME_UNKNOWN,
491 sizeof(info->hostname));
493 g_strlcpy(info->hostname, name,
494 sizeof(info->hostname));
495 } else if (type == MOBILE_AP_TYPE_BT) {
496 _bt_get_remote_device_name(obj, mac, &bt_remote_device_name);
497 if (bt_remote_device_name == NULL)
498 g_strlcpy(info->hostname,
499 MOBILE_AP_NAME_UNKNOWN,
500 sizeof(info->hostname));
502 g_strlcpy(info->hostname, bt_remote_device_name,
503 sizeof(info->hostname));
504 free(bt_remote_device_name);
510 if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
512 return DBUS_HANDLER_RESULT_HANDLED;
515 _get_station_count((gconstpointer)type,
516 _slist_find_station_by_interface, &n_station);
518 _stop_timeout_cb(type);
520 _send_dbus_station_info("DhcpConnected", info);
522 return DBUS_HANDLER_RESULT_HANDLED;
523 } else if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
524 "DhcpLeaseDeleted")) {
525 if (!dbus_message_get_args(msg, &error,
526 DBUS_TYPE_STRING, &ip_addr,
527 DBUS_TYPE_STRING, &mac,
528 DBUS_TYPE_STRING, &name,
529 DBUS_TYPE_INVALID)) {
530 ERR("Cannot read message, cause: %s\n", error.message);
531 dbus_error_free(&error);
532 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
535 DBG("DhcpLeaseDeleted signal : %s %s %s\n", ip_addr, mac, name);
537 _remove_station_info(ip_addr, _slist_find_station_by_ip_addr);
539 return DBUS_HANDLER_RESULT_HANDLED;
542 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
545 int main(int argc, char **argv)
547 TetheringObject *tethering_obj = NULL;
548 DBusError dbus_error;
549 char *rule = "type='signal',interface='"DNSMASQ_DBUS_INTERFACE"'";
550 DBusGConnection *tethering_bus = NULL;
551 DBusGProxy *tethering_bus_proxy = NULL;
553 GError *error = NULL;
554 int mobileap_vconf_key = VCONFKEY_MOBILE_HOTSPOT_MODE_NONE;
556 #if !GLIB_CHECK_VERSION(2,35,0)
560 if (appcore_set_i18n(MOBILEAP_LOCALE_COMMON_PKG, MOBILEAP_LOCALE_COMMON_RES) < 0)
563 if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobileap_vconf_key)) {
564 ERR("vconf_get_int FAIL\n");
565 mobileap_state = MOBILE_AP_STATE_NONE;
567 ERR("vconf_get_int OK(mobileap_vconf_key value is %d)\n",
569 mobileap_state = mobileap_vconf_key;
572 mainloop = g_main_loop_new(NULL, FALSE);
573 if (mainloop == NULL) {
574 ERR("Couldn't create GMainLoop\n");
578 tethering_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
580 ERR("Couldn't connect to system bus[%s]\n", error->message);
584 tethering_conn = dbus_g_connection_get_connection(tethering_bus);
586 DBG("Registering the well-known name (%s)\n", TETHERING_SERVICE_NAME);
588 tethering_bus_proxy = dbus_g_proxy_new_for_name(tethering_bus,
589 DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
590 if (tethering_bus_proxy == NULL) {
591 ERR("Failed to get a proxy for D-Bus\n");
595 if (!dbus_g_proxy_call(tethering_bus_proxy,
599 TETHERING_SERVICE_NAME,
600 G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID)) {
601 ERR("D-Bus.RequestName RPC failed[%s]\n", error->message);
606 ERR("Failed to get the primary well-known name.\n");
610 g_object_unref(tethering_bus_proxy);
611 tethering_bus_proxy = NULL;
613 tethering_obj = g_object_new(TETHERING_TYPE_OBJECT, NULL);
614 if (tethering_obj == NULL) {
615 ERR("Failed to create one MobileAP instance.\n");
619 /* Registering it on the D-Bus */
620 dbus_g_connection_register_g_object(tethering_bus,
621 TETHERING_SERVICE_OBJECT_PATH, G_OBJECT(tethering_obj));
623 DBG("Ready to serve requests.\n");
626 _register_wifi_station_handler();
627 _register_vconf_cb((void *)tethering_obj);
629 dbus_error_init(&dbus_error);
630 dbus_bus_add_match(tethering_conn, rule, &dbus_error);
631 if (dbus_error_is_set(&dbus_error)) {
632 ERR("Cannot add D-BUS match rule, cause: %s", dbus_error.message);
633 dbus_error_free(&dbus_error);
637 DBG("Listening to D-BUS signals from dnsmasq");
638 dbus_connection_add_filter(tethering_conn, __dnsmasq_signal_filter, tethering_obj, NULL);
640 g_main_loop_run(mainloop);
642 _unregister_vconf_cb((void *)tethering_obj);
646 ERR("Terminate the mobileap-agent\n");
649 dbus_g_connection_unref(tethering_bus);
650 if (tethering_bus_proxy)
651 g_object_unref(tethering_bus_proxy);
653 g_object_unref(tethering_obj);