diff --git a/usr.sbin/wpa/ndis_events/ndis_events.8 b/usr.sbin/wpa/ndis_events/ndis_events.8 index 4735db0fa7cf..983149fb235a 100644 --- a/usr.sbin/wpa/ndis_events/ndis_events.8 +++ b/usr.sbin/wpa/ndis_events/ndis_events.8 @@ -1,118 +1,129 @@ .\" Copyright (c) 2005 .\" Bill Paul All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by Bill Paul. .\" 4. Neither the name of the author nor the names of any co-contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF .\" THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd October 10, 2005 .Dt NDIS_EVENTS 8 .Os .Sh NAME .Nm ndis_events .Nd relay events from .Xr ndis 4 drivers to .Xr wpa_supplicant 8 .Sh SYNOPSIS .Nm +.Op Fl a .Op Fl d .Op Fl v .Sh DESCRIPTION The .Nm utility listens for events generated by an .Xr ndis 4 wireless network driver and relays them to .Xr wpa_supplicant 8 for possible processing. The three event types that can occur are media connect and disconnect events, such as when a wireless interface joins or leaves a network, and media-specific events. In particular, .Xr ndis 4 drivers that support WPA2 will generate media-specific events containing PMKID candidate information which .Xr wpa_supplicant 8 needs in order to properly associate with WPA2-capable access points. .Pp The .Nm daemon works by listening for interface information events via a routing socket. When it detects an event that was generated by an .Xr ndis 4 interface, it transmits it via UDP packet on the loopback interface, where .Xr wpa_supplicant 8 is presumeably listening. The standard .Xr wpa_supplicant 8 distribution includes its own version of this utility for use with .Tn Windows\[rg] . The .Fx version performs the same functions as the .Tn Windows\[rg] except that it uses an .Xr ioctl 4 and routing socket interface instead of WMI. .Pp Note that a single instance of .Nm is sufficient to scan for events for any number of .Xr ndis 4 interfaces in a system. .Sh OPTIONS The .Nm daemon supports the following options: .Bl -tag -width indent +.It Fl a +Process all events. By default, +.Nm +will only process and forward media-specific events, which contain +PMKID candidate information, and not bother forwarding connect and +disconnect events, since +.Xr wpa_supplicant 8 +normally can determine the current link state on its own. In some +cases, the additional connect and disconnect events only confuse it +and make the association and authentication process take longer. .It Fl d Run in debug mode. This causes .Nm to run in the foreground and generate any output to the standard error instead of using the .Xr syslog 3 facility. .It Fl v Run in verbose mode. This causes .Nm to emit notifications when it receives events. .El .Sh SEE ALSO .Xr ndis 4 , .Xr ndisapi 9 , .Xr wpa_supplicant 8 .Sh HISTORY The .Nm utility first appeared in .Fx 7.0 . .Sh AUTHORS The .Nm utility was written by .An Bill Paul Aq wpaul@windriver.com . diff --git a/usr.sbin/wpa/ndis_events/ndis_events.c b/usr.sbin/wpa/ndis_events/ndis_events.c index 1741a645683e..6180c8870652 100644 --- a/usr.sbin/wpa/ndis_events/ndis_events.c +++ b/usr.sbin/wpa/ndis_events/ndis_events.c @@ -1,330 +1,338 @@ /*- * Copyright (c) 2005 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * This program simulates the behavior of the ndis_events utility * supplied with wpa_supplicant for Windows. The original utility * is designed to translate Windows WMI events. We don't have WMI, * but we need to supply certain event info to wpa_supplicant in * order to make WPA2 work correctly, so we fake up the interface. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int verbose = 0; static int debug = 0; +static int all_events = 0; #define PROGNAME "ndis_events" #define WPA_SUPPLICANT_PORT 9876 #define NDIS_INDICATION_LEN 2048 #define EVENT_CONNECT 0 #define EVENT_DISCONNECT 1 #define EVENT_MEDIA_SPECIFIC 2 #define NDIS_STATUS_MEDIA_CONNECT 0x4001000B #define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C #define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012 struct ndis_evt { uint32_t ne_sts; uint32_t ne_len; #ifdef notdef char ne_buf[1]; #endif }; static int find_ifname(int, char *); static void announce_event(char *, int, struct sockaddr_in *); static void usage(char *); static void dbgmsg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (debug) vwarnx(fmt, ap); else vsyslog(LOG_INFO, fmt, ap); va_end(ap); return; } static int find_ifname(idx, name) int idx; char *name; { int mib[6]; size_t needed; struct if_msghdr *ifm; struct sockaddr_dl *sdl; char *buf, *lim, *next; needed = 0; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ mib[3] = 0; /* wildcard address family */ mib[4] = NET_RT_IFLIST; mib[5] = 0; /* no flags */ if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0) return(EIO); buf = malloc (needed); if (buf == NULL) return(ENOMEM); if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0) { free(buf); return(EIO); } lim = buf + needed; next = buf; while (next < lim) { ifm = (struct if_msghdr *)next; if (ifm->ifm_type == RTM_IFINFO) { sdl = (struct sockaddr_dl *)(ifm + 1); if (ifm->ifm_index == idx) { strncpy(name, sdl->sdl_data, sdl->sdl_nlen); name[sdl->sdl_nlen] = '\0'; free (buf); return (0); } } next += ifm->ifm_msglen; } free (buf); return(ENOENT); } static void announce_event(ifname, sock, dst) char *ifname; int sock; struct sockaddr_in *dst; { int s; char indication[NDIS_INDICATION_LEN]; struct ifreq ifr; struct ndis_evt *e; char buf[512], *pos, *end; int len, type, _type; s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) return; bzero((char *)&ifr, sizeof(ifr)); e = (struct ndis_evt *)indication; e->ne_len = NDIS_INDICATION_LEN - sizeof(struct ndis_evt); strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ifr.ifr_data = indication; if (ioctl(s, SIOCGPRIVATE_0, &ifr) < 0) { close(s); - dbgmsg("failed to read event info from %s\n", ifname); + dbgmsg("failed to read event info from %s: %d", ifname, errno); return; } if (e->ne_sts == NDIS_STATUS_MEDIA_CONNECT) { type = EVENT_CONNECT; if (verbose) dbgmsg("Received a connect event for %s", ifname); + if (!all_events) + return; } if (e->ne_sts == NDIS_STATUS_MEDIA_DISCONNECT) { type = EVENT_DISCONNECT; if (verbose) dbgmsg("Received a disconnect event for %s", ifname); + if (!all_events) + return; } if (e->ne_sts == NDIS_STATUS_MEDIA_SPECIFIC_INDICATION) { type = EVENT_MEDIA_SPECIFIC; if (verbose) dbgmsg("Received a media-specific event for %s", ifname); } end = buf + sizeof(buf); _type = (int) type; memcpy(buf, &_type, sizeof(_type)); pos = buf + sizeof(_type); len = snprintf(pos + 1, end - pos - 1, "%s", ifname); if (len < 0) return; if (len > 255) len = 255; *pos = (unsigned char) len; pos += 1 + len; if (e->ne_len) { if (e->ne_len > 255 || 1 + e->ne_len > end - pos) { dbgmsg("Not enough room for send_event data (%d)\n", e->ne_len); return; } *pos++ = (unsigned char) e->ne_len; memcpy(pos, (indication) + sizeof(struct ndis_evt), e->ne_len); pos += e->ne_len; } len = sendto(sock, buf, pos - buf, 0, (struct sockaddr *) dst, sizeof(struct sockaddr_in)); close(s); return; } static void usage(progname) char *progname; { - fprintf(stderr, "Usage: ndis_events [-d] [-v]\n", progname); + fprintf(stderr, "Usage: ndis_events [-a] [-d] [-v]\n", progname); exit(1); } int main(argc, argv) int argc; char *argv[]; { int s, r, n; struct sockaddr_in sin; char msg[NDIS_INDICATION_LEN]; struct rt_msghdr *rtm; struct if_msghdr *ifm; char ifname[IFNAMSIZ]; int ch; - while ((ch = getopt(argc, argv, "dv")) != -1) { + while ((ch = getopt(argc, argv, "dva")) != -1) { switch(ch) { case 'd': debug++; break; case 'v': verbose++; break; + case 'a': + all_events++; + break; default: usage(PROGNAME); break; } } if (!debug && daemon(0, 0)) err(1, "failed to daemonize ourselves"); if (!debug) openlog(PROGNAME, LOG_PID | LOG_CONS, LOG_DAEMON); bzero((char *)&sin, sizeof(sin)); /* Create a datagram socket. */ s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { dbgmsg("socket creation failed"); exit(1); } sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr("127.0.0.1"); sin.sin_port = htons(WPA_SUPPLICANT_PORT); /* Create a routing socket. */ r = socket (PF_ROUTE, SOCK_RAW, 0); if (r < 0) { dbgmsg("routing socket creation failed"); exit(1); } /* Now sit and spin, waiting for events. */ if (verbose) dbgmsg("Listening for events"); while (1) { n = read(r, msg, NDIS_INDICATION_LEN); rtm = (struct rt_msghdr *)msg; if (rtm->rtm_type != RTM_IFINFO) continue; ifm = (struct if_msghdr *)msg; if (find_ifname(ifm->ifm_index, ifname)) continue; if (strstr(ifname, "ndis")) announce_event(ifname, s, &sin); else { if (verbose) dbgmsg("Skipping ifinfo message from %s", ifname); } } /* NOTREACHED */ exit(0); }