tizen 2.3 release
[framework/connectivity/mobileap-agent.git] / src / mobileap_softap.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 <ctype.h>
30 #include <sys/wait.h>
31 #include <sys/types.h>
32 #include <fcntl.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <linux/wireless.h>
37 #include <openssl/evp.h>
38 #include <openssl/sha.h>
39
40 #include "mobileap_common.h"
41 #include "mobileap_softap.h"
42 #include "mobileap_handler.h"
43 #include "mobileap_wifi.h"
44 #include "mobileap_iptables.h"
45
46 #define NETCONFIG_SERVICE                               "net.netconfig"
47 #define NETCONFIG_WIFI_INTERFACE                "net.netconfig.wifi"
48 #define NETCONFIG_WIFI_PATH                             "/net/netconfig/wifi"
49
50 #define NETCONFIG_DBUS_REPLY_TIMEOUT    (10 * 1000)
51
52 static pid_t dnsmasq_pid = 0;
53 static pid_t hostapd_pid = 0;
54 static int hostapd_ctrl_fd = 0;
55 static int hostapd_monitor_fd = 0;
56 static GIOChannel *hostapd_io_channel = NULL;
57 static guint hostapd_io_source = 0;
58 GSList *sta_timer_list = NULL;
59
60 static gboolean __hostapd_connect_timer_cb(gpointer user_data);
61
62 static char *__find_first_caps_char(char *str)
63 {
64         if (str == NULL) {
65                 ERR("NULL string passes\n");
66                 return NULL;
67         }
68
69         while(*str) {
70                 if (isupper(*str)) {
71                         return str;
72                 }
73                 str++;
74         }
75         return NULL;
76 }
77
78 static int __issue_ioctl(int sock_fd, char *if_name, char *cmd, char *buf)
79 {
80         int ret_val = MOBILE_AP_ERROR_NONE;
81         struct iwreq iwr;
82
83         memset(buf, 0, MAX_BUF_SIZE);
84         memset(&iwr, 0, sizeof(iwr));
85
86         /* Configure ioctl parameters */
87         g_strlcpy(iwr.ifr_name, if_name, IFNAMSIZ);
88         g_strlcpy(buf, cmd, MAX_BUF_SIZE);
89         iwr.u.data.pointer = buf;
90         iwr.u.data.length = MAX_BUF_SIZE;
91
92         usleep(DRIVER_DELAY);
93
94         /* Issue ioctl */
95         if ((ioctl(sock_fd, SIOCSIWPRIV, &iwr)) < 0) {
96                 ERR("ioctl failed...!!!\n");
97                 ret_val = MOBILE_AP_ERROR_INTERNAL;
98         }
99
100         return ret_val;
101 }
102
103 static int __get_psk_hexascii(const char *pass, const unsigned char *salt,
104                 char *psk, unsigned int psk_len)
105 {
106         if (pass == NULL || salt == NULL || psk == NULL || psk_len <
107                         (SHA256_DIGEST_LENGTH * 2 + 1)) {
108                 ERR("Invalid parameter\n");
109                 return MOBILE_AP_ERROR_INVALID_PARAM;
110         }
111
112         int i = 0;
113         int d_16 = 0;
114         int r_16 = 0;
115         unsigned char buf[SHA256_DIGEST_LENGTH] = {0, };
116
117         if (!PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
118                                 salt, strlen((const char *)salt),
119                                 PSK_ITERATION_COUNT, sizeof(buf), buf)) {
120                 ERR("Getting psk is failed\n");
121                 return MOBILE_AP_ERROR_RESOURCE;
122         }
123
124         for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
125                 d_16 = buf[i] >> 4;
126                 r_16 = buf[i] & 0xf;
127
128                 psk[i << 1] = d_16 < 10 ? d_16 + '0' : d_16 - 10 + 'a';
129                 psk[(i << 1) + 1] = r_16 < 10 ? r_16 + '0' : r_16 - 10 + 'a';
130         }
131         psk[i << 1] = '\0';
132
133         return MOBILE_AP_ERROR_NONE;
134 }
135
136 static int __execute_hostapd(const mobile_ap_type_e type, const char *ssid,
137                 const char *security, const char *passphrase, int hide_mode)
138 {
139         DBG("+\n");
140
141         char *conf = NULL;
142         char *old_conf;
143         char buf[HOSTAPD_CONF_LEN] = "";
144         FILE *fp = NULL;
145         pid_t pid;
146         int ret;
147         char key[MOBILE_AP_WIFI_KEY_MAX_LEN + 1];
148         /* Default conf. */
149         snprintf(buf, sizeof(buf), HOSTAPD_CONF,
150                         WIFI_IF,
151                         HOSTAPD_CTRL_INTF_DIR,
152                         ssid,
153                         MOBILE_AP_WIFI_CHANNEL,
154                         hide_mode ? 2 : 0,
155                         MOBILE_AP_MAX_WIFI_STA);
156         conf = g_strdup(buf);
157
158         /* Vendor elements conf. */
159         if (type == MOBILE_AP_TYPE_WIFI) {
160                 snprintf(buf, sizeof(buf),
161                                 "vendor_elements=%s\n", HOSTAPD_VENDOR_ELEMENTS_TETH);
162         } else if (type == MOBILE_AP_TYPE_WIFI_AP) {
163                 snprintf(buf, sizeof(buf),
164                                 "vendor_elements=%s\n", HOSTAPD_VENDOR_ELEMENTS_WIFI_AP);
165         } else {
166                 ERR("Unknown type: %d\n", type);
167                 g_free(conf);
168                 return MOBILE_AP_ERROR_INVALID_PARAM;
169         }
170         old_conf = conf;
171         conf = g_strconcat(old_conf, buf, NULL);
172         g_free(old_conf);
173
174         /* Security conf. */
175         if (security != NULL && !strcmp(security, "wpa2-psk")) {
176                 ret = __get_psk_hexascii(passphrase, (const unsigned char *)ssid, key, sizeof(key));
177                 if (ret != MOBILE_AP_ERROR_NONE) {
178                         g_free(conf);
179                         ERR("hex conversion failed\n");
180                         return MOBILE_AP_ERROR_RESOURCE;
181                 }
182                 snprintf(buf, sizeof(buf),
183                                 "wpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", key);
184
185                 old_conf = conf;
186                 conf = g_strconcat(old_conf, buf, NULL);
187                 g_free(old_conf);
188         }
189
190         fp = fopen(HOSTAPD_CONF_FILE, "w");
191         if (NULL == fp) {
192                 ERR("Could not create the file.\n");
193                 g_free(conf);
194                 return MOBILE_AP_ERROR_RESOURCE;
195         }
196         fputs(conf, fp);
197         g_free(conf);
198         fclose(fp);
199
200         pid = fork();
201         if (pid < 0) {
202                 ERR("fork failed\n");
203                 return MOBILE_AP_ERROR_RESOURCE;
204         }
205
206         if (pid == 0) {
207                 if (execl(HOSTAPD_BIN, HOSTAPD_BIN, "-e", HOSTAPD_ENTROPY_FILE,
208                                         HOSTAPD_CONF_FILE,
209                                         "-f", HOSTAPD_DEBUG_FILE, "-ddd",
210                                         (char *)NULL)) {
211                         ERR("execl failed\n");
212                 }
213
214                 ERR("Should not get here!");
215                 return MOBILE_AP_ERROR_RESOURCE;
216         }
217
218         hostapd_pid = pid;
219
220         return MOBILE_AP_ERROR_NONE;
221 }
222
223 static int __terminate_hostapd()
224 {
225         DBG("+\n");
226
227         int ret;
228
229         if (hostapd_pid == 0) {
230                 ERR("There is no hostapd\n");
231                 return MOBILE_AP_ERROR_NONE;
232         }
233
234         kill(hostapd_pid, SIGTERM);
235         waitpid(hostapd_pid, NULL, 0);
236         hostapd_pid = 0;
237
238         ret = unlink(HOSTAPD_CONF_FILE);
239         if (ret < 0) {
240                 ERR("unlink is failed : %s\n", strerror(errno));
241         }
242
243         return MOBILE_AP_ERROR_NONE;
244 }
245
246 /*
247  * number NUM_STA(void)
248  * addr STA-FIRST(void)
249  * addr STA-NEXT(addr)
250  * void DISASSOCIATE(addr)
251  * void READ_WHITELIST(filename)
252  * void SET_MAXCLIENT(number)
253  */
254 static int __send_hostapd_req(int fd, const char *req, const int req_len,
255                 char *buf, int *buf_len)
256 {
257         if (fd < 0 || req == NULL || req_len <= 0 ||
258                         buf == NULL || buf_len == NULL || *buf_len <= 0) {
259                 ERR("Invalid param\n");
260                 return MOBILE_AP_ERROR_INVALID_PARAM;
261         }
262
263         struct timeval tv = {10, 0};
264         fd_set fds;
265         int ret = 0;
266
267         ret = send(fd, req, req_len, 0);
268         if (ret < 0) {
269                 ERR("send is failed : %s\n", strerror(errno));
270                 return MOBILE_AP_ERROR_INTERNAL;
271         }
272
273         while (TRUE) {
274                 FD_ZERO(&fds);
275                 FD_SET(fd, &fds);
276                 ret = select(fd + 1, &fds, NULL, NULL, &tv);
277                 if (ret < 0) {
278                         return MOBILE_AP_ERROR_INTERNAL;
279                 } else if (ret == 0) {
280                         ERR("There is no response from hostapd\n");
281                         return MOBILE_AP_ERROR_INTERNAL;
282                 } else if (!FD_ISSET(fd, &fds)) {
283                         ERR("Unknown case\n");
284                         return MOBILE_AP_ERROR_INTERNAL;
285                 }
286
287                 ret = recv(fd, buf, (*buf_len) - 1, 0);
288                 if (ret < 0) {
289                         ERR("recv is failed\n");
290                         return MOBILE_AP_ERROR_INTERNAL;
291                 }
292
293                 if (buf[0] == '<') {
294                         ERR("Unsolicited message\n");
295                         continue;
296                 }
297
298                 *buf_len = ret;
299                 buf[ret] = '\0';
300                 if (ret == 0) {
301                         ERR("socket is closed\n");
302                 }
303
304                 break;
305         }
306
307         return MOBILE_AP_ERROR_NONE;
308 }
309
310 static int __open_hostapd_intf(int *fd, const char *intf)
311 {
312         if (fd == NULL || intf == NULL) {
313                 ERR("fd is NULL\n");
314                 return MOBILE_AP_ERROR_INVALID_PARAM;
315         }
316
317         DBG("+\n");
318
319         int retry = 0;
320         char ctrl_intf[255] = {0, };
321         struct sockaddr_un src;
322         struct sockaddr_un dest;
323         struct stat stat_buf;
324
325         *fd = socket(PF_UNIX, SOCK_DGRAM, 0);
326         if (*fd < 0) {
327                 ERR("socket is failed\n");
328                 return MOBILE_AP_ERROR_INTERNAL;
329         }
330
331         src.sun_family = AF_UNIX;
332         g_strlcpy(src.sun_path, intf, sizeof(src.sun_path));
333
334         if (stat(src.sun_path, &stat_buf) == 0) {
335                 unlink(src.sun_path);
336         }
337
338         if (bind(*fd, (struct sockaddr *)&src, sizeof(src)) < 0) {
339                 ERR("bind is failed\n");
340                 close(*fd);
341                 *fd = -1;
342                 unlink(src.sun_path);
343                 return MOBILE_AP_ERROR_INTERNAL;
344         }
345
346         snprintf(ctrl_intf, sizeof(ctrl_intf), "%s/%s",
347                         HOSTAPD_CTRL_INTF_DIR, WIFI_IF);
348         dest.sun_family = AF_UNIX;
349         g_strlcpy(dest.sun_path, ctrl_intf, sizeof(dest.sun_path));
350
351         while (connect(*fd, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
352                 if (++retry >= HOSTAPD_RETRY_MAX)
353                         goto FAIL;
354                 usleep(HOSTAPD_RETRY_DELAY);
355         }
356
357         return MOBILE_AP_ERROR_NONE;
358
359 FAIL:
360         ERR("Cannot make connection to hostapd\n");
361         close(*fd);
362         *fd = -1;
363         unlink(src.sun_path);
364
365         return MOBILE_AP_ERROR_INTERNAL;
366 }
367
368 static int __close_hostapd_intf(int *fd)
369 {
370         DBG("+\n");
371
372         if (fd == NULL) {
373                 ERR("fd is NULL\n");
374                 return MOBILE_AP_ERROR_INVALID_PARAM;
375         }
376
377         if (*fd > 0)
378                 close(*fd);
379         *fd = -1;
380
381         return MOBILE_AP_ERROR_NONE;
382 }
383
384 static gboolean __hostapd_monitor_cb(GIOChannel *source)
385 {
386         DBG("+\n");
387
388         GSList *l;
389         char buf[HOSTAPD_REQ_MAX_LEN + 1] = {0, };
390         char *pbuf = NULL;
391         gsize read = 0;
392         int n_station = 0;
393         int type;
394         sta_timer_t *ptr = NULL;
395         char *mac = NULL;
396         char *end = NULL;
397         gboolean discon_event = FALSE;
398
399
400 #if !GLIB_CHECK_VERSION(2, 31, 0)
401         int ret = 0;
402
403         ret = g_io_channel_read(hostapd_io_channel, buf,
404                         HOSTAPD_REQ_MAX_LEN, &read);
405         if (ret != G_IO_ERROR_NONE) {
406                 ERR("g_io_channel_read is failed\n");
407                 return FALSE;
408         }
409 #else
410         GError *err = NULL;
411         GIOStatus ios;
412
413         ios = g_io_channel_read_chars(hostapd_io_channel, buf,
414                         HOSTAPD_REQ_MAX_LEN, &read, &err);
415         if (err != NULL) {
416                 ERR("g_io_channel_read_chars is failed : %s\n", err->message);
417                 g_error_free(err);
418                 return FALSE;
419         } else if (ios != G_IO_STATUS_NORMAL) {
420                 ERR("g_io_channel_read_chars is failed : %d\n", ios);
421                 return FALSE;
422         }
423 #endif
424
425         buf[read] = '\0';
426         pbuf = strrchr(buf, '\n');
427         if (pbuf != NULL)
428                 *pbuf = '\0';
429
430         SDBG("Read string from hostapd = [%s]\n", buf);
431         pbuf = buf;
432         /* concatenated string, containing multiple events can arrive */
433         while (pbuf && *pbuf) {
434                 pbuf = __find_first_caps_char(pbuf);
435                 if (!pbuf || !*pbuf) {
436                         break;
437                 }
438
439                 if (!strncmp(pbuf, HOSTAPD_STA_CONN, HOSTAPD_STA_CONN_LEN)) {
440                         pbuf = pbuf + HOSTAPD_STA_CONN_LEN;
441                         if (!pbuf || !*pbuf) {
442                                 ERR("No mac address\n");
443                                 return TRUE;
444                         }
445
446                         end = strchr(pbuf, '<');
447                         if (end && *end) {
448                                 mac = g_strndup(pbuf, (long)(end - pbuf));
449                                 pbuf = end + 1;
450                         } else {
451                                 mac = g_strdup(pbuf);
452                                 pbuf += strlen(mac);
453                         }
454
455                         if (mac == NULL) {
456                                 ERR("strdup failed\n");
457                                 return TRUE;
458                         }
459
460                         for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
461                                 ptr = (sta_timer_t *)l->data;
462                                 if (ptr == NULL) {
463                                         continue;
464                                 }
465
466                                 if (g_strcmp0(ptr->mac_addr, mac) == 0) {
467                                         g_free(mac);
468                                         mac = NULL;
469                                         break;
470                                 }
471                         }
472
473                         /* Matched station found, so skip */
474                         if (l != NULL) {
475                                 continue;
476                         }
477
478                         SDBG("%s%s\n", HOSTAPD_STA_CONN, mac);
479                         ptr = (sta_timer_t *)g_malloc(sizeof(sta_timer_t));
480                         ptr->mac_addr = mac;
481                         ptr->tid = g_timeout_add(HOSTAPD_DHCP_MAX_INTERVAL,
482                                         __hostapd_connect_timer_cb, mac);
483                         sta_timer_list = g_slist_append(sta_timer_list, ptr);
484
485                 } else if (!strncmp(pbuf, HOSTAPD_STA_DISCONN, HOSTAPD_STA_DISCONN_LEN)) {
486                         pbuf = pbuf + HOSTAPD_STA_DISCONN_LEN;
487                         if (!pbuf || !*pbuf) {
488                                 break;
489                         }
490
491                         end = strchr(pbuf, '<');
492                         if (end && *end) {
493                                 mac = g_strndup(pbuf, (long)(end - pbuf));
494                                 pbuf = end + 1;
495                         } else {
496                                 mac = g_strdup(pbuf);
497                                 pbuf += strlen(mac);
498                         }
499
500                         if (mac == NULL) {
501                                 ERR("strdup failed\n");
502                                 return TRUE;
503                         }
504
505                         SDBG("%s%s\n", HOSTAPD_STA_DISCONN, mac);
506                         _remove_station_info(mac, _slist_find_station_by_mac);
507
508                         /*
509                          * Destroy the timer if its not expired before disconnection
510                          */
511                         _destroy_dhcp_ack_timer(mac);
512                         g_free(mac);
513                         mac = NULL;
514                         discon_event = TRUE;
515
516                 } else {
517                         pbuf = strchr(pbuf, '>');
518                         if (pbuf == NULL)
519                                 break;
520                         pbuf++;
521                 }
522         }
523
524         if (discon_event == FALSE)
525                 goto DONE;
526
527         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
528                 type = MOBILE_AP_TYPE_WIFI;
529         } else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
530                 type = MOBILE_AP_TYPE_WIFI_AP;
531         } else {
532                 goto DONE;
533         }
534
535         _get_station_count((gconstpointer)type,
536                         _slist_find_station_by_interface, &n_station);
537
538         if (n_station == 0) {
539                 if (type == MOBILE_AP_TYPE_WIFI)
540                         _start_timeout_cb(type, time(NULL) + TETHERING_CONN_TIMEOUT);
541                 else if (type == MOBILE_AP_TYPE_WIFI_AP)
542                         _start_timeout_cb(type, time(NULL) + WIFI_AP_CONN_TIMEOUT);
543         }
544 DONE:
545         return TRUE;
546 }
547
548 static int __open_hostapd_monitor(int *fd)
549 {
550         if (fd == NULL) {
551                 ERR("fd is NULL\n");
552                 return MOBILE_AP_ERROR_INVALID_PARAM;
553         }
554
555         DBG("+\n");
556
557         char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
558         int buf_len = 0;
559
560         if (__open_hostapd_intf(fd, MH_MONITOR_INTF) != MOBILE_AP_ERROR_NONE) {
561                 ERR("__open_hostapd_intf() is failed\n");
562                 return MOBILE_AP_ERROR_INTERNAL;
563         }
564
565         hostapd_io_channel = g_io_channel_unix_new(*fd);
566         if (hostapd_io_channel == NULL) {
567                 ERR("g_io_channel_unix_new is failed\n");
568                 return MOBILE_AP_ERROR_INTERNAL;
569         }
570
571         g_io_channel_set_encoding(hostapd_io_channel, NULL, NULL);
572         g_io_channel_set_flags(hostapd_io_channel,
573                         G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK, NULL);
574
575         hostapd_io_source = g_io_add_watch(hostapd_io_channel, G_IO_IN,
576                         (GIOFunc)__hostapd_monitor_cb, NULL);
577
578         buf_len = sizeof(buf);
579         __send_hostapd_req(*fd, HOSTAPD_MONITOR_ATTACH,
580                         strlen(HOSTAPD_MONITOR_ATTACH), buf, &buf_len);
581
582         return MOBILE_AP_ERROR_NONE;
583 }
584
585 static int __close_hostapd_monitor(int *fd)
586 {
587         GError *err = NULL;
588         char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
589         int buf_len = 0;
590
591         buf_len = sizeof(buf);
592         __send_hostapd_req(*fd, HOSTAPD_MONITOR_DETACH,
593                         strlen(HOSTAPD_MONITOR_DETACH), buf, &buf_len);
594
595         if (hostapd_io_source != 0) {
596                 g_source_remove(hostapd_io_source);
597                 hostapd_io_source = 0;
598         }
599
600         if (hostapd_io_channel != NULL) {
601                 g_io_channel_shutdown(hostapd_io_channel, TRUE, &err);
602                 g_io_channel_unref(hostapd_io_channel);
603                 hostapd_io_channel = NULL;
604         }
605
606         __close_hostapd_intf(fd);
607
608         return MOBILE_AP_ERROR_NONE;
609 }
610
611 static mobile_ap_drv_interface_e __get_drv_interface(void)
612 {
613         static mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
614
615         if (drv_interface != MOBILE_AP_DRV_INTERFACE_NONE) {
616                 return drv_interface;
617         }
618
619         const char *drv_rfkill_path = "/sys/devices/platform";
620         const char *wext_drv[] = {
621                 "bcm4329-b1", "bcm4330-b0",
622                 "bcm4330-b1", "bcm4330-b2",
623                 NULL};
624
625         char path[MAX_BUF_SIZE] = { 0 };
626         struct stat stat_buf = { 0 };
627         int fd = 0;
628         int i = 0;
629
630         drv_interface = MOBILE_AP_NL80211;
631
632         for (i = 0; wext_drv[i] != NULL; i++) {
633                 snprintf(path, sizeof(path), "%s/%s",
634                                 drv_rfkill_path, wext_drv[i]);
635                 fd = open(path, O_RDONLY);
636                 if (fd < 0)
637                         continue;
638
639                 if (fstat(fd, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode)) {
640                         drv_interface = MOBILE_AP_WEXT;
641                         close(fd);
642                         break;
643                 }
644
645                 close(fd);
646         }
647
648         return drv_interface;
649 }
650
651 static int __mh_core_softap_firmware_start(void)
652 {
653         int err = 0;
654         DBusError error;
655         DBusMessageIter iter;
656         DBusMessage *reply = NULL;
657         DBusMessage *message = NULL;
658         DBusConnection *connection = NULL;
659         const char *device = "softap";
660
661         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
662         if (connection == NULL) {
663                 ERR("Failed to get system bus");
664                 return -EIO;
665         }
666
667         message = dbus_message_new_method_call(NETCONFIG_SERVICE,
668                         NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE ".Firmware", "Start");
669         if (message == NULL) {
670                 ERR("Failed DBus method call");
671                 dbus_connection_unref(connection);
672                 return -EIO;
673         }
674
675         dbus_message_iter_init_append(message, &iter);
676         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
677
678         dbus_error_init(&error);
679
680         reply = dbus_connection_send_with_reply_and_block(connection, message,
681                         NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
682         if (dbus_error_is_set(&error) == TRUE) {
683                 if (NULL != strstr(error.message, ".AlreadyExists")) {
684                         // softap already enabled
685                 } else {
686                         ERR("dbus_connection_send_with_reply_and_block() failed. "
687                                         "DBus error [%s: %s]", error.name, error.message);
688
689                         err = -EIO;
690
691                         dbus_error_free(&error);
692                 }
693
694                 dbus_error_free(&error);
695         }
696
697         if (reply != NULL)
698                 dbus_message_unref(reply);
699
700         dbus_message_unref(message);
701         dbus_connection_unref(connection);
702
703         return err;
704 }
705
706 static int __mh_core_softap_firmware_stop(void)
707 {
708         int err = 0;
709         DBusError error;
710         DBusMessageIter iter;
711         DBusMessage *reply = NULL;
712         DBusMessage *message = NULL;
713         DBusConnection *connection = NULL;
714         const char *device = "softap";
715
716         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
717         if (connection == NULL) {
718                 ERR("Failed to get system bus");
719                 return -EIO;
720         }
721
722         message = dbus_message_new_method_call(NETCONFIG_SERVICE,
723                         NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE ".Firmware", "Stop");
724         if (message == NULL) {
725                 ERR("Failed DBus method call");
726                 dbus_connection_unref(connection);
727                 return -EIO;
728         }
729
730         dbus_message_iter_init_append(message, &iter);
731         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
732
733         dbus_error_init(&error);
734
735         reply = dbus_connection_send_with_reply_and_block(connection, message,
736                         NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
737         if (dbus_error_is_set(&error) == TRUE) {
738                 if (NULL != strstr(error.message, ".AlreadyExists")) {
739                         // softap already disabled
740                 } else {
741                         ERR("dbus_connection_send_with_reply_and_block() failed. "
742                                         "DBus error [%s: %s]", error.name, error.message);
743
744                         err = -EIO;
745
746                         dbus_error_free(&error);
747                 }
748
749                 dbus_error_free(&error);
750         }
751
752         if (reply != NULL)
753                 dbus_message_unref(reply);
754
755         dbus_message_unref(message);
756         dbus_connection_unref(connection);
757
758         return err;
759 }
760
761 int _mh_core_enable_softap(const mobile_ap_type_e type, const char *ssid,
762                 const char *security, const char *key, int hide_mode)
763 {
764         if (ssid == NULL || security == NULL || key == NULL) {
765                 ERR("Invalid param\n");
766                 return MOBILE_AP_ERROR_INTERNAL;
767         }
768
769         char cmd[MAX_BUF_SIZE];
770         int ret_status = MOBILE_AP_ERROR_NONE;
771         mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
772
773         int sock_fd;
774         char *if_name = WIFI_IF;
775         char buf[MAX_BUF_SIZE] = { 0 };
776
777         char wext_ssid[MOBILE_AP_WIFI_SSID_MAX_LEN] = { 0 };
778         char *ptr = NULL;
779
780         if (__mh_core_softap_firmware_start() < 0)
781                 return MOBILE_AP_ERROR_INTERNAL;
782
783         drv_interface = __get_drv_interface();
784
785         switch (drv_interface) {
786         case MOBILE_AP_WEXT:
787                 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
788                         ERR("Failed to open socket...!!!\n");
789                         ret_status = MOBILE_AP_ERROR_RESOURCE;
790                         break;
791                 }
792
793                 /*
794                  * In case of Wireless extension interface,
795                  * 32 byte SSID including null character can be accepted.
796                  */
797                 g_strlcpy(wext_ssid, ssid, sizeof(wext_ssid));
798                 if (!g_utf8_validate(wext_ssid, -1, (const char **)&ptr))
799                         *ptr = '\0';
800
801                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_CFG,"
802                                         "SSID_LEN=%d,SSID=%s,"
803                                         "SEC=%s,KEY_LEN=%d,KEY=%s,CHANNEL=%d,"
804                                         "PREAMBLE=0,MAX_SCB=%d,HIDE=%d,END",
805                                         strlen(wext_ssid), wext_ssid,
806                                         security, strlen(key), key,
807                                         MOBILE_AP_WIFI_CHANNEL,
808                                         MOBILE_AP_MAX_WIFI_STA, hide_mode);
809                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
810                 if (ret_status != MOBILE_AP_ERROR_NONE) {
811                         ERR("__issue_ioctl failed...!!!\n");
812                         close(sock_fd);
813                         break;
814                 }
815
816                 /* Start broadcasting of BSS. */
817                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_START");
818                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
819                 if (ret_status != MOBILE_AP_ERROR_NONE) {
820                         ERR("__issue_ioctl failed...!!!\n");
821                         close(sock_fd);
822                         break;
823                 }
824
825                 close(sock_fd);
826
827                 ret_status = _mh_core_set_ip_address(SOFTAP_IF,
828                                 IP_ADDRESS_SOFTAP);
829                 if (ret_status != MOBILE_AP_ERROR_NONE) {
830                         ERR("_mh_core_set_ip_address of SOFTAP_IF is failed\n");
831                         break;
832                 }
833
834                 ret_status = _mh_core_set_ip_address(WIFI_IF,
835                                 IP_ADDRESS_WIFI);
836                 if (ret_status != MOBILE_AP_ERROR_NONE) {
837                         ERR("_mh_core_set_ip_address of WIFI_IF is failed\n");
838                         break;
839                 }
840                 break;
841
842         case MOBILE_AP_NL80211:
843
844                 ret_status = _mh_core_set_ip_address(WIFI_IF,
845                                 IP_ADDRESS_SOFTAP);
846                 if (ret_status != MOBILE_AP_ERROR_NONE) {
847                         ERR("_mh_core_set_ip_address is failed\n");
848                         break;
849                 }
850
851                 ret_status = __execute_hostapd(type, ssid, security, key, hide_mode);
852                 if (ret_status != MOBILE_AP_ERROR_NONE) {
853                         ERR("__execute_hostapd is failed\n");
854                         break;
855                 }
856
857                 ret_status = __open_hostapd_intf(&hostapd_ctrl_fd, MH_CTRL_INTF);
858                 if (ret_status != MOBILE_AP_ERROR_NONE) {
859                         ERR("__open_hostapd_intf is failed\n");
860                         __terminate_hostapd();
861                         break;
862                 }
863
864                 ret_status = __open_hostapd_monitor(&hostapd_monitor_fd);
865                 if (ret_status != MOBILE_AP_ERROR_NONE) {
866                         ERR("__open_hostapd_monitor is failed\n");
867                         __close_hostapd_intf(&hostapd_ctrl_fd);
868                         __terminate_hostapd();
869                         break;
870                 }
871
872                 break;
873
874         default:
875                 ERR("Unknown driver interface : %d\n", drv_interface);
876                 break;
877         }
878
879         if (ret_status != MOBILE_AP_ERROR_NONE)
880                 __mh_core_softap_firmware_stop();
881
882         return ret_status;
883 }
884
885 int _mh_core_disable_softap(void)
886 {
887         char cmd[MAX_BUF_SIZE] = { 0 };
888         int ret_status = MOBILE_AP_ERROR_NONE;
889         mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
890
891         int sock_fd = 0;
892         char buf[MAX_BUF_SIZE] = { 0 };
893         char *if_name = WIFI_IF;
894
895         drv_interface = __get_drv_interface();
896
897         switch (drv_interface) {
898         case MOBILE_AP_WEXT:
899                 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
900                         ERR("Failed to open socket...!!!\n");
901                         ret_status = MOBILE_AP_ERROR_RESOURCE;
902                         break;
903                 }
904
905                 /* Stop broadcasting of BSS. */
906                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_STOP");
907                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
908                 if (ret_status != MOBILE_AP_ERROR_NONE) {
909                         ERR("__issue_ioctl failed...!!!\n");
910                         close(sock_fd);
911                         break;
912                 }
913
914                 close(sock_fd);
915                 break;
916
917         case MOBILE_AP_NL80211:
918                 ret_status = __close_hostapd_intf(&hostapd_ctrl_fd);
919                 if (ret_status != MOBILE_AP_ERROR_NONE)
920                         ERR("hostapd termination is failed\n");
921
922                 ret_status = __close_hostapd_monitor(&hostapd_monitor_fd);
923                 if (ret_status != MOBILE_AP_ERROR_NONE)
924                         ERR("hostapd termination is failed\n");
925
926                 ret_status = __terminate_hostapd();
927                 if (ret_status != MOBILE_AP_ERROR_NONE) {
928                         ERR("hostapd termination is failed\n");
929                 }
930                 break;
931
932         default:
933                 ERR("Unknown driver interface : %d\n", drv_interface);
934                 break;
935         }
936
937         if (__mh_core_softap_firmware_stop() < 0)
938                 ret_status = MOBILE_AP_ERROR_INTERNAL;
939
940         return ret_status;
941 }
942
943 static int __get_device_info_by_wext(softap_device_info_t *di)
944 {
945         int sock_fd = 0;
946         char *if_name = SOFTAP_IF;
947         char cmd[MAX_BUF_SIZE];
948         char buf[MAX_BUF_SIZE] = { 0 };
949         int ret = MOBILE_AP_ERROR_NONE;
950
951         char *buf_ptr = NULL;
952         int i;
953
954         if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
955                 ERR("Failed to open socket...!!!\n");
956                 di->number = 0;
957                 return MOBILE_AP_ERROR_RESOURCE;
958         }
959
960         snprintf(cmd, MAX_BUF_SIZE, "AP_GET_STA_LIST");
961         ret = __issue_ioctl(sock_fd, if_name, cmd, buf);
962         if (ret != MOBILE_AP_ERROR_NONE) {
963                 ERR("__issue_ioctl failed...!!!\n");
964                 di->number = 0;
965                 close(sock_fd);
966                 return ret;
967         }
968
969         buf_ptr = buf;
970
971         sscanf(buf_ptr, "%02x", &di->number);
972
973         buf_ptr += 2;
974         for (i = 0; i < di->number; i++) {
975                 unsigned int l_bssid[MOBILE_AP_WIFI_BSSID_LEN];
976                 sscanf(buf_ptr, "%02X%02X%02X%02X%02X%02X", &l_bssid[0],
977                                         &l_bssid[1], &l_bssid[2], &l_bssid[3],
978                                         &l_bssid[4], &l_bssid[5]);
979                 snprintf(di->bssid[i], MOBILE_AP_STR_INFO_LEN,
980                                         "%02X:%02X:%02X:%02X:%02X:%02X",
981                                         l_bssid[0], l_bssid[1], l_bssid[2],
982                                         l_bssid[3], l_bssid[4], l_bssid[5]);
983
984                 SDBG("STA[%d] address[%s]\n", i, di->bssid[i]);
985
986                 buf_ptr += 12;
987         }
988
989         close(sock_fd);
990
991         return ret;
992 }
993
994 static int __get_device_info_by_nl80211(softap_device_info_t *di)
995 {
996         int ret = 0;
997         int no_of_sta = 0;
998         int buf_len = 0;
999         char req[HOSTAPD_REQ_MAX_LEN] = {0, };
1000         char buf[MOBILE_AP_STR_INFO_LEN] = {0, };
1001
1002         buf_len = sizeof(buf);
1003         g_strlcpy(req, "NUM_STA", sizeof(req));
1004         ret = __send_hostapd_req(hostapd_ctrl_fd,
1005                         req, strlen(req), buf, &buf_len);
1006         if (ret != MOBILE_AP_ERROR_NONE) {
1007                 ERR("__send_hostapd_req is failed : %d\n", ret);
1008                 return ret;
1009         }
1010
1011         DBG("The number of station : %s\n", buf);
1012         if (atoi(buf) == 0) {
1013                 DBG("There is no station\n");
1014                 return MOBILE_AP_ERROR_NONE;
1015         }
1016
1017         buf_len = sizeof(buf);
1018         g_strlcpy(req, "STA-FIRST", sizeof(req));
1019         ret = __send_hostapd_req(hostapd_ctrl_fd,
1020                         req, strlen(req), buf, &buf_len);
1021         if (ret != MOBILE_AP_ERROR_NONE) {
1022                 ERR("__send_hostapd_req is failed : %d\n", ret);
1023                 return ret;
1024         }
1025
1026         do {
1027                 if (!strncmp(buf, "FAIL", 4)) {
1028                         ERR("FAIL is returned\n");
1029                         break;
1030                 }
1031
1032                 if (buf[0] == '\0') {
1033                         ERR("NULL string\n");
1034                         break;
1035                 }
1036
1037                 SDBG("Station : %s\n", buf);
1038                 g_strlcpy(di->bssid[no_of_sta++], buf, MOBILE_AP_STR_INFO_LEN);
1039
1040                 buf_len = sizeof(buf);
1041                 snprintf(req, sizeof(req), "STA-NEXT %s", buf);
1042                 ret = __send_hostapd_req(hostapd_ctrl_fd,
1043                                 req, strlen(req), buf, &buf_len);
1044         } while (ret == MOBILE_AP_ERROR_NONE);
1045
1046         di->number = no_of_sta;
1047
1048         return ret;
1049 }
1050
1051 int _mh_core_get_device_info(softap_device_info_t *di)
1052 {
1053         if (di == NULL) {
1054                 ERR("Invalid param\n");
1055                 return MOBILE_AP_ERROR_INVALID_PARAM;
1056         }
1057
1058         int ret = MOBILE_AP_ERROR_NONE;
1059
1060         switch (__get_drv_interface()) {
1061         case MOBILE_AP_WEXT:
1062                 ret = __get_device_info_by_wext(di);
1063                 break;
1064
1065         case MOBILE_AP_NL80211:
1066                 ret = __get_device_info_by_nl80211(di);
1067                 break;
1068
1069         default:
1070                 ERR("Unknown interface\n");
1071                 break;
1072         }
1073
1074         return ret;
1075 }
1076
1077 int _mh_core_execute_dhcp_server(void)
1078 {
1079         char buf[DNSMASQ_CONF_LEN] = "";
1080         FILE *fp = NULL;
1081         pid_t pid;
1082
1083         fp = fopen(DNSMASQ_CONF_FILE, "w");
1084         if (NULL == fp) {
1085                 ERR("Could not create the file.\n");
1086                 return MOBILE_AP_ERROR_RESOURCE;
1087         }
1088         snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF);
1089         fputs(buf, fp);
1090         fclose(fp);
1091
1092         pid = fork();
1093         if (pid < 0) {
1094                 ERR("fork failed\n");
1095                 return MOBILE_AP_ERROR_RESOURCE;
1096         }
1097
1098         if (pid == 0) {
1099                 /* -d : Debug mode
1100                  * -p 0 : DNS off
1101                  * -C file : Configuration file path
1102                  */
1103                 if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
1104                                         "-p", "0", "-C", DNSMASQ_CONF_FILE,
1105                                         (char *)NULL)) {
1106                         ERR("execl failed\n");
1107                 }
1108
1109                 ERR("Should not get here!");
1110                 return MOBILE_AP_ERROR_RESOURCE;
1111         }
1112
1113         dnsmasq_pid = pid;
1114
1115         return MOBILE_AP_ERROR_NONE;
1116 }
1117
1118 int _mh_core_terminate_dhcp_server(void)
1119 {
1120         int ret;
1121
1122         if (dnsmasq_pid == 0) {
1123                 ERR("There is no dnsmasq\n");
1124                 return MOBILE_AP_ERROR_NONE;
1125         }
1126
1127         kill(dnsmasq_pid, SIGTERM);
1128         waitpid(dnsmasq_pid, NULL, 0);
1129         dnsmasq_pid = 0;
1130
1131         ret = unlink(DNSMASQ_CONF_FILE);
1132         if (ret < 0) {
1133                 ERR("unlink is failed : %s\n", strerror(errno));
1134         }
1135
1136         return MOBILE_AP_ERROR_NONE;
1137 }
1138
1139 int _mh_core_enable_masquerade(const char *ext_if)
1140 {
1141         if (ext_if == NULL || strlen(ext_if) == 0) {
1142                 ERR("ext_if[%s] is invalid\n", ext_if);
1143                 return MOBILE_AP_ERROR_INVALID_PARAM;
1144         }
1145
1146         int fd = -1;
1147
1148         fd = open(IP_FORWARD, O_WRONLY);
1149         if (fd < 0) {
1150                 ERR("open failed\n");
1151                 return MOBILE_AP_ERROR_RESOURCE;
1152         }
1153
1154         if (write(fd, "1", 1) != 1) {
1155                 ERR("write failed\n");
1156                 close(fd);
1157                 return MOBILE_AP_ERROR_INTERNAL;
1158         }
1159         close(fd);
1160
1161         _iptables_create_chain(TABLE_NAT, TETH_NAT_POST);
1162         _iptables_add_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_POST,
1163                         TETH_NAT_POST);
1164         _iptables_add_rule(MASQ_RULE, TABLE_NAT, TETH_NAT_POST, ext_if);
1165
1166         _iptables_create_chain(TABLE_FILTER, TETH_FILTER_FW);
1167
1168         _iptables_add_rule(PKT_REDIRECTION_RULE, TABLE_FILTER, CHAIN_FW,
1169                         TETH_FILTER_FW);
1170
1171         _iptables_add_rule(CLAMP_MSS_RULE, TABLE_FILTER, TETH_FILTER_FW);
1172
1173         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1174                 BT_IF_ALL, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
1175         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1176                 WIFI_IF, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
1177         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1178                 USB_IF, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
1179
1180         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1181                 ext_if, BT_IF_ALL, ACTION_DROP, STATE_INVALID);
1182         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1183                 ext_if, WIFI_IF, ACTION_DROP, STATE_INVALID);
1184         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1185                 ext_if, USB_IF, ACTION_DROP, STATE_INVALID);
1186
1187         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1188                 ext_if, BT_IF_ALL, ACTION_RETURN);
1189         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1190                 ext_if, WIFI_IF, ACTION_RETURN);
1191         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1192                 ext_if, USB_IF, ACTION_RETURN);
1193
1194         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1195                 BT_IF_ALL, ext_if, ACTION_RETURN);
1196         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1197                 WIFI_IF, ext_if, ACTION_RETURN);
1198         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1199                 USB_IF, ext_if, ACTION_RETURN);
1200
1201         _iptables_add_rule(DEFAULT_RULE, TABLE_FILTER, TETH_FILTER_FW,
1202                 ACTION_DROP);
1203
1204         return MOBILE_AP_ERROR_NONE;
1205 }
1206
1207 int _mh_core_disable_masquerade(const char *ext_if)
1208 {
1209         if (ext_if == NULL || strlen(ext_if) == 0) {
1210                 ERR("ext_if[%s] is invalid\n", ext_if);
1211                 return MOBILE_AP_ERROR_INVALID_PARAM;
1212         }
1213
1214         int fd = -1;
1215
1216         fd = open(IP_FORWARD, O_WRONLY);
1217         if (fd < 0) {
1218                 ERR("open failed\n");
1219                 return MOBILE_AP_ERROR_RESOURCE;
1220         }
1221
1222         if (write(fd, "0", 1) != 1) {
1223                 ERR("write failed\n");
1224                 close(fd);
1225                 return MOBILE_AP_ERROR_INTERNAL;
1226         }
1227         close(fd);
1228
1229         _iptables_delete_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_POST,
1230                         TETH_NAT_POST);
1231         _iptables_flush_rules(TABLE_NAT, TETH_NAT_POST);
1232         _iptables_delete_chain(TABLE_NAT, TETH_NAT_POST);
1233
1234         _iptables_delete_rule(PKT_REDIRECTION_RULE, TABLE_FILTER, CHAIN_FW,
1235                         TETH_FILTER_FW);
1236         _iptables_flush_rules(TABLE_FILTER, TETH_FILTER_FW);
1237         _iptables_delete_chain(TABLE_FILTER, TETH_FILTER_FW);
1238
1239         return MOBILE_AP_ERROR_NONE;
1240 }
1241
1242 void _mh_core_add_data_to_array(GPtrArray *array, guint type, gchar *dev_name)
1243 {
1244         GValue value = {0, {{0}}};
1245
1246         g_value_init(&value, DBUS_STRUCT_UINT_STRING);
1247         g_value_take_boxed(&value,
1248                         dbus_g_type_specialized_construct(DBUS_STRUCT_UINT_STRING));
1249         dbus_g_type_struct_set(&value, 0, type, 1, dev_name, G_MAXUINT);
1250         g_ptr_array_add(array, g_value_get_boxed(&value));
1251 }
1252
1253 int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
1254 {
1255         struct ifreq ifr;
1256         struct sockaddr_in addr;
1257         int sock_fd;
1258
1259         SDBG("if_name : %s ip address : 0x%X\n", if_name, ip);
1260
1261         if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1262                 ERR("socket open failed!!!\n");
1263                 return MOBILE_AP_ERROR_RESOURCE;
1264         }
1265
1266         g_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
1267
1268         memset(&addr, 0, sizeof(struct sockaddr));
1269         addr.sin_family = AF_INET;
1270         addr.sin_port = 0;
1271         addr.sin_addr.s_addr = htonl(ip);
1272
1273         memcpy(&ifr.ifr_addr, &addr, sizeof(struct sockaddr));
1274         if (ioctl(sock_fd, SIOCSIFADDR, &ifr) < 0) {
1275                 ERR("ioctl failed...!!!\n");
1276                 close(sock_fd);
1277                 return MOBILE_AP_ERROR_INTERNAL;
1278         }
1279
1280         if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0) {
1281                 ERR("ioctl failed...!!!\n");
1282                 close(sock_fd);
1283                 return MOBILE_AP_ERROR_INTERNAL;
1284         }
1285
1286         ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
1287         if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
1288                 ERR("ioctl failed...!!!\n");
1289                 close(sock_fd);
1290                 return MOBILE_AP_ERROR_INTERNAL;
1291         }
1292
1293         close(sock_fd);
1294
1295         return MOBILE_AP_ERROR_NONE;
1296 }
1297
1298 static gboolean __send_station_event_cb(gpointer data)
1299 {
1300         int sig = GPOINTER_TO_INT(data);
1301         int n_station = 0;
1302         int type;
1303         mobile_ap_station_info_t *si = NULL;
1304
1305         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
1306                 type = MOBILE_AP_TYPE_WIFI;
1307         else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
1308                 type = MOBILE_AP_TYPE_WIFI_AP;
1309         else
1310                 return FALSE;
1311
1312         if (sig == SIGUSR1) {
1313                 DBG("STA connected(%d)\n", sig);
1314                 /* STA connection is handled in the dnsmasq signal handler */
1315         } else if (sig == SIGUSR2) {
1316                 DBG("STA disconnected(%d)\n", sig);
1317
1318                 /* Temporarily care only one station.
1319                  * Driver team should be support detail information */
1320                 if (_get_station_info((gconstpointer)type,
1321                                 _slist_find_station_by_interface,
1322                                 &si) != MOBILE_AP_ERROR_NONE) {
1323                         return FALSE;
1324                 }
1325                 _remove_station_info(si->mac, _slist_find_station_by_mac);
1326
1327                 _get_station_count((gconstpointer)type,
1328                                 _slist_find_station_by_interface, &n_station);
1329                 if (n_station == 0) {
1330                         if (type == MOBILE_AP_TYPE_WIFI)
1331                                 _start_timeout_cb(type, time(NULL) + TETHERING_CONN_TIMEOUT);
1332                         else if (type == MOBILE_AP_TYPE_WIFI_AP)
1333                                 _start_timeout_cb(type, time(NULL) + WIFI_AP_CONN_TIMEOUT);
1334                 }
1335         }
1336
1337         return FALSE;
1338 }
1339
1340 static void __handle_station_signal(int sig)
1341 {
1342         g_idle_add(__send_station_event_cb, GINT_TO_POINTER(sig));
1343         return;
1344 }
1345
1346 void _register_wifi_station_handler(void)
1347 {
1348         struct sigaction sa;
1349
1350         if (__get_drv_interface() != MOBILE_AP_WEXT)
1351                 return;
1352
1353         memset(&sa, 0, sizeof(sa));
1354         sa.sa_handler = __handle_station_signal;
1355         sigaction(SIGUSR1, &sa, NULL);
1356         sigaction(SIGUSR2, &sa, NULL);
1357
1358         return;
1359 }
1360
1361 void _unregister_wifi_station_handler(void)
1362 {
1363         struct sigaction sa;
1364
1365         if (__get_drv_interface() != MOBILE_AP_WEXT)
1366                 return;
1367
1368         memset(&sa, 0, sizeof(sa));
1369         sa.sa_handler = SIG_DFL;
1370         sigaction(SIGUSR1, &sa, NULL);
1371         sigaction(SIGUSR2, &sa, NULL);
1372
1373         return;
1374 }
1375
1376 static gboolean __hostapd_connect_timer_cb(gpointer user_data)
1377 {
1378         char *mac = (char *)user_data;
1379         GSList *l = NULL;
1380         GSList *temp = NULL;
1381         sta_timer_t *ptr = NULL;
1382         mobile_ap_station_info_t *info = NULL;
1383         time_t tm;
1384         int n_station = 0;
1385         int type;
1386         int ret;
1387
1388         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
1389                 type = MOBILE_AP_TYPE_WIFI;
1390         else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
1391                 type = MOBILE_AP_TYPE_WIFI_AP;
1392         else
1393                 return FALSE;
1394
1395         for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
1396                 ptr = (sta_timer_t *)l->data;
1397                 if (ptr == NULL)
1398                         continue;
1399
1400                 if (!g_strcmp0(ptr->mac_addr, mac)) {
1401                         DBG("client with Static IP, Add station\n");
1402
1403                         info = (mobile_ap_station_info_t *)g_malloc(sizeof(mobile_ap_station_info_t));
1404                         if (info == NULL) {
1405                                 ERR("g_malloc failed\n");
1406                                 g_free(ptr->mac_addr);
1407                                 g_free(ptr);
1408                                 temp = l;
1409                                 l = g_slist_next(l);
1410                                 sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
1411                                 break;
1412                         }
1413
1414                         time(&tm);
1415                         info->tm = tm;
1416                         info->interface = type;
1417                         g_strlcpy(info->ip, "", sizeof(info->ip));
1418                         g_strlcpy(info->mac, mac, sizeof(info->mac));
1419
1420                         ret = _get_wifi_name_from_lease_info(mac, &info->hostname);
1421                         if (ret != MOBILE_AP_ERROR_NONE)
1422                                 info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
1423
1424                         g_free(ptr->mac_addr);
1425                         g_free(ptr);
1426                         temp = l;
1427                         l = g_slist_next(l);
1428                         sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
1429
1430                         goto SUCCESS;
1431                 }
1432         }
1433
1434         return FALSE;
1435
1436 SUCCESS :
1437         if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
1438                 g_free(info->hostname);
1439                 g_free(info);
1440                 return FALSE;
1441         }
1442
1443         _get_station_count((gconstpointer)type,
1444                         _slist_find_station_by_interface, &n_station);
1445         if (n_station == 1)
1446                 _stop_timeout_cb(type);
1447
1448         _send_dbus_station_info("DhcpConnected", info);
1449
1450         return FALSE;
1451 }
1452
1453 void _flush_dhcp_ack_timer(void)
1454 {
1455         DBG("+\n");
1456
1457         GSList *l = NULL;
1458         GSList *temp = NULL;
1459         sta_timer_t *ptr = NULL;
1460
1461         for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
1462                 ptr = (sta_timer_t *)l->data;
1463                 if (ptr) {
1464                         if (ptr->tid != 0) {
1465                                 g_source_remove(ptr->tid);
1466                                 ptr->tid = 0;
1467                         }
1468                         g_free(ptr->mac_addr);
1469                         g_free(ptr);
1470                 }
1471
1472                 temp = l;
1473                 l = g_slist_next(l);
1474                 sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
1475         }
1476
1477         DBG("-\n");
1478         return;
1479 }
1480
1481 void _destroy_dhcp_ack_timer(char *mac_addr)
1482 {
1483         DBG("+\n");
1484         if (mac_addr == NULL) {
1485                 ERR("mac address passed NULL\n");
1486                 return;
1487         }
1488
1489         GSList *l = NULL;
1490         GSList *temp = NULL;
1491         sta_timer_t *ptr = NULL;
1492
1493         for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
1494
1495                 ptr = (sta_timer_t *)l->data;
1496                 if (ptr == NULL)
1497                         continue;
1498
1499                 if (!g_strcmp0(ptr->mac_addr, mac_addr)) {
1500
1501                         if (ptr->tid != 0) {
1502                                 g_source_remove(ptr->tid);
1503                                 ptr->tid = 0;
1504                         }
1505                         g_free(ptr->mac_addr);
1506                         g_free(ptr);
1507                         temp = l;
1508                         l = g_slist_next(l);
1509                         sta_timer_list = g_slist_delete_link(sta_timer_list,
1510                                                 temp);
1511                         break;
1512                 }
1513         }
1514
1515         DBG("-\n");
1516         return;
1517 }