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