📄 wlanconfig.c.svn-base
字号:
/*- * Copyright (c) 2005 Sam Leffler, Errno Consulting * 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, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. * * $Id$ *//* * wlanconfig athX create wlandev wifiX * wlanmode station | adhoc | ibss | ap | monitor [bssid | -bssid] * wlanconfig athX destroy */#include <sys/types.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#include <ctype.h>#include <getopt.h>#include <err.h>#include <include/compat.h>#include "wireless_copy.h"#include "net80211/ieee80211.h"#include "net80211/ieee80211_crypto.h"#include "net80211/ieee80211_ioctl.h"/* * These are taken from ieee80211_node.h */#define IEEE80211_NODE_TURBOP 0x0001 /* Turbo prime enable */#define IEEE80211_NODE_COMP 0x0002 /* Compresssion enable */#define IEEE80211_NODE_FF 0x0004 /* Fast Frame capable */#define IEEE80211_NODE_XR 0x0008 /* Atheros WME enable */#define IEEE80211_NODE_AR 0x0010 /* AR capable */#define IEEE80211_NODE_BOOST 0x0080#define streq(a,b) (strncasecmp(a, b, sizeof(b) - 1) == 0)#undef ARRAY_SIZE#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))static int if_split_name(const char *, char **, unsigned int *);static void vap_create(struct ifreq *);static void vap_destroy(const char *);static void list_stations(const char *);static void list_scan(const char *);static void list_channels(const char *, int);static void list_keys(const char *);static void list_capabilities(const char *);static void list_wme(const char *);static void ieee80211_status(const char *);static void usage(void);static int getopmode(const char *);static int getflag(const char *);static int get80211param(const char *, int, void *, size_t);static int get80211priv(const char *, int, void *, size_t);static const char *getstamode(u_int8_t);size_t strlcat(char *, const char *, size_t);static int verbose = 0;intmain(int argc, char *argv[]){ const char *ifname, *cmd; unsigned char bnounit = 0; char *if_base = NULL; unsigned int unit_res = -1; int res = 0; if (argc < 2 || strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--h", 3) == 0) usage(); ifname = argv[1]; if (argc == 2) { ieee80211_status(ifname); return 0; } cmd = argv[2]; if (streq(cmd, "create")) { struct ieee80211_clone_params cp; struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); memset(&cp, 0, sizeof(cp)); strncpy(cp.icp_name, ifname, IFNAMSIZ); /* NB: station mode is the default */ cp.icp_opmode = IEEE80211_M_STA; /* NB: default is to request a unique bssid/mac */ cp.icp_flags = IEEE80211_CLONE_BSSID; while (argc > 3) { if (strcmp(argv[3], "wlanmode") == 0) { if (argc < 5) usage(); cp.icp_opmode = (u_int16_t) getopmode(argv[4]); argc--; argv++; } else if (strcmp(argv[3], "wlandev") == 0) { if (argc < 5) usage(); strncpy(ifr.ifr_name, argv[4], IFNAMSIZ); argc--; argv++; } else if (strcmp(argv[3], "nounit") == 0) { bnounit = 1; } else { int flag = getflag(argv[3]); if (flag < 0) cp.icp_flags &= ~(-flag); else cp.icp_flags |= flag; } argc--; argv++; } if (ifr.ifr_name[0] == '\0') errx(1, "no device specified with wlandev"); res = if_split_name(cp.icp_name, &if_base, &unit_res); if (res < 0) { err(1, "if_split_name() - malloc"); } else if ((res == 0) && (bnounit == 0)) { /* user gave a string only and using a unit */ snprintf(cp.icp_name + strlen(if_base), IFNAMSIZ - strlen(if_base), "%%d"); } free(if_base); if_base = NULL; ifr.ifr_data = (void *)&cp; vap_create(&ifr); printf("%s\n", ifr.ifr_name); } else if (streq(cmd, "destroy")) { vap_destroy(ifname); } else if (streq(cmd, "list")) { if (argc > 3) { const char *arg = argv[3]; if (streq(arg, "sta")) list_stations(ifname); else if (streq(arg, "scan") || streq(arg, "ap")) list_scan(ifname); else if (streq(arg, "chan") || streq(arg, "freq")) list_channels(ifname, 1); else if (streq(arg, "active")) list_channels(ifname, 0); else if (streq(arg, "keys")) list_keys(ifname); else if (streq(arg, "caps")) list_capabilities(ifname); else if (streq(arg, "wme")) list_wme(ifname); else err(1, "unknown 'list' option: %s", arg); } else /* NB: for compatibility */ list_stations(ifname); } else usage(); return 0;}// if_split_name - takes a name and splits it into the longest non-numeric only string// including the first character plus the value of the longest numeric // string including the last character// returns : < 0 on error// 0 on finding only a string// 1 on finding a numeric/unit at the end of the string//// NOTE Allocates memory.static int if_split_name(const char *if_name, char **if_base_name, unsigned int *unit) { int status = -1; const char *p = NULL; const char *l = NULL; /* * Look for the unit from end to start */ l = if_name + strlen(if_name) - 1; for (p = l; p >= if_name; --p) { if (!isdigit(*p)) break; } if (p < l) { if (unit != NULL) *unit = atoi(p + 1); status = 1; } else status = 0; /* * Wherever the unit began, one index before it is the ending of the string */ if (if_base_name != NULL) { *if_base_name = malloc(p - if_name + 2); if (*if_base_name != NULL) { memset(*if_base_name, 0, p - if_name + 2); strncpy(*if_base_name, if_name, p - if_name + 1); } else status = -1; } return status;}static voidvap_create(struct ifreq *ifr){ int s; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) err(1, "socket(SOCK_DGRAM)"); if (ioctl(s, SIOC80211IFCREATE, ifr) < 0) err(1, "ioctl"); close(s);}static voidvap_destroy(const char *ifname){ struct ifreq ifr; int s; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) err(1, "socket(SOCK_DGRAM)"); memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(s, SIOC80211IFDESTROY, &ifr) < 0) err(1, "ioctl"); close(s);}static voidusage(void){ fprintf(stderr, "usage: wlanconfig athX create [nounit] wlandev wifiY\n"); fprintf(stderr, " wlanmode [sta|adhoc|ap|monitor|wds|ahdemo] [uniquebssid]\n"); fprintf(stderr, "usage: wlanconfig athX destroy\n"); fprintf(stderr, "usage: wlanconfig athX list [active|ap|caps|chan|freq|keys|scan|sta|wme]\n"); exit(-1);}static intgetopmode(const char *s){ if (streq(s, "sta") || streq(s, "managed")) return IEEE80211_M_STA; if (streq(s, "ibss") || streq(s, "adhoc") || streq(s, "ad-hoc")) return IEEE80211_M_IBSS; if (streq(s, "mon")) return IEEE80211_M_MONITOR; if (streq(s, "ap") || streq(s, "hostap") || streq(s, "master")) return IEEE80211_M_HOSTAP; if (streq(s, "wds")) return IEEE80211_M_WDS; if (streq(s, "ahdemo")) return IEEE80211_M_AHDEMO; errx(1, "unknown operating mode %s", s); /*NOTREACHED*/ return -1;}static intgetflag(const char *s){ const char *cp; int flag = 0; cp = (s[0] == '-' ? s + 1 : s); if (strcmp(cp, "bssid") == 0) { printf("WARNING: the -bssid and bssid flags are deprecated.\n"); flag = IEEE80211_CLONE_BSSID; } if (strcmp(cp, "uniquebssid") == 0) flag = IEEE80211_CLONE_BSSID; if (strcmp(cp, "nosbeacon") == 0) { printf("WARNING: the nosbeacon flag has been deprecated.\n"); return 0; /* deprecated but skip */ } if (flag == 0) errx(1, "unknown create option %s", s); return (s[0] == '-' ? -flag : flag);}/* * Convert MHz frequency to IEEE channel number. */static u_intieee80211_mhz2ieee(u_int freq){ if (freq == 2484) return 14; if (freq < 2484) return (freq - 2407) / 5; if (freq < 5000) return 15 + ((freq - 2512) / 20); return (freq - 5000) / 5;}/* * Convert RSSI to dBm. */static u_intrssi2dbm(u_int rssi){ return rssi - 95;}static intgetmaxrate(uint8_t rates[15], uint8_t nrates){ int i, maxrate = -1; for (i = 0; i < nrates; i++) { int rate = rates[i] & IEEE80211_RATE_VAL; if (rate > maxrate) maxrate = rate; } return maxrate / 2;}static const char *getcaps(int capinfo){ static char capstring[32]; char *cp = capstring; if (capinfo & IEEE80211_CAPINFO_ESS) *cp++ = 'E'; if (capinfo & IEEE80211_CAPINFO_IBSS) *cp++ = 'I'; if (capinfo & IEEE80211_CAPINFO_CF_POLLABLE) *cp++ = 'c'; if (capinfo & IEEE80211_CAPINFO_CF_POLLREQ) *cp++ = 'C'; if (capinfo & IEEE80211_CAPINFO_PRIVACY) *cp++ = 'P'; if (capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) *cp++ = 'S'; if (capinfo & IEEE80211_CAPINFO_PBCC) *cp++ = 'B'; if (capinfo & IEEE80211_CAPINFO_CHNL_AGILITY) *cp++ = 'A'; if (capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) *cp++ = 's'; if (capinfo & IEEE80211_CAPINFO_RSN) *cp++ = 'R'; if (capinfo & IEEE80211_CAPINFO_DSSSOFDM) *cp++ = 'D'; *cp = '\0'; return capstring;}static const char *getathcaps(int capinfo){ static char capstring[32]; char *cp = capstring; if (capinfo & IEEE80211_NODE_TURBOP) *cp++ = 'D'; if (capinfo & IEEE80211_NODE_COMP) *cp++ = 'C'; if (capinfo & IEEE80211_NODE_FF) *cp++ = 'F'; if (capinfo & IEEE80211_NODE_XR) *cp++ = 'X'; if (capinfo & IEEE80211_NODE_AR) *cp++ = 'A'; if (capinfo & IEEE80211_NODE_BOOST) *cp++ = 'T'; *cp = '\0'; return capstring;}static const char *getstamode(u_int8_t opmode){ if (opmode == IEEE80211_STA_OPMODE_XR) return "XR"; return "Normal";}static voidprintie(const char *tag, const uint8_t *ie, size_t ielen, int maxlen){ printf("%s", tag); if (verbose) { maxlen -= strlen(tag) + 2; if (2 * ielen > maxlen) maxlen--; printf("<"); for (; ielen > 0; ie++, ielen--) { if (maxlen-- <= 0) break; printf("%02x", *ie); } if (ielen != 0) printf("-"); printf(">"); }}/* * Copy the ssid string contents into buf, truncating to fit. If the * ssid is entirely printable then just copy intact. Otherwise convert * to hexadecimal. If the result is truncated then replace the last * three characters with "...". */static intcopy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len){ const u_int8_t *p; int maxlen; int i; if (essid_len > bufsize) maxlen = bufsize; else maxlen = essid_len; /* determine printable or not */ for (i = 0, p = essid; i < maxlen; i++, p++) { if (*p < ' ' || *p > 0x7e) break; } if (i != maxlen) { /* not printable, print as hex */ if (bufsize < 3) return 0;#if 0 strlcpy(buf, "0x", bufsize);#else strncpy(buf, "0x", bufsize);#endif bufsize -= 2; p = essid; for (i = 0; i < maxlen && bufsize >= 2; i++) { sprintf(&buf[2 + 2 * i], "%02x", *p++); bufsize -= 2; } maxlen = 2 + 2 * i; } else { /* printable, truncate as needed */ memcpy(buf, essid, maxlen); } if (maxlen != essid_len) memcpy(buf+maxlen - 3, "...", 3); return maxlen;}/* unaligned little endian access */#define LE_READ_4(p) \ ((u_int32_t) \ ((((const u_int8_t *)(p))[0] ) | \ (((const u_int8_t *)(p))[1] << 8) | \ (((const u_int8_t *)(p))[2] << 16) | \ (((const u_int8_t *)(p))[3] << 24)))static __inline intiswpaoui(const u_int8_t *frm){ return frm[1] > 3 && LE_READ_4(frm + 2) == ((WPA_OUI_TYPE << 24) | WPA_OUI);}static __inline intiswmeoui(const u_int8_t *frm){ return frm[1] > 3 && LE_READ_4(frm + 2) == ((WME_OUI_TYPE << 24) | WME_OUI);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -