Initialize Tizen 2.3
[framework/connectivity/mobileap-agent.git] / src / mobileap_agent.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 <sys/stat.h>
19 #include <sys/un.h>
20 #include <errno.h>
21 #include <sys/ioctl.h>
22 #include <glib.h>
23 #include <glib-object.h>
24 #include <dbus/dbus-glib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <sys/wait.h>
30 #include <sys/types.h>
31 #include <fcntl.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <linux/wireless.h>
36
37 #include <openssl/evp.h>
38 #include <openssl/sha.h>
39
40 #include "mobileap_common.h"
41 #include "mobileap_agent.h"
42 #include "mobileap_handler.h"
43
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;
50
51 static int __issue_ioctl(int sock_fd, char *if_name, char *cmd, char *buf)
52 {
53         int ret_val = MOBILE_AP_ERROR_NONE;
54         struct iwreq iwr;
55
56         memset(buf, 0, MAX_BUF_SIZE);
57         memset(&iwr, 0, sizeof(iwr));
58
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;
64
65         usleep(DRIVER_DELAY);
66
67         /* Issue ioctl */
68         if ((ioctl(sock_fd, SIOCSIWPRIV, &iwr)) < 0) {
69                 ERR("ioctl failed...!!!\n");
70                 ret_val = MOBILE_AP_ERROR_INTERNAL;
71         }
72
73         return ret_val;
74 }
75
76 static int __get_psk_hexascii(const char *pass, const unsigned char *salt, char *psk, unsigned int psk_len)
77 {
78         if (pass == NULL || salt == NULL || psk == NULL || psk_len == 0) {
79                 ERR("Invalid parameter\n");
80                 return MOBILE_AP_ERROR_INVALID_PARAM;
81         }
82
83         if (psk_len < SHA256_DIGEST_LENGTH * 2 + 1) {
84                 ERR("Invalid parameter\n");
85                 return MOBILE_AP_ERROR_INVALID_PARAM;
86         }
87
88         int i;
89         int d_16;
90         int r_16;
91         unsigned char buf[SHA256_DIGEST_LENGTH] = {0, };
92
93         if (!PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
94                                 salt, strlen((const char *)salt),
95                                 PSK_ITERATION_COUNT, sizeof(buf), buf)) {
96                 ERR("Getting psk is failed\n");
97                 return MOBILE_AP_ERROR_INTERNAL;
98         }
99
100         for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
101                 d_16 = buf[i] >> 4;
102                 r_16 = buf[i] & 0xf;
103
104                 psk[i << 1] = d_16 < 10 ? d_16 + '0' : d_16 - 10 + 'a';
105                 psk[(i << 1) + 1] = r_16 < 10 ? r_16 + '0' : r_16 - 10 + 'a';
106         }
107         psk[i << 1] = '\0';
108
109         return MOBILE_AP_ERROR_NONE;
110 }
111
112 static int __execute_hostapd(const char *ssid, const char *security,
113                 const char *key, int hide_mode)
114 {
115         DBG("+\n");
116
117         char psk[2 * SHA256_DIGEST_LENGTH + 1] = {0, };
118         char buf[HOSTAPD_CONF_LEN] = "";
119         char sec_buf[HOSTAPD_CONF_LEN] = "";
120         FILE *fp = NULL;
121         pid_t pid;
122
123         if (security != NULL && !strcmp(security, "wpa2-psk")) {
124                 if (__get_psk_hexascii(key, (const unsigned char *)ssid, psk,
125                                         sizeof(psk)) != MOBILE_AP_ERROR_NONE) {
126                         ERR("Getting PSK(Hex ascii type) is failed\n");
127                         return MOBILE_AP_ERROR_INTERNAL;
128                 }
129
130                 snprintf(sec_buf, HOSTAPD_CONF_LEN,
131                                 "wpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\nwps_state=2\neap_server=1",
132                                 psk);
133         }
134
135         snprintf(buf, HOSTAPD_CONF_LEN, HOSTAPD_CONF,
136                         WIFI_IF,
137                         HOSTAPD_CTRL_INTF_DIR,
138                         ssid,
139                         MOBILE_AP_WIFI_CHANNEL,
140                         hide_mode ? 2 : 0,
141                         MOBILE_AP_MAX_WIFI_STA,
142                         sec_buf);
143
144         fp = fopen(HOSTAPD_CONF_FILE, "w");
145         if (NULL == fp) {
146                 ERR("Could not create the file.\n");
147                 return MOBILE_AP_ERROR_RESOURCE;
148         }
149         fputs(buf, fp);
150         fclose(fp);
151
152         pid = fork();
153         if (pid < 0) {
154                 ERR("fork failed\n");
155                 return MOBILE_AP_ERROR_RESOURCE;
156         }
157
158         if (pid == 0) {
159                 if (execl(HOSTAPD_BIN, HOSTAPD_BIN, "-e", HOSTAPD_ENTROPY_FILE,
160                                         HOSTAPD_CONF_FILE,
161                                         "-f", HOSTAPD_DEBUG_FILE, "-dd",
162                                         (char *)NULL)) {
163                         ERR("execl failed\n");
164                 }
165
166                 ERR("Should not get here!");
167                 return MOBILE_AP_ERROR_RESOURCE;
168         }
169
170         hostapd_pid = pid;
171
172         return MOBILE_AP_ERROR_NONE;
173 }
174
175 static int __terminate_hostapd()
176 {
177         DBG("+\n");
178
179         if (hostapd_pid == 0) {
180                 DBG("There is no hostapd\n");
181                 return MOBILE_AP_ERROR_NONE;
182         }
183
184         kill(hostapd_pid, SIGTERM);
185         waitpid(hostapd_pid, NULL, 0);
186         hostapd_pid = 0;
187
188         return MOBILE_AP_ERROR_NONE;
189 }
190
191 /*
192  * number NUM_STA(void)
193  * addr STA-FIRST(void)
194  * addr STA-NEXT(addr)
195  * void DISASSOCIATE(addr)
196  * void READ_WHITELIST(filename)
197  * void SET_MAXCLIENT(number)
198  */
199 static int __send_hostapd_req(int fd, const char *req, const int req_len,
200                 char *buf, int *buf_len)
201 {
202         if (fd < 0 || req == NULL || req_len <= 0 ||
203                         buf == NULL || buf_len == NULL || *buf_len <= 0) {
204                 ERR("Invalid param\n");
205                 return MOBILE_AP_ERROR_INVALID_PARAM;
206         }
207
208         struct timeval tv = {10, 0};
209         fd_set fds;
210         int ret = 0;
211
212         ret = send(fd, req, req_len, 0);
213         if (ret < 0) {
214                 ERR("send is failed : %s\n", strerror(errno));
215                 return MOBILE_AP_ERROR_INTERNAL;
216         }
217
218         while (TRUE) {
219                 FD_ZERO(&fds);
220                 FD_SET(fd, &fds);
221                 ret = select(fd + 1, &fds, NULL, NULL, &tv);
222                 if (ret < 0) {
223                         return MOBILE_AP_ERROR_INTERNAL;
224                 } else if (ret == 0) {
225                         ERR("There is no response from hostapd\n");
226                         return MOBILE_AP_ERROR_INTERNAL;
227                 } else if (!FD_ISSET(fd, &fds)) {
228                         ERR("Unknown case\n");
229                         return MOBILE_AP_ERROR_INTERNAL;
230                 }
231
232                 ret = recv(fd, buf, (*buf_len) - 1, 0);
233                 if (ret < 0) {
234                         ERR("recv is failed\n");
235                         return MOBILE_AP_ERROR_INTERNAL;
236                 }
237
238                 if (buf[0] == '<') {
239                         DBG("Unsolicited message\n");
240                         continue;
241                 }
242
243                 *buf_len = ret;
244                 buf[ret] = '\0';
245                 if (ret == 0) {
246                         ERR("socket is closed\n");
247                 }
248
249                 break;
250         }
251
252         return MOBILE_AP_ERROR_NONE;
253 }
254
255 static int __open_hostapd_intf(int *fd, const char *intf)
256 {
257         if (fd == NULL || intf == NULL) {
258                 ERR("fd is NULL\n");
259                 return MOBILE_AP_ERROR_INVALID_PARAM;
260         }
261
262         DBG("+\n");
263
264         int retry = 0;
265         char ctrl_intf[255] = {0, };
266         struct sockaddr_un src;
267         struct sockaddr_un dest;
268         struct stat stat_buf;
269
270         *fd = socket(PF_UNIX, SOCK_DGRAM, 0);
271         if (*fd < 0) {
272                 ERR("socket is failed\n");
273                 return MOBILE_AP_ERROR_INTERNAL;
274         }
275
276         src.sun_family = AF_UNIX;
277         g_strlcpy(src.sun_path, intf, sizeof(src.sun_path));
278
279         if (stat(src.sun_path, &stat_buf) == 0) {
280                 DBG("There is already mh interface. It will be removed\n");
281                 unlink(src.sun_path);
282         }
283
284         if (bind(*fd, (struct sockaddr *)&src, sizeof(src)) < 0) {
285                 ERR("bind is failed\n");
286                 close(*fd);
287                 *fd = -1;
288                 unlink(src.sun_path);
289                 return MOBILE_AP_ERROR_INTERNAL;
290         }
291
292         snprintf(ctrl_intf, sizeof(ctrl_intf), "%s/%s",
293                         HOSTAPD_CTRL_INTF_DIR, WIFI_IF);
294         dest.sun_family = AF_UNIX;
295         g_strlcpy(dest.sun_path, ctrl_intf, sizeof(dest.sun_path));
296
297         while (connect(*fd, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
298                 DBG("connect is failed : %s\n", strerror(errno));
299                 if (++retry >= HOSTAPD_RETRY_MAX)
300                         goto FAIL;
301                 usleep(HOSTAPD_RETRY_DELAY);
302         }
303
304         return MOBILE_AP_ERROR_NONE;
305
306 FAIL:
307         ERR("Cannot make connection to hostapd\n");
308         close(*fd);
309         *fd = -1;
310         unlink(src.sun_path);
311
312         return MOBILE_AP_ERROR_INTERNAL;
313 }
314
315 static int __close_hostapd_intf(int *fd)
316 {
317         DBG("+\n");
318
319         if (fd == NULL) {
320                 ERR("fd is NULL\n");
321                 return MOBILE_AP_ERROR_INVALID_PARAM;
322         }
323
324         if (*fd > 0)
325                 close(*fd);
326         *fd = -1;
327
328         return MOBILE_AP_ERROR_NONE;
329 }
330
331 static gboolean __hostapd_monitor_cb(GIOChannel *source)
332 {
333         DBG("+\n");
334
335         char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
336         char *pbuf = NULL;
337         gsize read = 0;
338         int n_station = 0;
339
340 #if !GLIB_CHECK_VERSION(2, 31, 0)
341         int ret = 0;
342
343         ret = g_io_channel_read(hostapd_io_channel, buf,
344                         HOSTAPD_REQ_MAX_LEN, &read);
345         if (ret != G_IO_ERROR_NONE) {
346                 ERR("g_io_channel_read is failed\n");
347                 return FALSE;
348         }
349 #else
350         GError *err = NULL;
351         GIOStatus ios;
352
353         ios = g_io_channel_read_chars(hostapd_io_channel, buf,
354                         HOSTAPD_REQ_MAX_LEN, &read, &err);
355         if (err != NULL) {
356                 ERR("g_io_channel_read_chars is failed : %s\n", err->message);
357                 g_error_free(err);
358                 return FALSE;
359         } else if (ios != G_IO_STATUS_NORMAL) {
360                 ERR("g_io_channel_read_chars is failed : %d\n", ios);
361                 return FALSE;
362         }
363 #endif
364
365         buf[read] = '\0';
366         pbuf = strrchr(buf, '\n');
367         if (pbuf != NULL)
368                 *pbuf = '\0';
369
370         if (buf[0] == '<' && (pbuf = strchr(buf, '>')) != NULL) {
371                 pbuf++;
372         } else {
373                 pbuf = buf;
374         }
375
376         DBG("Event : %s\n", pbuf);
377
378         if (!strncmp(pbuf, HOSTAPD_STA_DISCONN, strlen(HOSTAPD_STA_DISCONN))) {
379                 pbuf = strchr(pbuf, ' ');
380                 if (pbuf == NULL) {
381                         ERR("There is no info. for disconnected station\n");
382                         return TRUE;
383                 }
384                 pbuf++;
385
386                 DBG("Disconnected station MAC : %s\n", pbuf);
387                 _remove_station_info(pbuf, _slist_find_station_by_mac);
388
389                 _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
390                                 _slist_find_station_by_interface, &n_station);
391                 if (n_station == 0)
392                         _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
393
394                 return TRUE;
395         } else {
396                 DBG("Event is not handled\n");
397         }
398
399         return TRUE;
400 }
401
402 static int __open_hostapd_monitor(int *fd)
403 {
404         if (fd == NULL) {
405                 ERR("fd is NULL\n");
406                 return MOBILE_AP_ERROR_INVALID_PARAM;
407         }
408
409         DBG("+\n");
410
411         char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
412         int buf_len = 0;
413
414         if (__open_hostapd_intf(fd, MH_MONITOR_INTF) != MOBILE_AP_ERROR_NONE) {
415                 ERR("__open_hostapd_intf() is failed\n");
416                 return MOBILE_AP_ERROR_INTERNAL;
417         }
418
419         hostapd_io_channel = g_io_channel_unix_new(*fd);
420         if (hostapd_io_channel == NULL) {
421                 ERR("g_io_channel_unix_new is failed\n");
422                 return MOBILE_AP_ERROR_INTERNAL;
423         }
424
425         g_io_channel_set_encoding(hostapd_io_channel, NULL, NULL);
426         g_io_channel_set_flags(hostapd_io_channel,
427                         G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK, NULL);
428
429         hostapd_io_source = g_io_add_watch(hostapd_io_channel, G_IO_IN,
430                         (GIOFunc)__hostapd_monitor_cb, NULL);
431
432         buf_len = sizeof(buf);
433         __send_hostapd_req(*fd, HOSTAPD_MONITOR_ATTACH,
434                         strlen(HOSTAPD_MONITOR_ATTACH), buf, &buf_len);
435         DBG("return : %s\n", buf);
436
437         return MOBILE_AP_ERROR_NONE;
438 }
439
440 static int __close_hostapd_monitor(int *fd)
441 {
442         GError *err = NULL;
443         char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
444         int buf_len = 0;
445
446         buf_len = sizeof(buf);
447         __send_hostapd_req(*fd, HOSTAPD_MONITOR_DETACH,
448                         strlen(HOSTAPD_MONITOR_DETACH), buf, &buf_len);
449         DBG("return : %s\n", buf);
450
451         if (hostapd_io_source != 0) {
452                 g_source_remove(hostapd_io_source);
453                 hostapd_io_source = 0;
454         }
455
456         if (hostapd_io_channel != NULL) {
457                 g_io_channel_shutdown(hostapd_io_channel, TRUE, &err);
458                 g_io_channel_unref(hostapd_io_channel);
459                 hostapd_io_channel = NULL;
460         }
461
462         __close_hostapd_intf(fd);
463
464         return MOBILE_AP_ERROR_NONE;
465 }
466
467 static mobile_ap_drv_interface_e __get_drv_interface(void)
468 {
469         static mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
470
471         if (drv_interface != MOBILE_AP_DRV_INTERFACE_NONE) {
472                 return drv_interface;
473         }
474
475         const char *drv_rfkill_path = "/sys/devices/platform";
476         const char *wext_drv[] = {
477                 "bcm4329-b1", "bcm4330-b0",
478                 "bcm4330-b1", "bcm4330-b2",
479                 NULL};
480
481         char path[MAX_BUF_SIZE] = { 0 };
482         struct stat stat_buf = { 0 };
483         int fd = 0;
484         int i = 0;
485
486         drv_interface = MOBILE_AP_NL80211;
487
488         for (i = 0; wext_drv[i] != NULL; i++) {
489                 snprintf(path, sizeof(path), "%s/%s",
490                                 drv_rfkill_path, wext_drv[i]);
491                 fd = open(path, O_RDONLY);
492                 if (fd < 0)
493                         continue;
494
495                 if (fstat(fd, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode)) {
496                         drv_interface = MOBILE_AP_WEXT;
497                         close(fd);
498                         break;
499                 }
500
501                 close(fd);
502         }
503
504         return drv_interface;
505 }
506
507 int _mh_core_enable_softap(const char *ssid, const char *security,
508                 const char *key, int hide_mode)
509 {
510         if (ssid == NULL || security == NULL || key == NULL) {
511                 ERR("Invalid param\n");
512                 return MOBILE_AP_ERROR_INTERNAL;
513         }
514
515         char cmd[MAX_BUF_SIZE];
516         int ret_status = MOBILE_AP_ERROR_NONE;
517         mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
518
519         int sock_fd;
520         char *if_name = WIFI_IF;
521         char buf[MAX_BUF_SIZE] = { 0 };
522
523         snprintf(cmd, sizeof(cmd), "%s softap", WLAN_SCRIPT);
524         if (_execute_command(cmd)) {
525                 ERR("execute script failed : %s\n", cmd);
526                 return MOBILE_AP_ERROR_INTERNAL;
527         }
528
529         drv_interface = __get_drv_interface();
530
531         switch (drv_interface) {
532         case MOBILE_AP_WEXT:
533                 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
534                         ERR("Failed to open socket...!!!\n");
535                         ret_status = MOBILE_AP_ERROR_RESOURCE;
536                         break;
537                 }
538
539                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_CFG,"
540                                         "SSID_LEN=%d,SSID=%s,"
541                                         "SEC=%s,KEY_LEN=%d,KEY=%s,CHANNEL=%d,"
542                                         "PREAMBLE=0,MAX_SCB=%d,HIDE=%d,END",
543                                         strlen(ssid), ssid,
544                                         security, strlen(key), key,
545                                         MOBILE_AP_WIFI_CHANNEL,
546                                         MOBILE_AP_MAX_WIFI_STA, hide_mode);
547                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
548                 if (ret_status != MOBILE_AP_ERROR_NONE) {
549                         ERR("__issue_ioctl failed...!!!\n");
550                         close(sock_fd);
551                         break;
552                 }
553
554                 /* Start broadcasting of BSS. */
555                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_START");
556                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
557                 if (ret_status != MOBILE_AP_ERROR_NONE) {
558                         ERR("__issue_ioctl failed...!!!\n");
559                         close(sock_fd);
560                         break;
561                 }
562
563                 close(sock_fd);
564
565                 ret_status = _mh_core_set_ip_address(SOFTAP_IF,
566                                 IP_ADDRESS_SOFTAP);
567                 if (ret_status != MOBILE_AP_ERROR_NONE) {
568                         ERR("_mh_core_set_ip_address of SOFTAP_IF is failed\n");
569                         break;
570                 }
571
572                 DBG("Setting softap is OK\n");
573                 ret_status = _mh_core_set_ip_address(WIFI_IF,
574                                 IP_ADDRESS_WIFI);
575                 if (ret_status != MOBILE_AP_ERROR_NONE) {
576                         ERR("_mh_core_set_ip_address of WIFI_IF is failed\n");
577                         break;
578                 }
579                 break;
580
581         case MOBILE_AP_NL80211:
582                 ret_status = _mh_core_set_ip_address(WIFI_IF,
583                                 IP_ADDRESS_SOFTAP);
584                 if (ret_status != MOBILE_AP_ERROR_NONE) {
585                         ERR("_mh_core_set_ip_address is failed\n");
586                         break;
587                 }
588
589                 ret_status = __execute_hostapd(ssid, security, key, hide_mode);
590                 if (ret_status != MOBILE_AP_ERROR_NONE) {
591                         ERR("__execute_hostapd is failed\n");
592                         break;
593                 }
594
595                 ret_status = __open_hostapd_intf(&hostapd_ctrl_fd, MH_CTRL_INTF);
596                 if (ret_status != MOBILE_AP_ERROR_NONE) {
597                         ERR("__open_hostapd_intf is failed\n");
598                         __terminate_hostapd();
599                         break;
600                 }
601
602                 ret_status = __open_hostapd_monitor(&hostapd_monitor_fd);
603                 if (ret_status != MOBILE_AP_ERROR_NONE) {
604                         ERR("__open_hostapd_monitor is failed\n");
605                         __close_hostapd_intf(&hostapd_ctrl_fd);
606                         __terminate_hostapd();
607                         break;
608                 }
609
610                 break;
611
612         default:
613                 DBG("Unknown driver interface : %d\n", drv_interface);
614                 break;
615         }
616
617         if (ret_status != MOBILE_AP_ERROR_NONE) {
618                 snprintf(cmd, sizeof(cmd), "%s stop", WLAN_SCRIPT);
619                 if (_execute_command(cmd)) {
620                         ERR("execute script failed : %s\n", cmd);
621                 }
622         }
623
624         return ret_status;
625 }
626
627 int _mh_core_disable_softap(void)
628 {
629         char cmd[MAX_BUF_SIZE] = { 0 };
630         int ret_status = MOBILE_AP_ERROR_NONE;
631         mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
632
633         int sock_fd = 0;
634         char buf[MAX_BUF_SIZE] = { 0 };
635         char *if_name = WIFI_IF;
636
637         drv_interface = __get_drv_interface();
638
639         switch (drv_interface) {
640         case MOBILE_AP_WEXT:
641                 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
642                         ERR("Failed to open socket...!!!\n");
643                         ret_status = MOBILE_AP_ERROR_RESOURCE;
644                         break;
645                 }
646
647                 /* Stop broadcasting of BSS. */
648                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_STOP");
649                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
650                 if (ret_status != MOBILE_AP_ERROR_NONE) {
651                         ERR("__issue_ioctl failed...!!!\n");
652                         close(sock_fd);
653                         break;
654                 }
655
656                 close(sock_fd);
657                 break;
658
659         case MOBILE_AP_NL80211:
660                 ret_status = __close_hostapd_intf(&hostapd_ctrl_fd);
661                 if (ret_status != MOBILE_AP_ERROR_NONE)
662                         ERR("hostapd termination is failed\n");
663
664                 ret_status = __close_hostapd_monitor(&hostapd_monitor_fd);
665                 if (ret_status != MOBILE_AP_ERROR_NONE)
666                         ERR("hostapd termination is failed\n");
667
668                 ret_status = __terminate_hostapd();
669                 if (ret_status != MOBILE_AP_ERROR_NONE) {
670                         ERR("hostapd termination is failed\n");
671                 }
672                 break;
673
674         default:
675                 DBG("Unknown driver interface : %d\n", drv_interface);
676                 break;
677         }
678
679         snprintf(cmd, sizeof(cmd), "%s stop", WLAN_SCRIPT);
680         if (_execute_command(cmd)) {
681                 ERR("execute script failed : %s\n", cmd);
682                 ret_status = MOBILE_AP_ERROR_INTERNAL;
683         }
684
685         return ret_status;
686 }
687
688 static int __get_device_info_by_wext(softap_device_info_t *di)
689 {
690         int sock_fd = 0;
691         char *if_name = SOFTAP_IF;
692         char cmd[MAX_BUF_SIZE];
693         char buf[MAX_BUF_SIZE] = { 0 };
694         int ret = MOBILE_AP_ERROR_NONE;
695
696         char *buf_ptr = NULL;
697         int i;
698
699         if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
700                 ERR("Failed to open socket...!!!\n");
701                 di->number = 0;
702                 return MOBILE_AP_ERROR_RESOURCE;
703         }
704
705         snprintf(cmd, MAX_BUF_SIZE, "AP_GET_STA_LIST");
706         ret = __issue_ioctl(sock_fd, if_name, cmd, buf);
707         if (ret != MOBILE_AP_ERROR_NONE) {
708                 ERR("__issue_ioctl failed...!!!\n");
709                 di->number = 0;
710                 close(sock_fd);
711                 return ret;
712         }
713
714         buf_ptr = buf;
715
716         sscanf(buf_ptr, "%02x", &di->number);
717         DBG("connected station : %d\n", di->number);
718
719         buf_ptr += 2;
720         for (i = 0; i < di->number; i++) {
721                 unsigned int l_bssid[MOBILE_AP_WIFI_BSSID_LEN];
722                 sscanf(buf_ptr, "%02X%02X%02X%02X%02X%02X", &l_bssid[0],
723                                         &l_bssid[1], &l_bssid[2], &l_bssid[3],
724                                         &l_bssid[4], &l_bssid[5]);
725                 snprintf(di->bssid[i], MOBILE_AP_STR_INFO_LEN,
726                                         "%02X:%02X:%02X:%02X:%02X:%02X",
727                                         l_bssid[0], l_bssid[1], l_bssid[2],
728                                         l_bssid[3], l_bssid[4], l_bssid[5]);
729
730                 DBG("STA[%d] address[%s]\n", i, di->bssid[i]);
731
732                 buf_ptr += 12;
733         }
734
735         close(sock_fd);
736
737         return ret;
738 }
739
740 static int __get_device_info_by_nl80211(softap_device_info_t *di)
741 {
742         int ret = 0;
743         int no_of_sta = 0;
744         int buf_len = 0;
745         char req[HOSTAPD_REQ_MAX_LEN] = {0, };
746         char buf[MOBILE_AP_STR_INFO_LEN] = {0, };
747
748         buf_len = sizeof(buf);
749         g_strlcpy(req, "NUM_STA", sizeof(req));
750         ret = __send_hostapd_req(hostapd_ctrl_fd,
751                         req, strlen(req), buf, &buf_len);
752         if (ret != MOBILE_AP_ERROR_NONE) {
753                 ERR("__send_hostapd_req is failed : %d\n", ret);
754                 return ret;
755         }
756
757         DBG("The number of station : %s\n", buf);
758         if (atoi(buf) == 0) {
759                 DBG("There is no station\n");
760                 return MOBILE_AP_ERROR_NONE;
761         }
762
763         buf_len = sizeof(buf);
764         g_strlcpy(req, "STA-FIRST", sizeof(req));
765         ret = __send_hostapd_req(hostapd_ctrl_fd,
766                         req, strlen(req), buf, &buf_len);
767         if (ret != MOBILE_AP_ERROR_NONE) {
768                 ERR("__send_hostapd_req is failed : %d\n", ret);
769                 return ret;
770         }
771
772         do {
773                 if (!strncmp(buf, "FAIL", 4)) {
774                         ERR("FAIL is returned\n");
775                         break;
776                 }
777
778                 if (buf[0] == '\0') {
779                         ERR("NULL string\n");
780                         break;
781                 }
782
783                 DBG("Station : %s\n", buf);
784                 g_strlcpy(di->bssid[no_of_sta++], buf, MOBILE_AP_STR_INFO_LEN);
785
786                 buf_len = sizeof(buf);
787                 snprintf(req, sizeof(req), "STA-NEXT %s", buf);
788                 ret = __send_hostapd_req(hostapd_ctrl_fd,
789                                 req, strlen(req), buf, &buf_len);
790         } while (ret == MOBILE_AP_ERROR_NONE);
791
792         di->number = no_of_sta;
793
794         return ret;
795 }
796
797 int _mh_core_get_device_info(softap_device_info_t *di)
798 {
799         if (di == NULL) {
800                 ERR("Invalid param\n");
801                 return MOBILE_AP_ERROR_INVALID_PARAM;
802         }
803
804         int ret = MOBILE_AP_ERROR_NONE;
805
806         switch (__get_drv_interface()) {
807         case MOBILE_AP_WEXT:
808                 ret = __get_device_info_by_wext(di);
809                 break;
810
811         case MOBILE_AP_NL80211:
812                 ret = __get_device_info_by_nl80211(di);
813                 break;
814
815         default:
816                 ERR("Unknown interface\n");
817                 break;
818         }
819
820         return ret;
821 }
822
823 int _mh_core_execute_dhcp_server(void)
824 {
825         char buf[DNSMASQ_CONF_LEN] = "";
826         FILE *fp = NULL;
827         pid_t pid;
828
829         fp = fopen(DNSMASQ_CONF_FILE, "w");
830         if (NULL == fp) {
831                 ERR("Could not create the file.\n");
832                 return MOBILE_AP_ERROR_RESOURCE;
833         }
834         snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF);
835         fputs(buf, fp);
836         fclose(fp);
837
838         pid = fork();
839         if (pid < 0) {
840                 ERR("fork failed\n");
841                 return MOBILE_AP_ERROR_RESOURCE;
842         }
843
844         if (pid == 0) {
845                 /* -d : Debug mode
846                  * -p 0 : DNS off
847                  * -C file : Configuration file path
848                  */
849                 if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
850                                         "-p", "0", "-C", DNSMASQ_CONF_FILE,
851                                         (char *)NULL)) {
852                         ERR("execl failed\n");
853                 }
854
855                 ERR("Should not get here!");
856                 return MOBILE_AP_ERROR_RESOURCE;
857         }
858
859         dnsmasq_pid = pid;
860
861         return MOBILE_AP_ERROR_NONE;
862 }
863
864 int _mh_core_terminate_dhcp_server(void)
865 {
866         if (dnsmasq_pid == 0) {
867                 DBG("There is no dnsmasq\n");
868                 return MOBILE_AP_ERROR_NONE;
869         }
870
871         kill(dnsmasq_pid, SIGTERM);
872         waitpid(dnsmasq_pid, NULL, 0);
873         dnsmasq_pid = 0;
874
875         return MOBILE_AP_ERROR_NONE;
876 }
877
878 int _mh_core_enable_masquerade(const char *ext_if)
879 {
880         if (ext_if == NULL || strlen(ext_if) == 0) {
881                 ERR("ext_if[%s] is invalid\n", ext_if);
882                 return MOBILE_AP_ERROR_INVALID_PARAM;
883         }
884
885         int fd = -1;
886         char cmd[MAX_BUF_SIZE] = {0, };
887
888         fd = open(IP_FORWARD, O_WRONLY);
889         if (fd < 0) {
890                 ERR("open failed\n");
891                 return MOBILE_AP_ERROR_RESOURCE;
892         }
893
894         if (write(fd, "1", 1) != 1) {
895                 ERR("write failed\n");
896                 close(fd);
897                 return MOBILE_AP_ERROR_INTERNAL;
898         }
899         close(fd);
900
901         snprintf(cmd, sizeof(cmd), "%s -t nat -A POSTROUTING "MASQUERADE_RULE,
902                         IPTABLES, ext_if);
903         if (_execute_command(cmd)) {
904                 ERR("iptables failed : %s\n", cmd);
905                 return MOBILE_AP_ERROR_INTERNAL;
906         }
907
908         _add_data_usage_rule(WIFI_IF, ext_if);
909         _add_data_usage_rule(BT_IF_ALL, ext_if);
910         _add_data_usage_rule(USB_IF, ext_if);
911
912         return MOBILE_AP_ERROR_NONE;
913 }
914
915 int _mh_core_disable_masquerade(const char *ext_if)
916 {
917         if (ext_if == NULL || strlen(ext_if) == 0) {
918                 ERR("ext_if[%s] is invalid\n", ext_if);
919                 return MOBILE_AP_ERROR_INVALID_PARAM;
920         }
921
922         int fd = -1;
923         char cmd[MAX_BUF_SIZE] = {0, };
924
925         fd = open(IP_FORWARD, O_WRONLY);
926         if (fd < 0) {
927                 ERR("open failed\n");
928                 return MOBILE_AP_ERROR_RESOURCE;
929         }
930
931         if (write(fd, "0", 1) != 1) {
932                 ERR("write failed\n");
933                 close(fd);
934                 return MOBILE_AP_ERROR_INTERNAL;
935         }
936         close(fd);
937
938         snprintf(cmd, sizeof(cmd), "%s -t nat -D POSTROUTING "MASQUERADE_RULE,
939                         IPTABLES, ext_if);
940         if (_execute_command(cmd)) {
941                 ERR("iptables failed : %s\n", cmd);
942                 return MOBILE_AP_ERROR_INTERNAL;
943         }
944
945         _del_data_usage_rule(WIFI_IF, ext_if);
946         _del_data_usage_rule(BT_IF_ALL, ext_if);
947         _del_data_usage_rule(USB_IF, ext_if);
948
949         return MOBILE_AP_ERROR_NONE;
950 }
951
952 void _mh_core_add_data_to_array(GPtrArray *array, guint type, gchar *dev_name)
953 {
954         GValue value = {0, {{0}}};
955
956         g_value_init(&value, DBUS_STRUCT_UINT_STRING);
957         g_value_take_boxed(&value,
958                         dbus_g_type_specialized_construct(DBUS_STRUCT_UINT_STRING));
959         dbus_g_type_struct_set(&value, 0, type, 1, dev_name, G_MAXUINT);
960         g_ptr_array_add(array, g_value_get_boxed(&value));
961 }
962
963 int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
964 {
965         struct ifreq ifr;
966         struct sockaddr_in addr;
967         int sock_fd;
968
969         DBG("if_name : %s ip address : 0x%X\n", if_name, ip);
970
971         if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
972                 ERR("socket open failed!!!\n");
973                 perror("ioctl fail");
974                 return MOBILE_AP_ERROR_RESOURCE;
975         }
976
977         g_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
978
979         memset(&addr, 0, sizeof(struct sockaddr));
980         addr.sin_family = AF_INET;
981         addr.sin_port = 0;
982         addr.sin_addr.s_addr = htonl(ip);
983
984         memcpy(&ifr.ifr_addr, &addr, sizeof(struct sockaddr));
985         if (ioctl(sock_fd, SIOCSIFADDR, &ifr) < 0) {
986                 ERR("ioctl failed...!!!\n");
987                 perror("ioctl fail");
988                 close(sock_fd);
989                 return MOBILE_AP_ERROR_INTERNAL;
990         }
991
992         if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0) {
993                 ERR("ioctl failed...!!!\n");
994                 perror("ioctl fail");
995                 close(sock_fd);
996                 return MOBILE_AP_ERROR_INTERNAL;
997         }
998
999         ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
1000         if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
1001                 ERR("ioctl failed...!!!\n");
1002                 perror("ioctl fail");
1003                 close(sock_fd);
1004                 return MOBILE_AP_ERROR_INTERNAL;
1005         }
1006
1007         close(sock_fd);
1008
1009         return MOBILE_AP_ERROR_NONE;
1010 }