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>
33 #include <arpa/inet.h>
35 #include <net/ethernet.h>
36 #include <linux/wireless.h>
40 #include <connman/plugin.h>
41 #include <connman/iface.h>
43 #include "supplicant.h"
53 unsigned char wpa_ie[40];
55 unsigned char rsn_ie[40];
60 char ifname[IFNAMSIZ];
67 static struct station_data *create_station(struct iface_data *iface,
70 struct station_data *station;
73 for (list = iface->stations; list; list = list->next) {
76 if (g_ascii_strcasecmp(station->address, address) == 0)
80 station = g_try_new0(struct station_data, 1);
84 station->address = g_strdup(address);
85 if (station->address == NULL) {
90 iface->stations = g_slist_append(iface->stations, station);
95 static void load_stations(struct iface_data *iface)
98 gchar **groups, **group;
101 keyfile = g_key_file_new();
103 if (g_key_file_load_from_file(keyfile, "/tmp/stations.list",
104 G_KEY_FILE_KEEP_COMMENTS, NULL) == FALSE)
107 groups = g_key_file_get_groups(keyfile, &length);
109 for (group = groups; *group; group++) {
110 struct station_data *station;
112 station = create_station(iface, *group);
116 station->name = g_key_file_get_string(keyfile,
117 *group, "Name", NULL);
119 station->mode = g_key_file_get_integer(keyfile,
120 *group, "Mode", NULL);
126 g_key_file_free(keyfile);
128 printf("[802.11] loaded %d stations\n",
129 g_slist_length(iface->stations));
132 static void print_stations(struct iface_data *iface)
139 keyfile = g_key_file_new();
141 for (list = iface->stations; list; list = list->next) {
142 struct station_data *station = list->data;
144 //printf("Address:%s Mode:%d ESSID:\"%s\" Quality:%d/100\n",
145 // station->address, station->mode,
146 // station->name, station->qual);
148 g_key_file_set_string(keyfile, station->address,
149 "Name", station->name);
151 g_key_file_set_integer(keyfile, station->address,
152 "Mode", station->mode);
155 data = g_key_file_to_data(keyfile, &length, NULL);
157 g_file_set_contents("/tmp/stations.list", data, length, NULL);
159 g_key_file_free(keyfile);
162 static int iface_probe(struct connman_iface *iface)
164 struct iface_data *data;
168 sk = socket(PF_INET, SOCK_DGRAM, 0);
172 memset(&ifr, 0, sizeof(ifr));
173 ifr.ifr_ifindex = iface->index;
175 err = ioctl(sk, SIOCGIFNAME, &ifr);
182 printf("[802.11] probe %s\n", ifr.ifr_name);
184 data = malloc(sizeof(*data));
188 memset(data, 0, sizeof(*data));
190 memcpy(data->ifname, ifr.ifr_name, IFNAMSIZ);
192 iface->type = CONNMAN_IFACE_TYPE_80211;
194 iface->flags = CONNMAN_IFACE_FLAG_RTNL |
195 CONNMAN_IFACE_FLAG_IPV4;
197 connman_iface_set_data(iface, data);
204 static void iface_remove(struct connman_iface *iface)
206 struct iface_data *data = connman_iface_get_data(iface);
208 printf("[802.11] remove %s\n", data->ifname);
210 __supplicant_stop(iface);
212 connman_iface_set_data(iface, NULL);
214 g_free(data->network);
215 g_free(data->passphrase);
220 static int iface_activate(struct connman_iface *iface)
222 struct iface_data *data = connman_iface_get_data(iface);
224 printf("[802.11] activate %s\n", data->ifname);
226 connman_iface_update(iface, CONNMAN_IFACE_STATE_ENABLED);
231 static int iface_shutdown(struct connman_iface *iface)
233 struct iface_data *data = connman_iface_get_data(iface);
235 printf("[802.11] shutdown %s\n", data->ifname);
237 connman_iface_update(iface, CONNMAN_IFACE_STATE_SHUTDOWN);
242 static int iface_scan(struct connman_iface *iface)
244 struct iface_data *data = connman_iface_get_data(iface);
246 struct iw_scan_req iws;
249 printf("[802.11] scanning %s\n", data->ifname);
251 sk = socket(PF_INET, SOCK_DGRAM, 0);
255 memset(&iws, 0, sizeof(iws));
256 iws.scan_type = IW_SCAN_TYPE_PASSIVE;
257 //iws.scan_type = IW_SCAN_TYPE_ACTIVE;
259 memset(&iwr, 0, sizeof(iwr));
260 strncpy(iwr.ifr_name, data->ifname, IFNAMSIZ);
262 iwr.u.data.pointer = (caddr_t ) &iws;
263 iwr.u.data.length = sizeof(iws);
264 iwr.u.data.flags = IW_SCAN_DEFAULT;
266 err = ioctl(sk, SIOCSIWSCAN, &iwr);
271 printf("[802.11] scan initiate error %d\n", errno);
276 static int iface_connect(struct connman_iface *iface,
277 struct connman_network *network)
279 struct iface_data *data = connman_iface_get_data(iface);
281 printf("[802.11] connect %s\n", data->ifname);
283 __supplicant_start(iface);
285 __supplicant_connect(iface, data->network, data->passphrase);
290 static void iface_set_network(struct connman_iface *iface,
293 struct iface_data *data = connman_iface_get_data(iface);
295 printf("[802.11] set network %s\n", data->ifname);
297 g_free(data->network);
299 data->network = g_strdup(network);
302 static void iface_set_passphrase(struct connman_iface *iface,
303 const char *passphrase)
305 struct iface_data *data = connman_iface_get_data(iface);
307 printf("[802.11] set passphrase %s\n", data->ifname);
309 g_free(data->passphrase);
311 data->passphrase = g_strdup(passphrase);
314 static void iface_carrier(struct connman_iface *iface, int carrier)
316 printf("[802.11] carrier %s\n", carrier ? "on" : "off");
318 connman_iface_indicate_carrier(iface, carrier);
321 static void parse_genie(struct station_data *station,
322 unsigned char *data, int len)
326 while (offset <= len - 2) {
329 switch (data[offset]) {
330 case 0xdd: /* WPA1 (and other) */
332 case 0x30: /* WPA2 (RSN) */
338 //for (i = 0; i < len; i++)
339 // printf(" %02x", data[i]);
342 offset += data[offset + 1] + 2;
346 static void parse_scan_results(struct connman_iface *iface,
347 unsigned char *data, int len)
349 unsigned char *ptr = data;
350 struct station_data *station = NULL;
351 struct ether_addr *eth;
355 while (len > IW_EV_LCP_PK_LEN) {
356 struct iw_event *event = (void *) ptr;
358 switch (event->cmd) {
360 eth = (void *) &event->u.ap_addr.sa_data;
361 sprintf(addr, "%02X:%02X:%02X:%02X:%02X:%02X",
362 eth->ether_addr_octet[0],
363 eth->ether_addr_octet[1],
364 eth->ether_addr_octet[2],
365 eth->ether_addr_octet[3],
366 eth->ether_addr_octet[4],
367 eth->ether_addr_octet[5]);
368 station = create_station(connman_iface_get_data(iface),
373 if (station != NULL) {
374 station->name = malloc(event->len - 7);
375 if (station->name != NULL) {
376 memset(station->name, 0, event->len - 7);
377 memcpy(station->name, ptr + 8,
386 station->mode = event->u.mode;
391 if (station != NULL) {
392 if (!(event->u.data.flags & IW_ENCODE_DISABLED)) {
400 if (station != NULL) {
401 station->qual = event->u.qual.qual;
402 station->noise = event->u.qual.noise;
403 station->level = event->u.qual.level;
408 parse_genie(station, ptr + 8, event->len - 8);
413 printf("[802.11] scan element 0x%04x (len %d)\n",
414 event->cmd, event->len);
422 printf("[802.11] found %d networks\n", num);
425 static void iface_scan_results(struct connman_iface *iface)
427 struct iface_data *data = connman_iface_get_data(iface);
430 int sk, err, size = 1024;
432 sk = socket(PF_INET, SOCK_DGRAM, 0);
443 memset(&iwr, 0, sizeof(iwr));
444 strncpy(iwr.ifr_name, data->ifname, IFNAMSIZ);
445 iwr.u.data.pointer = buf;
446 iwr.u.data.length = size;
447 iwr.u.data.flags = 0;
449 err = ioctl(sk, SIOCGIWSCAN, &iwr);
451 if (errno == E2BIG) {
457 parse_scan_results(iface, iwr.u.data.pointer,
464 print_stations(data);
467 static void iface_wireless(struct connman_iface *iface,
468 void *data, unsigned short len)
470 struct iw_event *event = data;
471 struct iw_point point;
472 struct ether_addr *eth;
475 switch (event->cmd) {
477 printf("[802.11] Set Frequency (flags %d)\n",
478 event->u.freq.flags);
481 printf("[802.11] Set Mode (mode %d)\n", event->u.mode);
484 memcpy(&point, data + IW_EV_LCP_LEN -
485 IW_EV_POINT_OFF, sizeof(point));
486 point.pointer = data + IW_EV_LCP_LEN +
487 sizeof(point) - IW_EV_POINT_OFF;
488 printf("[802.11] Set ESSID (length %d flags %d) \"%s\"\n",
489 point.length, point.flags,
490 (char *) point.pointer);
493 printf("[802.11] Set Encryption key (flags %d)\n",
494 event->u.data.flags);
498 eth = (void *) &event->u.ap_addr.sa_data;
499 sprintf(addr, "%02X:%02X:%02X:%02X:%02X:%02X",
500 eth->ether_addr_octet[0],
501 eth->ether_addr_octet[1],
502 eth->ether_addr_octet[2],
503 eth->ether_addr_octet[3],
504 eth->ether_addr_octet[4],
505 eth->ether_addr_octet[5]);
506 printf("[802.11] New Access Point %s\n", addr);
509 iface_scan_results(iface);
512 printf("[802.11] Wireless event (cmd 0x%04x len %d)\n",
513 event->cmd, event->len);
518 static struct connman_iface_driver iface_driver = {
520 .capability = "net.80211",
521 .probe = iface_probe,
522 .remove = iface_remove,
523 .activate = iface_activate,
524 .shutdown = iface_shutdown,
526 .connect = iface_connect,
527 .set_network = iface_set_network,
528 .set_passphrase = iface_set_passphrase,
529 .rtnl_carrier = iface_carrier,
530 .rtnl_wireless = iface_wireless,
533 static int plugin_init(void)
535 connman_iface_register(&iface_driver);
540 static void plugin_exit(void)
542 connman_iface_unregister(&iface_driver);
545 CONNMAN_PLUGIN_DEFINE("80211", "IEEE 802.11 interface plugin", VERSION,
546 plugin_init, plugin_exit)