Update Boilerplate
[framework/connectivity/mobileap-agent.git] / src / mobileap_wifi.c
1 /*
2  * mobileap-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 #include <glib.h>
19 #include <dbus/dbus.h>
20 #include <dbus/dbus-glib.h>
21 #include <dbus/dbus-glib-lowlevel.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <ss_manager.h>
26
27 #include "mobileap_agent.h"
28 #include "mobileap_common.h"
29 #include "mobileap_wifi.h"
30 #include "mobileap_handler.h"
31
32 static int __generate_initial_passphrase(char *passphrase_buf);
33 static mobile_ap_error_code_e __get_hide_mode(int *hide_mode);
34 static mobile_ap_error_code_e __set_hide_mode(const int hide_mode);
35 static mobile_ap_error_code_e __get_ssid(char *ssid, unsigned int size);
36 static mobile_ap_error_code_e __get_security_type(char *security_type, unsigned int len);
37 static mobile_ap_error_code_e __set_security_type(const char *security_type);
38 static mobile_ap_error_code_e __get_passphrase(char *passphrase, unsigned int size, unsigned int *passphrase_len);
39 static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const unsigned int size);
40 static gboolean __send_station_event_cb(gpointer data);
41 static void __handle_station_signal(int sig);
42 static mobile_ap_error_code_e __update_wifi_data(MobileAPObject *obj);
43
44 static int __generate_initial_passphrase(char *passphrase_buf)
45 {
46         DBG("+\n");
47
48         guint32 rand_int;
49         int index;
50
51         for (index = 0; index < MOBILE_AP_WIFI_KEY_MIN_LEN; index++) {
52                 rand_int = g_random_int_range('a', 'z');
53                 passphrase_buf[index] = rand_int;
54         }
55         passphrase_buf[index] = '\0';
56
57         return index;
58 }
59
60 static mobile_ap_error_code_e __get_hide_mode(int *hide_mode)
61 {
62         if (hide_mode == NULL) {
63                 ERR("Invalid param\n");
64                 return MOBILE_AP_ERROR_INVALID_PARAM;
65         }
66
67         if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_HIDE, hide_mode) < 0) {
68                 ERR("vconf_get_int is failed\n");
69                 return MOBILE_AP_ERROR_RESOURCE;
70         }
71
72         return MOBILE_AP_ERROR_NONE;
73 }
74
75 static mobile_ap_error_code_e __set_hide_mode(const int hide_mode)
76 {
77         if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_HIDE, hide_mode) < 0) {
78                 ERR("vconf_set_int is failed\n");
79                 return MOBILE_AP_ERROR_RESOURCE;
80         }
81
82         return MOBILE_AP_ERROR_NONE;
83 }
84
85 static mobile_ap_error_code_e __get_ssid(char *ssid, unsigned int size)
86 {
87         if (ssid == NULL)
88                 return MOBILE_AP_ERROR_INVALID_PARAM;
89
90         char *ptr = NULL;
91         char *ptr_tmp = NULL;
92
93         ptr = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
94         if (ptr == NULL)
95                 return MOBILE_AP_ERROR_RESOURCE;
96
97         if (!g_utf8_validate(ptr, -1, (const char **)&ptr_tmp))
98                 *ptr_tmp = '\0';
99
100         g_strlcpy(ssid, ptr, size);
101         free(ptr);
102
103         return MOBILE_AP_ERROR_NONE;
104 }
105
106 static mobile_ap_error_code_e __get_security_type(char *security_type, unsigned int len)
107 {
108         if (security_type == NULL)
109                 return MOBILE_AP_ERROR_INVALID_PARAM;
110
111         char *type_str = NULL;
112         softap_security_type_e type;
113
114         if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, (int *)&type) < 0) {
115                 ERR("vconf_get_int is failed\n");
116                 return MOBILE_AP_ERROR_RESOURCE;
117         }
118
119         switch (type) {
120         case SOFTAP_SECURITY_TYPE_OPEN:
121                 type_str = SOFTAP_SECURITY_TYPE_OPEN_STR;
122                 break;
123
124         case SOFTAP_SECURITY_TYPE_WPA2_PSK:
125                 type_str = SOFTAP_SECURITY_TYPE_WPA2_PSK_STR;
126                 break;
127
128         default:
129                 ERR("Invalid data\n");
130                 return MOBILE_AP_ERROR_RESOURCE;
131         }
132
133         g_strlcpy(security_type, type_str, len);
134
135         return MOBILE_AP_ERROR_NONE;
136 }
137
138 static mobile_ap_error_code_e __set_security_type(const char *security_type)
139 {
140         if (security_type == NULL) {
141                 ERR("Invalid param\n");
142                 return MOBILE_AP_ERROR_INVALID_PARAM;
143         }
144
145         softap_security_type_e type;
146
147         if (!strcmp(security_type, SOFTAP_SECURITY_TYPE_OPEN_STR)) {
148                 type = SOFTAP_SECURITY_TYPE_OPEN;
149         } else if (!strcmp(security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR)) {
150                 type = SOFTAP_SECURITY_TYPE_WPA2_PSK;
151         } else {
152                 ERR("Invalid param\n");
153                 return MOBILE_AP_ERROR_INVALID_PARAM;
154         }
155
156         if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, type) < 0) {
157                 ERR("vconf_set_int is failed\n");
158                 return MOBILE_AP_ERROR_RESOURCE;
159         }
160
161         return MOBILE_AP_ERROR_NONE;
162 }
163
164 static mobile_ap_error_code_e __get_passphrase(char *passphrase,
165                 unsigned int size, unsigned int *passphrase_len)
166 {
167         if (passphrase == NULL || passphrase_len == NULL) {
168                 ERR("Invalid parameter\n");
169                 return MOBILE_AP_ERROR_INVALID_PARAM;
170         }
171
172         int ret = 0;
173         ssm_file_info_t sfi;
174
175         ret = ssm_getinfo(SOFTAP_PASSPHRASE_PATH, &sfi,
176                         SSM_FLAG_SECRET_OPERATION, NULL);
177         if (ret == -SS_FILE_OPEN_ERROR) {
178                 *passphrase_len = __generate_initial_passphrase(passphrase);
179
180                 ret = __set_passphrase(passphrase, *passphrase_len);
181                 if (ret != MOBILE_AP_ERROR_NONE) {
182                         memset(passphrase, 0x00, size);
183                         *passphrase_len = 0;
184                         return ret;
185                 }
186
187                 ret = ssm_getinfo(SOFTAP_PASSPHRASE_PATH, &sfi,
188                                 SSM_FLAG_SECRET_OPERATION, NULL);
189                 if (ret < 0) {
190                         ERR("ssm_getinfo is failed : %d\n", ret);
191                         memset(passphrase, 0x00, size);
192                         *passphrase_len = 0;
193                         return MOBILE_AP_ERROR_RESOURCE;
194                 }
195         } else if (ret < 0) {
196                 ERR("ssm_getinfo is failed : %d\n", ret);
197                 return MOBILE_AP_ERROR_RESOURCE;
198         }
199
200         memset(passphrase, 0x00, size);
201         ret = ssm_read(SOFTAP_PASSPHRASE_PATH, passphrase, sfi.originSize,
202                         passphrase_len, SSM_FLAG_SECRET_OPERATION, NULL);
203         if (ret < 0) {
204                 ERR("ssm_read is failed : %d\n", ret);
205                 return MOBILE_AP_ERROR_RESOURCE;
206         }
207
208         return MOBILE_AP_ERROR_NONE;
209 }
210
211 static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const unsigned int size)
212 {
213         if (size < MOBILE_AP_WIFI_KEY_MIN_LEN || size > MOBILE_AP_WIFI_KEY_MAX_LEN ||
214                         passphrase == NULL) {
215                 ERR("Invalid parameter\n");
216                 return MOBILE_AP_ERROR_INVALID_PARAM;
217         }
218
219         int ret = 0;
220
221         ret = ssm_write_buffer((char *)passphrase, size, SOFTAP_PASSPHRASE_PATH,
222                         SSM_FLAG_SECRET_OPERATION, NULL);
223         if (ret < 0) {
224                 ERR("ssm_write_buffer is failed : %d\n", ret);
225                 return MOBILE_AP_ERROR_RESOURCE;
226         }
227
228         return MOBILE_AP_ERROR_NONE;
229 }
230
231 static gboolean __send_station_event_cb(gpointer data)
232 {
233         int sig = GPOINTER_TO_INT(data);
234         int n_station = 0;
235         mobile_ap_station_info_t *si = NULL;
236
237         if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
238                 return FALSE;
239         }
240
241         if (sig == SIGUSR1) {
242                 DBG("STA connected(%d)\n", sig);
243                 /* STA connection is handled in the dnsmasq signal handler */
244         } else if (sig == SIGUSR2) {
245                 DBG("STA disconnected(%d)\n", sig);
246
247                 /* Temporarily care only one station.
248                  * Driver team should be support detail information */
249                 if (_get_station_info(MOBILE_AP_TYPE_WIFI,
250                                 _slist_find_station_by_interface,
251                                 &si) != MOBILE_AP_ERROR_NONE) {
252                         return FALSE;
253                 }
254                 _remove_station_info(si->mac, _slist_find_station_by_mac);
255
256                 _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
257                                 _slist_find_station_by_interface, &n_station);
258                 if (n_station == 0)
259                         _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
260         }
261
262         return FALSE;
263 }
264
265 static void __handle_station_signal(int sig)
266 {
267         g_idle_add(__send_station_event_cb, GINT_TO_POINTER(sig));
268         return;
269 }
270
271 void _register_wifi_station_handler(void)
272 {
273         struct sigaction sa;
274
275         memset(&sa, 0, sizeof(sa));
276         sa.sa_handler = __handle_station_signal;
277         sigaction(SIGUSR1, &sa, NULL);
278         sigaction(SIGUSR2, &sa, NULL);
279 }
280
281 void _add_wifi_device_to_array(softap_device_info_t *di, GPtrArray *array)
282 {
283         int i = 0;
284         GIOChannel *io = NULL;
285         gchar *line = NULL;
286         gchar *device_name = NULL;
287         gchar ip_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
288         gchar mac_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
289         gchar name[MOBILE_AP_STR_HOSTNAME_LEN] = {0, };
290         gchar expire[MOBILE_AP_STR_INFO_LEN] = {0, };
291         gchar extra[MOBILE_AP_STR_INFO_LEN] = {0, };
292
293         int found = 0;
294
295         for (i = 0; i < di->number; i++)
296                 DBG("bssid[%d]:%s\n", i, di->bssid[i]);
297
298         DBG("Number of connected device:%d\n", di->number);
299
300         io = g_io_channel_new_file(DNSMASQ_LEASES_FILE, "r", NULL);
301
302         while (g_io_channel_read_line(io, &line, NULL, NULL, NULL) ==
303                                                         G_IO_STATUS_NORMAL) {
304                 sscanf(line, "%19s %19s %19s %19s %19s", expire, mac_addr,
305                                                         ip_addr, name, extra);
306                 DBG("mac_addr:%s ip_addr:%s name:%s expire:%s\n", mac_addr,
307                                                         ip_addr, name, expire);
308
309                 for (i = 0; i < di->number; i++) {
310                         if (g_ascii_strcasecmp(di->bssid[i], mac_addr) == 0) {
311                                 if (!strcmp(name, "*"))
312                                         device_name = MOBILE_AP_NAME_UNKNOWN;
313                                 else
314                                         device_name = name;
315
316                                 _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
317                                                                 device_name);
318
319                                 found++;
320
321                                 break;
322                         }
323                 }
324
325                 g_free(line);
326         }
327         g_io_channel_unref(io);
328
329         /* Set the name UNKNOWN unless we got the name. */
330         for (i = found; i < di->number; i++) {
331                 _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
332                                                         MOBILE_AP_NAME_UNKNOWN);
333         }
334 }
335
336 mobile_ap_error_code_e _disable_wifi_tethering(MobileAPObject *obj)
337 {
338         int ret = MOBILE_AP_ERROR_NONE;
339
340         if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
341                 ERR("Wi-Fi tethering has not been activated\n");
342                 ret = MOBILE_AP_ERROR_NOT_ENABLED;
343                 return ret;
344         }
345
346         _deinit_timeout_cb(MOBILE_AP_TYPE_WIFI);
347
348         if (_remove_station_info_all(MOBILE_AP_TYPE_WIFI) !=
349                         MOBILE_AP_ERROR_NONE) {
350                 ERR("_remove_station_info_all is failed. Ignore it.\n");
351         }
352
353         ret = _mh_core_disable_softap();
354         if (ret != MOBILE_AP_ERROR_NONE) {
355                 ERR("_mh_core_disable_softap is failed : %d\n", ret);
356                 return ret;
357         }
358
359         _deinit_tethering(obj);
360         _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
361
362         DBG("_disable_wifi_tethering is done\n");
363
364         return ret;
365 }
366
367 static mobile_ap_error_code_e __update_wifi_data(MobileAPObject *obj)
368 {
369         if (obj == NULL) {
370                 ERR("Invalid param\n");
371                 return MOBILE_AP_ERROR_INVALID_PARAM;
372         }
373
374         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
375         unsigned int read_len = 0;
376
377         ret = __get_ssid(obj->ssid, sizeof(obj->ssid));
378         if (ret != MOBILE_AP_ERROR_NONE)
379                 return ret;
380
381         ret = __get_security_type(obj->security_type, sizeof(obj->security_type));
382         if (ret != MOBILE_AP_ERROR_NONE)
383                 return ret;
384
385         ret = __get_hide_mode(&obj->hide_mode);
386         if (ret != MOBILE_AP_ERROR_NONE)
387                 return ret;
388
389         if (strcmp(obj->security_type, SOFTAP_SECURITY_TYPE_OPEN_STR) == 0) {
390                 g_strlcpy(obj->key, "00000000", sizeof(obj->key));
391         } else if (strcmp(obj->security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR) == 0) {
392                 ret = __get_passphrase(obj->key, sizeof(obj->key), &read_len);
393                 if (ret != MOBILE_AP_ERROR_NONE)
394                         return ret;
395         } else {
396                 ERR("Unknown security type\n");
397                 return MOBILE_AP_ERROR_INTERNAL;
398         }
399
400         DBG("ssid : %s security type : %s hide mode : %d\n",
401                         obj->ssid, obj->security_type, obj->hide_mode);
402
403         return MOBILE_AP_ERROR_NONE;
404 }
405
406 gboolean mobileap_enable_wifi_tethering(MobileAPObject *obj, gchar *ssid,
407                 gchar *key, gint hide_mode, DBusGMethodInvocation *context)
408 {
409         int ret = MOBILE_AP_ERROR_NONE;
410
411         g_assert(obj != NULL);
412         g_assert(context != NULL);
413
414
415         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
416                 ERR("Wi-Fi tethering is already enabled\n");
417                 ret = MOBILE_AP_ERROR_ALREADY_ENABLED;
418                 dbus_g_method_return(context,
419                                 MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
420                 return FALSE;
421         }
422
423         /* Update global state */
424         if (!_mobileap_set_state(MOBILE_AP_STATE_WIFI)) {
425                 ret = MOBILE_AP_ERROR_RESOURCE;
426                 goto FAIL;
427         }
428
429         /* Update Wi-Fi hotspot data to common object */
430         ret = __update_wifi_data(obj);
431         if (ret != MOBILE_AP_ERROR_NONE) {
432                 goto FAIL;
433         }
434
435         /* Initialize tethering */
436         if (!_init_tethering(obj)) {
437                 ret = MOBILE_AP_ERROR_RESOURCE;
438                 goto FAIL;
439         }
440
441         /* Upload driver */
442         ret = _mh_core_enable_softap(obj->ssid, obj->security_type,
443                         obj->key, obj->hide_mode);
444         if (ret != MOBILE_AP_ERROR_NONE) {
445                 _deinit_tethering(obj);
446                 goto FAIL;
447         }
448
449         _init_timeout_cb(MOBILE_AP_TYPE_WIFI, (void *)obj);
450         _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
451
452         _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
453         dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
454
455         return TRUE;
456
457 FAIL:
458         _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
459         dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
460
461         return FALSE;
462 }
463
464 gboolean mobileap_disable_wifi_tethering(MobileAPObject *obj,
465                 DBusGMethodInvocation *context)
466 {
467         int ret = MOBILE_AP_ERROR_NONE;
468
469         DBG("+\n");
470         g_assert(obj != NULL);
471         g_assert(context != NULL);
472
473         ret = _disable_wifi_tethering(obj);
474
475         _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_OFF, NULL);
476         dbus_g_method_return(context, MOBILE_AP_DISABLE_WIFI_TETHERING_CFM, ret);
477
478         if (ret != MOBILE_AP_ERROR_NONE)
479                 return FALSE;
480         else
481                 return TRUE;
482 }
483
484 gboolean mobileap_get_wifi_tethering_hide_mode(MobileAPObject *obj,
485                 DBusGMethodInvocation *context)
486 {
487         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
488         int hide_mode = 0;
489
490         DBG("+\n");
491         g_assert(obj != NULL);
492         g_assert(context != NULL);
493
494         ret = __get_hide_mode(&hide_mode);
495         if (ret != MOBILE_AP_ERROR_NONE) {
496                 ERR("__get_hide_mode is failed : %d\n", ret);
497         }
498
499         dbus_g_method_return(context, hide_mode);
500
501         return TRUE;
502 }
503
504 gboolean mobileap_set_wifi_tethering_hide_mode(MobileAPObject *obj,
505                 gint hide_mode, DBusGMethodInvocation *context)
506 {
507         int ret = 0;
508
509         DBG("+\n");
510         g_assert(obj != NULL);
511         g_assert(context != NULL);
512
513         ret = __set_hide_mode(hide_mode);
514         if (ret < 0) {
515                 ERR("__set_hide_mode is failed : %d\n", ret);
516         }
517
518         dbus_g_method_return(context);
519
520         return TRUE;
521 }
522
523 gboolean mobileap_get_wifi_tethering_ssid(MobileAPObject *obj,
524                 DBusGMethodInvocation *context)
525 {
526         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
527         char ssid[MOBILE_AP_WIFI_SSID_MAX_LEN + 1] = {0, };
528
529         DBG("+\n");
530         g_assert(obj != NULL);
531         g_assert(context != NULL);
532
533         ret = __get_ssid(ssid, sizeof(ssid));
534         if (ret != MOBILE_AP_ERROR_NONE) {
535                 ERR("__get_ssid is failed : %d\n", ret);
536         }
537
538         dbus_g_method_return(context, ssid);
539
540         return TRUE;
541
542 }
543
544 gboolean mobileap_get_wifi_tethering_security_type(MobileAPObject *obj,
545                 DBusGMethodInvocation *context)
546 {
547         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
548         char security_type[SECURITY_TYPE_LEN] = {0, };
549
550         DBG("+\n");
551         g_assert(obj != NULL);
552         g_assert(context != NULL);
553
554         ret = __get_security_type(security_type, sizeof(security_type));
555         if (ret != MOBILE_AP_ERROR_NONE) {
556                 ERR("__get_security_type is failed : %d\n", ret);
557         }
558
559         dbus_g_method_return(context, security_type);
560
561         return TRUE;
562 }
563
564 gboolean mobileap_set_wifi_tethering_security_type(MobileAPObject *obj,
565                 gchar *security_type, DBusGMethodInvocation *context)
566 {
567         int ret = 0;
568
569         DBG("+\n");
570         g_assert(obj != NULL);
571         g_assert(context != NULL);
572
573         ret = __set_security_type(security_type);
574         if (ret < 0) {
575                 ERR("__set_security_type is failed: %d\n", ret);
576         }
577
578         dbus_g_method_return(context);
579
580         return TRUE;
581 }
582
583 gboolean mobileap_get_wifi_tethering_passphrase(MobileAPObject *obj,
584                 DBusGMethodInvocation *context)
585 {
586         int ret = MOBILE_AP_ERROR_NONE;
587         char passphrase[MOBILE_AP_WIFI_KEY_MAX_LEN + 1] = {0, };
588         unsigned int len = 0;
589
590         DBG("+\n");
591         g_assert(obj != NULL);
592         g_assert(context != NULL);
593
594         ret = __get_passphrase(passphrase, sizeof(passphrase), &len);
595         if (ret != MOBILE_AP_ERROR_NONE) {
596                 len = 0;
597                 ERR("__get_password is failed : %d\n", ret);
598         }
599
600         dbus_g_method_return(context, passphrase, len);
601
602         return TRUE;
603 }
604
605 gboolean mobileap_set_wifi_tethering_passphrase(MobileAPObject *obj,
606                 gchar *passphrase, guint len, DBusGMethodInvocation *context)
607 {
608         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
609
610         DBG("+\n");
611         g_assert(obj != NULL);
612         g_assert(context != NULL);
613
614         ret = __set_passphrase(passphrase, len);
615         if (ret != MOBILE_AP_ERROR_NONE) {
616                 ERR("__set_passphrase is failed : %d\n", ret);
617         }
618
619         dbus_g_method_return(context);
620
621         return TRUE;
622 }