summaryrefslogtreecommitdiffstats
path: root/usr.sbin/hostapd
diff options
context:
space:
mode:
authorreyk <reyk@openbsd.org>2006-12-31 03:25:58 +0000
committerreyk <reyk@openbsd.org>2006-12-31 03:25:58 +0000
commit0190821919273df457c0d78570fa8c57bff8ef51 (patch)
treea6ce1a9e6093f68358dd324fbda5acc45058723d /usr.sbin/hostapd
parentUse the same PCI product name strings we have in pcidevs_data.h for the (diff)
downloadwireguard-openbsd-0190821919273df457c0d78570fa8c57bff8ef51.tar.xz
wireguard-openbsd-0190821919273df457c0d78570fa8c57bff8ef51.zip
add a channel hopper for wireless interfaces. the channel hopper will
jump to the next available channel after a configurable delay for the specified list of wireless "hostap" interfaces, see the new "set hostap hopper" commands in hostapd.conf(5). with help by jsg@
Diffstat (limited to 'usr.sbin/hostapd')
-rw-r--r--usr.sbin/hostapd/apme.c78
-rw-r--r--usr.sbin/hostapd/hostapd.conf.514
-rw-r--r--usr.sbin/hostapd/hostapd.h18
-rw-r--r--usr.sbin/hostapd/parse.y43
-rw-r--r--usr.sbin/hostapd/privsep.c6
5 files changed, 154 insertions, 5 deletions
diff --git a/usr.sbin/hostapd/apme.c b/usr.sbin/hostapd/apme.c
index 7fa1513644a..34d63ff7d4f 100644
--- a/usr.sbin/hostapd/apme.c
+++ b/usr.sbin/hostapd/apme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: apme.c,v 1.13 2006/06/01 22:09:09 reyk Exp $ */
+/* $OpenBSD: apme.c,v 1.14 2006/12/31 03:25:58 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
@@ -46,6 +46,7 @@
#include "iapp.h"
void hostapd_apme_frame(struct hostapd_apme *, u_int8_t *, u_int);
+void hostapd_apme_hopper(int, short, void *);
int
hostapd_apme_add(struct hostapd_config *cfg, const char *name)
@@ -60,6 +61,7 @@ hostapd_apme_add(struct hostapd_config *cfg, const char *name)
strlcpy(apme->a_iface, name, sizeof(apme->a_iface));
apme->a_cfg = cfg;
+ apme->a_chanavail = NULL;
TAILQ_INSERT_TAIL(&cfg->c_apmes, apme, a_entries);
@@ -115,11 +117,85 @@ hostapd_apme_lookup(struct hostapd_config *cfg, const char *name)
return (NULL);
}
+struct hostapd_apme *
+hostapd_apme_addhopper(struct hostapd_config *cfg, const char *name)
+{
+ struct hostapd_apme *apme;
+
+ if ((apme = hostapd_apme_lookup(cfg, name)) == NULL)
+ return (NULL);
+ if (apme->a_chanavail != NULL)
+ return (NULL);
+ apme->a_curchan = IEEE80211_CHAN_MAX;
+ apme->a_maxchan = roundup(IEEE80211_CHAN_MAX, NBBY);
+ if ((apme->a_chanavail = (u_int8_t *)
+ calloc(apme->a_maxchan, sizeof(u_int8_t))) == NULL)
+ return (NULL);
+ memset(apme->a_chanavail, 0xff,
+ apme->a_maxchan * sizeof(u_int8_t));
+ strlcpy(apme->a_chanreq.i_name, apme->a_iface, IFNAMSIZ);
+
+ return (apme);
+}
+
+void
+hostapd_apme_sethopper(struct hostapd_apme *apme, int now)
+{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
+ struct timeval tv;
+
+ bzero(&tv, sizeof(tv));
+ if (!now)
+ bcopy(&cfg->c_apme_hopdelay, &tv, sizeof(tv));
+
+ if (!evtimer_initialized(&apme->a_chanev))
+ evtimer_set(&apme->a_chanev, hostapd_apme_hopper, apme);
+ evtimer_add(&apme->a_chanev, &tv);
+}
+
+void
+hostapd_apme_hopper(int fd, short sig, void *arg)
+{
+ struct hostapd_apme *apme = (struct hostapd_apme *)arg;
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
+ int ret;
+
+ if (apme->a_curchan >= IEEE80211_CHAN_MAX)
+ apme->a_curchan = 0;
+
+ do {
+ if (apme->a_curchan >= IEEE80211_CHAN_MAX)
+ return;
+ apme->a_curchan %= IEEE80211_CHAN_MAX;
+ apme->a_curchan++;
+ } while (isclr(apme->a_chanavail, apme->a_curchan));
+
+ apme->a_chanreq.i_channel = apme->a_curchan;
+ if ((ret = ioctl(cfg->c_apme_ctl, SIOCS80211CHANNEL,
+ &apme->a_chanreq)) != 0) {
+ hostapd_apme_sethopper(apme, 1);
+ return;
+ }
+
+ hostapd_log(HOSTAPD_LOG_DEBUG,
+ "[priv]: %s setting to channel %d",
+ apme->a_iface, apme->a_curchan);
+
+ hostapd_apme_sethopper(apme, 0);
+}
+
void
hostapd_apme_term(struct hostapd_apme *apme)
{
struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
+ /* Remove the channel hopper, if active */
+ if (apme->a_chanavail != NULL) {
+ event_del(&apme->a_chanev);
+ free(apme->a_chanavail);
+ apme->a_chanavail = NULL;
+ }
+
/* Kick a specified Host AP interface */
event_del(&apme->a_ev);
close(apme->a_raw);
diff --git a/usr.sbin/hostapd/hostapd.conf.5 b/usr.sbin/hostapd/hostapd.conf.5
index ba16596b637..5b9606289f5 100644
--- a/usr.sbin/hostapd/hostapd.conf.5
+++ b/usr.sbin/hostapd/hostapd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: hostapd.conf.5,v 1.34 2006/08/31 18:44:48 jmc Exp $
+.\" $OpenBSD: hostapd.conf.5,v 1.35 2006/12/31 03:25:58 reyk Exp $
.\"
.\" Copyright (c) 2004, 2005, 2006 Reyk Floeter <reyk@openbsd.org>
.\"
@@ -140,6 +140,18 @@ signal levels.
.It Ic pcap
Capture plain IEEE 802.11 frames.
.El
+.It Xo
+.Ic set hostap hopper interface
+.Ar interface \*(Ba\ \&
+.Pf { Ar interface0 , interface1 , ... No }
+.Xc
+Enable a channel hopper on the selected wireless interface.
+Multiple hostap interfaces may be specified as a comma-separated list,
+surrounded by curly braces.
+.It Ic set hostap hopper delay Ar number
+Set the delay in milliseconds for the channel hopper before hopping to
+the next available channel.
+The default value is 800 milliseconds.
.It Ic set iapp interface Ar interface
Specify the mandatory Inter-Access-Point (IAPP) interface.
It is important that the IAPP interface is on a trusted
diff --git a/usr.sbin/hostapd/hostapd.h b/usr.sbin/hostapd/hostapd.h
index 3048c3a9d18..3bf4a9e1761 100644
--- a/usr.sbin/hostapd/hostapd.h
+++ b/usr.sbin/hostapd/hostapd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostapd.h,v 1.19 2006/09/28 17:43:42 reyk Exp $ */
+/* $OpenBSD: hostapd.h,v 1.20 2006/12/31 03:25:58 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
@@ -279,9 +279,21 @@ struct hostapd_apme {
void *a_cfg;
struct sockaddr_in a_addr;
+ struct event a_chanev;
+ u_int8_t *a_chanavail;
+ u_int8_t a_curchan;
+ u_int a_maxchan;
+ struct ieee80211chanreq a_chanreq;
+
TAILQ_ENTRY(hostapd_apme) a_entries;
};
+#ifndef IEEE80211_CHAN_MAX
+#define IEEE80211_CHAN_MAX 255
+#endif
+
+#define HOSTAPD_HOPPER_MDELAY 800
+
struct hostapd_iapp {
u_int16_t i_cnt;
int i_raw;
@@ -313,6 +325,7 @@ struct hostapd_iapp {
struct hostapd_config {
int c_apme_ctl;
u_int c_apme_dlt;
+ struct timeval c_apme_hopdelay;
struct hostapd_iapp c_iapp;
@@ -413,6 +426,9 @@ int hostapd_apme_delnode(struct hostapd_apme *,
struct hostapd_node *node);
int hostapd_apme_offset(struct hostapd_apme *, u_int8_t *,
const u_int);
+struct hostapd_apme *hostapd_apme_addhopper(struct hostapd_config *,
+ const char *);
+void hostapd_apme_sethopper(struct hostapd_apme *, int);
void hostapd_iapp_init(struct hostapd_config *);
void hostapd_iapp_term(struct hostapd_config *);
diff --git a/usr.sbin/hostapd/parse.y b/usr.sbin/hostapd/parse.y
index d6b66d5768b..dd14209fa2d 100644
--- a/usr.sbin/hostapd/parse.y
+++ b/usr.sbin/hostapd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.26 2006/10/13 15:36:57 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.27 2006/12/31 03:25:58 reyk Exp $ */
/*
* Copyright (c) 2004, 2005, 2006 Reyk Floeter <reyk@openbsd.org>
@@ -105,10 +105,12 @@ typedef struct {
long val;
u_int16_t reason;
enum hostapd_op op;
+ struct timeval timeout;
} v;
int lineno;
} YYSTYPE;
+struct hostapd_apme *apme;
struct hostapd_table *table;
struct hostapd_entry *entry;
struct hostapd_frame frame, *frame_ptr;
@@ -149,6 +151,7 @@ struct hostapd_ieee80211_frame *frame_ieee80211;
%token REASON UNSPECIFIED EXPIRE LEAVE ASSOC TOOMANY NOT AUTHED ASSOCED
%token RESERVED RSN REQUIRED INCONSISTENT IE INVALID MIC FAILURE OPEN
%token ADDRESS PORT ON NOTIFY TTL INCLUDE ROUTE ROAMING RSSI TXRATE FREQ
+%token HOPPER DELAY
%token <v.string> STRING
%token <v.val> VALUE
%type <v.val> number
@@ -163,6 +166,7 @@ struct hostapd_ieee80211_frame *frame_ieee80211;
%type <v.val> txrate
%type <v.val> freq
%type <v.val> not
+%type <v.timeout> timeout
%%
@@ -201,6 +205,12 @@ option : SET HOSTAP INTERFACE hostapifaces
if (!TAILQ_EMPTY(&hostapd_cfg.c_apmes))
hostapd_cfg.c_flags |= HOSTAPD_CFG_F_APME;
}
+ | SET HOSTAP HOPPER INTERFACE hopperifaces
+ | SET HOSTAP HOPPER DELAY timeout
+ {
+ bcopy(&$5, &hostapd_cfg.c_apme_hopdelay,
+ sizeof(struct timeval));
+ }
| SET HOSTAP MODE hostapmode
| SET IAPP INTERFACE STRING passive
{
@@ -298,6 +308,26 @@ hostapiface : STRING
}
;
+hopperifaces : '{' optnl hopperifacelist optnl '}'
+ | hopperiface
+ ;
+
+hopperifacelist : hopperiface
+ | hopperifacelist comma hopperiface
+ ;
+
+hopperiface : STRING
+ {
+ if ((apme = hostapd_apme_addhopper(&hostapd_cfg,
+ $1)) == NULL) {
+ yyerror("failed to add hopper %s", $1);
+ free($1);
+ YYERROR;
+ }
+ free($1);
+ }
+ ;
+
hostapmatch : /* empty */
| ON not STRING
{
@@ -1151,6 +1181,13 @@ freq : STRING
free($1);
}
;
+
+timeout : number
+ {
+ $$.tv_sec = $1 / 1000;
+ $$.tv_usec = ($1 % 1000) * 1000;
+ }
+ ;
%%
/*
@@ -1187,6 +1224,7 @@ lookup(char *token)
{ "const", CONST },
{ "data", DATA },
{ "deauth", DEAUTH },
+ { "delay", DELAY },
{ "delete", DELETE },
{ "dir", DIR },
{ "disassoc", DISASSOC },
@@ -1197,6 +1235,7 @@ lookup(char *token)
{ "freq", FREQ },
{ "from", FROM },
{ "handle", HANDLE },
+ { "hopper", HOPPER },
{ "hostap", HOSTAP },
{ "iapp", IAPP },
{ "ie", IE },
@@ -1589,6 +1628,8 @@ hostapd_parse_file(struct hostapd_config *cfg)
cfg->c_iapp.i_multicast.sin_addr.s_addr = INADDR_ANY;
cfg->c_iapp.i_flags = HOSTAPD_IAPP_F_DEFAULT;
cfg->c_iapp.i_ttl = IP_DEFAULT_MULTICAST_TTL;
+ cfg->c_apme_hopdelay.tv_sec = HOSTAPD_HOPPER_MDELAY / 1000;
+ cfg->c_apme_hopdelay.tv_usec = (HOSTAPD_HOPPER_MDELAY % 1000) * 1000;
errors = 0;
diff --git a/usr.sbin/hostapd/privsep.c b/usr.sbin/hostapd/privsep.c
index 0cd46f9a056..a25129995b7 100644
--- a/usr.sbin/hostapd/privsep.c
+++ b/usr.sbin/hostapd/privsep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: privsep.c,v 1.20 2006/06/01 22:09:09 reyk Exp $ */
+/* $OpenBSD: privsep.c,v 1.21 2006/12/31 03:25:58 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
@@ -81,6 +81,7 @@ void
hostapd_priv_init(struct hostapd_config *cfg)
{
struct hostapd_iapp *iapp = &cfg->c_iapp;
+ struct hostapd_apme *apme;
int i, socks[2];
struct passwd *pw;
struct servent *se;
@@ -152,6 +153,9 @@ hostapd_priv_init(struct hostapd_config *cfg)
if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
if ((cfg->c_apme_ctl = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
hostapd_fatal("unable to open ioctl socket\n");
+ TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries)
+ if (apme->a_chanavail != NULL)
+ hostapd_apme_sethopper(apme, 0);
}
hostapd_roaming_init(cfg);