5 * Copyright (C) 2007 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
38 #include "supplicant.h"
40 struct supplicant_task {
44 struct connman_iface *iface;
49 static GSList *tasks = NULL;
51 static struct supplicant_task *find_task(int ifindex)
55 for (list = tasks; list; list = list->next) {
56 struct supplicant_task *task = list->data;
58 if (task->ifindex == ifindex)
65 static int exec_cmd(struct supplicant_task *task, char *cmd)
67 write(task->socket, cmd, strlen(cmd));
72 static gboolean control_event(GIOChannel *chan,
73 GIOCondition cond, gpointer data)
75 struct supplicant_task *task = data;
80 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
81 g_io_channel_unref(chan);
85 memset(buf, 0, sizeof(buf));
87 err = g_io_channel_read(chan, buf, sizeof(buf), &len);
89 if (err == G_IO_ERROR_AGAIN)
91 g_io_channel_unref(chan);
98 printf("[SUPPLICANT] %s\n", buf + 3);
100 if (g_str_has_prefix(buf + 3, "CTRL-EVENT-CONNECTED") == TRUE) {
101 printf("[SUPPLICANT] connected\n");
102 connman_iface_update(task->iface,
103 CONNMAN_IFACE_STATE_CARRIER);
106 if (g_str_has_prefix(buf + 3, "CTRL-EVENT-DISCONNECTED") == TRUE) {
107 printf("[SUPPLICANT] disconnected\n");
110 if (g_str_has_prefix(buf + 3, "CTRL-EVENT-TERMINATING") == TRUE) {
111 printf("[SUPPLICANT] terminating\n");
117 static int open_control(struct supplicant_task *task)
119 struct sockaddr_un addr;
122 printf("[SUPPLICANT] open control for %s\n", task->ifname);
124 sk = socket(PF_UNIX, SOCK_DGRAM, 0);
128 memset(&addr, 0, sizeof(addr));
129 addr.sun_family = AF_UNIX;
130 snprintf(addr.sun_path, sizeof(addr.sun_path),
131 "%s/%s.cli", STATEDIR, task->ifname);
132 //unlink(addr.sun_path);
134 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
139 memset(&addr, 0, sizeof(addr));
140 addr.sun_family = AF_UNIX;
141 snprintf(addr.sun_path, sizeof(addr.sun_path),
142 "%s/%s", STATEDIR, task->ifname);
144 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
151 task->channel = g_io_channel_unix_new(sk);
152 g_io_channel_set_close_on_unref(task->channel, TRUE);
154 g_io_add_watch(task->channel,
155 G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
156 control_event, task);
158 exec_cmd(task, "ATTACH");
159 exec_cmd(task, "ADD_NETWORK");
161 g_io_channel_unref(task->channel);
166 int __supplicant_start(struct connman_iface *iface)
169 struct supplicant_task *task;
173 sk = socket(PF_INET, SOCK_DGRAM, 0);
177 memset(&ifr, 0, sizeof(ifr));
178 ifr.ifr_ifindex = iface->index;
180 err = ioctl(sk, SIOCGIFNAME, &ifr);
187 printf("[SUPPLICANT] start %s\n", ifr.ifr_name);
189 task = g_try_new0(struct supplicant_task, 1);
193 task->ifindex = iface->index;
194 task->ifname = strdup(ifr.ifr_name);
197 if (task->ifname == NULL) {
202 argv[0] = "/sbin/wpa_supplicant";
209 argv[7] = task->ifname;
212 if (g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
213 NULL, NULL, &task->pid, NULL) == FALSE) {
214 printf("Failed to spawn wpa_supplicant\n");
218 tasks = g_slist_append(tasks, task);
220 printf("[SUPPLICANT] executed with pid %d\n", task->pid);
226 if (open_control(task) < 0)
227 printf("[SUPPLICANT] control failed\n");
232 int __supplicant_stop(struct connman_iface *iface)
234 struct supplicant_task *task;
235 char pathname[PATH_MAX];
237 task = find_task(iface->index);
241 printf("[SUPPLICANT] stop %s\n", task->ifname);
243 tasks = g_slist_remove(tasks, task);
245 exec_cmd(task, "DETACH");
249 kill(task->pid, SIGTERM);
251 //close(task->socket);
252 g_io_channel_unref(task->channel);
254 snprintf(pathname, sizeof(pathname),
255 "%s/%s.cli", STATEDIR, task->ifname);
265 int __supplicant_connect(struct connman_iface *iface,
266 const char *network, const char *passphrase)
268 struct supplicant_task *task;
271 task = find_task(iface->index);
275 printf("[SUPPLICANT] connect %s\n", task->ifname);
277 exec_cmd(task, "DISABLE_NETWORK 0");
279 sprintf(cmd, "SET_NETWORK 0 ssid \"%s\"", network);
282 if (passphrase && strlen(passphrase) > 0) {
283 exec_cmd(task, "SET_NETWORK 0 proto RSN WPA");
284 exec_cmd(task, "SET_NETWORK 0 key_mgmt WPA-PSK");
286 sprintf(cmd, "SET_NETWORK 0 psk \"%s\"", passphrase);
289 exec_cmd(task, "SET_NETWORK 0 proto RSN WPA");
290 exec_cmd(task, "SET_NETWORK 0 key_mgmt NONE");
293 exec_cmd(task, "ENABLE_NETWORK 0");