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];
64 char ifname[IFNAMSIZ];
71 static void report_station(struct connman_iface *iface,
72 struct station_data *station)
79 if (station->name == NULL)
89 connman_iface_indicate_station(iface, station->name,
90 station->qual, security);
93 static struct station_data *create_station(struct iface_data *iface,
96 struct station_data *station;
99 for (list = iface->stations; list; list = list->next) {
100 station = list->data;
102 if (g_ascii_strcasecmp(station->address, address) == 0)
106 station = g_try_new0(struct station_data, 1);
110 station->address = g_strdup(address);
111 if (station->address == NULL) {
116 iface->stations = g_slist_append(iface->stations, station);
121 static void load_stations(struct iface_data *iface)
124 gchar **groups, **group;
127 keyfile = g_key_file_new();
129 if (g_key_file_load_from_file(keyfile, "/tmp/stations.list",
130 G_KEY_FILE_KEEP_COMMENTS, NULL) == FALSE)
133 groups = g_key_file_get_groups(keyfile, &length);
135 for (group = groups; *group; group++) {
136 struct station_data *station;
138 station = create_station(iface, *group);
142 station->name = g_key_file_get_string(keyfile,
143 *group, "Name", NULL);
145 station->mode = g_key_file_get_integer(keyfile,
146 *group, "Mode", NULL);
152 g_key_file_free(keyfile);
154 printf("[802.11] loaded %d stations\n",
155 g_slist_length(iface->stations));
158 static void print_stations(struct iface_data *iface)
165 keyfile = g_key_file_new();
167 for (list = iface->stations; list; list = list->next) {
168 struct station_data *station = list->data;
170 //printf("Address:%s Mode:%d ESSID:\"%s\" Quality:%d/100\n",
171 // station->address, station->mode,
172 // station->name, station->qual);
174 if (station->name == NULL)
177 g_key_file_set_string(keyfile, station->address,
178 "Name", station->name);
180 g_key_file_set_integer(keyfile, station->address,
181 "Mode", station->mode);
184 data = g_key_file_to_data(keyfile, &length, NULL);
186 g_file_set_contents("/tmp/stations.list", data, length, NULL);
188 g_key_file_free(keyfile);
191 static int iface_probe(struct connman_iface *iface)
193 struct iface_data *data;
197 sk = socket(PF_INET, SOCK_DGRAM, 0);
201 memset(&ifr, 0, sizeof(ifr));
202 ifr.ifr_ifindex = iface->index;
204 err = ioctl(sk, SIOCGIFNAME, &ifr);
211 printf("[802.11] probe %s\n", ifr.ifr_name);
213 data = malloc(sizeof(*data));
217 memset(data, 0, sizeof(*data));
219 memcpy(data->ifname, ifr.ifr_name, IFNAMSIZ);
221 iface->type = CONNMAN_IFACE_TYPE_80211;
223 iface->flags = CONNMAN_IFACE_FLAG_RTNL |
224 CONNMAN_IFACE_FLAG_IPV4;
226 connman_iface_set_data(iface, data);
233 static void iface_remove(struct connman_iface *iface)
235 struct iface_data *data = connman_iface_get_data(iface);
237 printf("[802.11] remove %s\n", data->ifname);
239 __supplicant_stop(iface);
241 connman_iface_set_data(iface, NULL);
243 g_free(data->network);
244 g_free(data->passphrase);
249 static int iface_scan(struct connman_iface *iface)
251 struct iface_data *data = connman_iface_get_data(iface);
253 struct iw_scan_req iws;
256 printf("[802.11] scanning %s\n", data->ifname);
258 sk = socket(PF_INET, SOCK_DGRAM, 0);
262 memset(&iws, 0, sizeof(iws));
263 iws.scan_type = IW_SCAN_TYPE_PASSIVE;
264 //iws.scan_type = IW_SCAN_TYPE_ACTIVE;
266 memset(&iwr, 0, sizeof(iwr));
267 strncpy(iwr.ifr_name, data->ifname, IFNAMSIZ);
269 iwr.u.data.pointer = (caddr_t ) &iws;
270 iwr.u.data.length = sizeof(iws);
271 iwr.u.data.flags = IW_SCAN_DEFAULT;
273 err = ioctl(sk, SIOCSIWSCAN, &iwr);
278 printf("[802.11] scan initiate error %d\n", errno);
283 static int iface_connect(struct connman_iface *iface,
284 struct connman_network *network)
286 struct iface_data *data = connman_iface_get_data(iface);
288 printf("[802.11] connect %s\n", data->ifname);
290 __supplicant_start(iface);
292 if (data->network != NULL)
293 __supplicant_connect(iface, data->network, data->passphrase);
298 static int iface_disconnect(struct connman_iface *iface)
300 struct iface_data *data = connman_iface_get_data(iface);
302 printf("[802.11] disconnect %s\n", data->ifname);
304 if (data->network != NULL)
305 __supplicant_disconnect(iface);
307 __supplicant_stop(iface);
312 static void iface_set_network(struct connman_iface *iface,
315 struct iface_data *data = connman_iface_get_data(iface);
317 printf("[802.11] set network %s\n", data->ifname);
319 if (data->network != NULL)
320 __supplicant_disconnect(iface);
322 g_free(data->network);
324 data->network = g_strdup(network);
326 if (data->network != NULL)
327 __supplicant_connect(iface, data->network, data->passphrase);
330 static void iface_set_passphrase(struct connman_iface *iface,
331 const char *passphrase)
333 struct iface_data *data = connman_iface_get_data(iface);
335 printf("[802.11] set passphrase %s\n", data->ifname);
337 if (data->network != NULL)
338 __supplicant_disconnect(iface);
340 g_free(data->passphrase);
342 data->passphrase = g_strdup(passphrase);
344 if (data->network != NULL)
345 __supplicant_connect(iface, data->network, data->passphrase);
348 static void parse_genie(struct station_data *station,
349 unsigned char *data, int len)
353 while (offset <= len - 2) {
356 switch (data[offset]) {
357 case 0xdd: /* WPA1 (and other) */
358 station->has_wpa = 1;
360 case 0x30: /* WPA2 (RSN) */
361 station->has_rsn = 1;
367 //for (i = 0; i < len; i++)
368 // printf(" %02x", data[i]);
371 offset += data[offset + 1] + 2;
375 static void parse_scan_results(struct connman_iface *iface,
376 unsigned char *data, int len)
378 unsigned char *ptr = data;
379 struct station_data *station = NULL;
380 struct ether_addr *eth;
384 while (len > IW_EV_LCP_PK_LEN) {
385 struct iw_event *event = (void *) ptr;
387 switch (event->cmd) {
389 report_station(iface, station);
390 eth = (void *) &event->u.ap_addr.sa_data;
391 sprintf(addr, "%02X:%02X:%02X:%02X:%02X:%02X",
392 eth->ether_addr_octet[0],
393 eth->ether_addr_octet[1],
394 eth->ether_addr_octet[2],
395 eth->ether_addr_octet[3],
396 eth->ether_addr_octet[4],
397 eth->ether_addr_octet[5]);
398 station = create_station(connman_iface_get_data(iface),
403 if (station != NULL) {
404 station->name = malloc(event->len - IW_EV_POINT_LEN + 1);
405 if (station->name != NULL) {
406 memset(station->name, 0,
407 event->len - IW_EV_POINT_LEN + 1);
408 memcpy(station->name, ptr + IW_EV_POINT_LEN,
409 event->len - IW_EV_POINT_LEN);
417 station->mode = event->u.mode;
422 if (station != NULL) {
423 if (!(event->u.data.flags & IW_ENCODE_DISABLED))
424 station->has_wep = 1;
430 if (station != NULL) {
431 station->qual = event->u.qual.qual;
432 station->noise = event->u.qual.noise;
433 station->level = event->u.qual.level;
438 parse_genie(station, ptr + 8, event->len - 8);
443 printf("[802.11] scan element 0x%04x (len %d)\n",
444 event->cmd, event->len);
452 report_station(iface, station);
454 printf("[802.11] found %d networks\n", num);
457 static void iface_scan_results(struct connman_iface *iface)
459 struct iface_data *data = connman_iface_get_data(iface);
463 int sk, err, done = 0;
468 memset(&iwr, 0, sizeof(iwr));
469 memcpy(iwr.ifr_name, data->ifname, IFNAMSIZ);
471 sk = socket(PF_INET, SOCK_DGRAM, 0);
481 newbuf = g_realloc(buf, size);
482 if (newbuf == NULL) {
488 iwr.u.data.pointer = buf;
489 iwr.u.data.length = size;
490 iwr.u.data.flags = 0;
492 err = ioctl(sk, SIOCGIWSCAN, &iwr);
499 parse_scan_results(iface, iwr.u.data.pointer,
509 print_stations(data);
512 static void iface_wireless(struct connman_iface *iface,
513 void *data, unsigned short len)
515 struct iw_event *event = data;
516 struct iw_point point;
517 struct ether_addr *eth;
520 switch (event->cmd) {
522 printf("[802.11] Set Frequency (flags %d)\n",
523 event->u.freq.flags);
526 printf("[802.11] Set Mode (mode %d)\n", event->u.mode);
529 memcpy(&point, data + IW_EV_LCP_LEN -
530 IW_EV_POINT_OFF, sizeof(point));
531 point.pointer = data + IW_EV_LCP_LEN +
532 sizeof(point) - IW_EV_POINT_OFF;
533 printf("[802.11] Set ESSID (length %d flags %d) \"%s\"\n",
534 point.length, point.flags,
535 (char *) point.pointer);
538 printf("[802.11] Set Encryption key (flags %d)\n",
539 event->u.data.flags);
543 eth = (void *) &event->u.ap_addr.sa_data;
544 sprintf(addr, "%02X:%02X:%02X:%02X:%02X:%02X",
545 eth->ether_addr_octet[0],
546 eth->ether_addr_octet[1],
547 eth->ether_addr_octet[2],
548 eth->ether_addr_octet[3],
549 eth->ether_addr_octet[4],
550 eth->ether_addr_octet[5]);
551 printf("[802.11] New Access Point %s\n", addr);
554 iface_scan_results(iface);
557 printf("[802.11] Wireless event (cmd 0x%04x len %d)\n",
558 event->cmd, event->len);
563 static struct connman_iface_driver iface_driver = {
565 .capability = "net.80211",
566 .probe = iface_probe,
567 .remove = iface_remove,
569 .connect = iface_connect,
570 .disconnect = iface_disconnect,
571 .set_network = iface_set_network,
572 .set_passphrase = iface_set_passphrase,
573 .rtnl_wireless = iface_wireless,
576 static int plugin_init(void)
578 connman_iface_register(&iface_driver);
583 static void plugin_exit(void)
585 connman_iface_unregister(&iface_driver);
588 CONNMAN_PLUGIN_DEFINE("80211", "IEEE 802.11 interface plugin", VERSION,
589 plugin_init, plugin_exit)