From 212bc08104bbf0c1e8bb8eae992ee3ed4dcd9982 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Tue, 12 Sep 2017 02:45:43 +0200 Subject: [PATCH] ap: Add AP mode api Very basic WPA2-PSK only access point mode API with stubs of the start and stop functions. --- Makefile.am | 3 +- src/ap.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ap.h | 37 ++++++++++++++ src/main.c | 4 ++ 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 src/ap.c create mode 100644 src/ap.h diff --git a/Makefile.am b/Makefile.am index f46a2528..9204541d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -87,7 +87,8 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h \ src/watchlist.h src/watchlist.c \ src/ftutil.h src/ftutil.c \ src/iwd.h src/eap-sim.c src/eap-aka.c \ - src/simutil.h src/simutil.c + src/simutil.h src/simutil.c \ + src/ap.h src/ap.c src_iwd_LDADD = ell/libell-internal.la -ldl dist_sysconf_DATA = src/iwd.conf diff --git a/src/ap.c b/src/ap.c new file mode 100644 index 00000000..69872719 --- /dev/null +++ b/src/ap.c @@ -0,0 +1,142 @@ +/* + * + * Wireless daemon for Linux + * + * Copyright (C) 2017 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include "src/iwd.h" +#include "src/device.h" +#include "src/wiphy.h" +#include "src/ie.h" +#include "src/ap.h" + +struct ap_state { + struct device *device; + char *ssid; + char *psk; + ap_event_cb_t event_cb; + int channel; + unsigned int ciphers; + uint32_t beacon_interval; + struct l_uintset *rates; +}; + +static struct l_genl_family *nl80211 = NULL; + +static struct l_queue *ap_list = NULL; + +static void ap_free(void *data) +{ + struct ap_state *ap = data; + + l_free(ap->ssid); + memset(ap->psk, 0, strlen(ap->psk)); + l_free(ap->psk); + + if (ap->rates) + l_uintset_free(ap->rates); + + l_free(ap); +} + +static void ap_stopped(struct ap_state *ap) +{ + ap->event_cb(ap->device, AP_EVENT_STOPPED); + + ap_free(ap); + + l_queue_remove(ap_list, ap); +} + +static bool ap_match_device(const void *a, const void *b) +{ + const struct ap_state *ap = a; + + return ap->device == b; +} + +int ap_start(struct device *device, const char *ssid, const char *psk, + ap_event_cb_t event_cb) +{ + struct wiphy *wiphy = device_get_wiphy(device); + struct ap_state *ap; + + if (l_queue_find(ap_list, ap_match_device, device)) + return -EEXIST; + + ap = l_new(struct ap_state, 1); + ap->device = device; + ap->ssid = l_strdup(ssid); + ap->psk = l_strdup(psk); + ap->event_cb = event_cb; + /* TODO: Start a Get Survey to decide the channel */ + ap->channel = 6; + /* TODO: Add all ciphers supported by wiphy */ + ap->ciphers = wiphy_select_cipher(wiphy, 0xffff); + ap->beacon_interval = 100; + /* TODO: Use actual supported rates */ + ap->rates = l_uintset_new(200); + l_uintset_put(ap->rates, 2); /* 1 Mbps*/ + l_uintset_put(ap->rates, 11); /* 5.5 Mbps*/ + l_uintset_put(ap->rates, 22); /* 11 Mbps*/ + + if (!ap_list) + ap_list = l_queue_new(); + + l_queue_push_tail(ap_list, ap); + + return 0; +} + +int ap_stop(struct device *device) +{ + struct ap_state *ap = l_queue_find(ap_list, ap_match_device, device); + + if (!ap) + return -ENODEV; + + /* TODO: Send NL80211_CMD_STOP_AP */ + ap_stopped(ap); + + return 0; +} + +void ap_init(struct l_genl_family *in) +{ + nl80211 = in; + + /* + * TODO: Check wiphy supports AP mode, supported channels, + * check wiphy's NL80211_ATTR_TX_FRAME_TYPES. + */ +} + +void ap_exit(void) +{ + l_queue_destroy(ap_list, ap_free); +} diff --git a/src/ap.h b/src/ap.h new file mode 100644 index 00000000..8c56344c --- /dev/null +++ b/src/ap.h @@ -0,0 +1,37 @@ +/* + * + * Wireless daemon for Linux + * + * Copyright (C) 2017 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +enum ap_event { + AP_EVENT_STARTED, + AP_EVENT_STOPPED, +}; + +struct device; + +typedef void (*ap_event_cb_t)(struct device *device, enum ap_event event_type); + +int ap_start(struct device *device, const char *ssid, const char *psk, + ap_event_cb_t event_cb); +int ap_stop(struct device *device); + +void ap_init(struct l_genl_family *in); +void ap_exit(void); diff --git a/src/main.c b/src/main.c index f7f22eaf..ea438cda 100644 --- a/src/main.c +++ b/src/main.c @@ -43,6 +43,7 @@ #include "src/wsc.h" #include "src/knownnetworks.h" #include "src/rfkill.h" +#include "src/ap.h" #include "src/backtrace.h" @@ -144,12 +145,15 @@ static void nl80211_appeared(void *user_data) if (!wsc_init(nl80211)) l_error("Unable to init WSC functionality"); + + ap_init(nl80211); } static void nl80211_vanished(void *user_data) { l_debug("Lost nl80211 interface"); + ap_exit(); wsc_exit(); scan_exit(); netdev_exit();