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"
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);
44 static int __generate_initial_passphrase(char *passphrase_buf)
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;
55 passphrase_buf[index] = '\0';
60 static mobile_ap_error_code_e __get_hide_mode(int *hide_mode)
62 if (hide_mode == NULL) {
63 ERR("Invalid param\n");
64 return MOBILE_AP_ERROR_INVALID_PARAM;
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;
72 return MOBILE_AP_ERROR_NONE;
75 static mobile_ap_error_code_e __set_hide_mode(const int hide_mode)
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;
82 return MOBILE_AP_ERROR_NONE;
85 static mobile_ap_error_code_e __get_ssid(char *ssid, unsigned int size)
88 return MOBILE_AP_ERROR_INVALID_PARAM;
93 ptr = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
95 return MOBILE_AP_ERROR_RESOURCE;
97 if (!g_utf8_validate(ptr, -1, (const char **)&ptr_tmp))
100 g_strlcpy(ssid, ptr, size);
103 return MOBILE_AP_ERROR_NONE;
106 static mobile_ap_error_code_e __get_security_type(char *security_type, unsigned int len)
108 if (security_type == NULL)
109 return MOBILE_AP_ERROR_INVALID_PARAM;
111 char *type_str = NULL;
112 softap_security_type_e type;
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;
120 case SOFTAP_SECURITY_TYPE_OPEN:
121 type_str = SOFTAP_SECURITY_TYPE_OPEN_STR;
124 case SOFTAP_SECURITY_TYPE_WPA2_PSK:
125 type_str = SOFTAP_SECURITY_TYPE_WPA2_PSK_STR;
129 ERR("Invalid data\n");
130 return MOBILE_AP_ERROR_RESOURCE;
133 g_strlcpy(security_type, type_str, len);
135 return MOBILE_AP_ERROR_NONE;
138 static mobile_ap_error_code_e __set_security_type(const char *security_type)
140 if (security_type == NULL) {
141 ERR("Invalid param\n");
142 return MOBILE_AP_ERROR_INVALID_PARAM;
145 softap_security_type_e type;
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;
152 ERR("Invalid param\n");
153 return MOBILE_AP_ERROR_INVALID_PARAM;
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;
161 return MOBILE_AP_ERROR_NONE;
164 static mobile_ap_error_code_e __get_passphrase(char *passphrase,
165 unsigned int size, unsigned int *passphrase_len)
167 if (passphrase == NULL || passphrase_len == NULL) {
168 ERR("Invalid parameter\n");
169 return MOBILE_AP_ERROR_INVALID_PARAM;
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);
180 ret = __set_passphrase(passphrase, *passphrase_len);
181 if (ret != MOBILE_AP_ERROR_NONE) {
182 memset(passphrase, 0x00, size);
187 ret = ssm_getinfo(SOFTAP_PASSPHRASE_PATH, &sfi,
188 SSM_FLAG_SECRET_OPERATION, NULL);
190 ERR("ssm_getinfo is failed : %d\n", ret);
191 memset(passphrase, 0x00, size);
193 return MOBILE_AP_ERROR_RESOURCE;
195 } else if (ret < 0) {
196 ERR("ssm_getinfo is failed : %d\n", ret);
197 return MOBILE_AP_ERROR_RESOURCE;
200 memset(passphrase, 0x00, size);
201 ret = ssm_read(SOFTAP_PASSPHRASE_PATH, passphrase, sfi.originSize,
202 passphrase_len, SSM_FLAG_SECRET_OPERATION, NULL);
204 ERR("ssm_read is failed : %d\n", ret);
205 return MOBILE_AP_ERROR_RESOURCE;
208 return MOBILE_AP_ERROR_NONE;
211 static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const unsigned int size)
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;
221 ret = ssm_write_buffer((char *)passphrase, size, SOFTAP_PASSPHRASE_PATH,
222 SSM_FLAG_SECRET_OPERATION, NULL);
224 ERR("ssm_write_buffer is failed : %d\n", ret);
225 return MOBILE_AP_ERROR_RESOURCE;
228 return MOBILE_AP_ERROR_NONE;
231 static gboolean __send_station_event_cb(gpointer data)
233 int sig = GPOINTER_TO_INT(data);
235 mobile_ap_station_info_t *si = NULL;
237 if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
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);
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) {
254 _remove_station_info(si->mac, _slist_find_station_by_mac);
256 _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
257 _slist_find_station_by_interface, &n_station);
259 _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
265 static void __handle_station_signal(int sig)
267 g_idle_add(__send_station_event_cb, GINT_TO_POINTER(sig));
271 void _register_wifi_station_handler(void)
275 memset(&sa, 0, sizeof(sa));
276 sa.sa_handler = __handle_station_signal;
277 sigaction(SIGUSR1, &sa, NULL);
278 sigaction(SIGUSR2, &sa, NULL);
281 void _add_wifi_device_to_array(softap_device_info_t *di, GPtrArray *array)
284 GIOChannel *io = 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, };
295 for (i = 0; i < di->number; i++)
296 DBG("bssid[%d]:%s\n", i, di->bssid[i]);
298 DBG("Number of connected device:%d\n", di->number);
300 io = g_io_channel_new_file(DNSMASQ_LEASES_FILE, "r", NULL);
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);
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;
316 _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
327 g_io_channel_unref(io);
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);
336 mobile_ap_error_code_e _disable_wifi_tethering(MobileAPObject *obj)
338 int ret = MOBILE_AP_ERROR_NONE;
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;
346 _deinit_timeout_cb(MOBILE_AP_TYPE_WIFI);
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");
353 ret = _mh_core_disable_softap();
354 if (ret != MOBILE_AP_ERROR_NONE) {
355 ERR("_mh_core_disable_softap is failed : %d\n", ret);
359 _deinit_tethering(obj);
360 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
362 DBG("_disable_wifi_tethering is done\n");
367 static mobile_ap_error_code_e __update_wifi_data(MobileAPObject *obj)
370 ERR("Invalid param\n");
371 return MOBILE_AP_ERROR_INVALID_PARAM;
374 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
375 unsigned int read_len = 0;
377 ret = __get_ssid(obj->ssid, sizeof(obj->ssid));
378 if (ret != MOBILE_AP_ERROR_NONE)
381 ret = __get_security_type(obj->security_type, sizeof(obj->security_type));
382 if (ret != MOBILE_AP_ERROR_NONE)
385 ret = __get_hide_mode(&obj->hide_mode);
386 if (ret != MOBILE_AP_ERROR_NONE)
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)
396 ERR("Unknown security type\n");
397 return MOBILE_AP_ERROR_INTERNAL;
400 DBG("ssid : %s security type : %s hide mode : %d\n",
401 obj->ssid, obj->security_type, obj->hide_mode);
403 return MOBILE_AP_ERROR_NONE;
406 gboolean mobileap_enable_wifi_tethering(MobileAPObject *obj, gchar *ssid,
407 gchar *key, gint hide_mode, DBusGMethodInvocation *context)
409 int ret = MOBILE_AP_ERROR_NONE;
411 g_assert(obj != NULL);
412 g_assert(context != NULL);
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);
423 /* Update global state */
424 if (!_mobileap_set_state(MOBILE_AP_STATE_WIFI)) {
425 ret = MOBILE_AP_ERROR_RESOURCE;
429 /* Update Wi-Fi hotspot data to common object */
430 ret = __update_wifi_data(obj);
431 if (ret != MOBILE_AP_ERROR_NONE) {
435 /* Initialize tethering */
436 if (!_init_tethering(obj)) {
437 ret = MOBILE_AP_ERROR_RESOURCE;
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);
449 _init_timeout_cb(MOBILE_AP_TYPE_WIFI, (void *)obj);
450 _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
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);
458 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
459 dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
464 gboolean mobileap_disable_wifi_tethering(MobileAPObject *obj,
465 DBusGMethodInvocation *context)
467 int ret = MOBILE_AP_ERROR_NONE;
470 g_assert(obj != NULL);
471 g_assert(context != NULL);
473 ret = _disable_wifi_tethering(obj);
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);
478 if (ret != MOBILE_AP_ERROR_NONE)
484 gboolean mobileap_get_wifi_tethering_hide_mode(MobileAPObject *obj,
485 DBusGMethodInvocation *context)
487 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
491 g_assert(obj != NULL);
492 g_assert(context != NULL);
494 ret = __get_hide_mode(&hide_mode);
495 if (ret != MOBILE_AP_ERROR_NONE) {
496 ERR("__get_hide_mode is failed : %d\n", ret);
499 dbus_g_method_return(context, hide_mode);
504 gboolean mobileap_set_wifi_tethering_hide_mode(MobileAPObject *obj,
505 gint hide_mode, DBusGMethodInvocation *context)
510 g_assert(obj != NULL);
511 g_assert(context != NULL);
513 ret = __set_hide_mode(hide_mode);
515 ERR("__set_hide_mode is failed : %d\n", ret);
518 dbus_g_method_return(context);
523 gboolean mobileap_get_wifi_tethering_ssid(MobileAPObject *obj,
524 DBusGMethodInvocation *context)
526 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
527 char ssid[MOBILE_AP_WIFI_SSID_MAX_LEN + 1] = {0, };
530 g_assert(obj != NULL);
531 g_assert(context != NULL);
533 ret = __get_ssid(ssid, sizeof(ssid));
534 if (ret != MOBILE_AP_ERROR_NONE) {
535 ERR("__get_ssid is failed : %d\n", ret);
538 dbus_g_method_return(context, ssid);
544 gboolean mobileap_get_wifi_tethering_security_type(MobileAPObject *obj,
545 DBusGMethodInvocation *context)
547 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
548 char security_type[SECURITY_TYPE_LEN] = {0, };
551 g_assert(obj != NULL);
552 g_assert(context != NULL);
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);
559 dbus_g_method_return(context, security_type);
564 gboolean mobileap_set_wifi_tethering_security_type(MobileAPObject *obj,
565 gchar *security_type, DBusGMethodInvocation *context)
570 g_assert(obj != NULL);
571 g_assert(context != NULL);
573 ret = __set_security_type(security_type);
575 ERR("__set_security_type is failed: %d\n", ret);
578 dbus_g_method_return(context);
583 gboolean mobileap_get_wifi_tethering_passphrase(MobileAPObject *obj,
584 DBusGMethodInvocation *context)
586 int ret = MOBILE_AP_ERROR_NONE;
587 char passphrase[MOBILE_AP_WIFI_KEY_MAX_LEN + 1] = {0, };
588 unsigned int len = 0;
591 g_assert(obj != NULL);
592 g_assert(context != NULL);
594 ret = __get_passphrase(passphrase, sizeof(passphrase), &len);
595 if (ret != MOBILE_AP_ERROR_NONE) {
597 ERR("__get_password is failed : %d\n", ret);
600 dbus_g_method_return(context, passphrase, len);
605 gboolean mobileap_set_wifi_tethering_passphrase(MobileAPObject *obj,
606 gchar *passphrase, guint len, DBusGMethodInvocation *context)
608 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
611 g_assert(obj != NULL);
612 g_assert(context != NULL);
614 ret = __set_passphrase(passphrase, len);
615 if (ret != MOBILE_AP_ERROR_NONE) {
616 ERR("__set_passphrase is failed : %d\n", ret);
619 dbus_g_method_return(context);