aboutsummaryrefslogtreecommitdiffstats
path: root/hostapd
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-01-07 01:11:24 (GMT)
committerJouni Malinen <j@w1.fi>2008-01-07 01:11:24 (GMT)
commit7b23a70660fd4b5f5bb6ee0867443e157c2b1f35 (patch)
treeeb79f87636f6f1d84e76f06c7ae669a882943ed7 /hostapd
parentdfeb3e0a061586d283aec0a8dc34ec830b864986 (diff)
downloadhostap-history-7b23a70660fd4b5f5bb6ee0867443e157c2b1f35.zip
hostap-history-7b23a70660fd4b5f5bb6ee0867443e157c2b1f35.tar.gz
hostap-history-7b23a70660fd4b5f5bb6ee0867443e157c2b1f35.tar.bz2
WPS: Generate WPS IE for Beacon and Probe Response frames
WPS Registrar code is now generating WPS IEs for Beacon and Probe Response frames. These are passed through a wps_hostapd.c callback to the driver interface (set_wps_{beacon,probe_resp}_ie or set_beacon) and to the hostapd MLME code beacon.c for Probe Request processing.
Diffstat (limited to 'hostapd')
-rw-r--r--hostapd/beacon.c21
-rw-r--r--hostapd/driver.h25
-rw-r--r--hostapd/driver_test.c120
-rw-r--r--hostapd/hostapd.c4
-rw-r--r--hostapd/hostapd.h7
-rw-r--r--hostapd/wps_hostapd.c64
6 files changed, 216 insertions, 25 deletions
diff --git a/hostapd/beacon.c b/hostapd/beacon.c
index b84b51a..9348f23 100644
--- a/hostapd/beacon.c
+++ b/hostapd/beacon.c
@@ -2,6 +2,7 @@
* hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
* Copyright (c) 2002-2004, Instant802 Networks, Inc.
* Copyright (c) 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -236,7 +237,7 @@ void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */
-#define MAX_PROBERESP_LEN 512
+#define MAX_PROBERESP_LEN 768
resp = os_zalloc(MAX_PROBERESP_LEN);
if (resp == NULL)
return;
@@ -284,6 +285,14 @@ void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
if (hapd->conf->wme_enabled)
pos = hostapd_eid_wme(hapd, pos);
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
+ os_memcpy(pos, hapd->wps_probe_resp_ie,
+ hapd->wps_probe_resp_ie_len);
+ pos += hapd->wps_probe_resp_ie_len;
+ }
+#endif /* CONFIG_WPS */
+
if (hostapd_send_mgmt_frame(hapd, resp, pos - (u8 *) resp, 0) < 0)
perror("handle_probe_req: send");
@@ -306,7 +315,7 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
ERP_INFO_USE_PROTECTION) ? 1 : 0);
#define BEACON_HEAD_BUF_SIZE 256
-#define BEACON_TAIL_BUF_SIZE 256
+#define BEACON_TAIL_BUF_SIZE 512
head = os_zalloc(BEACON_HEAD_BUF_SIZE);
tailpos = tail = os_malloc(BEACON_TAIL_BUF_SIZE);
if (head == NULL || tail == NULL) {
@@ -375,6 +384,14 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
if (hapd->conf->wme_enabled)
tailpos = hostapd_eid_wme(hapd, tailpos);
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
+ os_memcpy(tailpos, hapd->wps_beacon_ie,
+ hapd->wps_beacon_ie_len);
+ tailpos += hapd->wps_beacon_ie_len;
+ }
+#endif /* CONFIG_WPS */
+
tail_len = tailpos > tail ? tailpos - tail : 0;
if (hostapd_set_beacon(hapd->conf->iface, hapd, (u8 *) head, head_len,
diff --git a/hostapd/driver.h b/hostapd/driver.h
index ffa28ac..55ebd15 100644
--- a/hostapd/driver.h
+++ b/hostapd/driver.h
@@ -159,6 +159,11 @@ struct wpa_driver_ops {
int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto,
const u8 *data, size_t data_len);
+
+ int (*set_wps_beacon_ie)(const char *ifname, void *priv,
+ const u8 *ie, size_t len);
+ int (*set_wps_probe_resp_ie)(const char *ifname, void *priv,
+ const u8 *ie, size_t len);
};
static inline void *
@@ -678,4 +683,24 @@ hostapd_driver_commit(struct hostapd_data *hapd)
return hapd->driver->commit(hapd->drv_priv);
}
+static inline int
+hostapd_set_wps_beacon_ie(struct hostapd_data *hapd, const u8 *ie, size_t len)
+{
+ if (hapd->driver == NULL || hapd->driver->set_wps_beacon_ie == NULL)
+ return 0;
+ return hapd->driver->set_wps_beacon_ie(hapd->conf->iface,
+ hapd->drv_priv, ie, len);
+}
+
+static inline int
+hostapd_set_wps_probe_resp_ie(struct hostapd_data *hapd, const u8 *ie,
+ size_t len)
+{
+ if (hapd->driver == NULL ||
+ hapd->driver->set_wps_probe_resp_ie == NULL)
+ return 0;
+ return hapd->driver->set_wps_probe_resp_ie(hapd->conf->iface,
+ hapd->drv_priv, ie, len);
+}
+
#endif /* DRIVER_H */
diff --git a/hostapd/driver_test.c b/hostapd/driver_test.c
index dfa7741..41f87b3 100644
--- a/hostapd/driver_test.c
+++ b/hostapd/driver_test.c
@@ -1,6 +1,6 @@
/*
* hostapd / Driver interface for development testing
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -44,6 +44,10 @@ struct test_driver_bss {
u8 bssid[ETH_ALEN];
u8 *ie;
size_t ielen;
+ u8 *wps_beacon_ie;
+ size_t wps_beacon_ie_len;
+ u8 *wps_probe_resp_ie;
+ size_t wps_probe_resp_ie_len;
u8 ssid[32];
size_t ssid_len;
int privacy;
@@ -62,6 +66,8 @@ struct test_driver_data {
static void test_driver_free_bss(struct test_driver_bss *bss)
{
free(bss->ie);
+ free(bss->wps_beacon_ie);
+ free(bss->wps_probe_resp_ie);
free(bss);
}
@@ -346,6 +352,8 @@ static void test_driver_scan(struct test_driver_data *drv,
return;
pos += ret;
pos += wpa_snprintf_hex(pos, end - pos, bss->ie, bss->ielen);
+ pos += wpa_snprintf_hex(pos, end - pos, bss->wps_probe_resp_ie,
+ bss->wps_probe_resp_ie_len);
if (bss->privacy) {
ret = snprintf(pos, end - pos, " PRIVACY");
@@ -675,36 +683,106 @@ static void test_driver_receive_unix(int sock, void *eloop_ctx, void *sock_ctx)
}
+static struct test_driver_bss *
+test_driver_get_bss(struct test_driver_data *drv, const char *ifname)
+{
+ struct test_driver_bss *bss;
+
+ for (bss = drv->bss; bss; bss = bss->next) {
+ if (strcmp(bss->ifname, ifname) == 0)
+ return bss;
+ }
+ return NULL;
+}
+
+
static int test_driver_set_generic_elem(const char *ifname, void *priv,
const u8 *elem, size_t elem_len)
{
struct test_driver_data *drv = priv;
struct test_driver_bss *bss;
- for (bss = drv->bss; bss; bss = bss->next) {
- if (strcmp(bss->ifname, ifname) != 0)
- continue;
+ bss = test_driver_get_bss(drv, ifname);
+ if (bss == NULL)
+ return -1;
- free(bss->ie);
+ free(bss->ie);
- if (elem == NULL) {
- bss->ie = NULL;
- bss->ielen = 0;
- return 0;
- }
+ if (elem == NULL) {
+ bss->ie = NULL;
+ bss->ielen = 0;
+ return 0;
+ }
- bss->ie = malloc(elem_len);
- if (bss->ie) {
- memcpy(bss->ie, elem, elem_len);
- bss->ielen = elem_len;
- return 0;
- } else {
- bss->ielen = 0;
- return -1;
- }
+ bss->ie = malloc(elem_len);
+ if (bss->ie == NULL) {
+ bss->ielen = 0;
+ return -1;
}
- return -1;
+ memcpy(bss->ie, elem, elem_len);
+ bss->ielen = elem_len;
+ return 0;
+}
+
+
+static int test_driver_set_wps_beacon_ie(const char *ifname, void *priv,
+ const u8 *ie, size_t len)
+{
+ struct test_driver_data *drv = priv;
+ struct test_driver_bss *bss;
+
+ bss = test_driver_get_bss(drv, ifname);
+ if (bss == NULL)
+ return -1;
+
+ free(bss->wps_beacon_ie);
+
+ if (ie == NULL) {
+ bss->wps_beacon_ie = NULL;
+ bss->wps_beacon_ie_len = 0;
+ return 0;
+ }
+
+ bss->wps_beacon_ie = malloc(len);
+ if (bss->wps_beacon_ie == NULL) {
+ bss->wps_beacon_ie_len = 0;
+ return -1;
+ }
+
+ memcpy(bss->wps_beacon_ie, ie, len);
+ bss->wps_beacon_ie_len = len;
+ return 0;
+}
+
+
+static int test_driver_set_wps_probe_resp_ie(const char *ifname, void *priv,
+ const u8 *ie, size_t len)
+{
+ struct test_driver_data *drv = priv;
+ struct test_driver_bss *bss;
+
+ bss = test_driver_get_bss(drv, ifname);
+ if (bss == NULL)
+ return -1;
+
+ free(bss->wps_probe_resp_ie);
+
+ if (ie == NULL) {
+ bss->wps_probe_resp_ie = NULL;
+ bss->wps_probe_resp_ie_len = 0;
+ return 0;
+ }
+
+ bss->wps_probe_resp_ie = malloc(len);
+ if (bss->wps_probe_resp_ie == NULL) {
+ bss->wps_probe_resp_ie_len = 0;
+ return -1;
+ }
+
+ memcpy(bss->wps_probe_resp_ie, ie, len);
+ bss->wps_probe_resp_ie_len = len;
+ return 0;
}
@@ -1154,4 +1232,6 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
.set_sta_vlan = test_driver_set_sta_vlan,
.sta_add = test_driver_sta_add,
.send_ether = test_driver_send_ether,
+ .set_wps_beacon_ie = test_driver_set_wps_beacon_ie,
+ .set_wps_probe_resp_ie = test_driver_set_wps_probe_resp_ie,
};
diff --git a/hostapd/hostapd.c b/hostapd/hostapd.c
index 2defbad..a8d5487 100644
--- a/hostapd/hostapd.c
+++ b/hostapd/hostapd.c
@@ -1296,8 +1296,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
return -1;
}
- ieee802_11_set_beacon(hapd);
-
if (vlan_init(hapd)) {
printf("VLAN initialization failed.\n");
return -1;
@@ -1316,6 +1314,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
if (hostapd_init_wps(hapd, conf))
return -1;
+ ieee802_11_set_beacon(hapd);
+
if (conf->radius_server_clients &&
hostapd_setup_radius_srv(hapd, conf))
return -1;
diff --git a/hostapd/hostapd.h b/hostapd/hostapd.h
index 59dab85..a203177 100644
--- a/hostapd/hostapd.h
+++ b/hostapd/hostapd.h
@@ -169,6 +169,13 @@ struct hostapd_data {
struct l2_packet_data *l2;
struct wps_registrar *wps_registrar;
+
+#ifdef CONFIG_WPS
+ u8 *wps_beacon_ie;
+ size_t wps_beacon_ie_len;
+ u8 *wps_probe_resp_ie;
+ size_t wps_probe_resp_ie_len;
+#endif /* CONFIG_WPS */
};
diff --git a/hostapd/wps_hostapd.c b/hostapd/wps_hostapd.c
index 9c64ffa..3e0ee88 100644
--- a/hostapd/wps_hostapd.c
+++ b/hostapd/wps_hostapd.c
@@ -15,6 +15,7 @@
#include "includes.h"
#include "hostapd.h"
+#include "driver.h"
#include "uuid.h"
#include "wps/wps.h"
#include "wps/wps_defs.h"
@@ -67,13 +68,72 @@ static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
}
+static int hostapd_wps_set_ie_cb(void *ctx, const u8 *beacon_ie,
+ size_t beacon_ie_len, const u8 *probe_resp_ie,
+ size_t probe_resp_ie_len)
+{
+ struct hostapd_data *hapd = ctx;
+
+ os_free(hapd->wps_beacon_ie);
+ if (beacon_ie_len == 0) {
+ hapd->wps_beacon_ie = NULL;
+ hapd->wps_beacon_ie_len = 0;
+ } else {
+ hapd->wps_beacon_ie = os_malloc(beacon_ie_len);
+ if (hapd->wps_beacon_ie == NULL) {
+ hapd->wps_beacon_ie_len = 0;
+ return -1;
+ }
+ os_memcpy(hapd->wps_beacon_ie, beacon_ie, beacon_ie_len);
+ hapd->wps_beacon_ie_len = beacon_ie_len;
+ }
+ hostapd_set_wps_beacon_ie(hapd, hapd->wps_beacon_ie,
+ hapd->wps_beacon_ie_len);
+
+ os_free(hapd->wps_probe_resp_ie);
+ if (probe_resp_ie_len == 0) {
+ hapd->wps_probe_resp_ie = NULL;
+ hapd->wps_probe_resp_ie_len = 0;
+ } else {
+ hapd->wps_probe_resp_ie = os_malloc(probe_resp_ie_len);
+ if (hapd->wps_probe_resp_ie == NULL) {
+ hapd->wps_probe_resp_ie_len = 0;
+ return -1;
+ }
+ os_memcpy(hapd->wps_probe_resp_ie, probe_resp_ie,
+ probe_resp_ie_len);
+ hapd->wps_probe_resp_ie_len = probe_resp_ie_len;
+ }
+ hostapd_set_wps_probe_resp_ie(hapd, hapd->wps_probe_resp_ie,
+ hapd->wps_probe_resp_ie_len);
+
+ return 0;
+}
+
+
+static void hostapd_wps_clear_ies(struct hostapd_data *hapd)
+{
+ os_free(hapd->wps_beacon_ie);
+ hapd->wps_beacon_ie = NULL;
+ hapd->wps_beacon_ie_len = 0;
+ hostapd_set_wps_beacon_ie(hapd, NULL, 0);
+
+ os_free(hapd->wps_probe_resp_ie);
+ hapd->wps_probe_resp_ie = NULL;
+ hapd->wps_probe_resp_ie_len = 0;
+ hostapd_set_wps_probe_resp_ie(hapd, NULL, 0);
+}
+
+
int hostapd_init_wps(struct hostapd_data *hapd,
struct hostapd_bss_config *conf)
{
struct wps_registrar_config cfg;
- if (conf->wps_state == 0)
+ if (conf->wps_state == 0) {
+ hostapd_wps_clear_ies(hapd);
return 0;
+ }
os_memset(&cfg, 0, sizeof(cfg));
cfg.wps_state = hapd->conf->wps_state;
@@ -133,6 +193,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
}
cfg.new_psk_cb = hostapd_wps_new_psk_cb;
+ cfg.set_ie_cb = hostapd_wps_set_ie_cb;
cfg.cb_ctx = hapd;
hapd->wps_registrar = wps_registrar_init(&cfg);
@@ -148,6 +209,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
void hostapd_deinit_wps(struct hostapd_data *hapd)
{
wps_registrar_deinit(hapd->wps_registrar);
+ hostapd_wps_clear_ies(hapd);
}