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