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.
19 #include <dbus/dbus.h>
20 #include <dbus/dbus-glib.h>
21 #include <dbus/dbus-glib-lowlevel.h>
25 #include <ss_manager.h>
27 #include "mobileap_agent.h"
28 #include "mobileap_common.h"
29 #include "mobileap_wifi.h"
30 #include "mobileap_handler.h"
31 #include "mobileap_notification.h"
33 static int __generate_initial_passphrase(char *passphrase_buf);
34 static mobile_ap_error_code_e __get_hide_mode(int *hide_mode);
35 static mobile_ap_error_code_e __set_hide_mode(const int hide_mode);
36 static mobile_ap_error_code_e __get_common_ssid(char *ssid, unsigned int size);
37 static mobile_ap_error_code_e __get_security_type(char *security_type, unsigned int len);
38 static mobile_ap_error_code_e __set_security_type(const char *security_type);
39 static mobile_ap_error_code_e __get_passphrase(char *passphrase, unsigned int size, unsigned int *passphrase_len);
40 static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const unsigned int size);
41 static gboolean __send_station_event_cb(gpointer data);
42 static void __handle_station_signal(int sig);
43 static mobile_ap_error_code_e __update_wifi_data(TetheringObject *obj);
45 static int __generate_initial_passphrase(char *passphrase_buf)
52 for (index = 0; index < MOBILE_AP_WIFI_KEY_MIN_LEN; index++) {
53 rand_int = g_random_int_range('a', 'z');
54 passphrase_buf[index] = rand_int;
56 passphrase_buf[index] = '\0';
61 static mobile_ap_error_code_e __get_hide_mode(int *hide_mode)
63 if (hide_mode == NULL) {
64 ERR("Invalid param\n");
65 return MOBILE_AP_ERROR_INVALID_PARAM;
68 if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_HIDE, hide_mode) < 0) {
69 ERR("vconf_get_int is failed\n");
70 return MOBILE_AP_ERROR_RESOURCE;
73 return MOBILE_AP_ERROR_NONE;
76 static mobile_ap_error_code_e __set_hide_mode(const int hide_mode)
78 if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_HIDE, hide_mode) < 0) {
79 ERR("vconf_set_int is failed\n");
80 return MOBILE_AP_ERROR_RESOURCE;
83 return MOBILE_AP_ERROR_NONE;
86 static mobile_ap_error_code_e __get_common_ssid(char *ssid, unsigned int size)
89 return MOBILE_AP_ERROR_INVALID_PARAM;
94 ptr = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
96 return MOBILE_AP_ERROR_RESOURCE;
98 if (!g_utf8_validate(ptr, -1, (const char **)&ptr_tmp))
101 g_strlcpy(ssid, ptr, size);
104 return MOBILE_AP_ERROR_NONE;
107 static mobile_ap_error_code_e __get_security_type(char *security_type, unsigned int len)
109 if (security_type == NULL)
110 return MOBILE_AP_ERROR_INVALID_PARAM;
112 char *type_str = NULL;
113 softap_security_type_e type;
115 if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, (int *)&type) < 0) {
116 ERR("vconf_get_int is failed\n");
117 return MOBILE_AP_ERROR_RESOURCE;
121 case SOFTAP_SECURITY_TYPE_OPEN:
122 type_str = SOFTAP_SECURITY_TYPE_OPEN_STR;
125 case SOFTAP_SECURITY_TYPE_WPA2_PSK:
126 type_str = SOFTAP_SECURITY_TYPE_WPA2_PSK_STR;
130 ERR("Invalid data\n");
131 return MOBILE_AP_ERROR_RESOURCE;
134 g_strlcpy(security_type, type_str, len);
136 return MOBILE_AP_ERROR_NONE;
139 static mobile_ap_error_code_e __set_security_type(const char *security_type)
141 if (security_type == NULL) {
142 ERR("Invalid param\n");
143 return MOBILE_AP_ERROR_INVALID_PARAM;
146 softap_security_type_e type;
148 if (!strcmp(security_type, SOFTAP_SECURITY_TYPE_OPEN_STR)) {
149 type = SOFTAP_SECURITY_TYPE_OPEN;
150 } else if (!strcmp(security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR)) {
151 type = SOFTAP_SECURITY_TYPE_WPA2_PSK;
153 ERR("Invalid param\n");
154 return MOBILE_AP_ERROR_INVALID_PARAM;
157 if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, type) < 0) {
158 ERR("vconf_set_int is failed\n");
159 return MOBILE_AP_ERROR_RESOURCE;
162 return MOBILE_AP_ERROR_NONE;
165 static mobile_ap_error_code_e __get_passphrase(char *passphrase,
166 unsigned int size, unsigned int *passphrase_len)
168 if (passphrase == NULL || passphrase_len == NULL) {
169 ERR("Invalid parameter\n");
170 return MOBILE_AP_ERROR_INVALID_PARAM;
176 ret = ssm_getinfo(SOFTAP_PASSPHRASE_PATH, &sfi,
177 SSM_FLAG_SECRET_OPERATION, NULL);
178 if (ret == -SS_FILE_OPEN_ERROR) {
179 *passphrase_len = __generate_initial_passphrase(passphrase);
181 ret = __set_passphrase(passphrase, *passphrase_len);
182 if (ret != MOBILE_AP_ERROR_NONE) {
183 memset(passphrase, 0x00, size);
188 ret = ssm_getinfo(SOFTAP_PASSPHRASE_PATH, &sfi,
189 SSM_FLAG_SECRET_OPERATION, NULL);
191 ERR("ssm_getinfo is failed : %d\n", ret);
192 memset(passphrase, 0x00, size);
194 return MOBILE_AP_ERROR_RESOURCE;
196 } else if (ret < 0) {
197 ERR("ssm_getinfo is failed : %d\n", ret);
198 return MOBILE_AP_ERROR_RESOURCE;
201 memset(passphrase, 0x00, size);
202 ret = ssm_read(SOFTAP_PASSPHRASE_PATH, passphrase, sfi.originSize,
203 passphrase_len, SSM_FLAG_SECRET_OPERATION, NULL);
205 ERR("ssm_read is failed : %d\n", ret);
206 return MOBILE_AP_ERROR_RESOURCE;
209 return MOBILE_AP_ERROR_NONE;
212 static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const unsigned int size)
214 if (size < MOBILE_AP_WIFI_KEY_MIN_LEN || size > MOBILE_AP_WIFI_KEY_MAX_LEN ||
215 passphrase == NULL) {
216 ERR("Invalid parameter\n");
217 return MOBILE_AP_ERROR_INVALID_PARAM;
222 ret = ssm_write_buffer((char *)passphrase, size, SOFTAP_PASSPHRASE_PATH,
223 SSM_FLAG_SECRET_OPERATION, NULL);
225 ERR("ssm_write_buffer is failed : %d\n", ret);
226 return MOBILE_AP_ERROR_RESOURCE;
229 return MOBILE_AP_ERROR_NONE;
232 static gboolean __send_station_event_cb(gpointer data)
234 int sig = GPOINTER_TO_INT(data);
236 mobile_ap_station_info_t *si = NULL;
238 if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
242 if (sig == SIGUSR1) {
243 DBG("STA connected(%d)\n", sig);
244 /* STA connection is handled in the dnsmasq signal handler */
245 } else if (sig == SIGUSR2) {
246 DBG("STA disconnected(%d)\n", sig);
248 /* Temporarily care only one station.
249 * Driver team should be support detail information */
250 if (_get_station_info(MOBILE_AP_TYPE_WIFI,
251 _slist_find_station_by_interface,
252 &si) != MOBILE_AP_ERROR_NONE) {
255 _remove_station_info(si->mac, _slist_find_station_by_mac);
257 _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
258 _slist_find_station_by_interface, &n_station);
260 _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
266 static void __handle_station_signal(int sig)
268 g_idle_add(__send_station_event_cb, GINT_TO_POINTER(sig));
272 void _register_wifi_station_handler(void)
276 memset(&sa, 0, sizeof(sa));
277 sa.sa_handler = __handle_station_signal;
278 sigaction(SIGUSR1, &sa, NULL);
279 sigaction(SIGUSR2, &sa, NULL);
282 void _add_wifi_device_to_array(softap_device_info_t *di, GPtrArray *array)
285 GIOChannel *io = NULL;
287 gchar *device_name = NULL;
288 gchar ip_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
289 gchar mac_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
290 gchar name[MOBILE_AP_STR_HOSTNAME_LEN] = {0, };
291 gchar expire[MOBILE_AP_STR_INFO_LEN] = {0, };
292 gchar extra[MOBILE_AP_STR_INFO_LEN] = {0, };
296 for (i = 0; i < di->number; i++)
297 DBG("bssid[%d]:%s\n", i, di->bssid[i]);
299 DBG("Number of connected device:%d\n", di->number);
301 io = g_io_channel_new_file(DNSMASQ_LEASES_FILE, "r", NULL);
303 while (g_io_channel_read_line(io, &line, NULL, NULL, NULL) ==
304 G_IO_STATUS_NORMAL) {
305 sscanf(line, "%19s %19s %19s %19s %19s", expire, mac_addr,
306 ip_addr, name, extra);
307 DBG("mac_addr:%s ip_addr:%s name:%s expire:%s\n", mac_addr,
308 ip_addr, name, expire);
310 for (i = 0; i < di->number; i++) {
311 if (g_ascii_strcasecmp(di->bssid[i], mac_addr) == 0) {
312 if (!strcmp(name, "*"))
313 device_name = MOBILE_AP_NAME_UNKNOWN;
317 _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
328 g_io_channel_unref(io);
330 /* Set the name UNKNOWN unless we got the name. */
331 for (i = found; i < di->number; i++) {
332 _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
333 MOBILE_AP_NAME_UNKNOWN);
337 mobile_ap_error_code_e _enable_wifi_tethering(TetheringObject *obj, gchar *ssid)
339 mobile_ap_error_code_e ret;
341 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
342 ERR("Wi-Fi tethering is already enabled\n");
343 ret = MOBILE_AP_ERROR_ALREADY_ENABLED;
347 /* Update global state */
348 if (!_mobileap_set_state(MOBILE_AP_STATE_WIFI)) {
349 ret = MOBILE_AP_ERROR_RESOURCE;
353 /* Update Wi-Fi hotspot data to common object */
354 ret = __update_wifi_data(obj);
355 if (ret != MOBILE_AP_ERROR_NONE) {
356 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
360 if (ssid != NULL && strlen(ssid) > 0) {
361 DBG("Private(Passed) SSID is used : %s\n", ssid);
362 g_strlcpy(obj->ssid, ssid, sizeof(obj->ssid));
365 /* Initialize tethering */
366 if (!_init_tethering(obj)) {
367 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
368 ret = MOBILE_AP_ERROR_RESOURCE;
373 ret = _mh_core_enable_softap(obj->ssid, obj->security_type,
374 obj->key, obj->hide_mode);
375 if (ret != MOBILE_AP_ERROR_NONE) {
376 _deinit_tethering(obj);
377 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
381 _delete_timeout_noti();
382 _init_timeout_cb(MOBILE_AP_TYPE_WIFI, (void *)obj);
383 _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
385 return MOBILE_AP_ERROR_NONE;
388 mobile_ap_error_code_e _disable_wifi_tethering(TetheringObject *obj)
390 int ret = MOBILE_AP_ERROR_NONE;
392 if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
393 ERR("Wi-Fi tethering has not been activated\n");
394 ret = MOBILE_AP_ERROR_NOT_ENABLED;
398 _deinit_timeout_cb(MOBILE_AP_TYPE_WIFI);
400 if (_remove_station_info_all(MOBILE_AP_TYPE_WIFI) !=
401 MOBILE_AP_ERROR_NONE) {
402 ERR("_remove_station_info_all is failed. Ignore it.\n");
405 ret = _mh_core_disable_softap();
406 if (ret != MOBILE_AP_ERROR_NONE) {
407 ERR("_mh_core_disable_softap is failed : %d\n", ret);
411 _deinit_tethering(obj);
412 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
414 DBG("_disable_wifi_tethering is done\n");
419 static mobile_ap_error_code_e __update_wifi_data(TetheringObject *obj)
422 ERR("Invalid param\n");
423 return MOBILE_AP_ERROR_INVALID_PARAM;
426 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
427 unsigned int read_len = 0;
429 ret = __get_common_ssid(obj->ssid, sizeof(obj->ssid));
430 if (ret != MOBILE_AP_ERROR_NONE)
433 ret = __get_security_type(obj->security_type, sizeof(obj->security_type));
434 if (ret != MOBILE_AP_ERROR_NONE)
437 ret = __get_hide_mode(&obj->hide_mode);
438 if (ret != MOBILE_AP_ERROR_NONE)
441 if (strcmp(obj->security_type, SOFTAP_SECURITY_TYPE_OPEN_STR) == 0) {
442 g_strlcpy(obj->key, "00000000", sizeof(obj->key));
443 } else if (strcmp(obj->security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR) == 0) {
444 ret = __get_passphrase(obj->key, sizeof(obj->key), &read_len);
445 if (ret != MOBILE_AP_ERROR_NONE)
448 ERR("Unknown security type\n");
449 return MOBILE_AP_ERROR_INTERNAL;
452 DBG("ssid : %s security type : %s hide mode : %d\n",
453 obj->ssid, obj->security_type, obj->hide_mode);
455 return MOBILE_AP_ERROR_NONE;
458 gboolean tethering_enable_wifi_tethering(TetheringObject *obj, gchar *ssid,
459 gchar *key, gint hide_mode, DBusGMethodInvocation *context)
461 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
462 gboolean ret_val = FALSE;
464 g_assert(obj != NULL);
465 g_assert(context != NULL);
468 ret = _enable_wifi_tethering(obj, ssid);
469 if (ret != MOBILE_AP_ERROR_NONE) {
470 ERR("_enable_wifi_tethering is failed\n");
472 _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
476 dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
482 gboolean tethering_disable_wifi_tethering(TetheringObject *obj,
483 DBusGMethodInvocation *context)
485 int ret = MOBILE_AP_ERROR_NONE;
488 g_assert(obj != NULL);
489 g_assert(context != NULL);
491 ret = _disable_wifi_tethering(obj);
493 _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_OFF, NULL);
494 dbus_g_method_return(context, MOBILE_AP_DISABLE_WIFI_TETHERING_CFM, ret);
496 if (ret != MOBILE_AP_ERROR_NONE)
502 gboolean tethering_get_wifi_tethering_hide_mode(TetheringObject *obj,
503 DBusGMethodInvocation *context)
505 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
509 g_assert(obj != NULL);
510 g_assert(context != NULL);
512 ret = __get_hide_mode(&hide_mode);
513 if (ret != MOBILE_AP_ERROR_NONE) {
514 ERR("__get_hide_mode is failed : %d\n", ret);
517 dbus_g_method_return(context, hide_mode);
522 gboolean tethering_set_wifi_tethering_hide_mode(TetheringObject *obj,
523 gint hide_mode, DBusGMethodInvocation *context)
528 g_assert(obj != NULL);
529 g_assert(context != NULL);
533 ret = __get_hide_mode(&old_hide_mode);
534 if (ret != MOBILE_AP_ERROR_NONE) {
535 ERR("__get_hide_mode is failed : %d\n", ret);
536 } else if (old_hide_mode == hide_mode) {
537 DBG("old_hide_mode == hide_mode\n");
538 dbus_g_method_return(context);
542 ret = __set_hide_mode(hide_mode);
544 ERR("__set_hide_mode is failed : %d\n", ret);
547 _emit_mobileap_dbus_signal(obj, E_SIGNAL_SSID_VISIBILITY_CHANGED,
548 hide_mode == VCONFKEY_MOBILE_AP_HIDE_OFF ?
549 SIGNAL_MSG_SSID_VISIBLE :
550 SIGNAL_MSG_SSID_HIDE);
551 dbus_g_method_return(context);
556 gboolean tethering_get_wifi_tethering_ssid(TetheringObject *obj,
557 DBusGMethodInvocation *context)
559 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
560 char ssid[MOBILE_AP_WIFI_SSID_MAX_LEN + 1] = {0, };
563 g_assert(obj != NULL);
564 g_assert(context != NULL);
566 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
567 g_strlcpy(ssid, obj->ssid, sizeof(ssid));
569 ret = __get_common_ssid(ssid, sizeof(ssid));
570 if (ret != MOBILE_AP_ERROR_NONE) {
571 ERR("__get_common_ssid is failed : %d\n", ret);
575 dbus_g_method_return(context, ssid);
580 gboolean tethering_get_wifi_tethering_security_type(TetheringObject *obj,
581 DBusGMethodInvocation *context)
583 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
584 char security_type[SECURITY_TYPE_LEN] = {0, };
587 g_assert(obj != NULL);
588 g_assert(context != NULL);
590 ret = __get_security_type(security_type, sizeof(security_type));
591 if (ret != MOBILE_AP_ERROR_NONE) {
592 ERR("__get_security_type is failed : %d\n", ret);
595 dbus_g_method_return(context, security_type);
600 gboolean tethering_set_wifi_tethering_security_type(TetheringObject *obj,
601 gchar *security_type, DBusGMethodInvocation *context)
603 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
604 char old_security_type[SECURITY_TYPE_LEN] = {0, };
607 g_assert(obj != NULL);
608 g_assert(context != NULL);
610 ret = __get_security_type(old_security_type, sizeof(old_security_type));
611 if (ret != MOBILE_AP_ERROR_NONE) {
612 ERR("__get_security_type is failed : %d\n", ret);
613 } else if (g_strcmp0(old_security_type, security_type) == 0) {
614 DBG("old_security_type == security_type\n");
615 dbus_g_method_return(context);
619 ret = __set_security_type(security_type);
621 ERR("__set_security_type is failed: %d\n", ret);
624 _emit_mobileap_dbus_signal(obj, E_SIGNAL_SECURITY_TYPE_CHANGED,
626 dbus_g_method_return(context);
631 gboolean tethering_get_wifi_tethering_passphrase(TetheringObject *obj,
632 DBusGMethodInvocation *context)
634 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
635 char passphrase[MOBILE_AP_WIFI_KEY_MAX_LEN + 1] = {0, };
636 unsigned int len = 0;
639 g_assert(obj != NULL);
640 g_assert(context != NULL);
642 ret = __get_passphrase(passphrase, sizeof(passphrase), &len);
643 if (ret != MOBILE_AP_ERROR_NONE) {
645 ERR("__get_password is failed : %d\n", ret);
648 dbus_g_method_return(context, passphrase, len);
653 gboolean tethering_set_wifi_tethering_passphrase(TetheringObject *obj,
654 gchar *passphrase, guint len, DBusGMethodInvocation *context)
656 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
657 char old_passphrase[MOBILE_AP_WIFI_KEY_MAX_LEN + 1] = {0, };
658 unsigned int old_len = 0;
661 g_assert(obj != NULL);
662 g_assert(context != NULL);
664 ret = __get_passphrase(old_passphrase, sizeof(old_passphrase), &old_len);
665 if (ret != MOBILE_AP_ERROR_NONE) {
666 ERR("__get_passphrase is failed : %d\n", ret);
667 } else if (old_len == len && !g_strcmp0(old_passphrase, passphrase)) {
668 dbus_g_method_return(context);
672 ret = __set_passphrase(passphrase, len);
673 if (ret != MOBILE_AP_ERROR_NONE) {
674 ERR("__set_passphrase is failed : %d\n", ret);
677 _emit_mobileap_dbus_signal(obj, E_SIGNAL_PASSPHRASE_CHANGED, NULL);
678 dbus_g_method_return(context);