summaryrefslogtreecommitdiff
path: root/usr.sbin/hostapd
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2005-11-20 12:02:05 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2005-11-20 12:02:05 +0000
commitb05043e12f26aea5fa605717b96f4ea768117995 (patch)
tree7703d31a9eb631ef49865c68a758bc2cca3ee219 /usr.sbin/hostapd
parent62e602307426f4c305a35efbfc3241794b36ffd6 (diff)
add support for multiple hostap (wireless) interfaces.
for example, if you run one hostapd with two ath(4) devices. you have to specify "set hostap interface { ath0, ath1 }" in hostapd.conf(5). man page bits by jmc@, tested by others
Diffstat (limited to 'usr.sbin/hostapd')
-rw-r--r--usr.sbin/hostapd/apme.c133
-rw-r--r--usr.sbin/hostapd/handle.c40
-rw-r--r--usr.sbin/hostapd/hostapd.c56
-rw-r--r--usr.sbin/hostapd/hostapd.conf.511
-rw-r--r--usr.sbin/hostapd/hostapd.h48
-rw-r--r--usr.sbin/hostapd/iapp.c50
-rw-r--r--usr.sbin/hostapd/parse.y39
-rw-r--r--usr.sbin/hostapd/privsep.c85
8 files changed, 300 insertions, 162 deletions
diff --git a/usr.sbin/hostapd/apme.c b/usr.sbin/hostapd/apme.c
index 153a99ccf51..6124f62b8e8 100644
--- a/usr.sbin/hostapd/apme.c
+++ b/usr.sbin/hostapd/apme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: apme.c,v 1.5 2005/10/07 22:32:52 reyk Exp $ */
+/* $OpenBSD: apme.c,v 1.6 2005/11/20 12:02:04 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -45,12 +45,63 @@
#include "hostapd.h"
#include "iapp.h"
-void hostapd_apme_frame(struct hostapd_config *, u_int8_t *, u_int);
+void hostapd_apme_frame(struct hostapd_apme *, u_int8_t *, u_int);
+
+int
+hostapd_apme_add(struct hostapd_config *cfg, const char *name)
+{
+ struct hostapd_apme *apme;
+
+ if (hostapd_apme_lookup(cfg, name) != NULL)
+ return (EEXIST);
+ if ((apme = (struct hostapd_apme *)
+ calloc(1, sizeof(struct hostapd_apme))) == NULL)
+ return (ENOMEM);
+
+ strlcpy(apme->a_iface, name, sizeof(apme->a_iface));
+ apme->a_cfg = cfg;
+
+ TAILQ_INSERT_TAIL(&cfg->c_apmes, apme, a_entries);
+
+ hostapd_log(HOSTAPD_LOG_DEBUG,
+ "%s: Host AP interface added\n", apme->a_iface);
+
+ return (0);
+}
+
+struct hostapd_apme *
+hostapd_apme_lookup(struct hostapd_config *cfg, const char *name)
+{
+ struct hostapd_apme *apme;
+
+ TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
+ if (strcmp(name, apme->a_iface) == 0)
+ return (apme);
+ }
+
+ return (NULL);
+}
+
+void
+hostapd_apme_term(struct hostapd_apme *apme)
+{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
+
+ hostapd_log(HOSTAPD_LOG_DEBUG,
+ "%s: Host AP interface removed\n", apme->a_iface);
+
+ /* Kick a specified Host AP interface */
+ event_del(&apme->a_ev);
+ close(apme->a_raw);
+
+ TAILQ_REMOVE(&cfg->c_apmes, apme, a_entries);
+ free(apme);
+}
void
hostapd_apme_input(int fd, short sig, void *arg)
{
- struct hostapd_config *cfg = (struct hostapd_config *)arg;
+ struct hostapd_apme *apme = (struct hostapd_apme *)arg;
u_int8_t buf[IAPP_MAXSIZE], *bp, *ep;
struct bpf_hdr *bph;
ssize_t len;
@@ -79,14 +130,14 @@ hostapd_apme_input(int fd, short sig, void *arg)
hdrlen = bph->bh_hdrlen;
/* Process frame */
- hostapd_apme_frame(cfg, bp + hdrlen, caplen);
+ hostapd_apme_frame(apme, bp + hdrlen, caplen);
bp += BPF_WORDALIGN(caplen + hdrlen);
}
}
int
-hostapd_apme_output(struct hostapd_config *cfg,
+hostapd_apme_output(struct hostapd_apme *apme,
struct hostapd_ieee80211_frame *frame)
{
struct iovec iov[2];
@@ -131,16 +182,17 @@ hostapd_apme_output(struct hostapd_config *cfg,
iov[1].iov_len = frame->i_data_len;
}
- if (writev(cfg->c_apme_raw, iov, iovcnt) == -1)
+ if (writev(apme->a_raw, iov, iovcnt) == -1)
return (errno);
return (0);
}
int
-hostapd_apme_offset(struct hostapd_config *cfg,
+hostapd_apme_offset(struct hostapd_apme *apme,
u_int8_t *buf, const u_int len)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
struct ieee80211_radiotap_header *rh;
u_int rh_len;
@@ -164,13 +216,15 @@ hostapd_apme_offset(struct hostapd_config *cfg,
}
void
-hostapd_apme_frame(struct hostapd_config *cfg, u_int8_t *buf, u_int len)
+hostapd_apme_frame(struct hostapd_apme *apme, u_int8_t *buf, u_int len)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
+ struct hostapd_apme *other_apme;
struct hostapd_node node;
struct ieee80211_frame *wh;
int offset;
- if ((offset = hostapd_apme_offset(cfg, buf, len)) < 0)
+ if ((offset = hostapd_apme_offset(apme, buf, len)) < 0)
return;
wh = (struct ieee80211_frame *)(buf + offset);
@@ -179,7 +233,7 @@ hostapd_apme_frame(struct hostapd_config *cfg, u_int8_t *buf, u_int len)
return;
/* Handle received frames */
- if ((hostapd_handle_input(cfg, buf, len) ==
+ if ((hostapd_handle_input(apme, buf, len) ==
(HOSTAPD_FRAME_F_RET_SKIP >> HOSTAPD_FRAME_F_RET_S)) ||
cfg->c_flags & HOSTAPD_CFG_F_IAPP_PASSIVE)
return;
@@ -198,8 +252,8 @@ hostapd_apme_frame(struct hostapd_config *cfg, u_int8_t *buf, u_int len)
/*
* ...sent by the Host AP (addr2) to our BSSID (addr3)
*/
- if (bcmp(wh->i_addr2, cfg->c_apme_bssid, IEEE80211_ADDR_LEN) != 0 ||
- bcmp(wh->i_addr3, cfg->c_apme_bssid, IEEE80211_ADDR_LEN) != 0)
+ if (bcmp(wh->i_addr2, apme->a_bssid, IEEE80211_ADDR_LEN) != 0 ||
+ bcmp(wh->i_addr3, apme->a_bssid, IEEE80211_ADDR_LEN) != 0)
return;
cfg->c_stats.cn_rx_apme++;
@@ -208,66 +262,77 @@ hostapd_apme_frame(struct hostapd_config *cfg, u_int8_t *buf, u_int len)
* Double-check if the station got associated to our Host AP
*/
bcopy(wh->i_addr1, node.ni_macaddr, IEEE80211_ADDR_LEN);
- if (hostapd_priv_apme_getnode(cfg, &node) != 0) {
+ if (hostapd_priv_apme_getnode(apme, &node) != 0) {
hostapd_log(HOSTAPD_LOG_DEBUG,
"%s: invalid association from %s on the Host AP\n",
- cfg->c_apme_iface, etheraddr_string(wh->i_addr1));
+ apme->a_iface, etheraddr_string(wh->i_addr1));
return;
}
cfg->c_stats.cn_tx_apme++;
- hostapd_iapp_add_notify(cfg, &node);
+ /*
+ * Delete node on other attached Host APs
+ */
+ TAILQ_FOREACH(other_apme, &cfg->c_apmes, a_entries) {
+ if (apme == other_apme)
+ continue;
+ if (hostapd_apme_delnode(other_apme, &node) == 0)
+ cfg->c_stats.cn_tx_apme++;
+ }
+
+ hostapd_iapp_add_notify(apme, &node);
}
void
-hostapd_apme_init(struct hostapd_config *cfg)
+hostapd_apme_init(struct hostapd_apme *apme)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
u_int i, dlt;
struct ifreq ifr;
- cfg->c_apme_raw = hostapd_bpf_open(O_RDWR);
+ apme->a_raw = hostapd_bpf_open(O_RDWR);
- cfg->c_apme_rawlen = IAPP_MAXSIZE;
- if (ioctl(cfg->c_apme_raw, BIOCSBLEN, &cfg->c_apme_rawlen) == -1)
+ apme->a_rawlen = IAPP_MAXSIZE;
+ if (ioctl(apme->a_raw, BIOCSBLEN, &apme->a_rawlen) == -1)
hostapd_fatal("failed to set BPF buffer len \"%s\": %s\n",
- cfg->c_apme_iface, strerror(errno));
+ apme->a_iface, strerror(errno));
i = 1;
- if (ioctl(cfg->c_apme_raw, BIOCIMMEDIATE, &i) == -1)
+ if (ioctl(apme->a_raw, BIOCIMMEDIATE, &i) == -1)
hostapd_fatal("failed to set BPF immediate mode on \"%s\": "
- "%s\n", cfg->c_apme_iface, strerror(errno));
+ "%s\n", apme->a_iface, strerror(errno));
bzero(&ifr, sizeof(struct ifreq));
- strlcpy(ifr.ifr_name, cfg->c_apme_iface, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, apme->a_iface, sizeof(ifr.ifr_name));
/* This may fail, ignore it */
- ioctl(cfg->c_apme_raw, BIOCPROMISC, NULL);
+ ioctl(apme->a_raw, BIOCPROMISC, NULL);
/* Associate the wireless network interface to the BPF descriptor */
- if (ioctl(cfg->c_apme_raw, BIOCSETIF, &ifr) == -1)
+ if (ioctl(apme->a_raw, BIOCSETIF, &ifr) == -1)
hostapd_fatal("failed to set BPF interface \"%s\": %s\n",
- cfg->c_apme_iface, strerror(errno));
+ apme->a_iface, strerror(errno));
dlt = cfg->c_apme_dlt;
- if (ioctl(cfg->c_apme_raw, BIOCSDLT, &dlt) == -1)
+ if (ioctl(apme->a_raw, BIOCSDLT, &dlt) == -1)
hostapd_fatal("failed to set BPF link type on \"%s\": %s\n",
- cfg->c_apme_iface, strerror(errno));
+ apme->a_iface, strerror(errno));
/* Lock the BPF descriptor, no further configuration */
- if (ioctl(cfg->c_apme_raw, BIOCLOCK, NULL) == -1)
+ if (ioctl(apme->a_raw, BIOCLOCK, NULL) == -1)
hostapd_fatal("failed to lock BPF interface on \"%s\": %s\n",
- cfg->c_apme_iface, strerror(errno));
+ apme->a_iface, strerror(errno));
}
int
-hostapd_apme_addnode(struct hostapd_config *cfg, struct hostapd_node *node)
+hostapd_apme_addnode(struct hostapd_apme *apme, struct hostapd_node *node)
{
- return (hostapd_priv_apme_setnode(cfg, node, 1));
+ return (hostapd_priv_apme_setnode(apme, node, 1));
}
int
-hostapd_apme_delnode(struct hostapd_config *cfg, struct hostapd_node *node)
+hostapd_apme_delnode(struct hostapd_apme *apme, struct hostapd_node *node)
{
- return (hostapd_priv_apme_setnode(cfg, node, 0));
+ return (hostapd_priv_apme_setnode(apme, node, 0));
}
diff --git a/usr.sbin/hostapd/handle.c b/usr.sbin/hostapd/handle.c
index 53bf929f237..8a1f71197de 100644
--- a/usr.sbin/hostapd/handle.c
+++ b/usr.sbin/hostapd/handle.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: handle.c,v 1.4 2005/10/11 14:22:22 reyk Exp $ */
+/* $OpenBSD: handle.c,v 1.5 2005/11/20 12:02:04 reyk Exp $ */
/*
* Copyright (c) 2005 Reyk Floeter <reyk@vantronix.net>
@@ -41,9 +41,9 @@
#include "hostapd.h"
-int hostapd_handle_frame(struct hostapd_config *, struct hostapd_frame *,
+int hostapd_handle_frame(struct hostapd_apme *, struct hostapd_frame *,
u_int8_t *, const u_int);
-int hostapd_handle_action(struct hostapd_config *, struct hostapd_frame *,
+int hostapd_handle_action(struct hostapd_apme *, struct hostapd_frame *,
u_int8_t *, u_int8_t *, u_int8_t *, u_int8_t *, const u_int);
void hostapd_handle_addr(const u_int32_t, u_int32_t *, u_int8_t *,
u_int8_t *, struct hostapd_table *);
@@ -51,13 +51,14 @@ void hostapd_handle_ref(u_int, u_int, u_int8_t *, u_int8_t *, u_int8_t *,
u_int8_t *);
int
-hostapd_handle_input(struct hostapd_config *cfg, u_int8_t *buf, u_int len)
+hostapd_handle_input(struct hostapd_apme *apme, u_int8_t *buf, u_int len)
{
- int ret;
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
struct hostapd_frame *frame;
+ int ret;
TAILQ_FOREACH(frame, &cfg->c_frames, f_entries) {
- if ((ret = hostapd_handle_frame(cfg, frame, buf, len)) != 0)
+ if ((ret = hostapd_handle_frame(apme, frame, buf, len)) != 0)
return (ret);
}
@@ -99,7 +100,7 @@ hostapd_handle_ref(u_int flags, u_int shift, u_int8_t *wfrom, u_int8_t *wto,
}
int
-hostapd_handle_frame(struct hostapd_config *cfg, struct hostapd_frame *frame,
+hostapd_handle_frame(struct hostapd_apme *apme, struct hostapd_frame *frame,
u_int8_t *buf, const u_int len)
{
struct ieee80211_frame *wh;
@@ -109,7 +110,7 @@ hostapd_handle_frame(struct hostapd_config *cfg, struct hostapd_frame *frame,
u_int32_t flags;
int offset, min_rate = 0;
- if ((offset = hostapd_apme_offset(cfg, buf, len)) < 0)
+ if ((offset = hostapd_apme_offset(apme, buf, len)) < 0)
return (0);
wh = (struct ieee80211_frame *)(buf + offset);
@@ -216,7 +217,7 @@ hostapd_handle_frame(struct hostapd_config *cfg, struct hostapd_frame *frame,
if (min_rate)
return (0);
- if (hostapd_handle_action(cfg, frame, wfrom, wto, wbssid, buf,
+ if (hostapd_handle_action(apme, frame, wfrom, wto, wbssid, buf,
len) != 0)
return (0);
@@ -228,10 +229,11 @@ hostapd_handle_frame(struct hostapd_config *cfg, struct hostapd_frame *frame,
}
int
-hostapd_handle_action(struct hostapd_config *cfg, struct hostapd_frame *frame,
+hostapd_handle_action(struct hostapd_apme *apme, struct hostapd_frame *frame,
u_int8_t *wfrom, u_int8_t *wto, u_int8_t *wbssid, u_int8_t *buf,
const u_int len)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
struct hostapd_action_data *action = &frame->f_action_data;
struct hostapd_node node;
u_int8_t *lladdr = NULL;
@@ -240,7 +242,7 @@ hostapd_handle_action(struct hostapd_config *cfg, struct hostapd_frame *frame,
switch (frame->f_action) {
case HOSTAPD_ACTION_RADIOTAP:
/* Send IAPP frame with radiotap/pcap payload */
- if ((ret = hostapd_iapp_radiotap(cfg, buf, len)) != 0)
+ if ((ret = hostapd_iapp_radiotap(apme, buf, len)) != 0)
return (ret);
if ((frame->f_action_flags & HOSTAPD_ACTION_VERBOSE) == 0)
@@ -256,10 +258,10 @@ hostapd_handle_action(struct hostapd_config *cfg, struct hostapd_frame *frame,
/* Log frame to syslog/stderr */
if (frame->f_rate && frame->f_rate_intval) {
hostapd_printf("%s: (rate: %ld/%ld sec) ",
- cfg->c_apme_iface, frame->f_rate_cnt,
+ apme->a_iface, frame->f_rate_cnt,
frame->f_rate_delay + 1);
} else
- hostapd_printf("%s: ", cfg->c_apme_iface);
+ hostapd_printf("%s: ", apme->a_iface);
hostapd_print_ieee80211(cfg->c_apme_dlt, frame->f_action_flags &
HOSTAPD_ACTION_VERBOSE, buf, len);
@@ -284,14 +286,14 @@ hostapd_handle_action(struct hostapd_config *cfg, struct hostapd_frame *frame,
bcopy(lladdr, &node.ni_macaddr, IEEE80211_ADDR_LEN);
if (frame->f_action == HOSTAPD_ACTION_DELNODE)
- ret = hostapd_apme_delnode(cfg, &node);
+ ret = hostapd_apme_delnode(apme, &node);
else
- ret = hostapd_apme_addnode(cfg, &node);
+ ret = hostapd_apme_addnode(apme, &node);
if (ret != 0) {
hostapd_log(HOSTAPD_LOG_DEBUG,
"%s: node add/delete %s failed: %s\n",
- cfg->c_apme_iface, etheraddr_string(lladdr),
+ apme->a_iface, etheraddr_string(lladdr),
strerror(ret));
}
break;
@@ -302,9 +304,9 @@ hostapd_handle_action(struct hostapd_config *cfg, struct hostapd_frame *frame,
case HOSTAPD_ACTION_RESEND:
/* Resend received raw IEEE 802.11 frame */
- if ((offset = hostapd_apme_offset(cfg, buf, len)) < 0)
+ if ((offset = hostapd_apme_offset(apme, buf, len)) < 0)
return (EINVAL);
- if (write(cfg->c_apme_raw, buf + offset, len - offset) == -1)
+ if (write(apme->a_raw, buf + offset, len - offset) == -1)
ret = errno;
break;
@@ -325,7 +327,7 @@ hostapd_handle_action(struct hostapd_config *cfg, struct hostapd_frame *frame,
}
/* Send a raw IEEE 802.11 frame */
- return (hostapd_apme_output(cfg, &action->a_frame));
+ return (hostapd_apme_output(apme, &action->a_frame));
default:
return (0);
diff --git a/usr.sbin/hostapd/hostapd.c b/usr.sbin/hostapd/hostapd.c
index d86c3507ad4..3a080ce9f93 100644
--- a/usr.sbin/hostapd/hostapd.c
+++ b/usr.sbin/hostapd/hostapd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostapd.c,v 1.22 2005/11/16 00:01:19 reyk Exp $ */
+/* $OpenBSD: hostapd.c,v 1.23 2005/11/20 12:02:04 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -308,12 +308,18 @@ void
hostapd_cleanup(struct hostapd_config *cfg)
{
struct ip_mreq mreq;
+ struct hostapd_apme *apme;
struct hostapd_table *table;
struct hostapd_entry *entry;
+ /* Release all Host APs */
+ if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
+ while ((apme = TAILQ_FIRST(&cfg->c_apmes)) != NULL)
+ hostapd_apme_term(apme);
+ }
+
if (cfg->c_flags & HOSTAPD_CFG_F_PRIV &&
- (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST) == 0 &&
- cfg->c_apme_n == 0) {
+ (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST) == 0) {
/*
* Disable multicast and let the kernel unsubscribe
* from the multicast group.
@@ -360,7 +366,8 @@ int
main(int argc, char *argv[])
{
struct hostapd_config *cfg = &hostapd_cfg;
- char *iapp_iface = NULL, *hostap_iface = NULL, *config = NULL;
+ struct hostapd_apme *apme;
+ char *config = NULL;
u_int debug = 0;
int ch;
@@ -396,14 +403,6 @@ main(int argc, char *argv[])
else
strlcpy(cfg->c_config, config, sizeof(cfg->c_config));
- if (iapp_iface != NULL)
- strlcpy(cfg->c_iapp_iface, iapp_iface,
- sizeof(cfg->c_iapp_iface));
-
- if (hostap_iface != NULL)
- strlcpy(cfg->c_apme_iface, hostap_iface,
- sizeof(cfg->c_apme_iface));
-
if (geteuid())
hostapd_fatal("need root privileges\n");
@@ -414,9 +413,6 @@ main(int argc, char *argv[])
if ((cfg->c_flags & HOSTAPD_CFG_F_IAPP) == 0)
hostapd_fatal("IAPP interface not specified\n");
- if ((cfg->c_flags & HOSTAPD_CFG_F_APME) == 0)
- strlcpy(cfg->c_apme_iface, "<none>", sizeof(cfg->c_apme_iface));
-
if (cfg->c_apme_dlt == 0)
cfg->c_apme_dlt = HOSTAPD_DLT;
@@ -434,17 +430,20 @@ main(int argc, char *argv[])
daemon(0, 0);
}
- if (cfg->c_flags & HOSTAPD_CFG_F_APME)
- hostapd_apme_init(cfg);
- else
- hostapd_log(HOSTAPD_LOG, "%s/%s: running without a Host AP\n",
- cfg->c_apme_iface, cfg->c_iapp_iface);
+ if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
+ TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries)
+ hostapd_apme_init(apme);
+ } else
+ hostapd_log(HOSTAPD_LOG, "%s: running without a Host AP\n",
+ cfg->c_iapp_iface);
/* Drop all privileges in an unprivileged child process */
hostapd_priv_init(cfg);
- setproctitle("Host AP: %s, IAPP: %s",
- cfg->c_apme_iface, cfg->c_iapp_iface);
+ if (cfg->c_flags & HOSTAPD_CFG_F_APME)
+ setproctitle("IAPP: %s, Host AP", cfg->c_iapp_iface);
+ else
+ setproctitle("IAPP: %s", cfg->c_iapp_iface);
/*
* Unprivileged child process
@@ -469,9 +468,11 @@ main(int argc, char *argv[])
* Schedule the Host AP listener
*/
if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
- event_set(&cfg->c_apme_ev, cfg->c_apme_raw,
- EV_READ | EV_PERSIST, hostapd_apme_input, cfg);
- event_add(&cfg->c_apme_ev, NULL);
+ TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
+ event_set(&apme->a_ev, apme->a_raw,
+ EV_READ | EV_PERSIST, hostapd_apme_input, apme);
+ event_add(&apme->a_ev, NULL);
+ }
}
/*
@@ -481,8 +482,8 @@ main(int argc, char *argv[])
hostapd_iapp_input, cfg);
event_add(&cfg->c_iapp_udp_ev, NULL);
- hostapd_log(HOSTAPD_LOG, "%s/%s: starting hostapd with pid %u\n",
- cfg->c_apme_iface, cfg->c_iapp_iface, getpid());
+ hostapd_log(HOSTAPD_LOG, "starting hostapd with pid %u\n",
+ getpid());
/* Run event loop */
event_dispatch();
@@ -595,4 +596,3 @@ hostapd_entry_cmp(struct hostapd_entry *a, struct hostapd_entry *b)
}
RB_GENERATE(hostapd_tree, hostapd_entry, e_nodes, hostapd_entry_cmp);
-
diff --git a/usr.sbin/hostapd/hostapd.conf.5 b/usr.sbin/hostapd/hostapd.conf.5
index 2e832856778..76b1c9fd7d6 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.19 2005/11/17 00:10:46 reyk Exp $
+.\" $OpenBSD: hostapd.conf.5,v 1.20 2005/11/20 12:02:04 reyk Exp $
.\"
.\" Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
.\"
@@ -106,11 +106,18 @@ table <myess> const {
.Sh GLOBAL CONFIGURATION
The following configuration settings are understood:
.Bl -tag -width Ds
-.It Ic set hostap interface Ar interface
+.It Xo
+.Ic set hostap interface
+.Ar interface \*(Ba\ \&
+.Pf { Ar interface0 , interface1 , ... No }
+.Xc
Specify the wireless interface running in Host AP mode.
This option could be omitted to use
.Xr hostapd 8
to log received IAPP messages.
+Multiple hostap interfaces may be specified
+as a comma-separated list,
+surrounded by curly braces.
.It Ic set hostap mode Ar mode
Specify the Host AP capture mode.
The supported modes are:
diff --git a/usr.sbin/hostapd/hostapd.h b/usr.sbin/hostapd/hostapd.h
index 7a92cebd8e5..57a2ac800f0 100644
--- a/usr.sbin/hostapd/hostapd.h
+++ b/usr.sbin/hostapd/hostapd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostapd.h,v 1.8 2005/10/07 22:32:52 reyk Exp $ */
+/* $OpenBSD: hostapd.h,v 1.9 2005/11/20 12:02:04 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -225,14 +225,19 @@ struct hostapd_frame {
TAILQ_ENTRY(hostapd_frame) f_entries;
};
+struct hostapd_apme {
+ int a_raw;
+ u_int a_rawlen;
+ struct event a_ev;
+ char a_iface[IFNAMSIZ];
+ u_int8_t a_bssid[IEEE80211_ADDR_LEN];
+ void *a_cfg;
+
+ TAILQ_ENTRY(hostapd_apme) a_entries;
+};
+
struct hostapd_config {
- int c_apme;
- int c_apme_raw;
- u_int c_apme_rawlen;
- struct event c_apme_ev;
- char c_apme_iface[IFNAMSIZ];
- int c_apme_n;
- u_int8_t c_apme_bssid[IEEE80211_ADDR_LEN];
+ int c_apme_ctl;
u_int c_apme_dlt;
u_int16_t c_iapp;
@@ -265,6 +270,7 @@ struct hostapd_config {
struct hostapd_counter c_stats;
+ TAILQ_HEAD(, hostapd_apme) c_apmes;
TAILQ_HEAD(, hostapd_table) c_tables;
TAILQ_HEAD(, hostapd_frame) c_frames;
};
@@ -316,35 +322,39 @@ int hostapd_parse_symset(char *);
void hostapd_priv_init(struct hostapd_config *);
int hostapd_priv_llc_xid(struct hostapd_config *, struct hostapd_node *);
-void hostapd_priv_apme_bssid(struct hostapd_config *);
-int hostapd_priv_apme_getnode(struct hostapd_config *,
+void hostapd_priv_apme_bssid(struct hostapd_apme *);
+int hostapd_priv_apme_getnode(struct hostapd_apme *,
struct hostapd_node *);
-int hostapd_priv_apme_setnode(struct hostapd_config *,
+int hostapd_priv_apme_setnode(struct hostapd_apme *,
struct hostapd_node *node, int);
-void hostapd_apme_init(struct hostapd_config *);
+void hostapd_apme_init(struct hostapd_apme *);
+int hostapd_apme_add(struct hostapd_config *, const char *);
+void hostapd_apme_term(struct hostapd_apme *);
+struct hostapd_apme *hostapd_apme_lookup(struct hostapd_config *,
+ const char *);
void hostapd_apme_input(int, short, void *);
-int hostapd_apme_output(struct hostapd_config *,
+int hostapd_apme_output(struct hostapd_apme *,
struct hostapd_ieee80211_frame *);
-int hostapd_apme_addnode(struct hostapd_config *,
+int hostapd_apme_addnode(struct hostapd_apme *,
struct hostapd_node *node);
-int hostapd_apme_delnode(struct hostapd_config *,
+int hostapd_apme_delnode(struct hostapd_apme *,
struct hostapd_node *node);
-int hostapd_apme_offset(struct hostapd_config *, u_int8_t *,
+int hostapd_apme_offset(struct hostapd_apme *, u_int8_t *,
const u_int);
void hostapd_iapp_init(struct hostapd_config *);
void hostapd_iapp_term(struct hostapd_config *);
-int hostapd_iapp_add_notify(struct hostapd_config *,
+int hostapd_iapp_add_notify(struct hostapd_apme *,
struct hostapd_node *);
-int hostapd_iapp_radiotap(struct hostapd_config *,
+int hostapd_iapp_radiotap(struct hostapd_apme *,
u_int8_t *, const u_int);
void hostapd_iapp_input(int, short, void *);
void hostapd_llc_init(struct hostapd_config *);
int hostapd_llc_send_xid(struct hostapd_config *, struct hostapd_node *);
-int hostapd_handle_input(struct hostapd_config *, u_int8_t *, u_int);
+int hostapd_handle_input(struct hostapd_apme *, u_int8_t *, u_int);
void hostapd_print_ieee80211(u_int, u_int, u_int8_t *, u_int);
diff --git a/usr.sbin/hostapd/iapp.c b/usr.sbin/hostapd/iapp.c
index c706b11be04..5ce76a7d993 100644
--- a/usr.sbin/hostapd/iapp.c
+++ b/usr.sbin/hostapd/iapp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iapp.c,v 1.8 2005/10/07 22:32:52 reyk Exp $ */
+/* $OpenBSD: iapp.c,v 1.9 2005/11/20 12:02:04 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -45,32 +45,40 @@
void
hostapd_iapp_init(struct hostapd_config *cfg)
{
+ struct hostapd_apme *apme;
+
if ((cfg->c_flags & HOSTAPD_CFG_F_APME) == 0)
return;
- /* Get Host AP's BSSID */
- hostapd_priv_apme_bssid(cfg);
-
- hostapd_log(HOSTAPD_LOG_VERBOSE,
- "%s: attaching to Host AP %s with BSSID \"%s\"\n",
- cfg->c_iapp_iface, cfg->c_apme_iface,
- etheraddr_string(cfg->c_apme_bssid));
+ TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
+ /* Get Host AP's BSSID */
+ hostapd_priv_apme_bssid(apme);
+ hostapd_log(HOSTAPD_LOG_VERBOSE,
+ "%s/%s: attached Host AP interface with BSSID \"%s\"\n",
+ cfg->c_iapp_iface, apme->a_iface,
+ etheraddr_string(apme->a_bssid));
+ }
}
void
hostapd_iapp_term(struct hostapd_config *cfg)
{
+ struct hostapd_apme *apme;
+
if ((cfg->c_flags & HOSTAPD_CFG_F_APME) == 0)
return;
- /* XXX not yet used but inspired by the APME TERMINATE action */
- hostapd_log(HOSTAPD_LOG_VERBOSE, "%s: detaching from Host AP %s\n",
- cfg->c_iapp_iface, cfg->c_apme_iface);
+ TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
+ hostapd_log(HOSTAPD_LOG_VERBOSE,
+ "%s/%s: detaching from Host AP\n",
+ cfg->c_iapp_iface, apme->a_iface);
+ }
}
int
-hostapd_iapp_add_notify(struct hostapd_config *cfg, struct hostapd_node *node)
+hostapd_iapp_add_notify(struct hostapd_apme *apme, struct hostapd_node *node)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
struct sockaddr_in *addr;
struct {
struct ieee80211_iapp_frame hdr;
@@ -105,17 +113,19 @@ hostapd_iapp_add_notify(struct hostapd_config *cfg, struct hostapd_node *node)
return (errno);
}
- hostapd_log(HOSTAPD_LOG, "%s: sent ADD notification for %s\n",
- cfg->c_iapp_iface, etheraddr_string(frame.add.a_macaddr));
+ hostapd_log(HOSTAPD_LOG, "%s/%s: sent ADD notification for %s\n",
+ apme->a_iface, cfg->c_iapp_iface,
+ etheraddr_string(frame.add.a_macaddr));
/* Send a LLC XID frame, see llc.c for details */
return (hostapd_priv_llc_xid(cfg, node));
}
int
-hostapd_iapp_radiotap(struct hostapd_config *cfg, u_int8_t *buf,
+hostapd_iapp_radiotap(struct hostapd_apme *apme, u_int8_t *buf,
const u_int len)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
struct sockaddr_in *addr;
struct ieee80211_iapp_frame hdr;
struct msghdr msg;
@@ -171,6 +181,7 @@ void
hostapd_iapp_input(int fd, short sig, void *arg)
{
struct hostapd_config *cfg = (struct hostapd_config *)arg;
+ struct hostapd_apme *apme;
struct sockaddr_in addr;
socklen_t addr_len;
ssize_t len;
@@ -237,14 +248,17 @@ hostapd_iapp_input(int fd, short sig, void *arg)
* ADD.notify message will be ignored.
*/
if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
- if ((ret = hostapd_apme_delnode(cfg, &node)) == 0)
- cfg->c_stats.cn_tx_apme++;
+ TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
+ if ((ret = hostapd_apme_delnode(apme,
+ &node)) == 0)
+ cfg->c_stats.cn_tx_apme++;
+ }
} else
ret = 0;
hostapd_log(HOSTAPD_LOG, "%s: %s ADD notification "
"for %s at %s\n",
- cfg->c_apme_iface, ret == 0 ?
+ cfg->c_iapp_iface, ret == 0 ?
"received" : "ignored",
etheraddr_string(node.ni_macaddr),
inet_ntoa(addr.sin_addr));
diff --git a/usr.sbin/hostapd/parse.y b/usr.sbin/hostapd/parse.y
index 8bbc0e25b32..19a1e941afa 100644
--- a/usr.sbin/hostapd/parse.y
+++ b/usr.sbin/hostapd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.12 2005/11/16 00:01:19 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.13 2005/11/20 12:02:04 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -149,18 +149,10 @@ grammar : /* empty */
| grammar error '\n' { errors++; }
;
-option : SET HOSTAP INTERFACE STRING
+option : SET HOSTAP INTERFACE hostapifaces
{
- strlcpy(hostapd_cfg.c_apme_iface, $4,
- sizeof(hostapd_cfg.c_apme_iface));
-
- hostapd_cfg.c_flags |= HOSTAPD_CFG_F_APME;
-
- hostapd_log(HOSTAPD_LOG_DEBUG,
- "parse %s: Host AP interface %s\n",
- hostapd_cfg.c_config, $4);
-
- free($4);
+ if (!TAILQ_EMPTY(&hostapd_cfg.c_apmes))
+ hostapd_cfg.c_flags |= HOSTAPD_CFG_F_APME;
}
| SET HOSTAP MODE hostapmode
| SET IAPP INTERFACE STRING passive
@@ -170,8 +162,8 @@ option : SET HOSTAP INTERFACE STRING
hostapd_cfg.c_flags |= HOSTAPD_CFG_F_IAPP;
- hostapd_log(HOSTAPD_LOG_DEBUG, "parse %s: "
- "IAPP interface %s\n", hostapd_cfg.c_config, $4);
+ hostapd_log(HOSTAPD_LOG_DEBUG,
+ "%s: IAPP interface added\n", $4);
free($4);
}
@@ -213,6 +205,24 @@ hostapmode : RADIOTAP
}
;
+hostapifaces : '{' optnl hostapifacelist optnl '}'
+ | hostapiface
+ ;
+
+hostapifacelist : hostapiface
+ | hostapifacelist comma hostapiface
+ ;
+
+hostapiface : STRING
+ {
+ if (hostapd_apme_add(&hostapd_cfg, $1) != 0) {
+ yyerror("failed to add hostap interface");
+ YYERROR;
+ }
+ free($1);
+ }
+ ;
+
event : HOSTAP HANDLE
{
bzero(&frame, sizeof(struct hostapd_frame));
@@ -1257,6 +1267,7 @@ hostapd_parse_file(struct hostapd_config *cfg)
}
/* Init tables and data structures */
+ TAILQ_INIT(&cfg->c_apmes);
TAILQ_INIT(&cfg->c_tables);
TAILQ_INIT(&cfg->c_frames);
cfg->c_iapp_multicast.sin_addr.s_addr = INADDR_ANY;
diff --git a/usr.sbin/hostapd/privsep.c b/usr.sbin/hostapd/privsep.c
index 7294841c83a..fed76080f6f 100644
--- a/usr.sbin/hostapd/privsep.c
+++ b/usr.sbin/hostapd/privsep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: privsep.c,v 1.14 2005/10/07 22:32:52 reyk Exp $ */
+/* $OpenBSD: privsep.c,v 1.15 2005/11/20 12:02:04 reyk Exp $ */
/*
* Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
@@ -61,6 +61,7 @@ enum hostapd_cmd_types {
};
void hostapd_priv(int, short, void *);
+struct hostapd_apme *hostapd_priv_getapme(int, struct hostapd_config *);
void hostapd_sig_relay(int);
void hostapd_sig_chld(int);
int hostapd_may_read(int, void *, size_t);
@@ -146,7 +147,7 @@ hostapd_priv_init(struct hostapd_config *cfg)
close(socks[1]);
if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
- if ((cfg->c_apme = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ if ((cfg->c_apme_ctl = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
hostapd_fatal("unable to open ioctl socket\n");
}
@@ -164,10 +165,28 @@ hostapd_priv_init(struct hostapd_config *cfg)
_exit(EXIT_SUCCESS);
}
+struct hostapd_apme *
+hostapd_priv_getapme(int fd, struct hostapd_config *cfg)
+{
+ struct hostapd_apme *apme;
+ char name[IFNAMSIZ];
+ int n;
+
+ hostapd_must_read(fd, name, IFNAMSIZ);
+ if ((cfg->c_flags & HOSTAPD_CFG_F_APME) == 0 ||
+ (apme = hostapd_apme_lookup(cfg, name)) == NULL) {
+ n = ENXIO;
+ hostapd_must_write(fd, &n, sizeof(int));
+ return (NULL);
+ }
+ return (apme);
+}
+
void
hostapd_priv(int fd, short sig, void *arg)
{
struct hostapd_config *cfg = (struct hostapd_config *)arg;
+ struct hostapd_apme *apme;
struct hostapd_node node;
struct ieee80211_bssid bssid;
struct ieee80211_nodereq nr;
@@ -191,15 +210,14 @@ hostapd_priv(int fd, short sig, void *arg)
hostapd_log(HOSTAPD_LOG_DEBUG,
"[priv]: msg PRIV_APME_BSSID received\n");
- strlcpy(bssid.i_name, cfg->c_apme_iface, sizeof(bssid.i_name));
+ if ((apme = hostapd_priv_getapme(fd, cfg)) == NULL)
+ break;
+ strlcpy(bssid.i_name, apme->a_iface, sizeof(bssid.i_name));
/* Try to get the APME's BSSID */
- if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
- if ((ret = ioctl(cfg->c_apme,
- SIOCG80211BSSID, &bssid)) != 0)
- ret = errno;
- } else
- ret = ENXIO;
+ if ((ret = ioctl(cfg->c_apme_ctl,
+ SIOCG80211BSSID, &bssid)) != 0)
+ ret = errno;
hostapd_must_write(fd, &ret, sizeof(int));
if (ret == 0)
@@ -214,15 +232,14 @@ hostapd_priv(int fd, short sig, void *arg)
hostapd_must_read(fd, &node, sizeof(struct hostapd_node));
bcopy(node.ni_macaddr, nr.nr_macaddr, IEEE80211_ADDR_LEN);
- strlcpy(nr.nr_ifname, cfg->c_apme_iface, sizeof(ifr.ifr_name));
+ if ((apme = hostapd_priv_getapme(fd, cfg)) == NULL)
+ break;
+ strlcpy(nr.nr_ifname, apme->a_iface, sizeof(ifr.ifr_name));
/* Try to get a station from the APME */
- if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
- if ((ret = ioctl(cfg->c_apme,
- SIOCG80211NODE, &nr)) != 0)
- ret = errno;
- } else
- ret = ENXIO;
+ if ((ret = ioctl(cfg->c_apme_ctl,
+ SIOCG80211NODE, &nr)) != 0)
+ ret = errno;
hostapd_must_write(fd, &ret, sizeof(int));
if (ret == 0) {
@@ -244,17 +261,17 @@ hostapd_priv(int fd, short sig, void *arg)
hostapd_must_read(fd, &node, sizeof(struct hostapd_node));
bcopy(node.ni_macaddr, nr.nr_macaddr, IEEE80211_ADDR_LEN);
- strlcpy(nr.nr_ifname, cfg->c_apme_iface, sizeof(ifr.ifr_name));
+ if ((apme = hostapd_priv_getapme(fd, cfg)) == NULL)
+ break;
+ strlcpy(nr.nr_ifname, apme->a_iface, sizeof(ifr.ifr_name));
request = cmd == PRIV_APME_ADDNODE ?
SIOCS80211NODE : SIOCS80211DELNODE;
/* Try to add/delete a station from the APME */
- if (cfg->c_flags & HOSTAPD_CFG_F_APME) {
- if ((ret = ioctl(cfg->c_apme, request, &nr)) != 0)
- ret = errno;
- } else
- ret = ENXIO;
+ if ((ret = ioctl(cfg->c_apme_ctl, request, &nr)) != 0)
+ ret = errno;
+
hostapd_must_write(fd, &ret, sizeof(int));
break;
@@ -273,14 +290,17 @@ hostapd_priv(int fd, short sig, void *arg)
hostapd_fatal("[priv]: unknown command %d\n", cmd);
}
event_add(&cfg->c_priv_ev, NULL);
+
+ return;
}
/*
* Unprivileged callers
*/
int
-hostapd_priv_apme_getnode(struct hostapd_config *cfg, struct hostapd_node *node)
+hostapd_priv_apme_getnode(struct hostapd_apme *apme, struct hostapd_node *node)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
int ret, cmd;
if (priv_fd < 0)
@@ -292,6 +312,7 @@ hostapd_priv_apme_getnode(struct hostapd_config *cfg, struct hostapd_node *node)
cmd = PRIV_APME_GETNODE;
hostapd_must_write(priv_fd, &cmd, sizeof(int));
hostapd_must_write(priv_fd, node, sizeof(struct hostapd_node));
+ hostapd_must_write(priv_fd, &apme->a_iface, IFNAMSIZ);
hostapd_must_read(priv_fd, &ret, sizeof(int));
if (ret != 0)
return (ret);
@@ -301,9 +322,10 @@ hostapd_priv_apme_getnode(struct hostapd_config *cfg, struct hostapd_node *node)
}
int
-hostapd_priv_apme_setnode(struct hostapd_config *cfg, struct hostapd_node *node,
+hostapd_priv_apme_setnode(struct hostapd_apme *apme, struct hostapd_node *node,
int add)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
int ret, cmd;
if (priv_fd < 0)
@@ -318,14 +340,21 @@ hostapd_priv_apme_setnode(struct hostapd_config *cfg, struct hostapd_node *node,
cmd = PRIV_APME_DELNODE;
hostapd_must_write(priv_fd, &cmd, sizeof(int));
hostapd_must_write(priv_fd, node, sizeof(struct hostapd_node));
+ hostapd_must_write(priv_fd, &apme->a_iface, IFNAMSIZ);
+
hostapd_must_read(priv_fd, &ret, sizeof(int));
+ if (ret == 0)
+ hostapd_log(HOSTAPD_LOG, "%s: %s node %s\n",
+ apme->a_iface, add ? "added" : "removed",
+ etheraddr_string(node->ni_macaddr));
return (ret);
}
void
-hostapd_priv_apme_bssid(struct hostapd_config *cfg)
+hostapd_priv_apme_bssid(struct hostapd_apme *apme)
{
+ struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
int ret, cmd;
if (priv_fd < 0)
@@ -336,13 +365,13 @@ hostapd_priv_apme_bssid(struct hostapd_config *cfg)
cmd = PRIV_APME_BSSID;
hostapd_must_write(priv_fd, &cmd, sizeof(int));
-
+ hostapd_must_write(priv_fd, &apme->a_iface, IFNAMSIZ);
hostapd_must_read(priv_fd, &ret, sizeof(int));
if (ret != 0)
hostapd_fatal("failed to get Host AP's BSSID on"
- " \"%s\": %s\n", cfg->c_apme_iface, strerror(errno));
+ " \"%s\": %s\n", apme->a_iface, strerror(errno));
- hostapd_must_read(priv_fd, &cfg->c_apme_bssid, IEEE80211_ADDR_LEN);
+ hostapd_must_read(priv_fd, &apme->a_bssid, IEEE80211_ADDR_LEN);
cfg->c_stats.cn_tx_apme++;
}