diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-11-20 12:02:05 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-11-20 12:02:05 +0000 |
commit | b05043e12f26aea5fa605717b96f4ea768117995 (patch) | |
tree | 7703d31a9eb631ef49865c68a758bc2cca3ee219 /usr.sbin/hostapd | |
parent | 62e602307426f4c305a35efbfc3241794b36ffd6 (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.c | 133 | ||||
-rw-r--r-- | usr.sbin/hostapd/handle.c | 40 | ||||
-rw-r--r-- | usr.sbin/hostapd/hostapd.c | 56 | ||||
-rw-r--r-- | usr.sbin/hostapd/hostapd.conf.5 | 11 | ||||
-rw-r--r-- | usr.sbin/hostapd/hostapd.h | 48 | ||||
-rw-r--r-- | usr.sbin/hostapd/iapp.c | 50 | ||||
-rw-r--r-- | usr.sbin/hostapd/parse.y | 39 | ||||
-rw-r--r-- | usr.sbin/hostapd/privsep.c | 85 |
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++; } |