c0ba52080f1370f8302ad7d39f17880e68e17885
[framework/connectivity/mobileap-agent.git] / src / mobileap_main.c
1 /*
2  *  mobileap-agent
3  *
4  * Copyright 2012-2013  Samsung Electronics Co., Ltd
5  *
6  * Licensed under the Flora License, Version 1.1 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://floralicense.org/license
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <glib.h>
23 #include <dbus/dbus.h>
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus-glib-lowlevel.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <pmapi.h>
30 #include <vconf.h>
31 #include <net_connection.h>
32
33 #include "mobileap_agent.h"
34 #include "mobileap_handler.h"
35 #include "mobileap_common.h"
36 #include "mobileap_bluetooth.h"
37 #include "mobileap_wifi.h"
38 #include "mobileap_usb.h"
39 #include "mobileap_network.h"
40
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)
44
45 GMainLoop *mainloop = NULL;
46 int mobileap_state = MOBILE_AP_STATE_NONE;
47 DBusConnection *tethering_conn = NULL;
48
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);
59
60 #include "tethering-server-stub.h"
61
62 int ref_agent = 0;
63
64 static void tethering_object_init(TetheringObject *obj)
65 {
66         DBG("+\n");
67         g_assert(obj != NULL);
68
69         obj->bt_context = NULL;
70         obj->usb_context = NULL;
71         obj->bt_device = NULL;
72         obj->rx_bytes = 0;
73         obj->tx_bytes = 0;
74         obj->transfer_check_count = 0;
75 }
76
77 static void tethering_object_finalize(GObject *obj)
78 {
79         DBG("+\n");
80
81         G_OBJECT_CLASS(tethering_object_parent_class)->finalize(obj);
82 }
83
84 static void tethering_object_class_init(TetheringObjectClass *klass)
85 {
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
103         };
104
105         int i = 0;
106
107         g_assert(klass != NULL);
108
109         object_class->finalize = tethering_object_finalize;
110
111         DBG("Creating signals\n");
112
113         for (i = 0; i < E_SIGNAL_MAX; i++) {
114                 guint signalId;
115
116                 signalId = g_signal_new(signalNames[i],
117                                         G_OBJECT_CLASS_TYPE(klass),
118                                         G_SIGNAL_RUN_LAST,
119                                         0, NULL, NULL,
120                                         g_cclosure_marshal_VOID__STRING,
121                                         G_TYPE_NONE, 1, G_TYPE_STRING);
122                 klass->signals[i] = signalId;
123         }
124
125         DBG("Binding to GLib/D-Bus\n");
126
127         dbus_g_object_type_install_info(TETHERING_TYPE_OBJECT,
128                                         &dbus_glib_tethering_object_info);
129 }
130
131 static void __add_station_info_to_array(gpointer data, gpointer user_data)
132 {
133         mobile_ap_station_info_t *si = (mobile_ap_station_info_t *)data;
134         GPtrArray *array = (GPtrArray *)user_data;
135         GValue value = {0, {{0}}};
136
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));
143 }
144
145 gboolean _mobileap_set_state(int state)
146 {
147         int vconf_ret = 0;
148
149         DBG("Before mobileap_state : %d\n", mobileap_state);
150         mobileap_state |= state;
151         DBG("After mobileap_state : %d\n", mobileap_state);
152
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);
156                 return FALSE;
157         }
158
159         return TRUE;
160 }
161
162 gboolean _mobileap_is_disabled(void)
163 {
164         return mobileap_state ? FALSE : TRUE;
165 }
166
167 gboolean _mobileap_is_enabled(int state)
168 {
169         return (mobileap_state & state) ? TRUE : FALSE;
170 }
171
172 gboolean _mobileap_is_enabled_by_type(mobile_ap_type_e type)
173 {
174         switch (type) {
175         case MOBILE_AP_TYPE_WIFI:
176                 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
177                         return TRUE;
178                 break;
179
180         case MOBILE_AP_TYPE_BT:
181                 if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
182                         return TRUE;
183                 break;
184
185         case MOBILE_AP_TYPE_USB:
186                 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
187                         return TRUE;
188                 break;
189
190         default:
191                 ERR("Unknow type : %d\n", type);
192                 break;
193         }
194
195         return FALSE;
196 }
197
198 gboolean _mobileap_clear_state(int state)
199 {
200         int vconf_ret = 0;
201
202         DBG("Before mobileap_state : %d\n", mobileap_state);
203         mobileap_state &= (~state);
204         DBG("After mobileap_state : %d\n", mobileap_state);
205
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);
209                 return FALSE;
210         }
211
212         return TRUE;
213 }
214
215 static void __block_device_sleep(void)
216 {
217         int ret = 0;
218
219         ret = pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
220
221         if (ret < 0)
222                 ERR("PM control [ERROR] result = %d\n", ret);
223         else
224                 DBG("PM control [SUCCESS]\n");
225 }
226
227 static void __unblock_device_sleep(void)
228 {
229         int ret = 0;
230
231         ret = pm_unlock_state(LCD_OFF, PM_SLEEP_MARGIN);
232         if (ret < 0)
233                 ERR("PM control [ERROR] result = %d\n", ret);
234         else
235                 DBG("PM control [SUCCESS]\n");
236 }
237
238 gboolean _init_tethering(TetheringObject *obj)
239 {
240         DBG("obj->init_count: %d\n", obj->init_count);
241
242         if (obj->init_count > 0) {
243                 DBG("Already env. is initialized for tethering: %d\n",
244                                 obj->init_count);
245                 obj->init_count++;
246                 return TRUE;
247         }
248
249         obj->init_count++;
250
251         __block_device_sleep();
252
253         DBG("Open network\n");
254         _open_network();
255
256         DBG("Run DHCP server\n");
257         _mh_core_execute_dhcp_server();
258
259         return TRUE;
260 }
261
262 gboolean _deinit_tethering(TetheringObject *obj)
263 {
264         DBG("obj->init_count: %d\n", obj->init_count);
265
266         if (obj->init_count > 1) {
267                 DBG("Already deinitialized\n");
268                 obj->init_count--;
269                 return TRUE;
270         } else if (obj->init_count <= 0) {
271                 ERR("Already deinitialized\n");
272                 obj->init_count = 0;
273                 return TRUE;
274         }
275
276         obj->init_count = 0;
277
278         DBG("Terminate DHCP / IPTABLES\n");
279         _mh_core_terminate_dhcp_server();
280         _close_network();
281         __unblock_device_sleep();
282
283         return TRUE;
284 }
285
286 gboolean tethering_init(TetheringObject *obj, GError **error)
287 {
288         DBG("There are [%d] references\n", ++ref_agent);
289
290         return TRUE;
291 }
292
293 gboolean tethering_deinit(TetheringObject *obj, GError **error)
294 {
295         if (--ref_agent <= 0 && _mobileap_is_disabled() &&
296                         !_is_trying_network_operation()) {
297                 DBG("Terminate mobileap-agent\n");
298                 g_main_loop_quit(mainloop);
299         }
300
301         DBG("There are [%d] references\n", ref_agent);
302
303         return TRUE;
304 }
305
306 gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context)
307 {
308         int ret = MOBILE_AP_ERROR_NONE;
309
310         DBG("+\n");
311         g_assert(obj != NULL);
312         g_assert(context != NULL);
313
314         if (_mobileap_is_disabled()) {
315                 ERR("Mobile hotspot has not been enabled\n");
316                 ret = MOBILE_AP_ERROR_NOT_ENABLED;
317                 dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
318                 return FALSE;
319         }
320
321         _disable_wifi_tethering(obj);
322         _disable_bt_tethering(obj);
323         _disable_usb_tethering(obj);
324
325         dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
326
327         return TRUE;
328 }
329
330 gboolean tethering_get_station_info(TetheringObject *obj,
331                                                 DBusGMethodInvocation *context)
332 {
333         DBG("+\n");
334
335         GPtrArray *array = g_ptr_array_new();
336
337         g_assert(obj != NULL);
338         g_assert(context != NULL);
339
340         _station_info_foreach(__add_station_info_to_array, array);
341
342         dbus_g_method_return(context, MOBILE_AP_GET_STATION_INFO_CFM, array);
343         g_ptr_array_free(array, TRUE);
344
345         DBG("-\n");
346
347         return TRUE;
348 }
349
350 gboolean tethering_get_data_packet_usage(TetheringObject *obj,
351                                                 DBusGMethodInvocation *context)
352 {
353         char *if_name = NULL;
354         unsigned long long wifi_tx_bytes = 0;
355         unsigned long long wifi_rx_bytes = 0;
356         unsigned long long bt_tx_bytes = 0;
357         unsigned long long bt_rx_bytes = 0;
358         unsigned long long usb_tx_bytes = 0;
359         unsigned long long usb_rx_bytes = 0;
360         unsigned long long tx_bytes = 0;
361         unsigned long long rx_bytes = 0;
362
363         if (_get_network_interface_name(&if_name) == FALSE) {
364                 ERR("No network interface\n");
365                 dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
366                                 0ULL, 0ULL);
367                 return FALSE;
368         }
369
370         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
371                 _get_data_usage(WIFI_IF, if_name,
372                                 &wifi_tx_bytes, &wifi_rx_bytes);
373
374         if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
375                 _get_data_usage(BT_IF_ALL, if_name,
376                                 &bt_tx_bytes, &bt_rx_bytes);
377
378         if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
379                 _get_data_usage(USB_IF, if_name,
380                                 &usb_tx_bytes, &usb_rx_bytes);
381         free(if_name);
382
383         tx_bytes = wifi_tx_bytes + bt_tx_bytes + usb_tx_bytes;
384         rx_bytes = wifi_rx_bytes + bt_rx_bytes + usb_rx_bytes;
385
386         dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
387                         tx_bytes, rx_bytes);
388
389         return TRUE;
390 }
391
392 gboolean tethering_set_ip_forward_status(TetheringObject *obj,
393                 gint forward_mode,  DBusGMethodInvocation *context)
394 {
395         g_assert(obj != NULL);
396
397         gboolean ret;
398
399         if (forward_mode == 0) {
400                 ret = _unset_masquerade();
401         } else {
402                 ret = _set_masquerade();
403         }
404
405         dbus_g_method_return(context, ret);
406
407         return TRUE;
408 }
409
410 gboolean tethering_get_ip_forward_status(TetheringObject *obj, gint *forward_mode)
411 {
412         g_assert(obj != NULL);
413
414         int fd;
415         int ret;
416         char value[2] = {0, };
417
418         fd = open(IP_FORWARD, O_RDONLY);
419         if (fd < 0) {
420                 ERR("open failed\n");
421                 return FALSE;
422         }
423
424         ret = read(fd, value, sizeof(value));
425         if (ret < 0) {
426                 ERR("read is failed\n");
427                 close(fd);
428                 return FALSE;
429         }
430         close(fd);
431
432         *forward_mode = atoi(value);
433
434         return TRUE;
435 }
436
437
438 static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
439                 DBusMessage *msg, void *user_data)
440 {
441         if (!user_data) {
442                 ERR("Invalid param\n");
443                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
444         }
445
446         char *ip_addr = NULL;
447         char *mac = NULL;
448         char *name = NULL;
449         char *bt_remote_device_name = NULL;
450         DBusError error;
451         mobile_ap_type_e type = MOBILE_AP_TYPE_MAX;
452         TetheringObject *obj = (TetheringObject *)user_data;
453         mobile_ap_station_info_t *info = NULL;
454         int n_station = 0;
455         time_t tm;
456
457         dbus_error_init(&error);
458         if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
459                                 "DhcpConnected")) {
460                 if (!dbus_message_get_args(msg, &error,
461                                         DBUS_TYPE_STRING, &ip_addr,
462                                         DBUS_TYPE_STRING, &mac,
463                                         DBUS_TYPE_STRING, &name,
464                                         DBUS_TYPE_INVALID)) {
465                         ERR("Cannot read message, cause: %s\n", error.message);
466                         dbus_error_free(&error);
467                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
468                 }
469                 DBG("DhcpConnected signal : %s  %s %s\n", ip_addr, mac, name);
470
471                 if (_get_tethering_type_from_ip(ip_addr, &type) != MOBILE_AP_ERROR_NONE)
472                         return DBUS_HANDLER_RESULT_HANDLED;
473
474                 if (_mobileap_is_enabled_by_type(type) == FALSE) {
475                         DBG("Tethering[%d] is disabled. Ignore ACK\n", type);
476                         return DBUS_HANDLER_RESULT_HANDLED;
477                 }
478
479                 info = (mobile_ap_station_info_t *)malloc(sizeof(mobile_ap_station_info_t));
480                 if (info == NULL) {
481                         ERR("malloc failed\n");
482                         return DBUS_HANDLER_RESULT_HANDLED;
483                 }
484
485                 info->interface = type;
486                 g_strlcpy(info->ip, ip_addr, sizeof(info->ip));
487                 g_strlcpy(info->mac, mac, sizeof(info->mac));
488                 if (type == MOBILE_AP_TYPE_WIFI || type == MOBILE_AP_TYPE_USB) {
489                         if (name[0] == '\0')
490                                 g_strlcpy(info->hostname,
491                                                 MOBILE_AP_NAME_UNKNOWN,
492                                                 sizeof(info->hostname));
493                         else
494                                 g_strlcpy(info->hostname, name,
495                                                 sizeof(info->hostname));
496                 } else if (type == MOBILE_AP_TYPE_BT) {
497                         _bt_get_remote_device_name(obj, mac, &bt_remote_device_name);
498                         if (bt_remote_device_name == NULL)
499                                 g_strlcpy(info->hostname,
500                                                 MOBILE_AP_NAME_UNKNOWN,
501                                                 sizeof(info->hostname));
502                         else {
503                                 g_strlcpy(info->hostname, bt_remote_device_name,
504                                                 sizeof(info->hostname));
505                                 free(bt_remote_device_name);
506                         }
507                 }
508                 time(&tm);
509                 info->tm = tm;
510
511                 if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
512                         free(info);
513                         return DBUS_HANDLER_RESULT_HANDLED;
514                 }
515
516                 _get_station_count((gconstpointer)type,
517                                 _slist_find_station_by_interface, &n_station);
518                 if (n_station == 1)
519                         _stop_timeout_cb(type);
520
521                 _send_dbus_station_info("DhcpConnected", info);
522
523                 return DBUS_HANDLER_RESULT_HANDLED;
524         } else if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
525                                 "DhcpLeaseDeleted")) {
526                 if (!dbus_message_get_args(msg, &error,
527                                         DBUS_TYPE_STRING, &ip_addr,
528                                         DBUS_TYPE_STRING, &mac,
529                                         DBUS_TYPE_STRING, &name,
530                                         DBUS_TYPE_INVALID)) {
531                         ERR("Cannot read message, cause: %s\n", error.message);
532                         dbus_error_free(&error);
533                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
534                 }
535
536                 DBG("DhcpLeaseDeleted signal : %s %s %s\n", ip_addr, mac, name);
537
538                 _remove_station_info(ip_addr, _slist_find_station_by_ip_addr);
539
540                 return DBUS_HANDLER_RESULT_HANDLED;
541         }
542
543         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
544 }
545
546 int main(int argc, char **argv)
547 {
548         TetheringObject *tethering_obj = NULL;
549         DBusError dbus_error;
550         char *rule = "type='signal',interface='"DNSMASQ_DBUS_INTERFACE"'";
551         DBusGConnection *tethering_bus = NULL;
552         DBusGProxy *tethering_bus_proxy = NULL;
553         guint result = 0;
554         GError *error = NULL;
555         int mobileap_vconf_key = VCONFKEY_MOBILE_HOTSPOT_MODE_NONE;
556
557 #if !GLIB_CHECK_VERSION(2,35,0)
558         g_type_init();
559 #endif
560
561         if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobileap_vconf_key)) {
562                 ERR("vconf_get_int FAIL\n");
563                 mobileap_state = MOBILE_AP_STATE_NONE;
564         } else {
565                 ERR("vconf_get_int OK(mobileap_vconf_key value is %d)\n",
566                                  mobileap_vconf_key);
567                 mobileap_state = mobileap_vconf_key;
568         }
569
570         mainloop = g_main_loop_new(NULL, FALSE);
571         if (mainloop == NULL) {
572                 ERR("Couldn't create GMainLoop\n");
573                 goto failure;
574         }
575
576         tethering_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
577         if (error != NULL) {
578                 ERR("Couldn't connect to system bus[%s]\n", error->message);
579                 goto failure;
580         }
581
582         tethering_conn = dbus_g_connection_get_connection(tethering_bus);
583
584         DBG("Registering the well-known name (%s)\n", TETHERING_SERVICE_NAME);
585
586         tethering_bus_proxy = dbus_g_proxy_new_for_name(tethering_bus,
587                                                        DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
588         if (tethering_bus_proxy == NULL) {
589                 ERR("Failed to get a proxy for D-Bus\n");
590                 goto failure;
591         }
592
593         if (!dbus_g_proxy_call(tethering_bus_proxy,
594                                "RequestName",
595                                &error,
596                                G_TYPE_STRING,
597                                TETHERING_SERVICE_NAME,
598                                G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID)) {
599                 ERR("D-Bus.RequestName RPC failed[%s]\n", error->message);
600                 goto failure;
601         }
602
603         if (result != 1) {
604                 ERR("Failed to get the primary well-known name.\n");
605                 goto failure;
606         }
607
608         g_object_unref(tethering_bus_proxy);
609         tethering_bus_proxy = NULL;
610
611         tethering_obj = g_object_new(TETHERING_TYPE_OBJECT, NULL);
612         if (tethering_obj == NULL) {
613                 ERR("Failed to create one MobileAP instance.\n");
614                 goto failure;
615         }
616
617         /* Registering it on the D-Bus */
618         dbus_g_connection_register_g_object(tethering_bus,
619                         TETHERING_SERVICE_OBJECT_PATH, G_OBJECT(tethering_obj));
620
621         DBG("Ready to serve requests.\n");
622
623         _init_network(NULL);
624         _register_wifi_station_handler();
625         _register_vconf_cb((void *)tethering_obj);
626
627         dbus_error_init(&dbus_error);
628         dbus_bus_add_match(tethering_conn, rule, &dbus_error);
629         if (dbus_error_is_set(&dbus_error)) {
630                 ERR("Cannot add D-BUS match rule, cause: %s", dbus_error.message);
631                 dbus_error_free(&dbus_error);
632                 goto failure;
633         }
634
635         DBG("Listening to D-BUS signals from dnsmasq");
636         dbus_connection_add_filter(tethering_conn, __dnsmasq_signal_filter, tethering_obj, NULL);
637
638         g_main_loop_run(mainloop);
639
640         _unregister_vconf_cb((void *)tethering_obj);
641         _deinit_network();
642
643  failure:
644         ERR("Terminate the mobileap-agent\n");
645
646         if (tethering_bus)
647                 dbus_g_connection_unref(tethering_bus);
648         if (tethering_bus_proxy)
649                 g_object_unref(tethering_bus_proxy);
650         if (tethering_obj)
651                 g_object_unref(tethering_obj);
652
653         return 0;
654 }