1/*- 2 * Copyright (c) 2005 3 * Bill Paul <wpaul@windriver.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h>
|
34__FBSDID("$FreeBSD: head/usr.sbin/wpa/ndis_events/ndis_events.c 151214 2005-10-10 17:51:12Z wpaul $");
|
34__FBSDID("$FreeBSD: head/usr.sbin/wpa/ndis_events/ndis_events.c 151223 2005-10-10 20:40:28Z wpaul $"); |
35 36/* 37 * This program simulates the behavior of the ndis_events utility 38 * supplied with wpa_supplicant for Windows. The original utility 39 * is designed to translate Windows WMI events. We don't have WMI, 40 * but we need to supply certain event info to wpa_supplicant in 41 * order to make WPA2 work correctly, so we fake up the interface. 42 */ 43 44#include <sys/types.h> 45#include <sys/cdefs.h> 46#include <sys/param.h> 47#include <sys/socket.h> 48#include <sys/ioctl.h> 49#include <sys/socket.h> 50#include <sys/errno.h> 51#include <sys/sysctl.h> 52#include <net/if.h> 53#include <net/if_dl.h> 54#include <net/if_var.h> 55 56#include <netinet/in.h> 57#include <arpa/inet.h> 58#include <netdb.h> 59#include <net/route.h> 60 61#include <stdio.h> 62#include <string.h> 63#include <stdlib.h> 64#include <unistd.h> 65#include <err.h> 66#include <syslog.h> 67#include <stdarg.h> 68 69static int verbose = 0; 70static int debug = 0;
|
71static int all_events = 0; |
72 73#define PROGNAME "ndis_events" 74 75#define WPA_SUPPLICANT_PORT 9876 76#define NDIS_INDICATION_LEN 2048 77 78#define EVENT_CONNECT 0 79#define EVENT_DISCONNECT 1 80#define EVENT_MEDIA_SPECIFIC 2 81 82#define NDIS_STATUS_MEDIA_CONNECT 0x4001000B 83#define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C 84#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012 85 86struct ndis_evt { 87 uint32_t ne_sts; 88 uint32_t ne_len; 89#ifdef notdef 90 char ne_buf[1]; 91#endif 92}; 93 94static int find_ifname(int, char *); 95static void announce_event(char *, int, struct sockaddr_in *); 96static void usage(char *); 97 98static void 99dbgmsg(const char *fmt, ...) 100{ 101 va_list ap; 102 103 va_start(ap, fmt); 104 if (debug) 105 vwarnx(fmt, ap); 106 else 107 vsyslog(LOG_INFO, fmt, ap); 108 va_end(ap); 109 110 return; 111} 112 113static int 114find_ifname(idx, name) 115 int idx; 116 char *name; 117{ 118 int mib[6]; 119 size_t needed; 120 struct if_msghdr *ifm; 121 struct sockaddr_dl *sdl; 122 char *buf, *lim, *next; 123 124 needed = 0; 125 mib[0] = CTL_NET; 126 mib[1] = PF_ROUTE; 127 mib[2] = 0; /* protocol */ 128 mib[3] = 0; /* wildcard address family */ 129 mib[4] = NET_RT_IFLIST; 130 mib[5] = 0; /* no flags */ 131 132 if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0) 133 return(EIO); 134 135 buf = malloc (needed); 136 if (buf == NULL) 137 return(ENOMEM); 138 139 if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0) { 140 free(buf); 141 return(EIO); 142 } 143 144 lim = buf + needed; 145 146 next = buf; 147 while (next < lim) { 148 ifm = (struct if_msghdr *)next; 149 if (ifm->ifm_type == RTM_IFINFO) { 150 sdl = (struct sockaddr_dl *)(ifm + 1); 151 if (ifm->ifm_index == idx) { 152 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 153 name[sdl->sdl_nlen] = '\0'; 154 free (buf); 155 return (0); 156 } 157 } 158 next += ifm->ifm_msglen; 159 } 160 161 free (buf); 162 163 return(ENOENT); 164} 165 166static void 167announce_event(ifname, sock, dst) 168 char *ifname; 169 int sock; 170 struct sockaddr_in *dst; 171{ 172 int s; 173 char indication[NDIS_INDICATION_LEN]; 174 struct ifreq ifr; 175 struct ndis_evt *e; 176 char buf[512], *pos, *end; 177 int len, type, _type; 178 179 s = socket(PF_INET, SOCK_DGRAM, 0); 180 181 if (s < 0) 182 return; 183 184 bzero((char *)&ifr, sizeof(ifr)); 185 e = (struct ndis_evt *)indication; 186 e->ne_len = NDIS_INDICATION_LEN - sizeof(struct ndis_evt); 187 188 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 189 ifr.ifr_data = indication; 190 191 if (ioctl(s, SIOCGPRIVATE_0, &ifr) < 0) { 192 close(s);
|
192 dbgmsg("failed to read event info from %s\n", ifname);
|
193 dbgmsg("failed to read event info from %s: %d", ifname, errno); |
194 return; 195 } 196 197 if (e->ne_sts == NDIS_STATUS_MEDIA_CONNECT) { 198 type = EVENT_CONNECT; 199 if (verbose) 200 dbgmsg("Received a connect event for %s", ifname);
|
201 if (!all_events) 202 return; |
203 } 204 if (e->ne_sts == NDIS_STATUS_MEDIA_DISCONNECT) { 205 type = EVENT_DISCONNECT; 206 if (verbose) 207 dbgmsg("Received a disconnect event for %s", ifname);
|
208 if (!all_events) 209 return; |
210 } 211 if (e->ne_sts == NDIS_STATUS_MEDIA_SPECIFIC_INDICATION) { 212 type = EVENT_MEDIA_SPECIFIC; 213 if (verbose) 214 dbgmsg("Received a media-specific event for %s", 215 ifname); 216 } 217 218 end = buf + sizeof(buf); 219 _type = (int) type; 220 memcpy(buf, &_type, sizeof(_type)); 221 pos = buf + sizeof(_type); 222 223 len = snprintf(pos + 1, end - pos - 1, "%s", ifname); 224 if (len < 0) 225 return; 226 if (len > 255) 227 len = 255; 228 *pos = (unsigned char) len; 229 pos += 1 + len; 230 if (e->ne_len) { 231 if (e->ne_len > 255 || 1 + e->ne_len > end - pos) { 232 dbgmsg("Not enough room for send_event data (%d)\n", 233 e->ne_len); 234 return; 235 } 236 *pos++ = (unsigned char) e->ne_len; 237 memcpy(pos, (indication) + sizeof(struct ndis_evt), e->ne_len); 238 pos += e->ne_len; 239 } 240 241 len = sendto(sock, buf, pos - buf, 0, (struct sockaddr *) dst, 242 sizeof(struct sockaddr_in)); 243 244 close(s); 245 return; 246} 247 248static void 249usage(progname) 250 char *progname; 251{
|
247 fprintf(stderr, "Usage: ndis_events [-d] [-v]\n", progname);
|
252 fprintf(stderr, "Usage: ndis_events [-a] [-d] [-v]\n", progname); |
253 exit(1); 254} 255 256int 257main(argc, argv) 258 int argc; 259 char *argv[]; 260{ 261 int s, r, n; 262 struct sockaddr_in sin; 263 char msg[NDIS_INDICATION_LEN]; 264 struct rt_msghdr *rtm; 265 struct if_msghdr *ifm; 266 char ifname[IFNAMSIZ]; 267 int ch; 268
|
264 while ((ch = getopt(argc, argv, "dv")) != -1) {
|
269 while ((ch = getopt(argc, argv, "dva")) != -1) { |
270 switch(ch) { 271 case 'd': 272 debug++; 273 break; 274 case 'v': 275 verbose++; 276 break;
|
277 case 'a': 278 all_events++; 279 break; |
280 default: 281 usage(PROGNAME); 282 break; 283 } 284 } 285 286 if (!debug && daemon(0, 0)) 287 err(1, "failed to daemonize ourselves"); 288 289 if (!debug) 290 openlog(PROGNAME, LOG_PID | LOG_CONS, LOG_DAEMON); 291 292 bzero((char *)&sin, sizeof(sin)); 293 294 /* Create a datagram socket. */ 295 296 s = socket(PF_INET, SOCK_DGRAM, 0); 297 if (s < 0) { 298 dbgmsg("socket creation failed"); 299 exit(1); 300 } 301 302 sin.sin_family = AF_INET; 303 sin.sin_addr.s_addr = inet_addr("127.0.0.1"); 304 sin.sin_port = htons(WPA_SUPPLICANT_PORT); 305 306 /* Create a routing socket. */ 307 308 r = socket (PF_ROUTE, SOCK_RAW, 0); 309 if (r < 0) { 310 dbgmsg("routing socket creation failed"); 311 exit(1); 312 } 313 314 /* Now sit and spin, waiting for events. */ 315 316 if (verbose) 317 dbgmsg("Listening for events"); 318 319 while (1) { 320 n = read(r, msg, NDIS_INDICATION_LEN); 321 rtm = (struct rt_msghdr *)msg; 322 if (rtm->rtm_type != RTM_IFINFO) 323 continue; 324 ifm = (struct if_msghdr *)msg; 325 if (find_ifname(ifm->ifm_index, ifname)) 326 continue; 327 if (strstr(ifname, "ndis")) 328 announce_event(ifname, s, &sin); 329 else { 330 if (verbose) 331 dbgmsg("Skipping ifinfo message from %s", 332 ifname); 333 } 334 } 335 336 /* NOTREACHED */ 337 exit(0); 338}
|