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.
21 #include <sys/ioctl.h>
23 #include <glib-object.h>
24 #include <dbus/dbus-glib.h>
30 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <linux/wireless.h>
37 #include <openssl/evp.h>
38 #include <openssl/sha.h>
40 #include "mobileap_common.h"
41 #include "mobileap_agent.h"
42 #include "mobileap_handler.h"
44 static pid_t dnsmasq_pid = 0;
45 static pid_t hostapd_pid = 0;
46 static int hostapd_ctrl_fd = 0;
47 static int hostapd_monitor_fd = 0;
48 static GIOChannel *hostapd_io_channel = NULL;
49 static guint hostapd_io_source = 0;
51 static int __issue_ioctl(int sock_fd, char *if_name, char *cmd, char *buf)
53 int ret_val = MOBILE_AP_ERROR_NONE;
56 memset(buf, 0, MAX_BUF_SIZE);
57 memset(&iwr, 0, sizeof(iwr));
59 /* Configure ioctl parameters */
60 g_strlcpy(iwr.ifr_name, if_name, IFNAMSIZ);
61 g_strlcpy(buf, cmd, MAX_BUF_SIZE);
62 iwr.u.data.pointer = buf;
63 iwr.u.data.length = MAX_BUF_SIZE;
68 if ((ioctl(sock_fd, SIOCSIWPRIV, &iwr)) < 0) {
69 ERR("ioctl failed...!!!\n");
70 ret_val = MOBILE_AP_ERROR_INTERNAL;
76 static int __get_dns_server(char *dns_server, int len)
78 #ifndef __USE_CONNMAN_DNS_ADDR__
79 g_strlcpy(dns_server, GOOGLE_PUBLIC_DNS, len);
80 DBG("DNS server [%s]\n", dns_server);
84 int ret = EXIT_FAILURE;
86 DBusGConnection *bus = NULL;
87 DBusGProxy *manager_proxy = NULL;
88 DBusGProxy *service_proxy = NULL;
89 gchar *service_object_path = NULL;
91 GHashTable *hash = NULL;
94 gchar **dns_server_list = NULL;
95 GPtrArray *service_list = NULL;
97 bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
99 ERR("Couldn't connect to the System bus[%s]", error->message);
104 manager_proxy = dbus_g_proxy_new_for_name(bus, "net.connman",
106 "net.connman.Manager");
107 if (!manager_proxy) {
108 ERR("Couldn't create the proxy object");
112 dbus_g_proxy_call(manager_proxy, "GetProperties", &error, G_TYPE_INVALID,
113 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
114 &hash, G_TYPE_INVALID);
116 ERR("GetProperties failed[%s]", error->message);
125 object path "/profile/default/cellular_45001_cellular_Samsung3G_1"
126 object path "/profile/default/cellular_45001_cellular_Samsung3G_MMS_2"
130 value = g_hash_table_lookup(hash, "Services");
132 service_list = g_value_get_boxed(value);
134 ERR("No service available");
138 service_object_path = g_ptr_array_index(service_list, 0);
139 DBG("service object path : %s\n", service_object_path);
141 service_proxy = dbus_g_proxy_new_for_name(bus, "net.connman",
143 "net.connman.Service");
144 if (!service_proxy) {
145 ERR("Couldn't create the proxy object");
149 dbus_g_proxy_call(service_proxy, "GetProperties", &error, G_TYPE_INVALID,
150 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
151 &hash, G_TYPE_INVALID);
153 ERR("GetProperties failed[%s]", error->message);
161 variant string "online"
167 string "165.213.73.226"
168 string "10.32.192.11"
172 value = g_hash_table_lookup(hash, "State");
173 state = value ? g_value_get_string(value) : NULL;
174 DBG("Network state : %s\n", state);
176 if (g_strcmp0(state, "ready") != 0 && g_strcmp0(state, "online") != 0) {
177 ERR("Network is not connected\n");
181 value = g_hash_table_lookup(hash, "Nameservers");
183 dns_server_list = g_value_get_boxed(value);
184 if (!dns_server_list) {
185 ERR("No Nameserver exist");
188 g_strlcpy(dns_server, *dns_server_list, len);
189 DBG("DNS server [%s]\n", dns_server);
194 g_strfreev(dns_server_list);
196 g_ptr_array_free(service_list, TRUE);
198 g_object_unref(manager_proxy);
200 g_object_unref(service_proxy);
202 dbus_g_connection_unref(bus);
208 static int __get_psk_hexascii(const char *pass, const unsigned char *salt, char *psk, unsigned int psk_len)
210 if (pass == NULL || salt == NULL || psk == NULL || psk_len == 0) {
211 ERR("Invalid parameter\n");
212 return MOBILE_AP_ERROR_INVALID_PARAM;
215 if (psk_len < SHA256_DIGEST_LENGTH * 2 + 1) {
216 ERR("Invalid parameter\n");
217 return MOBILE_AP_ERROR_INVALID_PARAM;
223 unsigned char buf[SHA256_DIGEST_LENGTH] = {0, };
225 if (!PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
226 salt, strlen((const char *)salt),
227 PSK_ITERATION_COUNT, sizeof(buf), buf)) {
228 ERR("Getting psk is failed\n");
229 return MOBILE_AP_ERROR_INTERNAL;
232 for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
236 psk[i << 1] = d_16 < 10 ? d_16 + '0' : d_16 - 10 + 'a';
237 psk[(i << 1) + 1] = r_16 < 10 ? r_16 + '0' : r_16 - 10 + 'a';
241 return MOBILE_AP_ERROR_NONE;
244 static int __execute_hostapd(const char *ssid, const char *security,
245 const char *key, int hide_mode)
249 char psk[2 * SHA256_DIGEST_LENGTH + 1] = {0, };
250 char buf[HOSTAPD_CONF_LEN] = "";
251 char sec_buf[HOSTAPD_CONF_LEN] = "";
255 if (security != NULL && !strcmp(security, "wpa2-psk")) {
256 if (__get_psk_hexascii(key, (const unsigned char *)ssid, psk,
257 sizeof(psk)) != MOBILE_AP_ERROR_NONE) {
258 ERR("Getting PSK(Hex ascii type) is failed\n");
259 return MOBILE_AP_ERROR_INTERNAL;
262 snprintf(sec_buf, HOSTAPD_CONF_LEN,
263 "\nwpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s",
267 snprintf(buf, HOSTAPD_CONF_LEN, HOSTAPD_CONF,
269 HOSTAPD_CTRL_INTF_DIR,
271 MOBILE_AP_WIFI_CHANNEL,
273 MOBILE_AP_MAX_WIFI_STA,
276 fp = fopen(HOSTAPD_CONF_FILE, "w");
278 ERR("Could not create the file.\n");
279 return MOBILE_AP_ERROR_RESOURCE;
286 ERR("fork failed\n");
287 return MOBILE_AP_ERROR_RESOURCE;
291 if (execl(HOSTAPD_BIN, HOSTAPD_BIN, "-e", HOSTAPD_ENTROPY_FILE,
293 "-f", HOSTAPD_DEBUG_FILE, "-d",
295 ERR("execl failed\n");
298 ERR("Should not get here!");
299 return MOBILE_AP_ERROR_RESOURCE;
304 return MOBILE_AP_ERROR_NONE;
307 static int __terminate_hostapd()
311 if (hostapd_pid == 0) {
312 DBG("There is no hostapd\n");
313 return MOBILE_AP_ERROR_NONE;
316 kill(hostapd_pid, SIGTERM);
317 waitpid(hostapd_pid, NULL, 0);
320 return MOBILE_AP_ERROR_NONE;
324 * number NUM_STA(void)
325 * addr STA-FIRST(void)
326 * addr STA-NEXT(addr)
327 * void DISASSOCIATE(addr)
328 * void READ_WHITELIST(filename)
329 * void SET_MAXCLIENT(number)
331 static int __send_hostapd_req(int fd, const char *req, const int req_len,
332 char *buf, int *buf_len)
334 if (fd < 0 || req == NULL || req_len <= 0 ||
335 buf == NULL || buf_len == NULL || *buf_len <= 0) {
336 ERR("Invalid param\n");
337 return MOBILE_AP_ERROR_INVALID_PARAM;
340 struct timeval tv = {10, 0};
344 ret = send(fd, req, req_len, 0);
346 ERR("send is failed : %s\n", strerror(errno));
347 return MOBILE_AP_ERROR_INTERNAL;
353 ret = select(fd + 1, &fds, NULL, NULL, &tv);
355 return MOBILE_AP_ERROR_INTERNAL;
356 } else if (ret == 0) {
357 ERR("There is no response from hostapd\n");
358 return MOBILE_AP_ERROR_INTERNAL;
359 } else if (!FD_ISSET(fd, &fds)) {
360 ERR("Unknown case\n");
361 return MOBILE_AP_ERROR_INTERNAL;
364 ret = recv(fd, buf, (*buf_len) - 1, 0);
366 ERR("recv is failed\n");
367 return MOBILE_AP_ERROR_INTERNAL;
371 DBG("Unsolicited message\n");
378 ERR("socket is closed\n");
384 return MOBILE_AP_ERROR_NONE;
387 static int __open_hostapd_intf(int *fd, const char *intf)
389 if (fd == NULL || intf == NULL) {
391 return MOBILE_AP_ERROR_INVALID_PARAM;
397 char ctrl_intf[255] = {0, };
398 struct sockaddr_un src;
399 struct sockaddr_un dest;
400 struct stat stat_buf;
402 *fd = socket(PF_UNIX, SOCK_DGRAM, 0);
404 ERR("socket is failed\n");
405 return MOBILE_AP_ERROR_INTERNAL;
408 src.sun_family = AF_UNIX;
409 g_strlcpy(src.sun_path, intf, sizeof(src.sun_path));
411 if (stat(src.sun_path, &stat_buf) == 0) {
412 DBG("There is already mh interface. It will be removed\n");
413 unlink(src.sun_path);
416 if (bind(*fd, (struct sockaddr *)&src, sizeof(src)) < 0) {
417 ERR("bind is failed\n");
420 unlink(src.sun_path);
421 return MOBILE_AP_ERROR_INTERNAL;
424 snprintf(ctrl_intf, sizeof(ctrl_intf), "%s/%s",
425 HOSTAPD_CTRL_INTF_DIR, WIFI_IF);
426 dest.sun_family = AF_UNIX;
427 g_strlcpy(dest.sun_path, ctrl_intf, sizeof(dest.sun_path));
429 while (connect(*fd, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
430 DBG("connect is failed : %s\n", strerror(errno));
431 if (++retry >= HOSTAPD_RETRY_MAX)
433 usleep(HOSTAPD_RETRY_DELAY);
436 return MOBILE_AP_ERROR_NONE;
439 ERR("Cannot make connection to hostapd\n");
442 unlink(src.sun_path);
444 return MOBILE_AP_ERROR_INTERNAL;
447 static int __close_hostapd_intf(int *fd)
453 return MOBILE_AP_ERROR_INVALID_PARAM;
460 return MOBILE_AP_ERROR_NONE;
463 static gboolean __hostapd_monitor_cb(GIOChannel *source)
467 char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
472 #if !GLIB_CHECK_VERSION(2, 31, 0)
475 ret = g_io_channel_read(hostapd_io_channel, buf,
476 HOSTAPD_REQ_MAX_LEN, &read);
477 if (ret != G_IO_ERROR_NONE) {
478 ERR("g_io_channel_read is failed\n");
484 g_io_channel_read_chars(hostapd_io_channel, buf,
485 HOSTAPD_REQ_MAX_LEN, &read, &err);
487 ERR("g_io_channel_read_chars is failed : %s\n", err->message);
494 pbuf = strrchr(buf, '\n');
498 if (buf[0] == '<' && (pbuf = strchr(buf, '>')) != NULL) {
504 DBG("Event : %s\n", pbuf);
506 if (!strncmp(pbuf, HOSTAPD_STA_DISCONN, strlen(HOSTAPD_STA_DISCONN))) {
507 pbuf = strchr(pbuf, ' ');
509 ERR("There is no info. for disconnected station\n");
514 DBG("Disconnected station MAC : %s\n", pbuf);
515 _remove_station_info(pbuf, _slist_find_station_by_mac);
517 _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
518 _slist_find_station_by_interface, &n_station);
520 _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
524 DBG("Event is not handled\n");
530 static int __open_hostapd_monitor(int *fd)
534 return MOBILE_AP_ERROR_INVALID_PARAM;
539 char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
542 if (__open_hostapd_intf(fd, MH_MONITOR_INTF) != MOBILE_AP_ERROR_NONE) {
543 ERR("__open_hostapd_intf() is failed\n");
544 return MOBILE_AP_ERROR_INTERNAL;
547 hostapd_io_channel = g_io_channel_unix_new(*fd);
548 if (hostapd_io_channel == NULL) {
549 ERR("g_io_channel_unix_new is failed\n");
550 return MOBILE_AP_ERROR_INTERNAL;
553 g_io_channel_set_encoding(hostapd_io_channel, NULL, NULL);
554 g_io_channel_set_flags(hostapd_io_channel,
555 G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK, NULL);
557 hostapd_io_source = g_io_add_watch(hostapd_io_channel, G_IO_IN,
558 (GIOFunc)__hostapd_monitor_cb, NULL);
560 buf_len = sizeof(buf);
561 __send_hostapd_req(*fd, HOSTAPD_MONITOR_ATTACH,
562 strlen(HOSTAPD_MONITOR_ATTACH), buf, &buf_len);
563 DBG("return : %s\n", buf);
565 return MOBILE_AP_ERROR_NONE;
568 static int __close_hostapd_monitor(int *fd)
571 char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
574 buf_len = sizeof(buf);
575 __send_hostapd_req(*fd, HOSTAPD_MONITOR_DETACH,
576 strlen(HOSTAPD_MONITOR_DETACH), buf, &buf_len);
577 DBG("return : %s\n", buf);
579 if (hostapd_io_source != 0) {
580 g_source_remove(hostapd_io_source);
581 hostapd_io_source = 0;
584 if (hostapd_io_channel != NULL) {
585 g_io_channel_shutdown(hostapd_io_channel, TRUE, &err);
586 g_io_channel_unref(hostapd_io_channel);
587 hostapd_io_channel = NULL;
590 __close_hostapd_intf(fd);
592 return MOBILE_AP_ERROR_NONE;
595 static mobile_ap_drv_interface_e __get_drv_interface(void)
597 static mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
599 if (drv_interface != MOBILE_AP_DRV_INTERFACE_NONE) {
600 return drv_interface;
603 const char *drv_rfkill_path = "/sys/devices/platform";
604 const char *wext_drv[] = {
605 "bcm4329-b1", "bcm4330-b0",
606 "bcm4330-b1", "bcm4330-b2",
609 char path[MAX_BUF_SIZE] = { 0 };
610 struct stat stat_buf = { 0 };
614 drv_interface = MOBILE_AP_NL80211;
616 for (i = 0; wext_drv[i] != NULL; i++) {
617 snprintf(path, sizeof(path), "%s/%s",
618 drv_rfkill_path, wext_drv[i]);
619 fd = open(path, O_RDONLY);
623 if (fstat(fd, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode)) {
624 drv_interface = MOBILE_AP_WEXT;
632 return drv_interface;
635 int _mh_core_enable_softap(const char *ssid, const char *security,
636 const char *key, int hide_mode)
638 if (ssid == NULL || security == NULL || key == NULL) {
639 ERR("Invalid param\n");
640 return MOBILE_AP_ERROR_INTERNAL;
643 char cmd[MAX_BUF_SIZE];
644 int ret_status = MOBILE_AP_ERROR_NONE;
645 mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
648 char *if_name = WIFI_IF;
649 char buf[MAX_BUF_SIZE] = { 0 };
651 snprintf(cmd, sizeof(cmd), "%s softap", WLAN_SCRIPT);
652 if (_execute_command(cmd)) {
653 ERR("execute script failed : %s\n", cmd);
654 return MOBILE_AP_ERROR_INTERNAL;
657 drv_interface = __get_drv_interface();
659 switch (drv_interface) {
661 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
662 ERR("Failed to open socket...!!!\n");
663 ret_status = MOBILE_AP_ERROR_RESOURCE;
667 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_CFG,"
668 "SSID_LEN=%d,SSID=%s,"
669 "SEC=%s,KEY_LEN=%d,KEY=%s,CHANNEL=%d,"
670 "PREAMBLE=0,MAX_SCB=%d,HIDE=%d,END",
672 security, strlen(key), key,
673 MOBILE_AP_WIFI_CHANNEL,
674 MOBILE_AP_MAX_WIFI_STA, hide_mode);
675 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
676 if (ret_status != MOBILE_AP_ERROR_NONE) {
677 ERR("__issue_ioctl failed...!!!\n");
682 /* Start broadcasting of BSS. */
683 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_START");
684 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
685 if (ret_status != MOBILE_AP_ERROR_NONE) {
686 ERR("__issue_ioctl failed...!!!\n");
693 ret_status = _mh_core_set_ip_address(SOFTAP_IF,
695 if (ret_status != MOBILE_AP_ERROR_NONE) {
696 ERR("_mh_core_set_ip_address of SOFTAP_IF is failed\n");
700 DBG("Setting softap is OK\n");
701 ret_status = _mh_core_set_ip_address(WIFI_IF,
703 if (ret_status != MOBILE_AP_ERROR_NONE) {
704 ERR("_mh_core_set_ip_address of WIFI_IF is failed\n");
709 case MOBILE_AP_NL80211:
710 ret_status = _mh_core_set_ip_address(WIFI_IF,
712 if (ret_status != MOBILE_AP_ERROR_NONE) {
713 ERR("_mh_core_set_ip_address is failed\n");
717 ret_status = __execute_hostapd(ssid, security, key, hide_mode);
718 if (ret_status != MOBILE_AP_ERROR_NONE) {
719 ERR("__execute_hostapd is failed\n");
723 ret_status = __open_hostapd_intf(&hostapd_ctrl_fd, MH_CTRL_INTF);
724 if (ret_status != MOBILE_AP_ERROR_NONE) {
725 ERR("__open_hostapd_intf is failed\n");
726 __terminate_hostapd();
730 ret_status = __open_hostapd_monitor(&hostapd_monitor_fd);
731 if (ret_status != MOBILE_AP_ERROR_NONE) {
732 ERR("__open_hostapd_monitor is failed\n");
733 __close_hostapd_intf(&hostapd_ctrl_fd);
734 __terminate_hostapd();
741 DBG("Unknown driver interface : %d\n", drv_interface);
745 if (ret_status != MOBILE_AP_ERROR_NONE) {
746 snprintf(cmd, sizeof(cmd), "%s stop", WLAN_SCRIPT);
747 if (_execute_command(cmd)) {
748 ERR("execute script failed : %s\n", cmd);
755 int _mh_core_disable_softap(void)
757 char cmd[MAX_BUF_SIZE] = { 0 };
758 int ret_status = MOBILE_AP_ERROR_NONE;
759 mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
762 char buf[MAX_BUF_SIZE] = { 0 };
763 char *if_name = WIFI_IF;
765 drv_interface = __get_drv_interface();
767 switch (drv_interface) {
769 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
770 ERR("Failed to open socket...!!!\n");
771 ret_status = MOBILE_AP_ERROR_RESOURCE;
775 /* Stop broadcasting of BSS. */
776 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_STOP");
777 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
778 if (ret_status != MOBILE_AP_ERROR_NONE) {
779 ERR("__issue_ioctl failed...!!!\n");
787 case MOBILE_AP_NL80211:
788 ret_status = __close_hostapd_intf(&hostapd_ctrl_fd);
789 if (ret_status != MOBILE_AP_ERROR_NONE)
790 ERR("hostapd termination is failed\n");
792 ret_status = __close_hostapd_monitor(&hostapd_monitor_fd);
793 if (ret_status != MOBILE_AP_ERROR_NONE)
794 ERR("hostapd termination is failed\n");
796 ret_status = __terminate_hostapd();
797 if (ret_status != MOBILE_AP_ERROR_NONE) {
798 ERR("hostapd termination is failed\n");
803 DBG("Unknown driver interface : %d\n", drv_interface);
807 snprintf(cmd, sizeof(cmd), "%s stop", WLAN_SCRIPT);
808 if (_execute_command(cmd)) {
809 ERR("execute script failed : %s\n", cmd);
810 ret_status = MOBILE_AP_ERROR_INTERNAL;
816 static int __get_device_info_by_wext(softap_device_info_t *di)
819 char *if_name = SOFTAP_IF;
820 char cmd[MAX_BUF_SIZE];
821 char buf[MAX_BUF_SIZE] = { 0 };
822 int ret = MOBILE_AP_ERROR_NONE;
824 char *buf_ptr = NULL;
827 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
828 ERR("Failed to open socket...!!!\n");
830 return MOBILE_AP_ERROR_RESOURCE;
833 snprintf(cmd, MAX_BUF_SIZE, "AP_GET_STA_LIST");
834 ret = __issue_ioctl(sock_fd, if_name, cmd, buf);
835 if (ret != MOBILE_AP_ERROR_NONE) {
836 ERR("__issue_ioctl failed...!!!\n");
844 sscanf(buf_ptr, "%02x", &di->number);
845 DBG("connected station : %d\n", di->number);
848 for (i = 0; i < di->number; i++) {
849 unsigned int l_bssid[MOBILE_AP_WIFI_BSSID_LEN];
850 sscanf(buf_ptr, "%02X%02X%02X%02X%02X%02X", &l_bssid[0],
851 &l_bssid[1], &l_bssid[2], &l_bssid[3],
852 &l_bssid[4], &l_bssid[5]);
853 snprintf(di->bssid[i], MOBILE_AP_STR_INFO_LEN,
854 "%02X:%02X:%02X:%02X:%02X:%02X",
855 l_bssid[0], l_bssid[1], l_bssid[2],
856 l_bssid[3], l_bssid[4], l_bssid[5]);
858 DBG("STA[%d] address[%s]\n", i, di->bssid[i]);
868 static int __get_device_info_by_nl80211(softap_device_info_t *di)
873 char req[HOSTAPD_REQ_MAX_LEN] = {0, };
874 char buf[MOBILE_AP_STR_INFO_LEN] = {0, };
876 buf_len = sizeof(buf);
877 g_strlcpy(req, "NUM_STA", sizeof(req));
878 ret = __send_hostapd_req(hostapd_ctrl_fd,
879 req, strlen(req), buf, &buf_len);
880 if (ret != MOBILE_AP_ERROR_NONE) {
881 ERR("__send_hostapd_req is failed : %d\n", ret);
885 DBG("The number of station : %s\n", buf);
886 if (atoi(buf) == 0) {
887 DBG("There is no station\n");
888 return MOBILE_AP_ERROR_NONE;
891 buf_len = sizeof(buf);
892 g_strlcpy(req, "STA-FIRST", sizeof(req));
893 ret = __send_hostapd_req(hostapd_ctrl_fd,
894 req, strlen(req), buf, &buf_len);
895 if (ret != MOBILE_AP_ERROR_NONE) {
896 ERR("__send_hostapd_req is failed : %d\n", ret);
901 if (!strncmp(buf, "FAIL", 4)) {
902 ERR("FAIL is returned\n");
906 if (buf[0] == '\0') {
907 ERR("NULL string\n");
911 DBG("Station : %s\n", buf);
912 g_strlcpy(di->bssid[no_of_sta++], buf, MOBILE_AP_STR_INFO_LEN);
914 buf_len = sizeof(buf);
915 snprintf(req, sizeof(req), "STA-NEXT %s", buf);
916 ret = __send_hostapd_req(hostapd_ctrl_fd,
917 req, strlen(req), buf, &buf_len);
918 } while (ret == MOBILE_AP_ERROR_NONE);
920 di->number = no_of_sta;
925 int _mh_core_get_device_info(softap_device_info_t *di)
928 ERR("Invalid param\n");
929 return MOBILE_AP_ERROR_INVALID_PARAM;
932 int ret = MOBILE_AP_ERROR_NONE;
934 switch (__get_drv_interface()) {
936 ret = __get_device_info_by_wext(di);
939 case MOBILE_AP_NL80211:
940 ret = __get_device_info_by_nl80211(di);
944 ERR("Unknown interface\n");
951 int _mh_core_execute_dhcp_server(void)
953 char buf[DNSMASQ_CONF_LEN] = "";
954 char dns_server[MOBILE_AP_STR_INFO_LEN] = {0, };
958 if (__get_dns_server(dns_server, sizeof(dns_server))) {
959 ERR("Getting DNS server failed\n");
960 return MOBILE_AP_ERROR_INTERNAL;
963 fp = fopen(DNSMASQ_CONF_FILE, "w");
965 ERR("Could not create the file.\n");
966 return MOBILE_AP_ERROR_RESOURCE;
968 snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF, dns_server);
974 ERR("fork failed\n");
975 return MOBILE_AP_ERROR_RESOURCE;
979 if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
980 "-p", "0", "-C", DNSMASQ_CONF_FILE,
982 ERR("execl failed\n");
985 ERR("Should not get here!");
986 return MOBILE_AP_ERROR_RESOURCE;
991 return MOBILE_AP_ERROR_NONE;
994 int _mh_core_terminate_dhcp_server(void)
996 if (dnsmasq_pid == 0) {
997 DBG("There is no dnsmasq\n");
998 return MOBILE_AP_ERROR_NONE;
1001 kill(dnsmasq_pid, SIGTERM);
1002 waitpid(dnsmasq_pid, NULL, 0);
1005 return MOBILE_AP_ERROR_NONE;
1008 int _mh_core_enable_masquerade(const char *ext_if)
1011 char cmd[MAX_BUF_SIZE] = {0, };
1013 fd = open(IP_FORWARD, O_WRONLY);
1015 ERR("open failed\n");
1016 return MOBILE_AP_ERROR_RESOURCE;
1019 if (write(fd, "1", 1) != 1) {
1020 ERR("write failed\n");
1022 return MOBILE_AP_ERROR_INTERNAL;
1026 snprintf(cmd, sizeof(cmd), "%s -t nat -A POSTROUTING "MASQUERADE_RULE,
1028 if (_execute_command(cmd)) {
1029 ERR("iptables failed : %s\n", cmd);
1030 return MOBILE_AP_ERROR_INTERNAL;
1033 _add_data_usage_rule(WIFI_IF, ext_if);
1034 _add_data_usage_rule(BT_IF_ALL, ext_if);
1035 _add_data_usage_rule(USB_IF, ext_if);
1037 return MOBILE_AP_ERROR_NONE;
1040 int _mh_core_disable_masquerade(const char *ext_if)
1043 char cmd[MAX_BUF_SIZE] = {0, };
1045 fd = open(IP_FORWARD, O_WRONLY);
1047 ERR("open failed\n");
1048 return MOBILE_AP_ERROR_RESOURCE;
1051 if (write(fd, "0", 1) != 1) {
1052 ERR("write failed\n");
1054 return MOBILE_AP_ERROR_INTERNAL;
1058 snprintf(cmd, sizeof(cmd), "%s -t nat -D POSTROUTING "MASQUERADE_RULE,
1060 if (_execute_command(cmd)) {
1061 ERR("iptables failed : %s\n", cmd);
1062 return MOBILE_AP_ERROR_INTERNAL;
1065 _del_data_usage_rule(WIFI_IF, ext_if);
1066 _del_data_usage_rule(BT_IF_ALL, ext_if);
1067 _del_data_usage_rule(USB_IF, ext_if);
1069 return MOBILE_AP_ERROR_NONE;
1072 void _mh_core_add_data_to_array(GPtrArray *array, guint type, gchar *dev_name)
1074 GValue value = {0, {{0}}};
1076 g_value_init(&value, DBUS_STRUCT_UINT_STRING);
1077 g_value_take_boxed(&value,
1078 dbus_g_type_specialized_construct(DBUS_STRUCT_UINT_STRING));
1079 dbus_g_type_struct_set(&value, 0, type, 1, dev_name, G_MAXUINT);
1080 g_ptr_array_add(array, g_value_get_boxed(&value));
1083 int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
1086 struct sockaddr_in addr;
1089 DBG("if_name : %s ip address : 0x%X\n", if_name, ip);
1091 if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1092 ERR("socket open failed!!!\n");
1093 perror("ioctl fail");
1094 return MOBILE_AP_ERROR_RESOURCE;
1097 g_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
1099 memset(&addr, 0, sizeof(struct sockaddr));
1100 addr.sin_family = AF_INET;
1102 addr.sin_addr.s_addr = htonl(ip);
1104 memcpy(&ifr.ifr_addr, &addr, sizeof(struct sockaddr));
1105 if (ioctl(sock_fd, SIOCSIFADDR, &ifr) < 0) {
1106 ERR("ioctl failed...!!!\n");
1107 perror("ioctl fail");
1109 return MOBILE_AP_ERROR_INTERNAL;
1112 if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0) {
1113 ERR("ioctl failed...!!!\n");
1114 perror("ioctl fail");
1116 return MOBILE_AP_ERROR_INTERNAL;
1119 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
1120 if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
1121 ERR("ioctl failed...!!!\n");
1122 perror("ioctl fail");
1124 return MOBILE_AP_ERROR_INTERNAL;
1129 return MOBILE_AP_ERROR_NONE;