tizen 2.3.1 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                         if (ptr == NULL) {
481                                 ERR("g_malloc failed\n");
482                                 g_free(mac);
483                                 mac = NULL;
484                                 return TRUE;
485                         }
486                         ptr->mac_addr = mac;
487                         ptr->tid = g_timeout_add(HOSTAPD_DHCP_MAX_INTERVAL,
488                                         __hostapd_connect_timer_cb, mac);
489                         sta_timer_list = g_slist_append(sta_timer_list, ptr);
490
491                 } else if (!strncmp(pbuf, HOSTAPD_STA_DISCONN, HOSTAPD_STA_DISCONN_LEN)) {
492                         pbuf = pbuf + HOSTAPD_STA_DISCONN_LEN;
493                         if (!pbuf || !*pbuf) {
494                                 break;
495                         }
496
497                         end = strchr(pbuf, '<');
498                         if (end && *end) {
499                                 mac = g_strndup(pbuf, (long)(end - pbuf));
500                                 pbuf = end + 1;
501                         } else {
502                                 mac = g_strdup(pbuf);
503                                 pbuf += strlen(mac);
504                         }
505
506                         if (mac == NULL) {
507                                 ERR("strdup failed\n");
508                                 return TRUE;
509                         }
510
511                         SDBG("%s%s\n", HOSTAPD_STA_DISCONN, mac);
512                         _remove_station_info(mac, _slist_find_station_by_mac);
513
514                         /*
515                          * Destroy the timer if its not expired before disconnection
516                          */
517                         _destroy_dhcp_ack_timer(mac);
518                         g_free(mac);
519                         mac = NULL;
520                         discon_event = TRUE;
521
522                 } else {
523                         pbuf = strchr(pbuf, '>');
524                         if (pbuf == NULL)
525                                 break;
526                         pbuf++;
527                 }
528         }
529
530         if (discon_event == FALSE)
531                 goto DONE;
532
533         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
534                 type = MOBILE_AP_TYPE_WIFI;
535         } else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
536                 type = MOBILE_AP_TYPE_WIFI_AP;
537         } else {
538                 goto DONE;
539         }
540
541         _get_station_count((gconstpointer)type,
542                         _slist_find_station_by_interface, &n_station);
543
544         if (n_station == 0) {
545                 if (type == MOBILE_AP_TYPE_WIFI)
546                         _start_timeout_cb(type, time(NULL) + TETHERING_CONN_TIMEOUT);
547                 else if (type == MOBILE_AP_TYPE_WIFI_AP)
548                         _start_timeout_cb(type, time(NULL) + WIFI_AP_CONN_TIMEOUT);
549         }
550 DONE:
551         return TRUE;
552 }
553
554 static int __open_hostapd_monitor(int *fd)
555 {
556         if (fd == NULL) {
557                 ERR("fd is NULL\n");
558                 return MOBILE_AP_ERROR_INVALID_PARAM;
559         }
560
561         DBG("+\n");
562
563         char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
564         int buf_len = 0;
565
566         if (__open_hostapd_intf(fd, MH_MONITOR_INTF) != MOBILE_AP_ERROR_NONE) {
567                 ERR("__open_hostapd_intf() is failed\n");
568                 return MOBILE_AP_ERROR_INTERNAL;
569         }
570
571         hostapd_io_channel = g_io_channel_unix_new(*fd);
572         if (hostapd_io_channel == NULL) {
573                 ERR("g_io_channel_unix_new is failed\n");
574                 return MOBILE_AP_ERROR_INTERNAL;
575         }
576
577         g_io_channel_set_encoding(hostapd_io_channel, NULL, NULL);
578         g_io_channel_set_flags(hostapd_io_channel,
579                         G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK, NULL);
580
581         hostapd_io_source = g_io_add_watch(hostapd_io_channel, G_IO_IN,
582                         (GIOFunc)__hostapd_monitor_cb, NULL);
583
584         buf_len = sizeof(buf);
585         __send_hostapd_req(*fd, HOSTAPD_MONITOR_ATTACH,
586                         strlen(HOSTAPD_MONITOR_ATTACH), buf, &buf_len);
587
588         return MOBILE_AP_ERROR_NONE;
589 }
590
591 static int __close_hostapd_monitor(int *fd)
592 {
593         GError *err = NULL;
594         char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
595         int buf_len = 0;
596
597         buf_len = sizeof(buf);
598         __send_hostapd_req(*fd, HOSTAPD_MONITOR_DETACH,
599                         strlen(HOSTAPD_MONITOR_DETACH), buf, &buf_len);
600
601         if (hostapd_io_source != 0) {
602                 g_source_remove(hostapd_io_source);
603                 hostapd_io_source = 0;
604         }
605
606         if (hostapd_io_channel != NULL) {
607                 g_io_channel_shutdown(hostapd_io_channel, TRUE, &err);
608                 g_io_channel_unref(hostapd_io_channel);
609                 hostapd_io_channel = NULL;
610         }
611
612         __close_hostapd_intf(fd);
613
614         return MOBILE_AP_ERROR_NONE;
615 }
616
617 static mobile_ap_drv_interface_e __get_drv_interface(void)
618 {
619         static mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
620
621         if (drv_interface != MOBILE_AP_DRV_INTERFACE_NONE) {
622                 return drv_interface;
623         }
624
625         const char *drv_rfkill_path = "/sys/devices/platform";
626         const char *wext_drv[] = {
627                 "bcm4329-b1", "bcm4330-b0",
628                 "bcm4330-b1", "bcm4330-b2",
629                 NULL};
630
631         char path[MAX_BUF_SIZE] = { 0 };
632         struct stat stat_buf = { 0 };
633         int fd = 0;
634         int i = 0;
635
636         drv_interface = MOBILE_AP_NL80211;
637
638         for (i = 0; wext_drv[i] != NULL; i++) {
639                 snprintf(path, sizeof(path), "%s/%s",
640                                 drv_rfkill_path, wext_drv[i]);
641                 fd = open(path, O_RDONLY);
642                 if (fd < 0)
643                         continue;
644
645                 if (fstat(fd, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode)) {
646                         drv_interface = MOBILE_AP_WEXT;
647                         close(fd);
648                         break;
649                 }
650
651                 close(fd);
652         }
653
654         return drv_interface;
655 }
656
657 static int __mh_core_softap_firmware_start(void)
658 {
659         int err = 0;
660         DBusError error;
661         DBusMessageIter iter;
662         DBusMessage *reply = NULL;
663         DBusMessage *message = NULL;
664         DBusConnection *connection = NULL;
665         const char *device = "softap";
666
667         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
668         if (connection == NULL) {
669                 ERR("Failed to get system bus");
670                 return -EIO;
671         }
672
673         message = dbus_message_new_method_call(NETCONFIG_SERVICE,
674                         NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE ".Firmware", "Start");
675         if (message == NULL) {
676                 ERR("Failed DBus method call");
677                 dbus_connection_unref(connection);
678                 return -EIO;
679         }
680
681         dbus_message_iter_init_append(message, &iter);
682         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
683
684         dbus_error_init(&error);
685
686         reply = dbus_connection_send_with_reply_and_block(connection, message,
687                         NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
688         if (dbus_error_is_set(&error) == TRUE) {
689                 if (NULL != strstr(error.message, ".AlreadyExists")) {
690                         // softap already enabled
691                 } else {
692                         ERR("dbus_connection_send_with_reply_and_block() failed. "
693                                         "DBus error [%s: %s]", error.name, error.message);
694
695                         err = -EIO;
696
697                         dbus_error_free(&error);
698                 }
699
700                 dbus_error_free(&error);
701         }
702
703         if (reply != NULL)
704                 dbus_message_unref(reply);
705
706         dbus_message_unref(message);
707         dbus_connection_unref(connection);
708
709         return err;
710 }
711
712 static int __mh_core_softap_firmware_stop(void)
713 {
714         int err = 0;
715         DBusError error;
716         DBusMessageIter iter;
717         DBusMessage *reply = NULL;
718         DBusMessage *message = NULL;
719         DBusConnection *connection = NULL;
720         const char *device = "softap";
721
722         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
723         if (connection == NULL) {
724                 ERR("Failed to get system bus");
725                 return -EIO;
726         }
727
728         message = dbus_message_new_method_call(NETCONFIG_SERVICE,
729                         NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE ".Firmware", "Stop");
730         if (message == NULL) {
731                 ERR("Failed DBus method call");
732                 dbus_connection_unref(connection);
733                 return -EIO;
734         }
735
736         dbus_message_iter_init_append(message, &iter);
737         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
738
739         dbus_error_init(&error);
740
741         reply = dbus_connection_send_with_reply_and_block(connection, message,
742                         NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
743         if (dbus_error_is_set(&error) == TRUE) {
744                 if (NULL != strstr(error.message, ".AlreadyExists")) {
745                         // softap already disabled
746                 } else {
747                         ERR("dbus_connection_send_with_reply_and_block() failed. "
748                                         "DBus error [%s: %s]", error.name, error.message);
749
750                         err = -EIO;
751
752                         dbus_error_free(&error);
753                 }
754
755                 dbus_error_free(&error);
756         }
757
758         if (reply != NULL)
759                 dbus_message_unref(reply);
760
761         dbus_message_unref(message);
762         dbus_connection_unref(connection);
763
764         return err;
765 }
766
767 int _mh_core_enable_softap(const mobile_ap_type_e type, const char *ssid,
768                 const char *security, const char *key, int hide_mode)
769 {
770         if (ssid == NULL || security == NULL || key == NULL) {
771                 ERR("Invalid param\n");
772                 return MOBILE_AP_ERROR_INTERNAL;
773         }
774
775         char cmd[MAX_BUF_SIZE];
776         int ret_status = MOBILE_AP_ERROR_NONE;
777         mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
778
779         int sock_fd;
780         char *if_name = WIFI_IF;
781         char buf[MAX_BUF_SIZE] = { 0 };
782
783         char wext_ssid[MOBILE_AP_WIFI_SSID_MAX_LEN] = { 0 };
784         char *ptr = NULL;
785
786         if (__mh_core_softap_firmware_start() < 0)
787                 return MOBILE_AP_ERROR_INTERNAL;
788
789         drv_interface = __get_drv_interface();
790
791         switch (drv_interface) {
792         case MOBILE_AP_WEXT:
793                 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
794                         ERR("Failed to open socket...!!!\n");
795                         ret_status = MOBILE_AP_ERROR_RESOURCE;
796                         break;
797                 }
798
799                 /*
800                  * In case of Wireless extension interface,
801                  * 32 byte SSID including null character can be accepted.
802                  */
803                 g_strlcpy(wext_ssid, ssid, sizeof(wext_ssid));
804                 if (!g_utf8_validate(wext_ssid, -1, (const char **)&ptr))
805                         *ptr = '\0';
806
807                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_CFG,"
808                                         "SSID_LEN=%d,SSID=%s,"
809                                         "SEC=%s,KEY_LEN=%d,KEY=%s,CHANNEL=%d,"
810                                         "PREAMBLE=0,MAX_SCB=%d,HIDE=%d,END",
811                                         strlen(wext_ssid), wext_ssid,
812                                         security, strlen(key), key,
813                                         MOBILE_AP_WIFI_CHANNEL,
814                                         MOBILE_AP_MAX_WIFI_STA, hide_mode);
815                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
816                 if (ret_status != MOBILE_AP_ERROR_NONE) {
817                         ERR("__issue_ioctl failed...!!!\n");
818                         close(sock_fd);
819                         break;
820                 }
821
822                 /* Start broadcasting of BSS. */
823                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_START");
824                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
825                 if (ret_status != MOBILE_AP_ERROR_NONE) {
826                         ERR("__issue_ioctl failed...!!!\n");
827                         close(sock_fd);
828                         break;
829                 }
830
831                 close(sock_fd);
832
833                 ret_status = _mh_core_set_ip_address(SOFTAP_IF,
834                                 IP_ADDRESS_SOFTAP);
835                 if (ret_status != MOBILE_AP_ERROR_NONE) {
836                         ERR("_mh_core_set_ip_address of SOFTAP_IF is failed\n");
837                         break;
838                 }
839
840                 ret_status = _mh_core_set_ip_address(WIFI_IF,
841                                 IP_ADDRESS_WIFI);
842                 if (ret_status != MOBILE_AP_ERROR_NONE) {
843                         ERR("_mh_core_set_ip_address of WIFI_IF is failed\n");
844                         break;
845                 }
846                 break;
847
848         case MOBILE_AP_NL80211:
849
850                 ret_status = _mh_core_set_ip_address(WIFI_IF,
851                                 IP_ADDRESS_SOFTAP);
852                 if (ret_status != MOBILE_AP_ERROR_NONE) {
853                         ERR("_mh_core_set_ip_address is failed\n");
854                         break;
855                 }
856
857                 ret_status = __execute_hostapd(type, ssid, security, key, hide_mode);
858                 if (ret_status != MOBILE_AP_ERROR_NONE) {
859                         ERR("__execute_hostapd is failed\n");
860                         break;
861                 }
862
863                 ret_status = __open_hostapd_intf(&hostapd_ctrl_fd, MH_CTRL_INTF);
864                 if (ret_status != MOBILE_AP_ERROR_NONE) {
865                         ERR("__open_hostapd_intf is failed\n");
866                         __terminate_hostapd();
867                         break;
868                 }
869
870                 ret_status = __open_hostapd_monitor(&hostapd_monitor_fd);
871                 if (ret_status != MOBILE_AP_ERROR_NONE) {
872                         ERR("__open_hostapd_monitor is failed\n");
873                         __close_hostapd_intf(&hostapd_ctrl_fd);
874                         __terminate_hostapd();
875                         break;
876                 }
877
878                 break;
879
880         default:
881                 ERR("Unknown driver interface : %d\n", drv_interface);
882                 break;
883         }
884
885         if (ret_status != MOBILE_AP_ERROR_NONE)
886                 __mh_core_softap_firmware_stop();
887
888         return ret_status;
889 }
890
891 int _mh_core_disable_softap(void)
892 {
893         char cmd[MAX_BUF_SIZE] = { 0 };
894         int ret_status = MOBILE_AP_ERROR_NONE;
895         mobile_ap_drv_interface_e drv_interface = MOBILE_AP_DRV_INTERFACE_NONE;
896
897         int sock_fd = 0;
898         char buf[MAX_BUF_SIZE] = { 0 };
899         char *if_name = WIFI_IF;
900
901         drv_interface = __get_drv_interface();
902
903         switch (drv_interface) {
904         case MOBILE_AP_WEXT:
905                 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
906                         ERR("Failed to open socket...!!!\n");
907                         ret_status = MOBILE_AP_ERROR_RESOURCE;
908                         break;
909                 }
910
911                 /* Stop broadcasting of BSS. */
912                 snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_BSS_STOP");
913                 ret_status = __issue_ioctl(sock_fd, if_name, cmd, buf);
914                 if (ret_status != MOBILE_AP_ERROR_NONE) {
915                         ERR("__issue_ioctl failed...!!!\n");
916                         close(sock_fd);
917                         break;
918                 }
919
920                 close(sock_fd);
921                 break;
922
923         case MOBILE_AP_NL80211:
924                 ret_status = __close_hostapd_intf(&hostapd_ctrl_fd);
925                 if (ret_status != MOBILE_AP_ERROR_NONE)
926                         ERR("hostapd termination is failed\n");
927
928                 ret_status = __close_hostapd_monitor(&hostapd_monitor_fd);
929                 if (ret_status != MOBILE_AP_ERROR_NONE)
930                         ERR("hostapd termination is failed\n");
931
932                 ret_status = __terminate_hostapd();
933                 if (ret_status != MOBILE_AP_ERROR_NONE) {
934                         ERR("hostapd termination is failed\n");
935                 }
936                 break;
937
938         default:
939                 ERR("Unknown driver interface : %d\n", drv_interface);
940                 break;
941         }
942
943         if (__mh_core_softap_firmware_stop() < 0)
944                 ret_status = MOBILE_AP_ERROR_INTERNAL;
945
946         return ret_status;
947 }
948
949 static int __get_device_info_by_wext(softap_device_info_t *di)
950 {
951         int sock_fd = 0;
952         char *if_name = SOFTAP_IF;
953         char cmd[MAX_BUF_SIZE];
954         char buf[MAX_BUF_SIZE] = { 0 };
955         int ret = MOBILE_AP_ERROR_NONE;
956
957         char *buf_ptr = NULL;
958         int i;
959
960         if ((sock_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
961                 ERR("Failed to open socket...!!!\n");
962                 di->number = 0;
963                 return MOBILE_AP_ERROR_RESOURCE;
964         }
965
966         snprintf(cmd, MAX_BUF_SIZE, "AP_GET_STA_LIST");
967         ret = __issue_ioctl(sock_fd, if_name, cmd, buf);
968         if (ret != MOBILE_AP_ERROR_NONE) {
969                 ERR("__issue_ioctl failed...!!!\n");
970                 di->number = 0;
971                 close(sock_fd);
972                 return ret;
973         }
974
975         buf_ptr = buf;
976
977         sscanf(buf_ptr, "%02x", &di->number);
978
979         buf_ptr += 2;
980         for (i = 0; i < di->number; i++) {
981                 unsigned int l_bssid[MOBILE_AP_WIFI_BSSID_LEN];
982                 sscanf(buf_ptr, "%02X%02X%02X%02X%02X%02X", &l_bssid[0],
983                                         &l_bssid[1], &l_bssid[2], &l_bssid[3],
984                                         &l_bssid[4], &l_bssid[5]);
985                 snprintf(di->bssid[i], MOBILE_AP_STR_INFO_LEN,
986                                         "%02X:%02X:%02X:%02X:%02X:%02X",
987                                         l_bssid[0], l_bssid[1], l_bssid[2],
988                                         l_bssid[3], l_bssid[4], l_bssid[5]);
989
990                 SDBG("STA[%d] address[%s]\n", i, di->bssid[i]);
991
992                 buf_ptr += 12;
993         }
994
995         close(sock_fd);
996
997         return ret;
998 }
999
1000 static int __get_device_info_by_nl80211(softap_device_info_t *di)
1001 {
1002         int ret = 0;
1003         int no_of_sta = 0;
1004         int buf_len = 0;
1005         char req[HOSTAPD_REQ_MAX_LEN] = {0, };
1006         char buf[MOBILE_AP_STR_INFO_LEN] = {0, };
1007
1008         buf_len = sizeof(buf);
1009         g_strlcpy(req, "NUM_STA", sizeof(req));
1010         ret = __send_hostapd_req(hostapd_ctrl_fd,
1011                         req, strlen(req), buf, &buf_len);
1012         if (ret != MOBILE_AP_ERROR_NONE) {
1013                 ERR("__send_hostapd_req is failed : %d\n", ret);
1014                 return ret;
1015         }
1016
1017         DBG("The number of station : %s\n", buf);
1018         if (atoi(buf) == 0) {
1019                 DBG("There is no station\n");
1020                 return MOBILE_AP_ERROR_NONE;
1021         }
1022
1023         buf_len = sizeof(buf);
1024         g_strlcpy(req, "STA-FIRST", sizeof(req));
1025         ret = __send_hostapd_req(hostapd_ctrl_fd,
1026                         req, strlen(req), buf, &buf_len);
1027         if (ret != MOBILE_AP_ERROR_NONE) {
1028                 ERR("__send_hostapd_req is failed : %d\n", ret);
1029                 return ret;
1030         }
1031
1032         do {
1033                 if (!strncmp(buf, "FAIL", 4)) {
1034                         ERR("FAIL is returned\n");
1035                         break;
1036                 }
1037
1038                 if (buf[0] == '\0') {
1039                         ERR("NULL string\n");
1040                         break;
1041                 }
1042
1043                 SDBG("Station : %s\n", buf);
1044                 g_strlcpy(di->bssid[no_of_sta++], buf, MOBILE_AP_STR_INFO_LEN);
1045
1046                 buf_len = sizeof(buf);
1047                 snprintf(req, sizeof(req), "STA-NEXT %s", buf);
1048                 ret = __send_hostapd_req(hostapd_ctrl_fd,
1049                                 req, strlen(req), buf, &buf_len);
1050         } while (ret == MOBILE_AP_ERROR_NONE);
1051
1052         di->number = no_of_sta;
1053
1054         return ret;
1055 }
1056
1057 int _mh_core_get_device_info(softap_device_info_t *di)
1058 {
1059         if (di == NULL) {
1060                 ERR("Invalid param\n");
1061                 return MOBILE_AP_ERROR_INVALID_PARAM;
1062         }
1063
1064         int ret = MOBILE_AP_ERROR_NONE;
1065
1066         switch (__get_drv_interface()) {
1067         case MOBILE_AP_WEXT:
1068                 ret = __get_device_info_by_wext(di);
1069                 break;
1070
1071         case MOBILE_AP_NL80211:
1072                 ret = __get_device_info_by_nl80211(di);
1073                 break;
1074
1075         default:
1076                 ERR("Unknown interface\n");
1077                 break;
1078         }
1079
1080         return ret;
1081 }
1082
1083 int _mh_core_execute_dhcp_server(void)
1084 {
1085         char buf[DNSMASQ_CONF_LEN] = "";
1086         FILE *fp = NULL;
1087         pid_t pid;
1088
1089         fp = fopen(DNSMASQ_CONF_FILE, "w");
1090         if (NULL == fp) {
1091                 ERR("Could not create the file.\n");
1092                 return MOBILE_AP_ERROR_RESOURCE;
1093         }
1094         snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF);
1095         fputs(buf, fp);
1096         fclose(fp);
1097
1098         pid = fork();
1099         if (pid < 0) {
1100                 ERR("fork failed\n");
1101                 return MOBILE_AP_ERROR_RESOURCE;
1102         }
1103
1104         if (pid == 0) {
1105                 /* -d : Debug mode
1106                  * -p 0 : DNS off
1107                  * -C file : Configuration file path
1108                  */
1109                 if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
1110                                         "-p", "0", "-C", DNSMASQ_CONF_FILE,
1111                                         (char *)NULL)) {
1112                         ERR("execl failed\n");
1113                 }
1114
1115                 ERR("Should not get here!");
1116                 return MOBILE_AP_ERROR_RESOURCE;
1117         }
1118
1119         dnsmasq_pid = pid;
1120
1121         return MOBILE_AP_ERROR_NONE;
1122 }
1123
1124 int _mh_core_terminate_dhcp_server(void)
1125 {
1126         int ret;
1127
1128         if (dnsmasq_pid == 0) {
1129                 ERR("There is no dnsmasq\n");
1130                 return MOBILE_AP_ERROR_NONE;
1131         }
1132
1133         kill(dnsmasq_pid, SIGTERM);
1134         waitpid(dnsmasq_pid, NULL, 0);
1135         dnsmasq_pid = 0;
1136
1137         ret = unlink(DNSMASQ_CONF_FILE);
1138         if (ret < 0) {
1139                 ERR("unlink is failed : %s\n", strerror(errno));
1140         }
1141
1142         return MOBILE_AP_ERROR_NONE;
1143 }
1144
1145 int _mh_core_enable_masquerade(const char *ext_if)
1146 {
1147         if (ext_if == NULL || strlen(ext_if) == 0) {
1148                 ERR("ext_if[%s] is invalid\n", ext_if);
1149                 return MOBILE_AP_ERROR_INVALID_PARAM;
1150         }
1151
1152         int fd = -1;
1153
1154         fd = open(IP_FORWARD, O_WRONLY);
1155         if (fd < 0) {
1156                 ERR("open failed\n");
1157                 return MOBILE_AP_ERROR_RESOURCE;
1158         }
1159
1160         if (write(fd, "1", 1) != 1) {
1161                 ERR("write failed\n");
1162                 close(fd);
1163                 return MOBILE_AP_ERROR_INTERNAL;
1164         }
1165         close(fd);
1166
1167         _iptables_create_chain(TABLE_NAT, TETH_NAT_POST);
1168         _iptables_add_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_POST,
1169                         TETH_NAT_POST);
1170         _iptables_add_rule(MASQ_RULE, TABLE_NAT, TETH_NAT_POST, ext_if);
1171
1172         _iptables_create_chain(TABLE_FILTER, TETH_FILTER_FW);
1173
1174         _iptables_add_rule(PKT_REDIRECTION_RULE, TABLE_FILTER, CHAIN_FW,
1175                         TETH_FILTER_FW);
1176
1177         _iptables_add_rule(CLAMP_MSS_RULE, TABLE_FILTER, TETH_FILTER_FW);
1178
1179         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1180                 BT_IF_ALL, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
1181         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1182                 WIFI_IF, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
1183         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1184                 USB_IF, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
1185
1186         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1187                 ext_if, BT_IF_ALL, ACTION_DROP, STATE_INVALID);
1188         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1189                 ext_if, WIFI_IF, ACTION_DROP, STATE_INVALID);
1190         _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
1191                 ext_if, USB_IF, ACTION_DROP, STATE_INVALID);
1192
1193         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1194                 ext_if, BT_IF_ALL, ACTION_RETURN);
1195         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1196                 ext_if, WIFI_IF, ACTION_RETURN);
1197         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1198                 ext_if, USB_IF, ACTION_RETURN);
1199
1200         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1201                 BT_IF_ALL, ext_if, ACTION_RETURN);
1202         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1203                 WIFI_IF, ext_if, ACTION_RETURN);
1204         _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
1205                 USB_IF, ext_if, ACTION_RETURN);
1206
1207         _iptables_add_rule(DEFAULT_RULE, TABLE_FILTER, TETH_FILTER_FW,
1208                 ACTION_DROP);
1209
1210         return MOBILE_AP_ERROR_NONE;
1211 }
1212
1213 int _mh_core_disable_masquerade(const char *ext_if)
1214 {
1215         if (ext_if == NULL || strlen(ext_if) == 0) {
1216                 ERR("ext_if[%s] is invalid\n", ext_if);
1217                 return MOBILE_AP_ERROR_INVALID_PARAM;
1218         }
1219
1220         int fd = -1;
1221
1222         fd = open(IP_FORWARD, O_WRONLY);
1223         if (fd < 0) {
1224                 ERR("open failed\n");
1225                 return MOBILE_AP_ERROR_RESOURCE;
1226         }
1227
1228         if (write(fd, "0", 1) != 1) {
1229                 ERR("write failed\n");
1230                 close(fd);
1231                 return MOBILE_AP_ERROR_INTERNAL;
1232         }
1233         close(fd);
1234
1235         _iptables_delete_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_POST,
1236                         TETH_NAT_POST);
1237         _iptables_flush_rules(TABLE_NAT, TETH_NAT_POST);
1238         _iptables_delete_chain(TABLE_NAT, TETH_NAT_POST);
1239
1240         _iptables_delete_rule(PKT_REDIRECTION_RULE, TABLE_FILTER, CHAIN_FW,
1241                         TETH_FILTER_FW);
1242         _iptables_flush_rules(TABLE_FILTER, TETH_FILTER_FW);
1243         _iptables_delete_chain(TABLE_FILTER, TETH_FILTER_FW);
1244
1245         return MOBILE_AP_ERROR_NONE;
1246 }
1247
1248 void _mh_core_add_data_to_array(GPtrArray *array, guint type, gchar *dev_name)
1249 {
1250         GValue value = {0, {{0}}};
1251
1252         g_value_init(&value, DBUS_STRUCT_UINT_STRING);
1253         g_value_take_boxed(&value,
1254                         dbus_g_type_specialized_construct(DBUS_STRUCT_UINT_STRING));
1255         dbus_g_type_struct_set(&value, 0, type, 1, dev_name, G_MAXUINT);
1256         g_ptr_array_add(array, g_value_get_boxed(&value));
1257 }
1258
1259 int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
1260 {
1261         struct ifreq ifr;
1262         struct sockaddr_in addr;
1263         int sock_fd;
1264
1265         SDBG("if_name : %s ip address : 0x%X\n", if_name, ip);
1266
1267         if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1268                 ERR("socket open failed!!!\n");
1269                 return MOBILE_AP_ERROR_RESOURCE;
1270         }
1271
1272         g_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
1273
1274         memset(&addr, 0, sizeof(struct sockaddr));
1275         addr.sin_family = AF_INET;
1276         addr.sin_port = 0;
1277         addr.sin_addr.s_addr = htonl(ip);
1278
1279         memcpy(&ifr.ifr_addr, &addr, sizeof(struct sockaddr));
1280         if (ioctl(sock_fd, SIOCSIFADDR, &ifr) < 0) {
1281                 ERR("ioctl failed...!!!\n");
1282                 close(sock_fd);
1283                 return MOBILE_AP_ERROR_INTERNAL;
1284         }
1285
1286         if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0) {
1287                 ERR("ioctl failed...!!!\n");
1288                 close(sock_fd);
1289                 return MOBILE_AP_ERROR_INTERNAL;
1290         }
1291
1292         ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
1293         if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
1294                 ERR("ioctl failed...!!!\n");
1295                 close(sock_fd);
1296                 return MOBILE_AP_ERROR_INTERNAL;
1297         }
1298
1299         close(sock_fd);
1300
1301         return MOBILE_AP_ERROR_NONE;
1302 }
1303
1304 static gboolean __send_station_event_cb(gpointer data)
1305 {
1306         int sig = GPOINTER_TO_INT(data);
1307         int n_station = 0;
1308         int type;
1309         mobile_ap_station_info_t *si = NULL;
1310
1311         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
1312                 type = MOBILE_AP_TYPE_WIFI;
1313         else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
1314                 type = MOBILE_AP_TYPE_WIFI_AP;
1315         else
1316                 return FALSE;
1317
1318         if (sig == SIGUSR1) {
1319                 DBG("STA connected(%d)\n", sig);
1320                 /* STA connection is handled in the dnsmasq signal handler */
1321         } else if (sig == SIGUSR2) {
1322                 DBG("STA disconnected(%d)\n", sig);
1323
1324                 /* Temporarily care only one station.
1325                  * Driver team should be support detail information */
1326                 if (_get_station_info((gconstpointer)type,
1327                                 _slist_find_station_by_interface,
1328                                 &si) != MOBILE_AP_ERROR_NONE) {
1329                         return FALSE;
1330                 }
1331                 _remove_station_info(si->mac, _slist_find_station_by_mac);
1332
1333                 _get_station_count((gconstpointer)type,
1334                                 _slist_find_station_by_interface, &n_station);
1335                 if (n_station == 0) {
1336                         if (type == MOBILE_AP_TYPE_WIFI)
1337                                 _start_timeout_cb(type, time(NULL) + TETHERING_CONN_TIMEOUT);
1338                         else if (type == MOBILE_AP_TYPE_WIFI_AP)
1339                                 _start_timeout_cb(type, time(NULL) + WIFI_AP_CONN_TIMEOUT);
1340                 }
1341         }
1342
1343         return FALSE;
1344 }
1345
1346 static void __handle_station_signal(int sig)
1347 {
1348         g_idle_add(__send_station_event_cb, GINT_TO_POINTER(sig));
1349         return;
1350 }
1351
1352 void _register_wifi_station_handler(void)
1353 {
1354         struct sigaction sa;
1355
1356         if (__get_drv_interface() != MOBILE_AP_WEXT)
1357                 return;
1358
1359         memset(&sa, 0, sizeof(sa));
1360         sa.sa_handler = __handle_station_signal;
1361         sigaction(SIGUSR1, &sa, NULL);
1362         sigaction(SIGUSR2, &sa, NULL);
1363
1364         return;
1365 }
1366
1367 void _unregister_wifi_station_handler(void)
1368 {
1369         struct sigaction sa;
1370
1371         if (__get_drv_interface() != MOBILE_AP_WEXT)
1372                 return;
1373
1374         memset(&sa, 0, sizeof(sa));
1375         sa.sa_handler = SIG_DFL;
1376         sigaction(SIGUSR1, &sa, NULL);
1377         sigaction(SIGUSR2, &sa, NULL);
1378
1379         return;
1380 }
1381
1382 static gboolean __hostapd_connect_timer_cb(gpointer user_data)
1383 {
1384         char *mac = (char *)user_data;
1385         GSList *l = NULL;
1386         GSList *temp = NULL;
1387         sta_timer_t *ptr = NULL;
1388         mobile_ap_station_info_t *info = NULL;
1389         time_t tm;
1390         int n_station = 0;
1391         int type;
1392         int ret;
1393
1394         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
1395                 type = MOBILE_AP_TYPE_WIFI;
1396         else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
1397                 type = MOBILE_AP_TYPE_WIFI_AP;
1398         else
1399                 return FALSE;
1400
1401         for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
1402                 ptr = (sta_timer_t *)l->data;
1403                 if (ptr == NULL)
1404                         continue;
1405
1406                 if (!g_strcmp0(ptr->mac_addr, mac)) {
1407                         DBG("client with Static IP, Add station\n");
1408
1409                         info = (mobile_ap_station_info_t *)g_malloc(sizeof(mobile_ap_station_info_t));
1410                         if (info == NULL) {
1411                                 ERR("g_malloc failed\n");
1412                                 g_free(ptr->mac_addr);
1413                                 g_free(ptr);
1414                                 temp = l;
1415                                 l = g_slist_next(l);
1416                                 sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
1417                                 break;
1418                         }
1419
1420                         time(&tm);
1421                         info->tm = tm;
1422                         info->interface = type;
1423                         g_strlcpy(info->ip, "", sizeof(info->ip));
1424                         g_strlcpy(info->mac, mac, sizeof(info->mac));
1425
1426                         ret = _get_wifi_name_from_lease_info(mac, &info->hostname);
1427                         if (ret != MOBILE_AP_ERROR_NONE)
1428                                 info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
1429
1430                         g_free(ptr->mac_addr);
1431                         g_free(ptr);
1432                         temp = l;
1433                         l = g_slist_next(l);
1434                         sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
1435
1436                         goto SUCCESS;
1437                 }
1438         }
1439
1440         return FALSE;
1441
1442 SUCCESS :
1443         if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
1444                 g_free(info->hostname);
1445                 g_free(info);
1446                 return FALSE;
1447         }
1448
1449         _get_station_count((gconstpointer)type,
1450                         _slist_find_station_by_interface, &n_station);
1451         if (n_station == 1)
1452                 _stop_timeout_cb(type);
1453
1454         _send_dbus_station_info("DhcpConnected", info);
1455
1456         return FALSE;
1457 }
1458
1459 void _flush_dhcp_ack_timer(void)
1460 {
1461         DBG("+\n");
1462
1463         GSList *l = NULL;
1464         GSList *temp = NULL;
1465         sta_timer_t *ptr = NULL;
1466
1467         for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
1468                 ptr = (sta_timer_t *)l->data;
1469                 if (ptr) {
1470                         if (ptr->tid != 0) {
1471                                 g_source_remove(ptr->tid);
1472                                 ptr->tid = 0;
1473                         }
1474                         g_free(ptr->mac_addr);
1475                         g_free(ptr);
1476                 }
1477
1478                 temp = l;
1479                 l = g_slist_next(l);
1480                 sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
1481         }
1482
1483         DBG("-\n");
1484         return;
1485 }
1486
1487 void _destroy_dhcp_ack_timer(char *mac_addr)
1488 {
1489         DBG("+\n");
1490         if (mac_addr == NULL) {
1491                 ERR("mac address passed NULL\n");
1492                 return;
1493         }
1494
1495         GSList *l = NULL;
1496         GSList *temp = NULL;
1497         sta_timer_t *ptr = NULL;
1498
1499         for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
1500
1501                 ptr = (sta_timer_t *)l->data;
1502                 if (ptr == NULL)
1503                         continue;
1504
1505                 if (!g_strcmp0(ptr->mac_addr, mac_addr)) {
1506
1507                         if (ptr->tid != 0) {
1508                                 g_source_remove(ptr->tid);
1509                                 ptr->tid = 0;
1510                         }
1511                         g_free(ptr->mac_addr);
1512                         g_free(ptr);
1513                         temp = l;
1514                         l = g_slist_next(l);
1515                         sta_timer_list = g_slist_delete_link(sta_timer_list,
1516                                                 temp);
1517                         break;
1518                 }
1519         }
1520
1521         DBG("-\n");
1522         return;
1523 }