diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2006-12-31 03:25:59 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2006-12-31 03:25:59 +0000 |
commit | 295cbfa8ffebb5d97209ef81c3ac5ea24f0f71ab (patch) | |
tree | 44a0adca183edf5de72f1fcc20e7801a71cfc6d5 /usr.sbin | |
parent | 64dfe7a539fee7a4ca51ad6b1f4eecbbc1653970 (diff) |
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')
-rw-r--r-- | usr.sbin/hostapd/apme.c | 78 | ||||
-rw-r--r-- | usr.sbin/hostapd/hostapd.conf.5 | 14 | ||||
-rw-r--r-- | usr.sbin/hostapd/hostapd.h | 18 | ||||
-rw-r--r-- | usr.sbin/hostapd/parse.y | 43 | ||||
-rw-r--r-- | usr.sbin/hostapd/privsep.c | 6 |
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); |