├── Makefile ├── Nexus5_Nougat ├── README.md └── libnexmonkali.so ├── Nexus6P_Oreo ├── README.md └── libnexmonkali.so ├── README.md ├── bcm_cfg.h ├── bcmdefs.h ├── bcmutils.h ├── bcmwifi_channels.h ├── libnexio.c ├── monitormode.h ├── nexioctls.h ├── nexmon.c └── typedefs.h /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | 3 | CFLAGS = -std=c99 -I./ -I/usr/include/libnl3 4 | LDFLAGS = -shared -fPIC -ldl libnexio.a 5 | 6 | all: libnexio.a libnexmonkali.so 7 | 8 | libnexmonkali.so: libnexio.a nexmon.c 9 | $(CC) -o libnexmonkali.so $(CFLAGS) nexmon.c $(LDFLAGS) 10 | 11 | libnexio.a: libnexio.c 12 | $(CC) -c libnexio.c 13 | ar rcs libnexio.a libnexio.o 14 | 15 | clean: 16 | rm libnexmonkali.so libnexio.a libnexio.o 17 | 18 | install: 19 | cp libnexmonkali.so /usr/lib/ 20 | chmod 0755 /usr/lib/libnexmonkali.so 21 | chmod +x /usr/lib/libnexmonkali.so 22 | 23 | uninstall: 24 | rm /usr/lib/libnexmonkali.so 25 | -------------------------------------------------------------------------------- /Nexus5_Nougat/README.md: -------------------------------------------------------------------------------- 1 | Pre-compiled .so, built for Nexus 5 running Android 7.1 Nougat ("razorloves" build), with NetHunter 2021.2. 2 |

3 | The stock version is found in `/system/lib/kalilibnexmon.so`. 4 | -------------------------------------------------------------------------------- /Nexus5_Nougat/libnexmonkali.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoninNada/libnexmonkali/4abdc7673233eda5ca86125e2d333a86af2545ab/Nexus5_Nougat/libnexmonkali.so -------------------------------------------------------------------------------- /Nexus6P_Oreo/README.md: -------------------------------------------------------------------------------- 1 | Pre-compiled .so, built for Nexus 6P running Android 8.1.0 Oreo, with NetHunter 2020.3. 2 |

3 | The stock version is found in `/system/lib64/kalilibnexmon.so`. 4 | -------------------------------------------------------------------------------- /Nexus6P_Oreo/libnexmonkali.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoninNada/libnexmonkali/4abdc7673233eda5ca86125e2d333a86af2545ab/Nexus6P_Oreo/libnexmonkali.so -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is `libnexmonkali`? 2 | It's an alternate version of libnexmon.so from https://github.com/seemoo-lab/nexmon for building and usage in Kali Nethunter Chroot. 3 | 4 | It's a wrapper that will allow standard Linux wifi tools such as the `aircrack-ng` suite to use the onboard wifi interfaces on some mobile phones. 5 | 6 | There are prebuilt versions of `libnexmonkali.so` available in the repo for the Nexus 5 and Nexus 6P. 7 | 8 | # What's changed in this version from the stock NetHunter one? 9 | This is a replacement for the `kalilibnexmon.so` that currently ships in Kali NetHunter, that implements a few improvements. 10 | 11 | This version adds ioctl() support for SIOCSIWFREQ and SIOCGIWFREQ, meaning that programs that use ioctl calls will be able to directly get/set the channel of the onboard wifi instead of relying on the `nexutil` tool. 12 | 13 | Additionally, it adds a 50 millisecond delay after each injected frame, which seems to eliminate driver crashes when doing deauths with aireplay-ng. 14 | 15 | Now it's also intercepting `netlink` messages, which is a newer method for programs to tell drivers to do things like change wifi channels. The intent is to allow more programs to function with the non-standard wifi drivers found on the Nexus 5 and 6P. It's not a full implementation, but it helps some. 16 | 17 | # How does the `netlink` part work? 18 | We are intercepting the `nl_send_auto_complete` function that programs such as airodump-ng and kismet use to initiate a Netlink message, asking the kernel to tell the driver to change channels. 19 | We pass that message on to the kernel as usual, but also read the message and set the channel appropriately ourselves. 20 | Because this isn't the real driver, we won't send anything back to the program -- but airodump-ng and kismet don't bother to listen for replies anyway, so that's okay. 21 | Programs like `iw` do listen for a reply message, which we can't fake. They will complain that the channel change didn't work, but it actually did. 22 | 23 | ``` 24 | root@kali:~# nexutil -k 25 | chanspec: 0x1006, 6 26 | root@kali:~# LD_PRELOAD=/root/libnexmonkali/libnexmonkali.so iw dev wlan0 set channel 36 27 | command failed: Operation not supported (-95) 28 | root@kali:~# nexutil -k 29 | chanspec: 0xd024, 36 30 | ``` 31 | 32 | 33 | # Steps to Build 34 | Do the following from within your Kali NetHunter chroot environment. 35 | 36 | Clone the repo: 37 | `git clone https://github.com/dracode/libnexmonkali` 38 | 39 | Install dependencies: 40 | `apt install libnl-3-dev` 41 | 42 | Build: 43 | `make` 44 | 45 | Install: 46 | `make install` 47 | 48 | Use: 49 | `LD_PRELOAD=/path/to/libnexmonkali.so airodump-ng wlan0` 50 | 51 | -------------------------------------------------------------------------------- /bcm_cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BCM common config options 3 | * 4 | * Copyright (C) 1999-2013, Broadcom Corporation 5 | * 6 | * Unless you and Broadcom execute a separate written software license 7 | * agreement governing use of this software, this software is licensed to you 8 | * under the terms of the GNU General Public License version 2 (the "GPL"), 9 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 | * following added to such license: 11 | * 12 | * As a special exception, the copyright holders of this software give you 13 | * permission to link this software with independent modules, and to copy and 14 | * distribute the resulting executable under terms of your choice, provided that 15 | * you also meet, for each linked independent module, the terms and conditions of 16 | * the license of that module. An independent module is a module which is not 17 | * derived from this software. The special exception does not apply to any 18 | * modifications of the software. 19 | * 20 | * Notwithstanding the above, under no circumstances may you combine this 21 | * software in any way with any other Broadcom software provided under a license 22 | * other than the GPL, without Broadcom's express prior written consent. 23 | * 24 | * $Id: bcm_cfg.h 351867 2012-08-21 18:46:16Z $ 25 | */ 26 | 27 | #ifndef _bcm_cfg_h_ 28 | #define _bcm_cfg_h_ 29 | #endif /* _bcm_cfg_h_ */ 30 | -------------------------------------------------------------------------------- /bcmdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Misc system wide definitions 3 | * 4 | * Copyright (C) 1999-2013, Broadcom Corporation 5 | * 6 | * Unless you and Broadcom execute a separate written software license 7 | * agreement governing use of this software, this software is licensed to you 8 | * under the terms of the GNU General Public License version 2 (the "GPL"), 9 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 | * following added to such license: 11 | * 12 | * As a special exception, the copyright holders of this software give you 13 | * permission to link this software with independent modules, and to copy and 14 | * distribute the resulting executable under terms of your choice, provided that 15 | * you also meet, for each linked independent module, the terms and conditions of 16 | * the license of that module. An independent module is a module which is not 17 | * derived from this software. The special exception does not apply to any 18 | * modifications of the software. 19 | * 20 | * Notwithstanding the above, under no circumstances may you combine this 21 | * software in any way with any other Broadcom software provided under a license 22 | * other than the GPL, without Broadcom's express prior written consent. 23 | * 24 | * $Id: bcmdefs.h 416231 2013-08-02 07:38:34Z $ 25 | */ 26 | 27 | #ifndef _bcmdefs_h_ 28 | #define _bcmdefs_h_ 29 | 30 | /* 31 | * One doesn't need to include this file explicitly, gets included automatically if 32 | * typedefs.h is included. 33 | */ 34 | 35 | /* Use BCM_REFERENCE to suppress warnings about intentionally-unused function 36 | * arguments or local variables. 37 | */ 38 | #define BCM_REFERENCE(data) ((void)(data)) 39 | 40 | /* Compile-time assert can be used in place of ASSERT if the expression evaluates 41 | * to a constant at compile time. 42 | */ 43 | #define STATIC_ASSERT(expr) { \ 44 | /* Make sure the expression is constant. */ \ 45 | typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e; \ 46 | /* Make sure the expression is true. */ \ 47 | typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1]; \ 48 | } 49 | 50 | /* Reclaiming text and data : 51 | * The following macros specify special linker sections that can be reclaimed 52 | * after a system is considered 'up'. 53 | * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN, 54 | * as in most cases, the attach function calls the detach function to clean up on error). 55 | */ 56 | 57 | #define bcmreclaimed 0 58 | #define _data _data 59 | #define _fn _fn 60 | #define BCMPREATTACHDATA(_data) _data 61 | #define BCMPREATTACHFN(_fn) _fn 62 | #define _data _data 63 | #define _fn _fn 64 | #define _fn _fn 65 | #define BCMNMIATTACHFN(_fn) _fn 66 | #define BCMNMIATTACHDATA(_data) _data 67 | #define CONST const 68 | 69 | /* Do not put BCM47XX and __ARM_ARCH_7A__ to the same line. 70 | * DHD build has problem because the BCM47XX will be excluded in DHD release. 71 | */ 72 | #undef BCM47XX_CA9 73 | #ifdef __ARM_ARCH_7A__ 74 | #define BCM47XX_CA9 75 | #endif /* __ARM_ARCH_7A__ */ 76 | #ifndef BCMFASTPATH 77 | #if defined(BCM47XX_CA9) 78 | #define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) 79 | #define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) 80 | #else 81 | #define BCMFASTPATH 82 | #define BCMFASTPATH_HOST 83 | #endif 84 | #endif /* BCMFASTPATH */ 85 | 86 | 87 | /* Put some library data/code into ROM to reduce RAM requirements */ 88 | #define _data _data 89 | #define BCMROMDAT_NAME(_data) _data 90 | #define _fn _fn 91 | #define _fn _fn 92 | #define STATIC static 93 | #define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data) 94 | #define BCMROMDAT_SIZEOF(data) sizeof(data) 95 | #define BCMROMDAT_APATCH(data) 96 | #define BCMROMDAT_SPATCH(data) 97 | 98 | /* Bus types */ 99 | #define SI_BUS 0 /* SOC Interconnect */ 100 | #define PCI_BUS 1 /* PCI target */ 101 | #define PCMCIA_BUS 2 /* PCMCIA target */ 102 | #define SDIO_BUS 3 /* SDIO target */ 103 | #define JTAG_BUS 4 /* JTAG */ 104 | #define USB_BUS 5 /* USB (does not support R/W REG) */ 105 | #define SPI_BUS 6 /* gSPI target */ 106 | #define RPC_BUS 7 /* RPC target */ 107 | 108 | /* Allows size optimization for single-bus image */ 109 | #ifdef BCMBUSTYPE 110 | #define BUSTYPE(bus) (BCMBUSTYPE) 111 | #else 112 | #define BUSTYPE(bus) (bus) 113 | #endif 114 | 115 | /* Allows size optimization for single-backplane image */ 116 | #ifdef BCMCHIPTYPE 117 | #define CHIPTYPE(bus) (BCMCHIPTYPE) 118 | #else 119 | #define CHIPTYPE(bus) (bus) 120 | #endif 121 | 122 | 123 | /* Allows size optimization for SPROM support */ 124 | #if defined(BCMSPROMBUS) 125 | #define SPROMBUS (BCMSPROMBUS) 126 | #elif defined(SI_PCMCIA_SROM) 127 | #define SPROMBUS (PCMCIA_BUS) 128 | #else 129 | #define SPROMBUS (PCI_BUS) 130 | #endif 131 | 132 | /* Allows size optimization for single-chip image */ 133 | #ifdef BCMCHIPID 134 | #define CHIPID(chip) (BCMCHIPID) 135 | #else 136 | #define CHIPID(chip) (chip) 137 | #endif 138 | 139 | #ifdef BCMCHIPREV 140 | #define CHIPREV(rev) (BCMCHIPREV) 141 | #else 142 | #define CHIPREV(rev) (rev) 143 | #endif 144 | 145 | /* Defines for DMA Address Width - Shared between OSL and HNDDMA */ 146 | #define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ 147 | #define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ 148 | #define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ 149 | 150 | #define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ 151 | #define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ 152 | #define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ 153 | #define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ 154 | 155 | #ifdef BCMDMA64OSL 156 | typedef struct { 157 | uint32 loaddr; 158 | uint32 hiaddr; 159 | } dma64addr_t; 160 | 161 | typedef dma64addr_t dmaaddr_t; 162 | #define PHYSADDRHI(_pa) ((_pa).hiaddr) 163 | #define PHYSADDRHISET(_pa, _val) \ 164 | do { \ 165 | (_pa).hiaddr = (_val); \ 166 | } while (0) 167 | #define PHYSADDRLO(_pa) ((_pa).loaddr) 168 | #define PHYSADDRLOSET(_pa, _val) \ 169 | do { \ 170 | (_pa).loaddr = (_val); \ 171 | } while (0) 172 | 173 | #else 174 | typedef unsigned long dmaaddr_t; 175 | #define PHYSADDRHI(_pa) (0) 176 | #define PHYSADDRHISET(_pa, _val) 177 | #define PHYSADDRLO(_pa) ((_pa)) 178 | #define PHYSADDRLOSET(_pa, _val) \ 179 | do { \ 180 | (_pa) = (_val); \ 181 | } while (0) 182 | #endif /* BCMDMA64OSL */ 183 | 184 | /* One physical DMA segment */ 185 | typedef struct { 186 | dmaaddr_t addr; 187 | uint32 length; 188 | } hnddma_seg_t; 189 | 190 | #define MAX_DMA_SEGS 4 191 | 192 | 193 | typedef struct { 194 | void *oshdmah; /* Opaque handle for OSL to store its information */ 195 | uint origsize; /* Size of the virtual packet */ 196 | uint nsegs; 197 | hnddma_seg_t segs[MAX_DMA_SEGS]; 198 | } hnddma_seg_map_t; 199 | 200 | 201 | /* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). 202 | * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. 203 | * There is a compile time check in wlc.c which ensure that this value is at least as big 204 | * as TXOFF. This value is used in dma_rxfill (hnddma.c). 205 | */ 206 | 207 | #if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) 208 | /* add 40 bytes to allow for extra RPC header and info */ 209 | #define BCMEXTRAHDROOM 260 210 | #else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ 211 | #if defined(BCM47XX_CA9) 212 | #define BCMEXTRAHDROOM 224 213 | #else 214 | #define BCMEXTRAHDROOM 204 215 | #endif /* linux && BCM47XX_CA9 */ 216 | #endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ 217 | 218 | /* Packet alignment for most efficient SDIO (can change based on platform) */ 219 | #ifndef SDALIGN 220 | #define SDALIGN 32 221 | #endif 222 | 223 | /* Headroom required for dongle-to-host communication. Packets allocated 224 | * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should 225 | * leave this much room in front for low-level message headers which may 226 | * be needed to get across the dongle bus to the host. (These messages 227 | * don't go over the network, so room for the full WL header above would 228 | * be a waste.). 229 | */ 230 | #define BCMDONGLEHDRSZ 12 231 | #define BCMDONGLEPADSZ 16 232 | 233 | #define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) 234 | 235 | 236 | #if defined(NO_BCMDBG_ASSERT) 237 | # undef BCMDBG_ASSERT 238 | # undef BCMASSERT_LOG 239 | #endif 240 | 241 | #if defined(BCMASSERT_LOG) 242 | #define BCMASSERT_SUPPORT 243 | #endif 244 | 245 | /* Macros for doing definition and get/set of bitfields 246 | * Usage example, e.g. a three-bit field (bits 4-6): 247 | * #define _M BITFIELD_MASK(3) 248 | * #define _S 4 249 | * ... 250 | * regval = R_REG(osh, ®s->regfoo); 251 | * field = GFIELD(regval, ); 252 | * regval = SFIELD(regval, , 1); 253 | * W_REG(osh, ®s->regfoo, regval); 254 | */ 255 | #define BITFIELD_MASK(width) \ 256 | (((unsigned)1 << (width)) - 1) 257 | #define GFIELD(val, field) \ 258 | (((val) >> field ## _S) & field ## _M) 259 | #define SFIELD(val, field, bits) \ 260 | (((val) & (~(field ## _M << field ## _S))) | \ 261 | ((unsigned)(bits) << field ## _S)) 262 | 263 | /* define BCMSMALL to remove misc features for memory-constrained environments */ 264 | #ifdef BCMSMALL 265 | #undef BCMSPACE 266 | #define bcmspace FALSE /* if (bcmspace) code is discarded */ 267 | #else 268 | #define BCMSPACE 269 | #define bcmspace TRUE /* if (bcmspace) code is retained */ 270 | #endif 271 | 272 | /* Max. nvram variable table size */ 273 | #define MAXSZ_NVRAM_VARS 4096 274 | 275 | 276 | /* Max size for reclaimable NVRAM array */ 277 | #ifdef DL_NVRAM 278 | #define NVRAM_ARRAY_MAXSIZE DL_NVRAM 279 | #else 280 | #define NVRAM_ARRAY_MAXSIZE MAXSZ_NVRAM_VARS 281 | #endif /* DL_NVRAM */ 282 | 283 | #ifdef BCMUSBDEV_ENABLED 284 | extern uint32 gFWID; 285 | #endif 286 | 287 | #endif /* _bcmdefs_h_ */ 288 | -------------------------------------------------------------------------------- /bcmutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Misc useful os-independent macros and functions. 3 | * 4 | * Copyright (C) 1999-2013, Broadcom Corporation 5 | * 6 | * Unless you and Broadcom execute a separate written software license 7 | * agreement governing use of this software, this software is licensed to you 8 | * under the terms of the GNU General Public License version 2 (the "GPL"), 9 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 | * following added to such license: 11 | * 12 | * As a special exception, the copyright holders of this software give you 13 | * permission to link this software with independent modules, and to copy and 14 | * distribute the resulting executable under terms of your choice, provided that 15 | * you also meet, for each linked independent module, the terms and conditions of 16 | * the license of that module. An independent module is a module which is not 17 | * derived from this software. The special exception does not apply to any 18 | * modifications of the software. 19 | * 20 | * Notwithstanding the above, under no circumstances may you combine this 21 | * software in any way with any other Broadcom software provided under a license 22 | * other than the GPL, without Broadcom's express prior written consent. 23 | * 24 | * $Id: bcmutils.h 412804 2013-07-16 16:26:39Z $ 25 | */ 26 | 27 | #ifndef _bcmutils_h_ 28 | #define _bcmutils_h_ 29 | 30 | #define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src)) 31 | #define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count)) 32 | #define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src)) 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #ifdef PKTQ_LOG 39 | #include 40 | #endif 41 | 42 | /* ctype replacement */ 43 | #define _BCM_U 0x01 /* upper */ 44 | #define _BCM_L 0x02 /* lower */ 45 | #define _BCM_D 0x04 /* digit */ 46 | #define _BCM_C 0x08 /* cntrl */ 47 | #define _BCM_P 0x10 /* punct */ 48 | #define _BCM_S 0x20 /* white space (space/lf/tab) */ 49 | #define _BCM_X 0x40 /* hex digit */ 50 | #define _BCM_SP 0x80 /* hard space (0x20) */ 51 | 52 | extern const unsigned char bcm_ctype[]; 53 | #define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) 54 | 55 | #define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) 56 | #define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) 57 | #define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) 58 | #define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) 59 | #define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) 60 | #define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) 61 | #define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) 62 | #define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) 63 | #define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) 64 | #define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) 65 | #define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) 66 | #define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) 67 | #define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) 68 | 69 | /* Buffer structure for collecting string-formatted data 70 | * using bcm_bprintf() API. 71 | * Use bcm_binit() to initialize before use 72 | */ 73 | 74 | struct bcmstrbuf { 75 | char *buf; /* pointer to current position in origbuf */ 76 | unsigned int size; /* current (residual) size in bytes */ 77 | char *origbuf; /* unmodified pointer to orignal buffer */ 78 | unsigned int origsize; /* unmodified orignal buffer size in bytes */ 79 | }; 80 | 81 | /* ** driver-only section ** */ 82 | #ifdef BCMDRIVER 83 | #include 84 | 85 | #define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ 86 | 87 | /* 88 | * Spin at most 'us' microseconds while 'exp' is true. 89 | * Caller should explicitly test 'exp' when this completes 90 | * and take appropriate error action if 'exp' is still true. 91 | */ 92 | #define SPINWAIT(exp, us) { \ 93 | uint countdown = (us) + 9; \ 94 | while ((exp) && (countdown >= 10)) {\ 95 | OSL_DELAY(10); \ 96 | countdown -= 10; \ 97 | } \ 98 | } 99 | 100 | /* osl multi-precedence packet queue */ 101 | #ifndef PKTQ_LEN_DEFAULT 102 | #define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ 103 | #endif 104 | #ifndef PKTQ_MAX_PREC 105 | #define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ 106 | #endif 107 | 108 | typedef struct pktq_prec { 109 | void *head; /* first packet to dequeue */ 110 | void *tail; /* last packet to dequeue */ 111 | uint16 len; /* number of queued packets */ 112 | uint16 max; /* maximum number of queued packets */ 113 | } pktq_prec_t; 114 | 115 | #ifdef PKTQ_LOG 116 | typedef struct { 117 | uint32 requested; /* packets requested to be stored */ 118 | uint32 stored; /* packets stored */ 119 | uint32 saved; /* packets saved, 120 | because a lowest priority queue has given away one packet 121 | */ 122 | uint32 selfsaved; /* packets saved, 123 | because an older packet from the same queue has been dropped 124 | */ 125 | uint32 full_dropped; /* packets dropped, 126 | because pktq is full with higher precedence packets 127 | */ 128 | uint32 dropped; /* packets dropped because pktq per that precedence is full */ 129 | uint32 sacrificed; /* packets dropped, 130 | in order to save one from a queue of a highest priority 131 | */ 132 | uint32 busy; /* packets droped because of hardware/transmission error */ 133 | uint32 retry; /* packets re-sent because they were not received */ 134 | uint32 ps_retry; /* packets retried again prior to moving power save mode */ 135 | uint32 retry_drop; /* packets finally dropped after retry limit */ 136 | uint32 max_avail; /* the high-water mark of the queue capacity for packets - 137 | goes to zero as queue fills 138 | */ 139 | uint32 max_used; /* the high-water mark of the queue utilisation for packets - 140 | increases with use ('inverse' of max_avail) 141 | */ 142 | uint32 queue_capacity; /* the maximum capacity of the queue */ 143 | uint32 rtsfail; /* count of rts attempts that failed to receive cts */ 144 | uint32 acked; /* count of packets sent (acked) successfully */ 145 | } pktq_counters_t; 146 | #endif /* PKTQ_LOG */ 147 | 148 | 149 | #define PKTQ_COMMON \ 150 | uint16 num_prec; /* number of precedences in use */ \ 151 | uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \ 152 | uint16 max; /* total max packets */ \ 153 | uint16 len; /* total number of packets */ 154 | 155 | /* multi-priority pkt queue */ 156 | struct pktq { 157 | PKTQ_COMMON 158 | /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ 159 | struct pktq_prec q[PKTQ_MAX_PREC]; 160 | #ifdef PKTQ_LOG 161 | pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ 162 | pktq_counters_t _prec_bytes[PKTQ_MAX_PREC]; /* Byte count per queue */ 163 | uint32 _logtime; /* timestamp of last counter clear */ 164 | #endif 165 | }; 166 | 167 | /* simple, non-priority pkt queue */ 168 | struct spktq { 169 | PKTQ_COMMON 170 | /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ 171 | struct pktq_prec q[1]; 172 | }; 173 | 174 | #define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) 175 | 176 | /* fn(pkt, arg). return true if pkt belongs to if */ 177 | typedef bool (*ifpkt_cb_t)(void*, int); 178 | 179 | #ifdef BCMPKTPOOL 180 | #define POOL_ENAB(pool) ((pool) && (pool)->inited) 181 | #define SHARED_POOL (pktpool_shared) 182 | #else /* BCMPKTPOOL */ 183 | #define POOL_ENAB(bus) 0 184 | #define SHARED_POOL ((struct pktpool *)NULL) 185 | #endif /* BCMPKTPOOL */ 186 | 187 | #ifndef PKTPOOL_LEN_MAX 188 | #define PKTPOOL_LEN_MAX 40 189 | #endif /* PKTPOOL_LEN_MAX */ 190 | #define PKTPOOL_CB_MAX 3 191 | 192 | struct pktpool; 193 | typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); 194 | typedef struct { 195 | pktpool_cb_t cb; 196 | void *arg; 197 | } pktpool_cbinfo_t; 198 | 199 | #ifdef BCMDBG_POOL 200 | /* pkt pool debug states */ 201 | #define POOL_IDLE 0 202 | #define POOL_RXFILL 1 203 | #define POOL_RXDH 2 204 | #define POOL_RXD11 3 205 | #define POOL_TXDH 4 206 | #define POOL_TXD11 5 207 | #define POOL_AMPDU 6 208 | #define POOL_TXENQ 7 209 | 210 | typedef struct { 211 | void *p; 212 | uint32 cycles; 213 | uint32 dur; 214 | } pktpool_dbg_t; 215 | 216 | typedef struct { 217 | uint8 txdh; /* tx to host */ 218 | uint8 txd11; /* tx to d11 */ 219 | uint8 enq; /* waiting in q */ 220 | uint8 rxdh; /* rx from host */ 221 | uint8 rxd11; /* rx from d11 */ 222 | uint8 rxfill; /* dma_rxfill */ 223 | uint8 idle; /* avail in pool */ 224 | } pktpool_stats_t; 225 | #endif /* BCMDBG_POOL */ 226 | 227 | typedef struct pktpool { 228 | bool inited; 229 | uint16 r; 230 | uint16 w; 231 | uint16 len; 232 | uint16 maxlen; 233 | uint16 plen; 234 | bool istx; 235 | bool empty; 236 | uint8 cbtoggle; 237 | uint8 cbcnt; 238 | uint8 ecbcnt; 239 | bool emptycb_disable; 240 | pktpool_cbinfo_t *availcb_excl; 241 | pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX]; 242 | pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; 243 | void *q[PKTPOOL_LEN_MAX + 1]; 244 | 245 | #ifdef BCMDBG_POOL 246 | uint8 dbg_cbcnt; 247 | pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; 248 | uint16 dbg_qlen; 249 | pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; 250 | #endif 251 | } pktpool_t; 252 | 253 | extern pktpool_t *pktpool_shared; 254 | 255 | extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx); 256 | extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); 257 | extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); 258 | extern void* pktpool_get(pktpool_t *pktp); 259 | extern void pktpool_free(pktpool_t *pktp, void *p); 260 | extern int pktpool_add(pktpool_t *pktp, void *p); 261 | extern uint16 pktpool_avail(pktpool_t *pktp); 262 | extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); 263 | extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); 264 | extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 265 | extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 266 | extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); 267 | extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); 268 | extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); 269 | extern bool pktpool_emptycb_disabled(pktpool_t *pktp); 270 | 271 | #define POOLPTR(pp) ((pktpool_t *)(pp)) 272 | #define pktpool_len(pp) (POOLPTR(pp)->len - 1) 273 | #define pktpool_plen(pp) (POOLPTR(pp)->plen) 274 | #define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen) 275 | 276 | #ifdef BCMDBG_POOL 277 | extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 278 | extern int pktpool_start_trigger(pktpool_t *pktp, void *p); 279 | extern int pktpool_dbg_dump(pktpool_t *pktp); 280 | extern int pktpool_dbg_notify(pktpool_t *pktp); 281 | extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); 282 | #endif /* BCMDBG_POOL */ 283 | 284 | /* forward definition of ether_addr structure used by some function prototypes */ 285 | 286 | struct ether_addr; 287 | 288 | extern int ether_isbcast(const void *ea); 289 | extern int ether_isnulladdr(const void *ea); 290 | 291 | /* operations on a specific precedence in packet queue */ 292 | 293 | #define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) 294 | #define pktq_pmax(pq, prec) ((pq)->q[prec].max) 295 | #define pktq_plen(pq, prec) ((pq)->q[prec].len) 296 | #define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) 297 | #define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) 298 | #define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) 299 | 300 | #define pktq_ppeek(pq, prec) ((pq)->q[prec].head) 301 | #define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) 302 | 303 | extern void *pktq_penq(struct pktq *pq, int prec, void *p); 304 | extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); 305 | extern void *pktq_pdeq(struct pktq *pq, int prec); 306 | extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); 307 | extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg); 308 | extern void *pktq_pdeq_tail(struct pktq *pq, int prec); 309 | /* Empty the queue at particular precedence level */ 310 | extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, 311 | ifpkt_cb_t fn, int arg); 312 | /* Remove a specified packet from its queue */ 313 | extern bool pktq_pdel(struct pktq *pq, void *p, int prec); 314 | 315 | /* operations on a set of precedences in packet queue */ 316 | 317 | extern int pktq_mlen(struct pktq *pq, uint prec_bmp); 318 | extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); 319 | extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); 320 | 321 | /* operations on packet queue as a whole */ 322 | 323 | #define pktq_len(pq) ((int)(pq)->len) 324 | #define pktq_max(pq) ((int)(pq)->max) 325 | #define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) 326 | #define pktq_full(pq) ((pq)->len >= (pq)->max) 327 | #define pktq_empty(pq) ((pq)->len == 0) 328 | 329 | /* operations for single precedence queues */ 330 | #define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) 331 | #define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) 332 | #define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) 333 | #define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) 334 | #define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) 335 | 336 | extern void pktq_init(struct pktq *pq, int num_prec, int max_len); 337 | extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); 338 | 339 | /* prec_out may be NULL if caller is not interested in return value */ 340 | extern void *pktq_deq(struct pktq *pq, int *prec_out); 341 | extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); 342 | extern void *pktq_peek(struct pktq *pq, int *prec_out); 343 | extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); 344 | extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg); 345 | 346 | /* externs */ 347 | /* packet */ 348 | extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); 349 | extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); 350 | extern uint pkttotlen(osl_t *osh, void *p); 351 | extern void *pktlast(osl_t *osh, void *p); 352 | extern uint pktsegcnt(osl_t *osh, void *p); 353 | extern uint pktsegcnt_war(osl_t *osh, void *p); 354 | extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset); 355 | extern void *pktoffset(osl_t *osh, void *p, uint offset); 356 | 357 | /* Get priority from a packet and pass it back in scb (or equiv) */ 358 | #define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ 359 | #define PKTPRIO_VLAN 0x200 /* VLAN prio found */ 360 | #define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ 361 | #define PKTPRIO_DSCP 0x800 /* DSCP prio found */ 362 | 363 | /* DSCP type definitions (RFC4594) */ 364 | /* AF1x: High-Throughput Data (RFC2597) */ 365 | #define DSCP_AF11 0x0A 366 | #define DSCP_AF12 0x0C 367 | #define DSCP_AF13 0x0E 368 | /* AF2x: Low-Latency Data (RFC2597) */ 369 | #define DSCP_AF21 0x12 370 | #define DSCP_AF22 0x14 371 | #define DSCP_AF23 0x16 372 | /* AF3x: Multimedia Streaming (RFC2597) */ 373 | #define DSCP_AF31 0x1A 374 | #define DSCP_AF32 0x1C 375 | #define DSCP_AF33 0x1E 376 | /* EF: Telephony (RFC3246) */ 377 | #define DSCP_EF 0x2E 378 | 379 | extern uint pktsetprio(void *pkt, bool update_vtag); 380 | 381 | /* string */ 382 | extern int bcm_atoi(const char *s); 383 | extern ulong bcm_strtoul(const char *cp, char **endp, uint base); 384 | extern char *bcmstrstr(const char *haystack, const char *needle); 385 | extern char *bcmstrcat(char *dest, const char *src); 386 | extern char *bcmstrncat(char *dest, const char *src, uint size); 387 | extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); 388 | char* bcmstrtok(char **string, const char *delimiters, char *tokdelim); 389 | int bcmstricmp(const char *s1, const char *s2); 390 | int bcmstrnicmp(const char* s1, const char* s2, int cnt); 391 | 392 | 393 | /* ethernet address */ 394 | extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf); 395 | extern int bcm_ether_atoe(const char *p, struct ether_addr *ea); 396 | 397 | /* ip address */ 398 | struct ipv4_addr; 399 | extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); 400 | 401 | /* delay */ 402 | extern void bcm_mdelay(uint ms); 403 | /* variable access */ 404 | #define NVRAM_RECLAIM_CHECK(name) 405 | 406 | extern char *getvar(char *vars, const char *name); 407 | extern int getintvar(char *vars, const char *name); 408 | extern int getintvararray(char *vars, const char *name, int index); 409 | extern int getintvararraysize(char *vars, const char *name); 410 | extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); 411 | #define bcm_perf_enable() 412 | #define bcmstats(fmt) 413 | #define bcmlog(fmt, a1, a2) 414 | #define bcmdumplog(buf, size) *buf = '\0' 415 | #define bcmdumplogent(buf, idx) -1 416 | 417 | #define bcmtslog(tstamp, fmt, a1, a2) 418 | #define bcmprinttslogs() 419 | #define bcmprinttstamp(us) 420 | #define bcmdumptslog(buf, size) 421 | 422 | extern char *bcm_nvram_vars(uint *length); 423 | extern int bcm_nvram_cache(void *sih); 424 | 425 | /* Support for sharing code across in-driver iovar implementations. 426 | * The intent is that a driver use this structure to map iovar names 427 | * to its (private) iovar identifiers, and the lookup function to 428 | * find the entry. Macros are provided to map ids and get/set actions 429 | * into a single number space for a switch statement. 430 | */ 431 | 432 | /* iovar structure */ 433 | typedef struct bcm_iovar { 434 | const char *name; /* name for lookup and display */ 435 | uint16 varid; /* id for switch */ 436 | uint16 flags; /* driver-specific flag bits */ 437 | uint16 type; /* base type of argument */ 438 | uint16 minlen; /* min length for buffer vars */ 439 | } bcm_iovar_t; 440 | 441 | /* varid definitions are per-driver, may use these get/set bits */ 442 | 443 | /* IOVar action bits for id mapping */ 444 | #define IOV_GET 0 /* Get an iovar */ 445 | #define IOV_SET 1 /* Set an iovar */ 446 | 447 | /* Varid to actionid mapping */ 448 | #define IOV_GVAL(id) ((id) * 2) 449 | #define IOV_SVAL(id) ((id) * 2 + IOV_SET) 450 | #define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) 451 | #define IOV_ID(actionid) (actionid >> 1) 452 | 453 | /* flags are per-driver based on driver attributes */ 454 | 455 | extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); 456 | extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); 457 | #if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ 458 | defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) 459 | extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); 460 | #endif 461 | #endif /* BCMDRIVER */ 462 | 463 | /* Base type definitions */ 464 | #define IOVT_VOID 0 /* no value (implictly set only) */ 465 | #define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ 466 | #define IOVT_INT8 2 /* integer values are range-checked */ 467 | #define IOVT_UINT8 3 /* unsigned int 8 bits */ 468 | #define IOVT_INT16 4 /* int 16 bits */ 469 | #define IOVT_UINT16 5 /* unsigned int 16 bits */ 470 | #define IOVT_INT32 6 /* int 32 bits */ 471 | #define IOVT_UINT32 7 /* unsigned int 32 bits */ 472 | #define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ 473 | #define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) 474 | 475 | /* Initializer for IOV type strings */ 476 | #define BCM_IOV_TYPE_INIT { \ 477 | "void", \ 478 | "bool", \ 479 | "int8", \ 480 | "uint8", \ 481 | "int16", \ 482 | "uint16", \ 483 | "int32", \ 484 | "uint32", \ 485 | "buffer", \ 486 | "" } 487 | 488 | #define BCM_IOVT_IS_INT(type) (\ 489 | (type == IOVT_BOOL) || \ 490 | (type == IOVT_INT8) || \ 491 | (type == IOVT_UINT8) || \ 492 | (type == IOVT_INT16) || \ 493 | (type == IOVT_UINT16) || \ 494 | (type == IOVT_INT32) || \ 495 | (type == IOVT_UINT32)) 496 | 497 | /* ** driver/apps-shared section ** */ 498 | 499 | #define BCME_STRLEN 64 /* Max string length for BCM errors */ 500 | #define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) 501 | 502 | 503 | /* 504 | * error codes could be added but the defined ones shouldn't be changed/deleted 505 | * these error codes are exposed to the user code 506 | * when ever a new error code is added to this list 507 | * please update errorstring table with the related error string and 508 | * update osl files with os specific errorcode map 509 | */ 510 | 511 | #define BCME_OK 0 /* Success */ 512 | #define BCME_ERROR -1 /* Error generic */ 513 | #define BCME_BADARG -2 /* Bad Argument */ 514 | #define BCME_BADOPTION -3 /* Bad option */ 515 | #define BCME_NOTUP -4 /* Not up */ 516 | #define BCME_NOTDOWN -5 /* Not down */ 517 | #define BCME_NOTAP -6 /* Not AP */ 518 | #define BCME_NOTSTA -7 /* Not STA */ 519 | #define BCME_BADKEYIDX -8 /* BAD Key Index */ 520 | #define BCME_RADIOOFF -9 /* Radio Off */ 521 | #define BCME_NOTBANDLOCKED -10 /* Not band locked */ 522 | #define BCME_NOCLK -11 /* No Clock */ 523 | #define BCME_BADRATESET -12 /* BAD Rate valueset */ 524 | #define BCME_BADBAND -13 /* BAD Band */ 525 | #define BCME_BUFTOOSHORT -14 /* Buffer too short */ 526 | #define BCME_BUFTOOLONG -15 /* Buffer too long */ 527 | #define BCME_BUSY -16 /* Busy */ 528 | #define BCME_NOTASSOCIATED -17 /* Not Associated */ 529 | #define BCME_BADSSIDLEN -18 /* Bad SSID len */ 530 | #define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ 531 | #define BCME_BADCHAN -20 /* Bad Channel */ 532 | #define BCME_BADADDR -21 /* Bad Address */ 533 | #define BCME_NORESOURCE -22 /* Not Enough Resources */ 534 | #define BCME_UNSUPPORTED -23 /* Unsupported */ 535 | #define BCME_BADLEN -24 /* Bad length */ 536 | #define BCME_NOTREADY -25 /* Not Ready */ 537 | #define BCME_EPERM -26 /* Not Permitted */ 538 | #define BCME_NOMEM -27 /* No Memory */ 539 | #define BCME_ASSOCIATED -28 /* Associated */ 540 | #define BCME_RANGE -29 /* Not In Range */ 541 | #define BCME_NOTFOUND -30 /* Not Found */ 542 | #define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ 543 | #define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ 544 | #define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ 545 | #define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ 546 | #define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ 547 | #define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ 548 | #define BCME_VERSION -37 /* Incorrect version */ 549 | #define BCME_TXFAIL -38 /* TX failure */ 550 | #define BCME_RXFAIL -39 /* RX failure */ 551 | #define BCME_NODEVICE -40 /* Device not present */ 552 | #define BCME_NMODE_DISABLED -41 /* NMODE disabled */ 553 | #define BCME_NONRESIDENT -42 /* access to nonresident overlay */ 554 | #define BCME_SCANREJECT -43 /* reject scan request */ 555 | #define BCME_USAGE_ERROR -44 /* WLCMD usage error */ 556 | #define BCME_IOCTL_ERROR -45 /* WLCMD ioctl error */ 557 | #define BCME_SERIAL_PORT_ERR -46 /* RWL serial port error */ 558 | #define BCME_LAST BCME_SERIAL_PORT_ERR 559 | 560 | /* These are collection of BCME Error strings */ 561 | #define BCMERRSTRINGTABLE { \ 562 | "OK", \ 563 | "Undefined error", \ 564 | "Bad Argument", \ 565 | "Bad Option", \ 566 | "Not up", \ 567 | "Not down", \ 568 | "Not AP", \ 569 | "Not STA", \ 570 | "Bad Key Index", \ 571 | "Radio Off", \ 572 | "Not band locked", \ 573 | "No clock", \ 574 | "Bad Rate valueset", \ 575 | "Bad Band", \ 576 | "Buffer too short", \ 577 | "Buffer too long", \ 578 | "Busy", \ 579 | "Not Associated", \ 580 | "Bad SSID len", \ 581 | "Out of Range Channel", \ 582 | "Bad Channel", \ 583 | "Bad Address", \ 584 | "Not Enough Resources", \ 585 | "Unsupported", \ 586 | "Bad length", \ 587 | "Not Ready", \ 588 | "Not Permitted", \ 589 | "No Memory", \ 590 | "Associated", \ 591 | "Not In Range", \ 592 | "Not Found", \ 593 | "WME Not Enabled", \ 594 | "TSPEC Not Found", \ 595 | "ACM Not Supported", \ 596 | "Not WME Association", \ 597 | "SDIO Bus Error", \ 598 | "Dongle Not Accessible", \ 599 | "Incorrect version", \ 600 | "TX Failure", \ 601 | "RX Failure", \ 602 | "Device Not Present", \ 603 | "NMODE Disabled", \ 604 | "Nonresident overlay access", \ 605 | "Scan Rejected", \ 606 | "WLCMD usage error", \ 607 | "WLCMD ioctl error", \ 608 | "RWL serial port error", \ 609 | } 610 | 611 | #ifndef ABS 612 | #define ABS(a) (((a) < 0) ? -(a) : (a)) 613 | #endif /* ABS */ 614 | 615 | #ifndef MIN 616 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 617 | #endif /* MIN */ 618 | 619 | #ifndef MAX 620 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 621 | #endif /* MAX */ 622 | 623 | /* limit to [min, max] */ 624 | #ifndef LIMIT_TO_RANGE 625 | #define LIMIT_TO_RANGE(x, min, max) \ 626 | ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) 627 | #endif /* LIMIT_TO_RANGE */ 628 | 629 | /* limit to max */ 630 | #ifndef LIMIT_TO_MAX 631 | #define LIMIT_TO_MAX(x, max) \ 632 | (((x) > (max) ? (max) : (x))) 633 | #endif /* LIMIT_TO_MAX */ 634 | 635 | /* limit to min */ 636 | #ifndef LIMIT_TO_MIN 637 | #define LIMIT_TO_MIN(x, min) \ 638 | (((x) < (min) ? (min) : (x))) 639 | #endif /* LIMIT_TO_MIN */ 640 | 641 | #define CEIL(x, y) (((x) + ((y) - 1)) / (y)) 642 | #define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) 643 | #define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) 644 | #define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \ 645 | & ~((boundary) - 1)) 646 | #define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \ 647 | & ~((boundary) - 1)) 648 | #define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0) 649 | #define VALID_MASK(mask) !((mask) & ((mask) + 1)) 650 | 651 | #ifndef OFFSETOF 652 | #ifdef __ARMCC_VERSION 653 | /* 654 | * The ARM RVCT compiler complains when using OFFSETOF where a constant 655 | * expression is expected, such as an initializer for a static object. 656 | * offsetof from the runtime library doesn't have that problem. 657 | */ 658 | #include 659 | #define OFFSETOF(type, member) offsetof(type, member) 660 | #else 661 | #define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) 662 | #endif /* __ARMCC_VERSION */ 663 | #endif /* OFFSETOF */ 664 | 665 | #ifndef ARRAYSIZE 666 | #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) 667 | #endif 668 | 669 | #ifndef ARRAYLAST /* returns pointer to last array element */ 670 | #define ARRAYLAST(a) (&a[ARRAYSIZE(a)-1]) 671 | #endif 672 | 673 | /* Reference a function; used to prevent a static function from being optimized out */ 674 | extern void *_bcmutils_dummy_fn; 675 | #define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f)) 676 | 677 | /* bit map related macros */ 678 | #ifndef setbit 679 | #ifndef NBBY /* the BSD family defines NBBY */ 680 | #define NBBY 8 /* 8 bits per byte */ 681 | #endif /* #ifndef NBBY */ 682 | #ifdef BCMUTILS_BIT_MACROS_USE_FUNCS 683 | extern void setbit(void *array, uint bit); 684 | extern void clrbit(void *array, uint bit); 685 | extern bool isset(const void *array, uint bit); 686 | extern bool isclr(const void *array, uint bit); 687 | #else 688 | #define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) 689 | #define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) 690 | #define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) 691 | #define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) 692 | #endif 693 | #endif /* setbit */ 694 | 695 | #define isbitset(a, i) (((a) & (1 << (i))) != 0) 696 | 697 | #define NBITS(type) (sizeof(type) * 8) 698 | #define NBITVAL(nbits) (1 << (nbits)) 699 | #define MAXBITVAL(nbits) ((1 << (nbits)) - 1) 700 | #define NBITMASK(nbits) MAXBITVAL(nbits) 701 | #define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) 702 | 703 | /* basic mux operation - can be optimized on several architectures */ 704 | #define MUX(pred, true, false) ((pred) ? (true) : (false)) 705 | 706 | /* modulo inc/dec - assumes x E [0, bound - 1] */ 707 | #define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) 708 | #define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) 709 | 710 | /* modulo inc/dec, bound = 2^k */ 711 | #define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) 712 | #define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) 713 | 714 | /* modulo add/sub - assumes x, y E [0, bound - 1] */ 715 | #define MODADD(x, y, bound) \ 716 | MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) 717 | #define MODSUB(x, y, bound) \ 718 | MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) 719 | 720 | /* module add/sub, bound = 2^k */ 721 | #define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) 722 | #define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) 723 | 724 | /* crc defines */ 725 | #define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ 726 | #define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ 727 | #define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ 728 | #define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ 729 | #define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ 730 | #define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ 731 | 732 | /* use for direct output of MAC address in printf etc */ 733 | #define MACF "%02x:%02x:%02x:%02x:%02x:%02x" 734 | #define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \ 735 | ((struct ether_addr *) (ea))->octet[1], \ 736 | ((struct ether_addr *) (ea))->octet[2], \ 737 | ((struct ether_addr *) (ea))->octet[3], \ 738 | ((struct ether_addr *) (ea))->octet[4], \ 739 | ((struct ether_addr *) (ea))->octet[5] 740 | 741 | #define ETHER_TO_MACF(ea) (ea).octet[0], \ 742 | (ea).octet[1], \ 743 | (ea).octet[2], \ 744 | (ea).octet[3], \ 745 | (ea).octet[4], \ 746 | (ea).octet[5] 747 | #if !defined(SIMPLE_MAC_PRINT) 748 | #define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" 749 | #define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] 750 | #else 751 | #define MACDBG "%02x:%02x:%02x" 752 | #define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5] 753 | #endif /* SIMPLE_MAC_PRINT */ 754 | 755 | /* bcm_format_flags() bit description structure */ 756 | typedef struct bcm_bit_desc { 757 | uint32 bit; 758 | const char* name; 759 | } bcm_bit_desc_t; 760 | 761 | /* bcm_format_field */ 762 | typedef struct bcm_bit_desc_ex { 763 | uint32 mask; 764 | const bcm_bit_desc_t *bitfield; 765 | } bcm_bit_desc_ex_t; 766 | 767 | 768 | /* tag_ID/length/value_buffer tuple */ 769 | typedef struct bcm_tlv { 770 | uint8 id; 771 | uint8 len; 772 | uint8 data[1]; 773 | } bcm_tlv_t; 774 | 775 | /* Check that bcm_tlv_t fits into the given buflen */ 776 | #define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) 777 | 778 | /* buffer length for ethernet address from bcm_ether_ntoa() */ 779 | #define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ 780 | 781 | /* crypto utility function */ 782 | /* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */ 783 | static INLINE void 784 | xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) 785 | { 786 | if ( 787 | #ifdef __i386__ 788 | 1 || 789 | #endif 790 | (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { 791 | /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */ 792 | /* x86 supports unaligned. This version runs 6x-9x faster on x86. */ 793 | ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0]; 794 | ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1]; 795 | ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2]; 796 | ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3]; 797 | } else { 798 | /* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */ 799 | int k; 800 | for (k = 0; k < 16; k++) 801 | dst[k] = src1[k] ^ src2[k]; 802 | } 803 | } 804 | 805 | /* externs */ 806 | /* crc */ 807 | extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); 808 | extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc); 809 | extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); 810 | 811 | /* format/print */ 812 | #if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ 813 | defined(WLMSG_ASSOC) 814 | /* print out the value a field has: fields may have 1-32 bits and may hold any value */ 815 | extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len); 816 | /* print out which bits in flags are set */ 817 | extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); 818 | #endif 819 | 820 | #if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ 821 | defined(WLMSG_ASSOC) || defined(WLMEDIA_PEAKRATE) 822 | extern int bcm_format_hex(char *str, const void *bytes, int len); 823 | #endif 824 | 825 | extern const char *bcm_crypto_algo_name(uint algo); 826 | extern char *bcm_chipname(uint chipid, char *buf, uint len); 827 | extern char *bcm_brev_str(uint32 brev, char *buf); 828 | extern void printbig(char *buf); 829 | extern void prhex(const char *msg, uchar *buf, uint len); 830 | 831 | /* IE parsing */ 832 | extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen); 833 | extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); 834 | extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); 835 | 836 | /* bcmerror */ 837 | extern const char *bcmerrorstr(int bcmerror); 838 | /* extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); */ 839 | 840 | /* multi-bool data type: set of bools, mbool is true if any is set */ 841 | typedef uint32 mbool; 842 | #define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ 843 | #define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ 844 | #define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */ 845 | #define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) 846 | 847 | /* generic datastruct to help dump routines */ 848 | struct fielddesc { 849 | const char *nameandfmt; 850 | uint32 offset; 851 | uint32 len; 852 | }; 853 | 854 | extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); 855 | extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len); 856 | 857 | extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount); 858 | extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes); 859 | extern void bcm_print_bytes(const char *name, const uchar *cdata, int len); 860 | 861 | typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset); 862 | extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str, 863 | char *buf, uint32 bufsize); 864 | extern uint bcm_bitcount(uint8 *bitmap, uint bytelength); 865 | 866 | extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); 867 | 868 | /* power conversion */ 869 | extern uint16 bcm_qdbm_to_mw(uint8 qdbm); 870 | extern uint8 bcm_mw_to_qdbm(uint16 mw); 871 | extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); 872 | 873 | unsigned int process_nvram_vars(char *varbuf, unsigned int len); 874 | extern bcm_tlv_t *find_vendor_ie(void *tlvs, int tlvs_len, 875 | const char *voui, uint8 *type, int type_len); 876 | 877 | /* calculate a * b + c */ 878 | extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c); 879 | /* calculate a / b */ 880 | extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b); 881 | 882 | #ifdef __cplusplus 883 | } 884 | #endif 885 | 886 | #endif /* _bcmutils_h_ */ 887 | -------------------------------------------------------------------------------- /bcmwifi_channels.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Misc utility routines for WL and Apps 3 | * This header file housing the define and function prototype use by 4 | * both the wl driver, tools & Apps. 5 | * 6 | * Copyright (C) 1999-2013, Broadcom Corporation 7 | * 8 | * Unless you and Broadcom execute a separate written software license 9 | * agreement governing use of this software, this software is licensed to you 10 | * under the terms of the GNU General Public License version 2 (the "GPL"), 11 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the 12 | * following added to such license: 13 | * 14 | * As a special exception, the copyright holders of this software give you 15 | * permission to link this software with independent modules, and to copy and 16 | * distribute the resulting executable under terms of your choice, provided that 17 | * you also meet, for each linked independent module, the terms and conditions of 18 | * the license of that module. An independent module is a module which is not 19 | * derived from this software. The special exception does not apply to any 20 | * modifications of the software. 21 | * 22 | * Notwithstanding the above, under no circumstances may you combine this 23 | * software in any way with any other Broadcom software provided under a license 24 | * other than the GPL, without Broadcom's express prior written consent. 25 | * 26 | * $Id: bcmwifi_channels.h 309193 2012-01-19 00:03:57Z $ 27 | */ 28 | 29 | #ifndef _bcmwifi_channels_h_ 30 | #define _bcmwifi_channels_h_ 31 | 32 | 33 | /* A chanspec holds the channel number, band, bandwidth and control sideband */ 34 | typedef uint16 chanspec_t; 35 | 36 | /* channel defines */ 37 | #define CH_UPPER_SB 0x01 38 | #define CH_LOWER_SB 0x02 39 | #define CH_EWA_VALID 0x04 40 | #define CH_80MHZ_APART 16 41 | #define CH_40MHZ_APART 8 42 | #define CH_20MHZ_APART 4 43 | #define CH_10MHZ_APART 2 44 | #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ 45 | #define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ 46 | #define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216, 47 | * this is that + 1 rounded up to a multiple of NBBY (8). 48 | * DO NOT MAKE it > 255: channels are uint8's all over 49 | */ 50 | #define CHSPEC_CTLOVLP(sp1, sp2, sep) (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < \ 51 | (sep)) 52 | 53 | /* All builds use the new 11ac ratespec/chanspec */ 54 | #undef D11AC_IOTYPES 55 | #define D11AC_IOTYPES 56 | 57 | #ifndef D11AC_IOTYPES 58 | 59 | #define WL_CHANSPEC_CHAN_MASK 0x00ff 60 | #define WL_CHANSPEC_CHAN_SHIFT 0 61 | 62 | #define WL_CHANSPEC_CTL_SB_MASK 0x0300 63 | #define WL_CHANSPEC_CTL_SB_SHIFT 8 64 | #define WL_CHANSPEC_CTL_SB_LOWER 0x0100 65 | #define WL_CHANSPEC_CTL_SB_UPPER 0x0200 66 | #define WL_CHANSPEC_CTL_SB_NONE 0x0300 67 | 68 | #define WL_CHANSPEC_BW_MASK 0x0C00 69 | #define WL_CHANSPEC_BW_SHIFT 10 70 | #define WL_CHANSPEC_BW_10 0x0400 71 | #define WL_CHANSPEC_BW_20 0x0800 72 | #define WL_CHANSPEC_BW_40 0x0C00 73 | 74 | #define WL_CHANSPEC_BAND_MASK 0xf000 75 | #define WL_CHANSPEC_BAND_SHIFT 12 76 | #ifdef WL_CHANSPEC_BAND_5G 77 | #undef WL_CHANSPEC_BAND_5G 78 | #endif 79 | #ifdef WL_CHANSPEC_BAND_2G 80 | #undef WL_CHANSPEC_BAND_2G 81 | #endif 82 | #define WL_CHANSPEC_BAND_5G 0x1000 83 | #define WL_CHANSPEC_BAND_2G 0x2000 84 | #define INVCHANSPEC 255 85 | 86 | /* channel defines */ 87 | #define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) 88 | #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ 89 | ((channel) + CH_10MHZ_APART) : 0) 90 | 91 | #define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) 92 | #define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ 93 | ((channel) + 3 * CH_10MHZ_APART) : 0) 94 | #define LU_20_SB(channel) LOWER_20_SB(channel) 95 | #define UL_20_SB(channel) UPPER_20_SB(channel) 96 | 97 | #define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) 98 | #define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ 99 | WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ 100 | WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) 101 | #define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ 102 | ((channel) + CH_20MHZ_APART) : 0) 103 | #define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 104 | ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ 105 | ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ 106 | WL_CHANSPEC_BAND_5G)) 107 | #define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) 108 | #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) 109 | 110 | /* chanspec stores radio channel & flags to indicate control channel location, i.e. upper/lower */ 111 | #define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) 112 | #define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) 113 | 114 | #ifdef WL11N_20MHZONLY 115 | 116 | #define CHSPEC_IS10(chspec) 0 117 | #define CHSPEC_IS20(chspec) 1 118 | #ifndef CHSPEC_IS40 119 | #define CHSPEC_IS40(chspec) 0 120 | #endif 121 | 122 | #else /* !WL11N_20MHZONLY */ 123 | 124 | #define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) 125 | #define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) 126 | #ifndef CHSPEC_IS40 127 | #define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) 128 | #endif 129 | 130 | #endif /* !WL11N_20MHZONLY */ 131 | 132 | #define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) 133 | #define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) 134 | #define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) 135 | #define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) 136 | #define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) 137 | #define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ 138 | (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ 139 | (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) 140 | #define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) 141 | 142 | #define CHANSPEC_STR_LEN 8 143 | 144 | #else /* D11AC_IOTYPES */ 145 | 146 | #define WL_CHANSPEC_CHAN_MASK 0x00ff 147 | #define WL_CHANSPEC_CHAN_SHIFT 0 148 | #define WL_CHANSPEC_CHAN1_MASK 0x000f 149 | #define WL_CHANSPEC_CHAN1_SHIFT 0 150 | #define WL_CHANSPEC_CHAN2_MASK 0x00f0 151 | #define WL_CHANSPEC_CHAN2_SHIFT 4 152 | 153 | #define WL_CHANSPEC_CTL_SB_MASK 0x0700 154 | #define WL_CHANSPEC_CTL_SB_SHIFT 8 155 | #define WL_CHANSPEC_CTL_SB_LLL 0x0000 156 | #define WL_CHANSPEC_CTL_SB_LLU 0x0100 157 | #define WL_CHANSPEC_CTL_SB_LUL 0x0200 158 | #define WL_CHANSPEC_CTL_SB_LUU 0x0300 159 | #define WL_CHANSPEC_CTL_SB_ULL 0x0400 160 | #define WL_CHANSPEC_CTL_SB_ULU 0x0500 161 | #define WL_CHANSPEC_CTL_SB_UUL 0x0600 162 | #define WL_CHANSPEC_CTL_SB_UUU 0x0700 163 | #define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL 164 | #define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU 165 | #define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL 166 | #define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU 167 | #define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL 168 | #define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU 169 | #define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL 170 | #define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU 171 | 172 | #define WL_CHANSPEC_BW_MASK 0x3800 173 | #define WL_CHANSPEC_BW_SHIFT 11 174 | #define WL_CHANSPEC_BW_5 0x0000 175 | #define WL_CHANSPEC_BW_10 0x0800 176 | #define WL_CHANSPEC_BW_20 0x1000 177 | #define WL_CHANSPEC_BW_40 0x1800 178 | #define WL_CHANSPEC_BW_80 0x2000 179 | #define WL_CHANSPEC_BW_160 0x2800 180 | #define WL_CHANSPEC_BW_8080 0x3000 181 | 182 | #define WL_CHANSPEC_BAND_MASK 0xc000 183 | #define WL_CHANSPEC_BAND_SHIFT 14 184 | #define WL_CHANSPEC_BAND_2G 0x0000 185 | #define WL_CHANSPEC_BAND_3G 0x4000 186 | #define WL_CHANSPEC_BAND_4G 0x8000 187 | #define WL_CHANSPEC_BAND_5G 0xc000 188 | #define INVCHANSPEC 255 189 | 190 | /* channel defines */ 191 | #define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ 192 | ((channel) - CH_10MHZ_APART) : 0) 193 | #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ 194 | ((channel) + CH_10MHZ_APART) : 0) 195 | 196 | #define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) 197 | #define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ 198 | ((channel) + 3 * CH_10MHZ_APART) : 0) 199 | #define LU_20_SB(channel) LOWER_20_SB(channel) 200 | #define UL_20_SB(channel) UPPER_20_SB(channel) 201 | 202 | #define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART) 203 | #define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART) 204 | #define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) 205 | #define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ 206 | (((channel) <= CH_MAX_2G_CHANNEL) ? \ 207 | WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) 208 | #define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ 209 | ((channel) + CH_20MHZ_APART) : 0) 210 | #define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 211 | ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ 212 | ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ 213 | WL_CHANSPEC_BAND_5G)) 214 | #define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 215 | ((channel) | (ctlsb) | \ 216 | WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G) 217 | #define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 218 | ((channel) | (ctlsb) | \ 219 | WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G) 220 | 221 | /* simple MACROs to get different fields of chanspec */ 222 | #define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) 223 | #define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) 224 | #define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) 225 | #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) 226 | #define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) 227 | #define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) 228 | 229 | #ifdef WL11N_20MHZONLY 230 | 231 | #define CHSPEC_IS10(chspec) 0 232 | #define CHSPEC_IS20(chspec) 1 233 | #ifndef CHSPEC_IS40 234 | #define CHSPEC_IS40(chspec) 0 235 | #endif 236 | #ifndef CHSPEC_IS80 237 | #define CHSPEC_IS80(chspec) 0 238 | #endif 239 | #ifndef CHSPEC_IS160 240 | #define CHSPEC_IS160(chspec) 0 241 | #endif 242 | #ifndef CHSPEC_IS8080 243 | #define CHSPEC_IS8080(chspec) 0 244 | #endif 245 | 246 | #else /* !WL11N_20MHZONLY */ 247 | 248 | #define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) 249 | #define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) 250 | #ifndef CHSPEC_IS40 251 | #define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) 252 | #endif 253 | #ifndef CHSPEC_IS80 254 | #define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) 255 | #endif 256 | #ifndef CHSPEC_IS160 257 | #define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) 258 | #endif 259 | #ifndef CHSPEC_IS8080 260 | #define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) 261 | #endif 262 | 263 | #endif /* !WL11N_20MHZONLY */ 264 | 265 | #define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) 266 | #define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) 267 | #define CHSPEC_SB_UPPER(chspec) \ 268 | ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ 269 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) 270 | #define CHSPEC_SB_LOWER(chspec) \ 271 | ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ 272 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) 273 | #define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) 274 | 275 | /** 276 | * Number of chars needed for wf_chspec_ntoa() destination character buffer. 277 | */ 278 | #define CHANSPEC_STR_LEN 20 279 | 280 | 281 | /* Legacy Chanspec defines 282 | * These are the defines for the previous format of the chanspec_t 283 | */ 284 | #define WL_LCHANSPEC_CHAN_MASK 0x00ff 285 | #define WL_LCHANSPEC_CHAN_SHIFT 0 286 | 287 | #define WL_LCHANSPEC_CTL_SB_MASK 0x0300 288 | #define WL_LCHANSPEC_CTL_SB_SHIFT 8 289 | #define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 290 | #define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 291 | #define WL_LCHANSPEC_CTL_SB_NONE 0x0300 292 | 293 | #define WL_LCHANSPEC_BW_MASK 0x0C00 294 | #define WL_LCHANSPEC_BW_SHIFT 10 295 | #define WL_LCHANSPEC_BW_10 0x0400 296 | #define WL_LCHANSPEC_BW_20 0x0800 297 | #define WL_LCHANSPEC_BW_40 0x0C00 298 | 299 | #define WL_LCHANSPEC_BAND_MASK 0xf000 300 | #define WL_LCHANSPEC_BAND_SHIFT 12 301 | #define WL_LCHANSPEC_BAND_5G 0x1000 302 | #define WL_LCHANSPEC_BAND_2G 0x2000 303 | 304 | #define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) 305 | #define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) 306 | #define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) 307 | #define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) 308 | #define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10) 309 | #define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) 310 | #define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) 311 | #define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) 312 | #define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) 313 | 314 | #define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) 315 | 316 | #define CH20MHZ_LCHSPEC(channel) \ 317 | (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \ 318 | WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ 319 | WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G)) 320 | 321 | #endif /* D11AC_IOTYPES */ 322 | 323 | /* 324 | * WF_CHAN_FACTOR_* constants are used to calculate channel frequency 325 | * given a channel number. 326 | * chan_freq = chan_factor * 500Mhz + chan_number * 5 327 | */ 328 | 329 | /** 330 | * Channel Factor for the starting frequence of 2.4 GHz channels. 331 | * The value corresponds to 2407 MHz. 332 | */ 333 | #define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ 334 | 335 | /** 336 | * Channel Factor for the starting frequence of 5 GHz channels. 337 | * The value corresponds to 5000 MHz. 338 | */ 339 | #define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ 340 | 341 | /** 342 | * Channel Factor for the starting frequence of 4.9 GHz channels. 343 | * The value corresponds to 4000 MHz. 344 | */ 345 | #define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ 346 | 347 | #define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ 348 | 349 | /** 350 | * Convert chanspec to ascii string 351 | * 352 | * @param chspec chanspec format 353 | * @param buf ascii string of chanspec 354 | * 355 | * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes 356 | * 357 | * @see CHANSPEC_STR_LEN 358 | */ 359 | extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); 360 | 361 | /** 362 | * Convert ascii string to chanspec 363 | * 364 | * @param a pointer to input string 365 | * 366 | * @return >= 0 if successful or 0 otherwise 367 | */ 368 | extern chanspec_t wf_chspec_aton(const char *a); 369 | 370 | /** 371 | * Verify the chanspec fields are valid. 372 | * 373 | * Verify the chanspec is using a legal set field values, i.e. that the chanspec 374 | * specified a band, bw, ctl_sb and channel and that the combination could be 375 | * legal given some set of circumstances. 376 | * 377 | * @param chanspec input chanspec to verify 378 | * 379 | * @return TRUE if the chanspec is malformed, FALSE if it looks good. 380 | */ 381 | extern bool wf_chspec_malformed(chanspec_t chanspec); 382 | 383 | /** 384 | * Verify the chanspec specifies a valid channel according to 802.11. 385 | * 386 | * @param chanspec input chanspec to verify 387 | * 388 | * @return TRUE if the chanspec is a valid 802.11 channel 389 | */ 390 | extern bool wf_chspec_valid(chanspec_t chanspec); 391 | 392 | /** 393 | * Return the primary (control) channel. 394 | * 395 | * This function returns the channel number of the primary 20MHz channel. For 396 | * 20MHz channels this is just the channel number. For 40MHz or wider channels 397 | * it is the primary 20MHz channel specified by the chanspec. 398 | * 399 | * @param chspec input chanspec 400 | * 401 | * @return Returns the channel number of the primary 20MHz channel 402 | */ 403 | extern uint8 wf_chspec_ctlchan(chanspec_t chspec); 404 | 405 | /** 406 | * Return the primary (control) chanspec. 407 | * 408 | * This function returns the chanspec of the primary 20MHz channel. For 20MHz 409 | * channels this is just the chanspec. For 40MHz or wider channels it is the 410 | * chanspec of the primary 20MHZ channel specified by the chanspec. 411 | * 412 | * @param chspec input chanspec 413 | * 414 | * @return Returns the chanspec of the primary 20MHz channel 415 | */ 416 | extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); 417 | 418 | /** 419 | * Return a channel number corresponding to a frequency. 420 | * 421 | * This function returns the chanspec for the primary 40MHz of an 80MHz channel. 422 | * The control sideband specifies the same 20MHz channel that the 80MHz channel is using 423 | * as the primary 20MHz channel. 424 | */ 425 | extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec); 426 | 427 | /* 428 | * Return the channel number for a given frequency and base frequency. 429 | * The returned channel number is relative to the given base frequency. 430 | * If the given base frequency is zero, a base frequency of 5 GHz is assumed for 431 | * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. 432 | * 433 | * Frequency is specified in MHz. 434 | * The base frequency is specified as (start_factor * 500 kHz). 435 | * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for 436 | * 2.4 GHz and 5 GHz bands. 437 | * 438 | * The returned channel will be in the range [1, 14] in the 2.4 GHz band 439 | * and [0, 200] otherwise. 440 | * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the 441 | * frequency is not a 2.4 GHz channel, or if the frequency is not and even 442 | * multiple of 5 MHz from the base frequency to the base plus 1 GHz. 443 | * 444 | * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 445 | * 446 | * @param freq frequency in MHz 447 | * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz 448 | * 449 | * @return Returns a channel number 450 | * 451 | * @see WF_CHAN_FACTOR_2_4_G 452 | * @see WF_CHAN_FACTOR_5_G 453 | */ 454 | extern int wf_mhz2channel(uint freq, uint start_factor); 455 | 456 | /** 457 | * Return the center frequency in MHz of the given channel and base frequency. 458 | * 459 | * Return the center frequency in MHz of the given channel and base frequency. 460 | * The channel number is interpreted relative to the given base frequency. 461 | * 462 | * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. 463 | * The base frequency is specified as (start_factor * 500 kHz). 464 | * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for 465 | * 2.4 GHz and 5 GHz bands. 466 | * The channel range of [1, 14] is only checked for a start_factor of 467 | * WF_CHAN_FACTOR_2_4_G (4814). 468 | * Odd start_factors produce channels on .5 MHz boundaries, in which case 469 | * the answer is rounded down to an integral MHz. 470 | * -1 is returned for an out of range channel. 471 | * 472 | * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 473 | * 474 | * @param channel input channel number 475 | * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz 476 | * 477 | * @return Returns a frequency in MHz 478 | * 479 | * @see WF_CHAN_FACTOR_2_4_G 480 | * @see WF_CHAN_FACTOR_5_G 481 | */ 482 | extern int wf_channel2mhz(uint channel, uint start_factor); 483 | 484 | /** 485 | * Convert ctl chan and bw to chanspec 486 | * 487 | * @param ctl_ch channel 488 | * @param bw bandwidth 489 | * 490 | * @return > 0 if successful or 0 otherwise 491 | * 492 | */ 493 | extern uint16 wf_channel2chspec(uint ctl_ch, uint bw); 494 | 495 | extern uint wf_channel2freq(uint channel); 496 | extern uint wf_freq2channel(uint freq); 497 | 498 | 499 | #endif /* _bcmwifi_channels_h_ */ 500 | -------------------------------------------------------------------------------- /libnexio.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * ########### ########### ########## ########## * 4 | * ############ ############ ############ ############ * 5 | * ## ## ## ## ## ## ## * 6 | * ## ## ## ## ## ## ## * 7 | * ########### #### ###### ## ## ## ## ###### * 8 | * ########### #### # ## ## ## ## # # * 9 | * ## ## ###### ## ## ## ## # # * 10 | * ## ## # ## ## ## ## # # * 11 | * ############ ##### ###### ## ## ## ##### ###### * 12 | * ########### ########### ## ## ## ########## * 13 | * * 14 | * S E C U R E M O B I L E N E T W O R K I N G * 15 | * * 16 | * This file is part of NexMon. * 17 | * * 18 | * Copyright (c) 2016 NexMon Team * 19 | * * 20 | * NexMon is free software: you can redistribute it and/or modify * 21 | * it under the terms of the GNU General Public License as published by * 22 | * the Free Software Foundation, either version 3 of the License, or * 23 | * (at your option) any later version. * 24 | * * 25 | * NexMon is distributed in the hope that it will be useful, * 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 28 | * GNU General Public License for more details. * 29 | * * 30 | * You should have received a copy of the GNU General Public License * 31 | * along with NexMon. If not, see . * 32 | * * 33 | **************************************************************************/ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #ifdef BUILD_ON_RPI 47 | #include 48 | #else 49 | #include 50 | #endif 51 | #include 52 | #include 53 | 54 | #include 55 | #include 56 | 57 | #include 58 | 59 | #define WLC_IOCTL_MAGIC 0x14e46c77 60 | #define DHD_IOCTL_MAGIC 0x00444944 61 | 62 | #define WLC_GET_MAGIC 0 63 | #define DHD_GET_MAGIC 0 64 | 65 | #define NEXUDP_IOCTL 0 66 | #define NEXUDP_INJECT_RADIOTAP 1 67 | 68 | #define NETLINK_USER 31 69 | 70 | #define IPADDR(a,b,c,d) ((d) << 24 | (c) << 16 | (b) << 8 | (a)) 71 | 72 | #define NEXIO_TYPE_IOCTL 0 73 | #define NEXIO_TYPE_UDP 1 74 | #define NEXIO_TYPE_NETLINK 2 75 | 76 | struct nexio { 77 | int type; 78 | struct ifreq *ifr; 79 | int sock_rx_ioctl; 80 | int sock_rx_frame; 81 | int sock_tx; 82 | unsigned int securitycookie; 83 | }; 84 | 85 | struct nex_ioctl { 86 | unsigned int cmd; /* common ioctl definition */ 87 | void *buf; /* pointer to user buffer */ 88 | unsigned int len; /* length of user buffer */ 89 | bool set; /* get or set request (optional) */ 90 | unsigned int used; /* bytes read or written (optional) */ 91 | unsigned int needed; /* bytes needed (optional) */ 92 | unsigned int driver; /* to identify target driver */ 93 | }; 94 | 95 | struct nexudp_header { 96 | char nex[3]; 97 | char type; 98 | int securitycookie; 99 | } __attribute__((packed)); 100 | 101 | struct nexudp_ioctl_header { 102 | struct nexudp_header nexudphdr; 103 | unsigned int cmd; 104 | unsigned int set; 105 | char payload[1]; 106 | } __attribute__((packed)); 107 | 108 | 109 | static int 110 | __nex_driver_io(struct ifreq *ifr, struct nex_ioctl *ioc) 111 | { 112 | int s; 113 | int ret = 0; 114 | 115 | /* pass ioctl data */ 116 | ifr->ifr_data = (void *) ioc; 117 | 118 | /* open socket to kernel */ 119 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 120 | fprintf(stderr, "error: socket\n"); 121 | 122 | ret = ioctl(s, SIOCDEVPRIVATE, ifr); 123 | if (ret < 0 && errno != EAGAIN) 124 | fprintf(stderr, "%s: error (%d: %s)\n", __FUNCTION__, errno, strerror(errno)); 125 | 126 | /* cleanup */ 127 | close(s); 128 | return ret; 129 | } 130 | 131 | static int 132 | __nex_driver_udp(struct nexio *nexio, struct nex_ioctl *ioc) 133 | { 134 | int frame_len = ioc->len + sizeof(struct nexudp_ioctl_header) - sizeof(char); 135 | int rx_frame_len = 0; 136 | struct nexudp_ioctl_header *frame = (struct nexudp_ioctl_header *) malloc(frame_len); 137 | int ret = 0; 138 | 139 | memcpy(&frame->nexudphdr.nex, "NEX", 3); 140 | frame->nexudphdr.type = NEXUDP_IOCTL; 141 | frame->nexudphdr.securitycookie = nexio->securitycookie; 142 | 143 | frame->cmd = ioc->cmd; 144 | frame->set = ioc->set; 145 | 146 | memcpy(frame->payload, ioc->buf, ioc->len); 147 | 148 | send(nexio->sock_tx, frame, frame_len, 0); 149 | 150 | rx_frame_len = recv(nexio->sock_rx_ioctl, frame, frame_len, 0); 151 | 152 | if (ioc->set == 0 && rx_frame_len > 0 && *(unsigned int *) frame == ioc->cmd) { 153 | memcpy(ioc->buf, ((char *) frame) + sizeof(frame->cmd) + sizeof(frame->set), 154 | (rx_frame_len - sizeof(frame->cmd) - sizeof(frame->set)) < ioc->len ? 155 | (rx_frame_len - sizeof(frame->cmd) - sizeof(frame->set)) : ioc->len); 156 | } 157 | 158 | free(frame); 159 | 160 | if (rx_frame_len < 0) { 161 | ret = -1; 162 | fprintf(stderr, "ERR (%s): no valid answer received\n", __FUNCTION__); 163 | } 164 | 165 | return ret; 166 | } 167 | 168 | static int 169 | __nex_driver_netlink(struct nexio *nexio, struct nex_ioctl *ioc) 170 | { 171 | int frame_len = ioc->len + sizeof(struct nexudp_ioctl_header) - sizeof(char); 172 | int rx_frame_len = 0; 173 | struct nexudp_ioctl_header *frame; 174 | int ret = 0; 175 | 176 | struct iovec iov = { 0 }; 177 | struct msghdr msg = { 0 }; 178 | 179 | struct nlmsghdr *nlh = (struct nlmsghdr *) malloc(NLMSG_SPACE(frame_len)); 180 | memset(nlh, 0, NLMSG_SPACE(frame_len)); 181 | nlh->nlmsg_len = NLMSG_SPACE(frame_len); 182 | nlh->nlmsg_pid = getpid(); 183 | nlh->nlmsg_flags = 0; 184 | frame = (struct nexudp_ioctl_header *) NLMSG_DATA(nlh); 185 | 186 | memcpy(&frame->nexudphdr.nex, "NEX", 3); 187 | frame->nexudphdr.type = NEXUDP_IOCTL; 188 | frame->nexudphdr.securitycookie = nexio->securitycookie; 189 | 190 | frame->cmd = ioc->cmd; 191 | frame->set = ioc->set; 192 | 193 | memcpy(frame->payload, ioc->buf, ioc->len); 194 | 195 | // printf("%s: before send. nlh->nlmsg_len: %d ioc->len: %d\n", __FUNCTION__, nlh->nlmsg_len, ioc->len); 196 | send(nexio->sock_tx, nlh, nlh->nlmsg_len, 0); 197 | 198 | rx_frame_len = recv(nexio->sock_rx_ioctl, nlh, nlh->nlmsg_len, 0); 199 | 200 | // printf("%s: framelen %d %d %s\n", __FUNCTION__, rx_frame_len, nlh->nlmsg_len, (char *) frame); 201 | 202 | if (ioc->set == 0 && rx_frame_len > 0 && frame->cmd == ioc->cmd) { 203 | memcpy(ioc->buf, frame->payload, 204 | (rx_frame_len - sizeof(struct nexudp_ioctl_header) + sizeof(char)) < ioc->len ? 205 | (rx_frame_len - sizeof(struct nexudp_ioctl_header) + sizeof(char)) : ioc->len); 206 | } 207 | 208 | free(nlh); 209 | 210 | if (rx_frame_len < 0) { 211 | ret = -1; 212 | fprintf(stderr, "ERR (%s): no valid answer received\n", __FUNCTION__); 213 | } 214 | 215 | return ret; 216 | } 217 | 218 | /* This function is called by ioctl_setinformation_fe or ioctl_queryinformation_fe 219 | * for executing remote commands or local commands 220 | */ 221 | int 222 | nex_ioctl(struct nexio *nexio, int cmd, void *buf, int len, bool set) 223 | { 224 | struct nex_ioctl ioc; 225 | int ret = 0; 226 | 227 | /* do it */ 228 | ioc.cmd = cmd; 229 | ioc.buf = buf; 230 | ioc.len = len; 231 | ioc.set = set; 232 | ioc.driver = WLC_IOCTL_MAGIC; 233 | 234 | 235 | if (nexio != 0) { 236 | switch(nexio->type) { 237 | case NEXIO_TYPE_IOCTL: 238 | ret = __nex_driver_io(nexio->ifr, &ioc); 239 | break; 240 | case NEXIO_TYPE_UDP: 241 | ret = __nex_driver_udp(nexio, &ioc); 242 | break; 243 | case NEXIO_TYPE_NETLINK: 244 | ret = __nex_driver_netlink(nexio, &ioc); 245 | break; 246 | default: 247 | fprintf(stderr, "%s: not initialized correctly\n", __FUNCTION__); 248 | } 249 | } else { 250 | fprintf(stderr, "%s: not initialized\n", __FUNCTION__); 251 | } 252 | 253 | if (ret < 0 && cmd != WLC_GET_MAGIC) 254 | ret = -1; 255 | 256 | return ret; 257 | } 258 | 259 | struct nexio * 260 | nex_init_ioctl(const char *ifname) 261 | { 262 | struct nexio *nexio = (struct nexio *) malloc(sizeof(struct nexio)); 263 | memset(nexio, 0, sizeof(struct nexio)); 264 | 265 | nexio->ifr = (struct ifreq *) malloc(sizeof(struct ifreq)); 266 | memset(nexio->ifr, 0, sizeof(struct ifreq)); 267 | snprintf(nexio->ifr->ifr_name, sizeof(nexio->ifr->ifr_name), "%s", ifname); 268 | 269 | nexio->type = NEXIO_TYPE_IOCTL; 270 | 271 | return nexio; 272 | } 273 | 274 | struct nexio * 275 | nex_init_udp(unsigned int securitycookie, unsigned int txip) 276 | { 277 | struct nexio *nexio = (struct nexio *) malloc(sizeof(struct nexio)); 278 | memset(nexio, 0, sizeof(struct nexio)); 279 | 280 | nexio->securitycookie = securitycookie; 281 | 282 | struct sockaddr_in *sin_tx = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in)); 283 | struct sockaddr_in *sin_rx_ioctl = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in)); 284 | struct sockaddr_in *sin_rx_frame = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in)); 285 | 286 | memset(sin_tx, 0, sizeof(struct sockaddr_in)); 287 | memset(sin_rx_ioctl, 0, sizeof(struct sockaddr_in)); 288 | memset(sin_rx_frame, 0, sizeof(struct sockaddr_in)); 289 | 290 | sin_tx->sin_family = AF_INET; 291 | sin_tx->sin_port = htons(5500); 292 | sin_tx->sin_addr.s_addr = txip; 293 | 294 | sin_rx_ioctl->sin_family = AF_INET; 295 | sin_rx_ioctl->sin_port = htons(5500); 296 | sin_rx_ioctl->sin_addr.s_addr = IPADDR(255,255,255,255); 297 | 298 | sin_rx_frame->sin_family = AF_INET; 299 | sin_rx_frame->sin_port = htons(5600); 300 | sin_rx_frame->sin_addr.s_addr = IPADDR(255,255,255,255); 301 | 302 | nexio->sock_tx = socket(sin_tx->sin_family, SOCK_DGRAM, IPPROTO_UDP); 303 | nexio->sock_rx_ioctl = socket(sin_rx_ioctl->sin_family, SOCK_DGRAM, IPPROTO_UDP); 304 | nexio->sock_rx_frame = socket(sin_rx_frame->sin_family, SOCK_DGRAM, IPPROTO_UDP); 305 | 306 | // Enable broadcasts for transmit socket 307 | int broadcast_enable = 1; 308 | setsockopt(nexio->sock_tx, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)); 309 | 310 | // Set 1 second timeout on ioctl receive socket 311 | struct timeval tv = { 312 | .tv_sec = 1, 313 | .tv_usec = 0 314 | }; 315 | setsockopt(nexio->sock_rx_ioctl, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 316 | 317 | connect(nexio->sock_tx, (struct sockaddr *) sin_tx, sizeof(struct sockaddr)); 318 | bind(nexio->sock_rx_ioctl, (struct sockaddr *) sin_rx_ioctl, sizeof(struct sockaddr)); 319 | bind(nexio->sock_rx_frame, (struct sockaddr *) sin_rx_frame, sizeof(struct sockaddr)); 320 | 321 | nexio->type = NEXIO_TYPE_UDP; 322 | 323 | return nexio; 324 | } 325 | 326 | struct nexio * 327 | nex_init_netlink(void) 328 | { 329 | // printf("%s: Enter\n", __FUNCTION__); 330 | int err = 0; 331 | struct nexio *nexio = (struct nexio *) malloc(sizeof(struct nexio)); 332 | memset(nexio, 0, sizeof(struct nexio)); 333 | 334 | struct sockaddr_nl *snl_tx = (struct sockaddr_nl *) malloc(sizeof(struct sockaddr_nl)); 335 | struct sockaddr_nl *snl_rx_ioctl = (struct sockaddr_nl *) malloc(sizeof(struct sockaddr_nl)); 336 | 337 | memset(snl_tx, 0, sizeof(struct sockaddr_nl)); 338 | memset(snl_rx_ioctl, 0, sizeof(struct sockaddr_nl)); 339 | 340 | snl_tx->nl_family = AF_NETLINK; 341 | snl_tx->nl_pid = 0; /* For Linux Kernel */ 342 | snl_tx->nl_groups = 0; /* unicast */ 343 | 344 | snl_rx_ioctl->nl_family = AF_NETLINK; 345 | snl_rx_ioctl->nl_pid = getpid(); 346 | 347 | nexio->sock_tx = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER); 348 | if (nexio->sock_tx < 0) fprintf(stderr, "%s: socket error (%d: %s)\n", __FUNCTION__, errno, strerror(errno)); 349 | nexio->sock_rx_ioctl = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER); 350 | if (nexio->sock_rx_ioctl < 0) fprintf(stderr, "%s: socket error (%d: %s)\n", __FUNCTION__, errno, strerror(errno)); 351 | 352 | // Set 1 second timeout on ioctl receive socket 353 | struct timeval tv = { 354 | .tv_sec = 1, 355 | .tv_usec = 0 356 | }; 357 | setsockopt(nexio->sock_rx_ioctl, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 358 | 359 | // printf("%s: Before connect\n", __FUNCTION__); 360 | err = bind(nexio->sock_rx_ioctl, (struct sockaddr *) snl_rx_ioctl, sizeof(struct sockaddr)); 361 | if (err) fprintf(stderr, "%s: bind error (%d: %s)\n", __FUNCTION__, errno, strerror(errno)); 362 | 363 | err = connect(nexio->sock_tx, (struct sockaddr *) snl_tx, sizeof(struct sockaddr)); 364 | if (err) fprintf(stderr, "%s: connect error (%d: %s)\n", __FUNCTION__, errno, strerror(errno)); 365 | 366 | // printf("%s: Exit\n", __FUNCTION__); 367 | 368 | nexio->type = NEXIO_TYPE_NETLINK; 369 | 370 | return nexio; 371 | } 372 | -------------------------------------------------------------------------------- /monitormode.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * ########### ########### ########## ########## * 4 | * ############ ############ ############ ############ * 5 | * ## ## ## ## ## ## ## * 6 | * ## ## ## ## ## ## ## * 7 | * ########### #### ###### ## ## ## ## ###### * 8 | * ########### #### # ## ## ## ## # # * 9 | * ## ## ###### ## ## ## ## # # * 10 | * ## ## # ## ## ## ## # # * 11 | * ############ ##### ###### ## ## ## ##### ###### * 12 | * ########### ########### ## ## ## ########## * 13 | * * 14 | * S E C U R E M O B I L E N E T W O R K I N G * 15 | * * 16 | * This file is part of NexMon. * 17 | * * 18 | * Copyright (c) 2016 NexMon Team * 19 | * * 20 | * NexMon is free software: you can redistribute it and/or modify * 21 | * it under the terms of the GNU General Public License as published by * 22 | * the Free Software Foundation, either version 3 of the License, or * 23 | * (at your option) any later version. * 24 | * * 25 | * NexMon is distributed in the hope that it will be useful, * 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 28 | * GNU General Public License for more details. * 29 | * * 30 | * You should have received a copy of the GNU General Public License * 31 | * along with NexMon. If not, see . * 32 | * * 33 | **************************************************************************/ 34 | 35 | #define MONITOR_DISABLED 0 36 | #define MONITOR_IEEE80211 (1 << 0) // 1 37 | #define MONITOR_RADIOTAP (1 << 1) // 2 38 | #define MONITOR_DROP_FRM (1 << 2) // 4 39 | #define MONITOR_IPV4_UDP (1 << 3) // 8 40 | #define MONITOR_LOG_ONLY (1 << 4) // 16 41 | #define MONITOR_ACTIVATE_BADFCS (1 << 5) // 32 42 | #define MONITOR_STS (1 << 6) // 64 43 | -------------------------------------------------------------------------------- /nexioctls.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * ########### ########### ########## ########## * 4 | * ############ ############ ############ ############ * 5 | * ## ## ## ## ## ## ## * 6 | * ## ## ## ## ## ## ## * 7 | * ########### #### ###### ## ## ## ## ###### * 8 | * ########### #### # ## ## ## ## # # * 9 | * ## ## ###### ## ## ## ## # # * 10 | * ## ## # ## ## ## ## # # * 11 | * ############ ##### ###### ## ## ## ##### ###### * 12 | * ########### ########### ## ## ## ########## * 13 | * * 14 | * S E C U R E M O B I L E N E T W O R K I N G * 15 | * * 16 | * This file is part of NexMon. * 17 | * * 18 | * Copyright (c) 2016 NexMon Team * 19 | * * 20 | * NexMon is free software: you can redistribute it and/or modify * 21 | * it under the terms of the GNU General Public License as published by * 22 | * the Free Software Foundation, either version 3 of the License, or * 23 | * (at your option) any later version. * 24 | * * 25 | * NexMon is distributed in the hope that it will be useful, * 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 28 | * GNU General Public License for more details. * 29 | * * 30 | * You should have received a copy of the GNU General Public License * 31 | * along with NexMon. If not, see . * 32 | * * 33 | **************************************************************************/ 34 | 35 | #define IOCTL_ERROR -23 36 | #define IOCTL_SUCCESS 0 37 | 38 | // IOCTLs used by Nexmon 39 | #define NEX_GET_CAPABILITIES 400 40 | #define NEX_WRITE_TO_CONSOLE 401 41 | #define NEX_CT_EXPERIMENTS 402 42 | #define NEX_GET_CONSOLE 403 43 | #define NEX_GET_PHYREG 404 44 | #define NEX_SET_PHYREG 405 45 | #define NEX_READ_OBJMEM 406 46 | #define NEX_WRITE_OBJMEM 407 47 | #define NEX_INJECT_FRAME 408 48 | #define NEX_PRINT_TIMERS 409 49 | #define NEX_GET_SECURITYCOOKIE 410 50 | #define NEX_SET_SECURITYCOOKIE 411 51 | #define NEX_GET_WL_CNT 412 52 | #define NEX_GET_VERSION_STRING 413 53 | #define NEX_TEST_ARGPRINTF 414 54 | #define NEX_GET_RSPEC_OVERRIDE 415 55 | #define NEX_SET_RSPEC_OVERRIDE 416 56 | #define NEX_CLEAR_CONSOLE 417 57 | #define NEX_GET_CHANSPEC_OVERRIDE 418 58 | #define NEX_SET_CHANSPEC_OVERRIDE 419 59 | #define NEX_GET_AMPDU_TX 420 60 | #define NEX_SET_AMPDU_TX 421 61 | #define NEX_TRIGGER_EVENT 422 62 | #define NEX_TRIGGER_TDLS_DISCOVER 423 63 | #define NEX_TRIGGER_TDLS_SETUP 424 64 | #define NEX_TRIGGER_TDLS_TEARDOWN 425 65 | #define NEX_WRITE_TEMPLATE_RAM 426 66 | #define NEX_SDR_START_TRANSMISSION 427 67 | #define NEX_SDR_STOP_TRANSMISSION 428 68 | 69 | 70 | // IOCTLs used in original firmware 71 | #define WLC_GET_MAGIC 0 72 | #define WLC_GET_VERSION 1 73 | #define WLC_UP 2 74 | #define WLC_DOWN 3 75 | #define WLC_GET_LOOP 4 76 | #define WLC_SET_LOOP 5 77 | #define WLC_DUMP 6 78 | #define WLC_GET_MSGLEVEL 7 79 | #define WLC_SET_MSGLEVEL 8 80 | #define WLC_GET_PROMISC 9 81 | #define WLC_SET_PROMISC 10 82 | #define WLC_OVERLAY_IOCTL 11 83 | #define WLC_GET_RATE 12 84 | #define WLC_GET_MAX_RATE 13 85 | #define WLC_GET_INSTANCE 14 86 | #define WLC_GET_FRAG 15 87 | #define WLC_SET_FRAG 16 88 | #define WLC_GET_RTS 17 89 | #define WLC_SET_RTS 18 90 | #define NEX_READ_D11_OBJMEM 15 91 | #define WLC_GET_INFRA 19 92 | #define WLC_SET_INFRA 20 93 | #define WLC_GET_AUTH 21 94 | #define WLC_SET_AUTH 22 95 | #define WLC_GET_BSSID 23 96 | #define WLC_SET_BSSID 24 97 | #define WLC_GET_SSID 25 98 | #define WLC_SET_SSID 26 99 | #define WLC_RESTART 27 100 | #define WLC_TERMINATED 28 101 | #define WLC_GET_CHANNEL 29 102 | #define WLC_SET_CHANNEL 30 103 | #define WLC_GET_SRL 31 104 | #define WLC_SET_SRL 32 105 | #define WLC_GET_LRL 33 106 | #define WLC_SET_LRL 34 107 | #define WLC_GET_PLCPHDR 35 108 | #define WLC_SET_PLCPHDR 36 109 | #define WLC_GET_RADIO 37 110 | #define WLC_SET_RADIO 38 111 | #define WLC_GET_PHYTYPE 39 112 | #define WLC_DUMP_RATE 40 113 | #define WLC_SET_RATE_PARAMS 41 114 | #define WLC_GET_FIXRATE 42 115 | #define WLC_SET_FIXRATE 43 116 | #define WLC_GET_KEY 44 117 | #define WLC_SET_KEY 45 118 | #define WLC_GET_REGULATORY 46 119 | #define WLC_SET_REGULATORY 47 120 | #define WLC_GET_PASSIVE_SCAN 48 121 | #define WLC_SET_PASSIVE_SCAN 49 122 | #define WLC_SCAN 50 123 | #define WLC_SCAN_RESULTS 51 124 | #define WLC_DISASSOC 52 125 | #define WLC_REASSOC 53 126 | #define WLC_GET_ROAM_TRIGGER 54 127 | #define WLC_SET_ROAM_TRIGGER 55 128 | #define WLC_GET_ROAM_DELTA 56 129 | #define WLC_SET_ROAM_DELTA 57 130 | #define WLC_GET_ROAM_SCAN_PERIOD 58 131 | #define WLC_SET_ROAM_SCAN_PERIOD 59 132 | #define WLC_EVM 60 133 | #define WLC_GET_TXANT 61 134 | #define WLC_SET_TXANT 62 135 | #define WLC_GET_ANTDIV 63 136 | #define WLC_SET_ANTDIV 64 137 | #define WLC_GET_TXPWR 65 138 | #define WLC_SET_TXPWR 66 139 | #define WLC_GET_CLOSED 67 140 | #define WLC_SET_CLOSED 68 141 | #define WLC_GET_MACLIST 69 142 | #define WLC_SET_MACLIST 70 143 | #define WLC_GET_RATESET 71 144 | #define WLC_SET_RATESET 72 145 | #define WLC_GET_LOCALE 73 146 | #define WLC_LONGTRAIN 74 147 | #define WLC_GET_BCNPRD 75 148 | #define WLC_SET_BCNPRD 76 149 | #define WLC_GET_DTIMPRD 77 150 | #define WLC_SET_DTIMPRD 78 151 | #define WLC_GET_SROM 79 152 | #define WLC_SET_SROM 80 153 | #define WLC_GET_WEP_RESTRICT 81 154 | #define WLC_SET_WEP_RESTRICT 82 155 | #define WLC_GET_COUNTRY 83 156 | #define WLC_SET_COUNTRY 84 157 | #define WLC_GET_PM 85 158 | #define WLC_SET_PM 86 159 | #define WLC_GET_WAKE 87 160 | #define WLC_SET_WAKE 88 161 | #define WLC_GET_D11CNTS 89 162 | #define WLC_GET_FORCELINK 90 163 | #define WLC_SET_FORCELINK 91 164 | #define WLC_FREQ_ACCURACY 92 165 | #define WLC_CARRIER_SUPPRESS 93 166 | #define WLC_GET_PHYREG 94 167 | #define WLC_SET_PHYREG 95 168 | #define WLC_GET_RADIOREG 96 169 | #define WLC_SET_RADIOREG 97 170 | #define WLC_GET_REVINFO 98 171 | #define WLC_GET_UCANTDIV 99 172 | #define WLC_SET_UCANTDIV 100 173 | #define WLC_R_REG 101 174 | #define WLC_W_REG 102 175 | #define WLC_DIAG_LOOPBACK 103 176 | #define WLC_RESET_D11CNTS 104 177 | #define WLC_GET_MACMODE 105 178 | #define WLC_SET_MACMODE 106 179 | #define WLC_GET_MONITOR 107 180 | #define WLC_SET_MONITOR 108 181 | #define WLC_GET_GMODE 109 182 | #define WLC_SET_GMODE 110 183 | #define WLC_GET_LEGACY_ERP 111 184 | #define WLC_SET_LEGACY_ERP 112 185 | #define WLC_GET_RX_ANT 113 186 | #define WLC_GET_CURR_RATESET 114 187 | #define WLC_GET_SCANSUPPRESS 115 188 | #define WLC_SET_SCANSUPPRESS 116 189 | #define WLC_GET_AP 117 190 | #define WLC_SET_AP 118 191 | #define WLC_GET_EAP_RESTRICT 119 192 | #define WLC_SET_EAP_RESTRICT 120 193 | #define WLC_SCB_AUTHORIZE 121 194 | #define WLC_SCB_DEAUTHORIZE 122 195 | #define WLC_GET_WDSLIST 123 196 | #define WLC_SET_WDSLIST 124 197 | #define WLC_GET_ATIM 125 198 | #define WLC_SET_ATIM 126 199 | #define WLC_GET_RSSI 127 200 | #define WLC_GET_PHYANTDIV 128 201 | #define WLC_SET_PHYANTDIV 129 202 | #define WLC_AP_RX_ONLY 130 203 | #define WLC_GET_TX_PATH_PWR 131 204 | #define WLC_SET_TX_PATH_PWR 132 205 | #define WLC_GET_WSEC 133 206 | #define WLC_SET_WSEC 134 207 | #define WLC_GET_PHY_NOISE 135 208 | #define WLC_GET_BSS_INFO 136 209 | #define WLC_GET_PKTCNTS 137 210 | #define WLC_GET_LAZYWDS 138 211 | #define WLC_SET_LAZYWDS 139 212 | #define WLC_GET_BANDLIST 140 213 | #define WLC_GET_BAND 141 214 | #define WLC_SET_BAND 142 215 | #define WLC_SCB_DEAUTHENTICATE 143 216 | #define WLC_GET_SHORTSLOT 144 217 | #define WLC_GET_SHORTSLOT_OVERRIDE 145 218 | #define WLC_SET_SHORTSLOT_OVERRIDE 146 219 | #define WLC_GET_SHORTSLOT_RESTRICT 147 220 | #define WLC_SET_SHORTSLOT_RESTRICT 148 221 | #define WLC_GET_GMODE_PROTECTION 149 222 | #define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 223 | #define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 224 | #define WLC_UPGRADE 152 225 | #define WLC_GET_MRATE 153 226 | #define WLC_SET_MRATE 154 227 | #define WLC_GET_IGNORE_BCNS 155 228 | #define WLC_SET_IGNORE_BCNS 156 229 | #define WLC_GET_SCB_TIMEOUT 157 230 | #define WLC_SET_SCB_TIMEOUT 158 231 | #define WLC_GET_ASSOCLIST 159 232 | #define WLC_GET_CLK 160 233 | #define WLC_SET_CLK 161 234 | #define WLC_GET_UP 162 235 | #define WLC_OUT 163 236 | #define WLC_GET_WPA_AUTH 164 237 | #define WLC_SET_WPA_AUTH 165 238 | #define WLC_GET_UCFLAGS 166 239 | #define WLC_SET_UCFLAGS 167 240 | #define WLC_GET_PWRIDX 168 241 | #define WLC_SET_PWRIDX 169 242 | #define WLC_GET_TSSI 170 243 | #define WLC_GET_SUP_RATESET_OVERRIDE 171 244 | #define WLC_SET_SUP_RATESET_OVERRIDE 172 245 | #define WLC_SET_FAST_TIMER 173 246 | #define WLC_GET_FAST_TIMER 174 247 | #define WLC_SET_SLOW_TIMER 175 248 | #define WLC_GET_SLOW_TIMER 176 249 | #define WLC_DUMP_PHYREGS 177 250 | #define WLC_GET_PROTECTION_CONTROL 178 251 | #define WLC_SET_PROTECTION_CONTROL 179 252 | #define WLC_GET_PHYLIST 180 253 | #define WLC_ENCRYPT_STRENGTH 181 254 | #define WLC_DECRYPT_STATUS 182 255 | #define WLC_GET_KEY_SEQ 183 256 | #define WLC_GET_SCAN_CHANNEL_TIME 184 257 | #define WLC_SET_SCAN_CHANNEL_TIME 185 258 | #define WLC_GET_SCAN_UNASSOC_TIME 186 259 | #define WLC_SET_SCAN_UNASSOC_TIME 187 260 | #define WLC_GET_SCAN_HOME_TIME 188 261 | #define WLC_SET_SCAN_HOME_TIME 189 262 | #define WLC_GET_SCAN_NPROBES 190 263 | #define WLC_SET_SCAN_NPROBES 191 264 | #define WLC_GET_PRB_RESP_TIMEOUT 192 265 | #define WLC_SET_PRB_RESP_TIMEOUT 193 266 | #define WLC_GET_ATTEN 194 267 | #define WLC_SET_ATTEN 195 268 | #define WLC_GET_SHMEM 196 269 | #define WLC_SET_SHMEM 197 270 | #define WLC_GET_GMODE_PROTECTION_CTS 198 271 | #define WLC_SET_GMODE_PROTECTION_CTS 199 272 | #define WLC_SET_WSEC_TEST 200 273 | #define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201 274 | #define WLC_TKIP_COUNTERMEASURES 202 275 | #define WLC_GET_PIOMODE 203 276 | #define WLC_SET_PIOMODE 204 277 | #define WLC_SET_ASSOC_PREFER 205 278 | #define WLC_GET_ASSOC_PREFER 206 279 | #define WLC_SET_ROAM_PREFER 207 280 | #define WLC_GET_ROAM_PREFER 208 281 | #define WLC_SET_LED 209 282 | #define WLC_GET_LED 210 283 | #define WLC_GET_INTERFERENCE_MODE 211 284 | #define WLC_SET_INTERFERENCE_MODE 212 285 | #define WLC_GET_CHANNEL_QA 213 286 | #define WLC_START_CHANNEL_QA 214 287 | #define WLC_GET_CHANNEL_SEL 215 288 | #define WLC_START_CHANNEL_SEL 216 289 | #define WLC_GET_VALID_CHANNELS 217 290 | #define WLC_GET_FAKEFRAG 218 291 | #define WLC_SET_FAKEFRAG 219 292 | #define WLC_GET_PWROUT_PERCENTAGE 220 293 | #define WLC_SET_PWROUT_PERCENTAGE 221 294 | #define WLC_SET_BAD_FRAME_PREEMPT 222 295 | #define WLC_GET_BAD_FRAME_PREEMPT 223 296 | #define WLC_SET_LEAP_LIST 224 297 | #define WLC_GET_LEAP_LIST 225 298 | #define WLC_GET_CWMIN 226 299 | #define WLC_SET_CWMIN 227 300 | #define WLC_GET_CWMAX 228 301 | #define WLC_SET_CWMAX 229 302 | #define WLC_GET_WET 230 303 | #define WLC_SET_WET 231 304 | #define WLC_GET_PUB 232 305 | #define WLC_GET_KEY_PRIMARY 235 306 | #define WLC_SET_KEY_PRIMARY 236 307 | #define WLC_GET_VAR 262 /* get value of named variable */ 308 | #define WLC_SET_VAR 263 /* set named variable to value */ 309 | -------------------------------------------------------------------------------- /nexmon.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * * 3 | * ########### ########### ########## ########## * 4 | * ############ ############ ############ ############ * 5 | * ## ## ## ## ## ## ## * 6 | * ## ## ## ## ## ## ## * 7 | * ########### #### ###### ## ## ## ## ###### * 8 | * ########### #### # ## ## ## ## # # * 9 | * ## ## ###### ## ## ## ## # # * 10 | * ## ## # ## ## ## ## # # * 11 | * ############ ##### ###### ## ## ## ##### ###### * 12 | * ########### ########### ## ## ## ########## * 13 | * * 14 | * S E C U R E M O B I L E N E T W O R K I N G * 15 | * * 16 | * This file is part of NexMon. * 17 | * * 18 | * Based on: * 19 | * * 20 | * This code is based on the ldpreloadhook example by Pau Oliva Fora * 21 | * and the idea of hooking ioctls to fake a monitor mode * 22 | * interface, which was presented by Omri Ildis, Yuval Ofir and Ruby * 23 | * Feinstein at recon2013. * 24 | * * 25 | * Copyright (c) 2016 NexMon Team * 26 | * * 27 | * NexMon is free software: you can redistribute it and/or modify * 28 | * it under the terms of the GNU General Public License as published by * 29 | * the Free Software Foundation, either version 3 of the License, or * 30 | * (at your option) any later version. * 31 | * * 32 | * NexMon is distributed in the hope that it will be useful, * 33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 35 | * GNU General Public License for more details. * 36 | * * 37 | * You should have received a copy of the GNU General Public License * 38 | * along with NexMon. If not, see . * 39 | * * 40 | **************************************************************************/ 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #define CONFIG_LIBNL 58 | 59 | #ifdef CONFIG_LIBNL 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #endif // CONFIG_LIBNL 68 | 69 | #define __USE_POSIX199309 70 | #define _POSIX_C_SOURCE 199309L 71 | #include 72 | 73 | typedef unsigned int uint; 74 | 75 | #define TYPEDEF_BOOL // define this to make not throw an error trying to redefine bool 76 | #include 77 | #include 78 | 79 | #define WLC_GET_MONITOR 107 80 | #define WLC_SET_MONITOR 108 81 | 82 | struct nexio { 83 | struct ifreq *ifr; 84 | int sock_rx_ioctl; 85 | int sock_rx_frame; 86 | int sock_tx; 87 | }; 88 | 89 | extern int nex_ioctl(struct nexio *nexio, int cmd, void *buf, int len, bool set); 90 | extern struct nexio *nex_init_ioctl(const char *ifname); 91 | 92 | #ifndef RTLD_NEXT 93 | #define RTLD_NEXT ((void *) -1l) 94 | #endif 95 | 96 | #define REAL_LIBC RTLD_NEXT 97 | #ifdef CONFIG_LIBNL 98 | #define REAL_LIBNL RTLD_NEXT 99 | #endif // CONFIG_LIBNL 100 | 101 | int frequency_to_channel(int); 102 | int nex_set_channel_simple(int); 103 | int nex_set_channel_full(uint32, uint32, uint32, uint32); 104 | 105 | typedef int request_t; 106 | 107 | typedef void (*sighandler_t)(int); 108 | 109 | static struct nexio *nexio = NULL; 110 | 111 | static const char *ifname = "wlan0"; 112 | 113 | static int (*func_sendto) (int, const void *, size_t, int, const struct sockaddr *, socklen_t) = NULL; 114 | static int (*func_ioctl) (int, request_t, void *) = NULL; 115 | static int (*func_socket) (int, int, int) = NULL; 116 | static int (*func_bind) (int, const struct sockaddr *, int) = NULL; 117 | static int (*func_write) (int, const void *, size_t) = NULL; 118 | #ifdef CONFIG_LIBNL 119 | static int (*func_nl_send_auto_complete) (struct nl_sock *, struct nl_msg *) = NULL; 120 | #endif // CONFIG_LIBNL 121 | 122 | static void _libmexmon_init() __attribute__ ((constructor)); 123 | static void _libmexmon_init() { 124 | nexio = nex_init_ioctl(ifname); 125 | 126 | if (! func_ioctl) 127 | func_ioctl = (int (*) (int, request_t, void *)) dlsym (REAL_LIBC, "ioctl"); 128 | 129 | if (! func_socket) 130 | func_socket = (int (*) (int, int, int)) dlsym (REAL_LIBC, "socket"); 131 | 132 | if (! func_bind) 133 | func_bind = (int (*) (int, const struct sockaddr *, int)) dlsym (REAL_LIBC, "bind"); 134 | 135 | if (! func_write) 136 | func_write = (int (*) (int, const void *, size_t)) dlsym (REAL_LIBC, "write"); 137 | 138 | if (! func_sendto) 139 | func_sendto = (int (*) (int, const void *, size_t, int, const struct sockaddr *, socklen_t)) dlsym (REAL_LIBC, "sendto"); 140 | 141 | #ifdef CONFIG_LIBNL 142 | if (! func_nl_send_auto_complete) 143 | func_nl_send_auto_complete = (int (*) (struct nl_sock *, struct nl_msg *)) dlsym(REAL_LIBNL, "nl_send_auto_complete"); 144 | #endif // CONFIG_LIBNL 145 | } 146 | 147 | #ifdef CONFIG_LIBNL 148 | static int _nl80211_type = 0; 149 | int nl80211_type() 150 | { 151 | if(_nl80211_type) 152 | { 153 | // fprintf(stderr, "cached\n"); 154 | return _nl80211_type; 155 | } 156 | 157 | int rval; 158 | struct nl_sock *nl_sock = NULL; 159 | struct nl_cache *nl_cache = NULL; 160 | struct genl_family *nl80211 = NULL; 161 | 162 | // fprintf(stderr, "beginning\n"); 163 | nl_sock = nl_socket_alloc(); 164 | // fprintf(stderr, "nl_sock=%d\n", nl_sock); 165 | if(!nl_sock) 166 | return 0; 167 | 168 | rval = genl_connect(nl_sock); 169 | // fprintf(stderr, "genl_connect=%d\n", rval); 170 | if(rval) 171 | { 172 | nl_socket_free(nl_sock); 173 | return 0; 174 | } 175 | 176 | rval = genl_ctrl_alloc_cache(nl_sock, &nl_cache); 177 | // fprintf(stderr, "genl_ctrl_allocate_cache=%d\n", rval); 178 | if(rval) 179 | { 180 | nl_socket_free(nl_sock); 181 | return 0; 182 | } 183 | 184 | nl80211 = genl_ctrl_search_by_name(nl_cache, "nl80211"); 185 | // fprintf(stderr, "genl_ctrl_search_by_name=%d\n", !!nl80211); 186 | 187 | if(nl80211) 188 | { 189 | _nl80211_type = genl_family_get_id(nl80211); 190 | // fprintf(stderr, "_nl80211_type=%d\n", _nl80211_type); 191 | } 192 | 193 | nl_cache_free(nl_cache); 194 | nl_socket_free(nl_sock); 195 | return _nl80211_type; 196 | } 197 | 198 | int handle_nl_msg(struct nl_msg *msg) 199 | { 200 | int retval; 201 | struct nlmsghdr *nlh; 202 | struct genlmsghdr *ghdr; 203 | struct nlattr *attr[NL80211_ATTR_MAX+1]; 204 | struct nla_policy policy[4] = { 205 | [0] = { .type = NLA_U32 }, 206 | }; 207 | 208 | nlh = nlmsg_hdr(msg); 209 | 210 | 211 | // if this isn't an nl80211 message, we don't want it 212 | if(nlh->nlmsg_type != nl80211_type()) 213 | return 0; 214 | if(nlmsg_get_proto(msg) != NETLINK_GENERIC) 215 | return 0; 216 | 217 | // fprintf(stderr, "nlmsg_parse\n"); 218 | retval = nlmsg_parse(nlh, GENL_HDRLEN, attr, NL80211_ATTR_MAX, policy); 219 | // fprintf(stderr, "retval=%d\n", retval); 220 | if(retval) 221 | return 0; 222 | 223 | ghdr = nlmsg_data(nlh); 224 | if(ghdr->cmd == NL80211_CMD_SET_WIPHY) 225 | { 226 | int chan = 0; 227 | int ht_mode = NL80211_CHAN_HT20; 228 | int bandwidth = WL_CHANSPEC_BW_20; 229 | int band = WL_CHANSPEC_BAND_2G; 230 | int ctl_sb = 0; 231 | 232 | if(!attr[NL80211_ATTR_IFINDEX]) 233 | return 0; 234 | if( nla_get_u32(attr[NL80211_ATTR_IFINDEX]) != if_nametoindex(ifname)) 235 | return 0; 236 | // fprintf(stderr, "NL80211_ATTR_IFINDEX = %u\n", nla_get_u32(attr[NL80211_ATTR_IFINDEX])); 237 | 238 | if(attr[NL80211_ATTR_WIPHY_FREQ]) 239 | { 240 | int freq = nla_get_u32(attr[NL80211_ATTR_WIPHY_FREQ]); 241 | chan = frequency_to_channel(freq); 242 | if(freq >= 5000) 243 | band = WL_CHANSPEC_BAND_5G; 244 | // fprintf(stderr, "NL80211_ATTR_WIPHY_FREQ = %u (%d)\n", freq, chan); 245 | } 246 | // HT20/HT40-/HT40+/... there are more but our device doesn't support that anyway 247 | if(attr[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) 248 | { 249 | ht_mode = nla_get_u32(attr[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); 250 | // fprintf(stderr, "NL80211_ATTR_WIPHY_CHANNEL_TYPE = %u\n", nla_get_u32(attr[NL80211_ATTR_WIPHY_CHANNEL_TYPE])); 251 | } 252 | if(attr[NL80211_ATTR_CHANNEL_WIDTH]) 253 | { 254 | if(nla_get_u32(attr[NL80211_ATTR_CHANNEL_WIDTH]) == NL80211_CHAN_WIDTH_40) 255 | bandwidth = WL_CHANSPEC_BW_40; 256 | // fprintf(stderr, "NL80211_ATTR_CHANNEL_WIDTH = %u\n", nla_get_u32(attr[NL80211_ATTR_CHANNEL_WIDTH])); 257 | } 258 | if(attr[NL80211_ATTR_CENTER_FREQ1]) 259 | { 260 | int freq = nla_get_u32(attr[NL80211_ATTR_CENTER_FREQ1]); 261 | int ctl_chan = frequency_to_channel(freq); 262 | if(ctl_chan > chan) 263 | ctl_sb = WL_CHANSPEC_CTL_SB_LLL; 264 | else if (ctl_chan < chan) 265 | ctl_sb = WL_CHANSPEC_CTL_SB_LLU; 266 | chan = ctl_chan; 267 | // fprintf(stderr, "NL80211_ATTR_CENTER_FREQ1 = %u\n", freq, frequency_to_channel(freq)); 268 | } 269 | // this device doesn't support 80+80 anyway 270 | // if(attr[NL80211_ATTR_CENTER_FREQ2]) 271 | // fprintf(stderr, "NL80211_ATTR_CENTER_FREQ2 = %u\n", nla_get_u32(attr[NL80211_ATTR_CENTER_FREQ2])); 272 | 273 | if(ht_mode == NL80211_CHAN_HT40PLUS) 274 | { 275 | if(band == WL_CHANSPEC_BAND_2G) 276 | { 277 | bandwidth = WL_CHANSPEC_BW_40; 278 | chan = LOWER_20_SB(chan); 279 | ctl_sb = WL_CHANSPEC_CTL_SB_LLU; 280 | } 281 | else 282 | ht_mode = NL80211_CHAN_HT40MINUS; // there is only one sideband allowed for 40MHz in 5G band 283 | } 284 | if(ht_mode == NL80211_CHAN_HT40MINUS) 285 | { 286 | bandwidth = WL_CHANSPEC_BW_40; 287 | chan = UPPER_20_SB(chan); 288 | ctl_sb = WL_CHANSPEC_CTL_SB_LLL; 289 | } 290 | 291 | if(chan) 292 | // nex_set_channel_simple(chan); 293 | return nex_set_channel_full(chan, band, bandwidth, ctl_sb); 294 | 295 | } 296 | if(ghdr->cmd == NL80211_CMD_SET_INTERFACE) 297 | { 298 | if(!attr[NL80211_ATTR_IFINDEX]) 299 | return 0; 300 | if( nla_get_u32(attr[NL80211_ATTR_IFINDEX]) != if_nametoindex(ifname)) 301 | return 0; 302 | // fprintf(stderr, "NL80211_ATTR_IFINDEX = %u\n", nla_get_u32(attr[NL80211_ATTR_IFINDEX])); 303 | 304 | // we could set monitor/managed mode based on this message 305 | if(attr[NL80211_ATTR_IFTYPE]) 306 | { 307 | // fprintf(stderr, "NL80211_ATTR_IFTYPE = %u\n", nla_get_u32(attr[NL80211_ATTR_IFTYPE])); 308 | } 309 | } 310 | 311 | return 0; 312 | } 313 | 314 | // there are several other functions that can send netlink messages, but it looks like airodump-ng and kismet both use this one, so this is good enough for now 315 | int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg) 316 | { 317 | int ret; 318 | 319 | ret = func_nl_send_auto_complete(sk, msg); 320 | 321 | // fprintf(stderr, "\nnl_send_auto_complete()\n"); 322 | ret = handle_nl_msg(msg); 323 | return ret; 324 | } 325 | #endif // CONFIG_LIBNL 326 | 327 | int frequency_to_channel(int freq_in_MHz) 328 | { 329 | if(freq_in_MHz == 2484) 330 | return 14; 331 | if(freq_in_MHz >= 2412 && freq_in_MHz <= 2472) 332 | return (freq_in_MHz-2407)/5; 333 | if(freq_in_MHz >= 5000 && freq_in_MHz <= 6000) 334 | return (freq_in_MHz-5000)/5; 335 | 336 | return 0; 337 | } 338 | 339 | int nex_set_channel_simple(int channel) 340 | { 341 | int band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); 342 | return nex_set_channel_full(channel, band, WL_CHANSPEC_BW_20, 0); 343 | } 344 | 345 | int nex_set_channel_full(uint32 channel, uint32 band, uint32 bw, uint32 ctl_sb) 346 | { 347 | char charbuf[13] = "chanspec"; 348 | uint32 *chanspec = (uint32*) &charbuf[9]; 349 | 350 | *chanspec = (channel | band | bw | ctl_sb); 351 | // fprintf(stderr, "setting channel: channel=%08x band=%08x bw=%08x ctl_sb=%08x chanspec=%08x\n", channel, band, bw, ctl_sb, *chanspec); 352 | return nex_ioctl(nexio, WLC_SET_VAR, charbuf, 13, true); 353 | } 354 | 355 | int 356 | ioctl(int fd, request_t request, ...) 357 | { 358 | va_list args; 359 | void *argp; 360 | int ret; 361 | 362 | va_start (args, request); 363 | argp = va_arg (args, void *); 364 | va_end (args); 365 | 366 | ret = func_ioctl(fd, request, argp); 367 | //if (ret < 0) { 368 | // fprintf(stderr, "LIBNEXMON: original response: %d, request: 0x%x\n", ret, request); 369 | //} 370 | 371 | switch (request) { 372 | case SIOCGIFHWADDR: 373 | { 374 | int buf; 375 | struct ifreq* p_ifr = (struct ifreq *) argp; 376 | if (!strncmp(p_ifr->ifr_ifrn.ifrn_name, ifname, strlen(ifname))) { 377 | nex_ioctl(nexio, WLC_GET_MONITOR, &buf, 4, false); 378 | 379 | if (buf & MONITOR_IEEE80211) p_ifr->ifr_hwaddr.sa_family = ARPHRD_IEEE80211; 380 | else if (buf & MONITOR_RADIOTAP) p_ifr->ifr_hwaddr.sa_family = ARPHRD_IEEE80211_RADIOTAP; 381 | else if (buf & MONITOR_DISABLED || buf & MONITOR_LOG_ONLY || buf & MONITOR_DROP_FRM || buf & MONITOR_IPV4_UDP) 382 | p_ifr->ifr_hwaddr.sa_family = ARPHRD_ETHER; 383 | 384 | ret = 0; 385 | } 386 | } 387 | break; 388 | 389 | case SIOCGIWMODE: 390 | { 391 | int buf; 392 | struct iwreq* p_wrq = (struct iwreq*) argp; 393 | 394 | if (!strncmp(p_wrq->ifr_ifrn.ifrn_name, ifname, strlen(ifname))) { 395 | nex_ioctl(nexio, WLC_GET_MONITOR, &buf, 4, false); 396 | 397 | if (buf & MONITOR_RADIOTAP || buf & MONITOR_IEEE80211 || buf & MONITOR_LOG_ONLY || buf & MONITOR_DROP_FRM || buf & MONITOR_IPV4_UDP) { 398 | p_wrq->u.mode = IW_MODE_MONITOR; 399 | } 400 | 401 | ret = 0; 402 | } 403 | } 404 | break; 405 | 406 | case SIOCSIWMODE: 407 | { 408 | int buf; 409 | struct iwreq* p_wrq = (struct iwreq*) argp; 410 | 411 | if (!strncmp(p_wrq->ifr_ifrn.ifrn_name, ifname, strlen(ifname))) { 412 | if (p_wrq->u.mode == IW_MODE_MONITOR) { 413 | buf = MONITOR_RADIOTAP; 414 | } else { 415 | buf = MONITOR_DISABLED; 416 | } 417 | 418 | ret = nex_ioctl(nexio, WLC_SET_MONITOR, &buf, 4, true); 419 | } 420 | } 421 | break; 422 | 423 | case SIOCSIWFREQ: // set channel/frequency (Hz) 424 | { 425 | struct iwreq* p_wrq = (struct iwreq*) argp; 426 | 427 | if (!strncmp(p_wrq->ifr_ifrn.ifrn_name, ifname, strlen(ifname))) { 428 | char charbuf[13] = "chanspec"; 429 | uint32 *chanspec = (uint32*) &charbuf[9]; 430 | int channel = p_wrq->u.freq.m; 431 | int exp = p_wrq->u.freq.e; 432 | 433 | // TODO: test this! 434 | // fprintf(stderr, "SIWFREQ: chan/freq: m=%d e=%d\n", channel, exp); 435 | // if this is > 500 (or 1000, depending on the source), it's a frequency, not a channel 436 | if(channel > 500 || exp > 0) 437 | { 438 | // convert from Hz to MHz 439 | if(exp < 6) 440 | { 441 | for(int i=0;iifr_ifrn.ifrn_name, ifname, strlen(ifname))) { 469 | char charbuf[9] = "chanspec"; 470 | uint16 chanspec; 471 | int32 channel; 472 | ret = nex_ioctl(nexio, WLC_GET_VAR, charbuf, 9, false); 473 | if(ret >= 0) { 474 | chanspec = *(uint16 *) charbuf; 475 | channel = chanspec & 0xFF; 476 | p_wrq->u.freq.e = 0; 477 | p_wrq->u.freq.m = channel; 478 | // fprintf(stderr, "GIWFREQ: channel=%d\n", channel); 479 | } 480 | 481 | } 482 | 483 | 484 | //if (ret < 0) 485 | //fprintf(stderr, "LIBNEXMON: SIOCGIWFREQ not fully implemented\n"); 486 | } 487 | break; 488 | } 489 | return ret; 490 | } 491 | 492 | void 493 | hexdump(const char *desc, const void *addr, int len) 494 | { 495 | int i; 496 | unsigned char buff[17]; 497 | unsigned char *pc = (unsigned char*)addr; 498 | 499 | // Output description if given. 500 | if (desc != 0) 501 | printf ("%s:\n", desc); 502 | 503 | // Process every byte in the data. 504 | for (i = 0; i < len; i++) { 505 | // Multiple of 16 means new line (with line offset). 506 | 507 | if ((i % 16) == 0) { 508 | // Just don't print ASCII for the zeroth line. 509 | if (i != 0) 510 | printf (" %s\n", buff); 511 | 512 | // Output the offset. 513 | printf (" %04x ", i); 514 | } 515 | 516 | // Now the hex code for the specific character. 517 | printf (" %02x", pc[i]); 518 | 519 | // And store a printable ASCII character for later. 520 | if ((pc[i] < 0x20) || (pc[i] > 0x7e)) 521 | buff[i % 16] = '.'; 522 | else 523 | buff[i % 16] = pc[i]; 524 | buff[(i % 16) + 1] = '\0'; 525 | } 526 | 527 | // Pad out last line if not exactly 16 characters. 528 | while ((i % 16) != 0) { 529 | printf (" "); 530 | i++; 531 | } 532 | 533 | // And print the final ASCII bit. 534 | printf (" %s\n", buff); 535 | } 536 | 537 | static char sock_types[][16] = { 538 | "SOCK_STREAM", 539 | "SOCK_DGRAM", 540 | "SOCK_RAW", 541 | "SOCK_RDM", 542 | "SOCK_SEQPACKET", 543 | }; 544 | 545 | static char domain_types[][16] = { 546 | "AF_UNSPEC", 547 | "AF_UNIX", 548 | "AF_INET", 549 | "AF_AX25", 550 | "AF_IPX", 551 | "AF_APPLETALK", 552 | "AF_NETROM", 553 | "AF_BRIDGE", 554 | "AF_ATMPVC", 555 | "AF_X25", 556 | "AF_INET6", 557 | "AF_ROSE", 558 | "AF_DECnet", 559 | "AF_NETBEUI", 560 | "AF_SECURITY", 561 | "AF_KEY", 562 | "AF_NETLINK", 563 | "AF_PACKET", 564 | "AF_ASH", 565 | "AF_ECONET", 566 | "AF_ATMSVC", 567 | "AF_RDS", 568 | "AF_SNA", 569 | "AF_IRDA", 570 | "AF_PPPOX", 571 | "AF_WANPIPE", 572 | "AF_LLC", 573 | "AF_IB", 574 | "AF_MPLS", 575 | "AF_CAN", 576 | "AF_TIPC", 577 | "AF_BLUETOOTH", 578 | "AF_IUCV", 579 | "AF_RXRPC", 580 | "AF_ISDN", 581 | "AF_PHONET", 582 | "AF_IEEE802154", 583 | "AF_CAIF", 584 | "AF_ALG", 585 | "AF_NFC", 586 | "AF_VSOCK", 587 | "AF_KCM", 588 | "AF_QIPCRTR", 589 | "AF_SMC" 590 | }; 591 | 592 | int socket_to_type[100] = { 0 }; 593 | char bound_to_correct_if[100] = { 0 }; 594 | 595 | int 596 | socket(int domain, int type, int protocol) 597 | { 598 | int ret; 599 | 600 | ret = func_socket(domain, type, protocol); 601 | 602 | // save the socket type 603 | if (ret < sizeof(socket_to_type)/sizeof(socket_to_type[0])) 604 | socket_to_type[ret] = type; 605 | 606 | //if ((type - 1 < sizeof(sock_types)/sizeof(sock_types[0])) && (domain - 1 < sizeof(domain_types)/sizeof(domain_types[0]))) 607 | // printf("LIBNEXMON: %d = %s(%s(%d), %s(%d), %d)\n", ret, __FUNCTION__, domain_types[domain], domain, sock_types[type - 1], type, protocol); 608 | 609 | return ret; 610 | } 611 | 612 | int 613 | bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) 614 | { 615 | int ret; 616 | struct sockaddr_ll *sll = (struct sockaddr_ll *) addr; 617 | 618 | ret = func_bind(sockfd, addr, addrlen); 619 | 620 | char sll_ifname[IF_NAMESIZE] = { 0 }; 621 | if_indextoname(sll->sll_ifindex, sll_ifname); 622 | 623 | if ((sockfd < sizeof(bound_to_correct_if)/sizeof(bound_to_correct_if[0])) && !strncmp(ifname, sll_ifname, sizeof(ifname))) 624 | bound_to_correct_if[sockfd] = 1; 625 | 626 | //printf("LIBNEXMON: %d = %s(%d, 0x%p, %d) sll_ifindex=%d ifname=%s\n", ret, __FUNCTION__, sockfd, addr, addrlen, sll->sll_ifindex, sll_ifname); 627 | 628 | return ret; 629 | } 630 | 631 | struct inject_frame { 632 | unsigned short len; 633 | unsigned char pad; 634 | unsigned char type; 635 | char data[]; 636 | }; 637 | 638 | ssize_t 639 | write(int fd, const void *buf, size_t count) 640 | { 641 | ssize_t ret; 642 | 643 | // check if the user wants to write on a raw socket 644 | if ((fd > 2) && (fd < sizeof(socket_to_type)/sizeof(socket_to_type[0])) && (socket_to_type[fd] == SOCK_RAW) && (bound_to_correct_if[fd] == 1)) { 645 | struct inject_frame *buf_dup = (struct inject_frame *) malloc(count + sizeof(struct inject_frame)); 646 | 647 | buf_dup->len = count + sizeof(struct inject_frame); 648 | buf_dup->pad = 0; 649 | buf_dup->type = 1; 650 | memcpy(buf_dup->data, buf, count); 651 | 652 | // fprintf(stderr, "injecting!\n"); 653 | nex_ioctl(nexio, NEX_INJECT_FRAME, buf_dup, count + sizeof(struct inject_frame), true); 654 | free(buf_dup); 655 | 656 | // this is probably frowned on, but it works on the Nexus 6P 657 | // rate-limiting keeps the driver from crashing when doing aireplay-ng 658 | struct timespec ts; 659 | ts.tv_sec = 0; 660 | ts.tv_nsec = 50 * 1000000; // 50 ms 661 | nanosleep(&ts, NULL); 662 | 663 | ret = count; 664 | } else { 665 | // otherwise write the regular frame to the socket 666 | ret = func_write(fd, buf, count); 667 | } 668 | 669 | return ret; 670 | } 671 | 672 | ssize_t 673 | sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) 674 | { 675 | ssize_t ret; 676 | 677 | // check if the user wants to write on a raw socket 678 | if ((sockfd > 2) && (sockfd < sizeof(socket_to_type)/sizeof(socket_to_type[0])) && (socket_to_type[sockfd] == SOCK_RAW) && (bound_to_correct_if[sockfd] == 1)) { 679 | struct inject_frame *buf_dup = (struct inject_frame *) malloc(len + sizeof(struct inject_frame)); 680 | 681 | buf_dup->len = len + sizeof(struct inject_frame); 682 | buf_dup->pad = 0; 683 | buf_dup->type = 1; 684 | memcpy(buf_dup->data, buf, len); 685 | 686 | nex_ioctl(nexio, NEX_INJECT_FRAME, buf_dup, len + sizeof(struct inject_frame), true); 687 | 688 | free(buf_dup); 689 | 690 | ret = len; 691 | } else { 692 | // otherwise write the regular frame to the socket 693 | ret = func_sendto(sockfd, buf, len, flags, dest_addr, addrlen); 694 | } 695 | 696 | return ret; 697 | } 698 | -------------------------------------------------------------------------------- /typedefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1999-2013, Broadcom Corporation 3 | * 4 | * Unless you and Broadcom execute a separate written software license 5 | * agreement governing use of this software, this software is licensed to you 6 | * under the terms of the GNU General Public License version 2 (the "GPL"), 7 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the 8 | * following added to such license: 9 | * 10 | * As a special exception, the copyright holders of this software give you 11 | * permission to link this software with independent modules, and to copy and 12 | * distribute the resulting executable under terms of your choice, provided that 13 | * you also meet, for each linked independent module, the terms and conditions of 14 | * the license of that module. An independent module is a module which is not 15 | * derived from this software. The special exception does not apply to any 16 | * modifications of the software. 17 | * 18 | * Notwithstanding the above, under no circumstances may you combine this 19 | * software in any way with any other Broadcom software provided under a license 20 | * other than the GPL, without Broadcom's express prior written consent. 21 | * $Id: typedefs.h 397286 2013-04-18 01:42:19Z $ 22 | */ 23 | 24 | #ifndef _TYPEDEFS_H_ 25 | #define _TYPEDEFS_H_ 26 | 27 | #ifdef SITE_TYPEDEFS 28 | 29 | /* 30 | * Define SITE_TYPEDEFS in the compile to include a site-specific 31 | * typedef file "site_typedefs.h". 32 | * 33 | * If SITE_TYPEDEFS is not defined, then the code section below makes 34 | * inferences about the compile environment based on defined symbols and 35 | * possibly compiler pragmas. 36 | * 37 | * Following these two sections is the Default Typedefs section. 38 | * This section is only processed if USE_TYPEDEF_DEFAULTS is 39 | * defined. This section has a default set of typedefs and a few 40 | * preprocessor symbols (TRUE, FALSE, NULL, ...). 41 | */ 42 | 43 | #include "site_typedefs.h" 44 | 45 | #else 46 | 47 | /* 48 | * Infer the compile environment based on preprocessor symbols and pragmas. 49 | * Override type definitions as needed, and include configuration-dependent 50 | * header files to define types. 51 | */ 52 | 53 | #ifdef __cplusplus 54 | 55 | #define TYPEDEF_BOOL 56 | #ifndef FALSE 57 | #define FALSE false 58 | #endif 59 | #ifndef TRUE 60 | #define TRUE true 61 | #endif 62 | 63 | #else /* ! __cplusplus */ 64 | 65 | 66 | #endif /* ! __cplusplus */ 67 | 68 | #if defined(__x86_64__) 69 | #define TYPEDEF_UINTPTR 70 | typedef unsigned long long int uintptr; 71 | #endif 72 | 73 | 74 | 75 | 76 | 77 | #if defined(_NEED_SIZE_T_) 78 | typedef long unsigned int size_t; 79 | #endif 80 | 81 | 82 | 83 | 84 | 85 | #if defined(__sparc__) 86 | #define TYPEDEF_ULONG 87 | #endif 88 | 89 | 90 | /* 91 | * If this is either a Linux hybrid build or the per-port code of a hybrid build 92 | * then use the Linux header files to get some of the typedefs. Otherwise, define 93 | * them entirely in this file. We can't always define the types because we get 94 | * a duplicate typedef error; there is no way to "undefine" a typedef. 95 | * We know when it's per-port code because each file defines LINUX_PORT at the top. 96 | */ 97 | #if !defined(LINUX_HYBRID) || defined(LINUX_PORT) 98 | #define TYPEDEF_UINT 99 | #ifndef TARGETENV_android 100 | #define TYPEDEF_USHORT 101 | #define TYPEDEF_ULONG 102 | #endif /* TARGETENV_android */ 103 | #ifdef __KERNEL__ 104 | #include 105 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) 106 | #define TYPEDEF_BOOL 107 | #endif /* >= 2.6.19 */ 108 | /* special detection for 2.6.18-128.7.1.0.1.el5 */ 109 | #if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18)) 110 | #include 111 | #ifdef noinline_for_stack 112 | #define TYPEDEF_BOOL 113 | #endif 114 | #endif /* == 2.6.18 */ 115 | #endif /* __KERNEL__ */ 116 | #endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ 117 | 118 | 119 | 120 | 121 | /* Do not support the (u)int64 types with strict ansi for GNU C */ 122 | #if defined(__GNUC__) && defined(__STRICT_ANSI__) 123 | #define TYPEDEF_INT64 124 | #define TYPEDEF_UINT64 125 | #endif /* defined(__GNUC__) && defined(__STRICT_ANSI__) */ 126 | 127 | /* ICL accepts unsigned 64 bit type only, and complains in ANSI mode 128 | * for signed or unsigned 129 | */ 130 | #if defined(__ICL) 131 | 132 | #define TYPEDEF_INT64 133 | 134 | #if defined(__STDC__) 135 | #define TYPEDEF_UINT64 136 | #endif 137 | 138 | #endif /* __ICL */ 139 | 140 | #if !defined(__DJGPP__) 141 | 142 | /* pick up ushort & uint from standard types.h */ 143 | #if defined(__KERNEL__) 144 | 145 | /* See note above */ 146 | #if !defined(LINUX_HYBRID) || defined(LINUX_PORT) 147 | #include /* sys/types.h and linux/types.h are oil and water */ 148 | #endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ 149 | 150 | #else 151 | 152 | 153 | #include 154 | 155 | #endif /* linux && __KERNEL__ */ 156 | 157 | #endif 158 | 159 | 160 | 161 | /* use the default typedefs in the next section of this file */ 162 | #define USE_TYPEDEF_DEFAULTS 163 | 164 | #endif /* SITE_TYPEDEFS */ 165 | 166 | 167 | /* 168 | * Default Typedefs 169 | */ 170 | 171 | #ifdef USE_TYPEDEF_DEFAULTS 172 | #undef USE_TYPEDEF_DEFAULTS 173 | 174 | #ifndef TYPEDEF_BOOL 175 | typedef /* @abstract@ */ unsigned char bool; 176 | #endif 177 | 178 | /* define uchar, ushort, uint, ulong */ 179 | 180 | #ifndef TYPEDEF_UCHAR 181 | typedef unsigned char uchar; 182 | #endif 183 | 184 | #ifndef TYPEDEF_USHORT 185 | typedef unsigned short ushort; 186 | #endif 187 | 188 | #ifndef TYPEDEF_UINT 189 | typedef unsigned int uint; 190 | #endif 191 | 192 | #ifndef TYPEDEF_ULONG 193 | typedef unsigned long ulong; 194 | #endif 195 | 196 | /* define [u]int8/16/32/64, uintptr */ 197 | 198 | #ifndef TYPEDEF_UINT8 199 | typedef unsigned char uint8; 200 | #endif 201 | 202 | #ifndef TYPEDEF_UINT16 203 | typedef unsigned short uint16; 204 | #endif 205 | 206 | #ifndef TYPEDEF_UINT32 207 | typedef unsigned int uint32; 208 | #endif 209 | 210 | #ifndef TYPEDEF_UINT64 211 | typedef unsigned long long uint64; 212 | #endif 213 | 214 | #ifndef TYPEDEF_UINTPTR 215 | typedef unsigned int uintptr; 216 | #endif 217 | 218 | #ifndef TYPEDEF_INT8 219 | typedef signed char int8; 220 | #endif 221 | 222 | #ifndef TYPEDEF_INT16 223 | typedef signed short int16; 224 | #endif 225 | 226 | #ifndef TYPEDEF_INT32 227 | typedef signed int int32; 228 | #endif 229 | 230 | #ifndef TYPEDEF_INT64 231 | typedef signed long long int64; 232 | #endif 233 | 234 | /* define float32/64, float_t */ 235 | 236 | #ifndef TYPEDEF_FLOAT32 237 | typedef float float32; 238 | #endif 239 | 240 | #ifndef TYPEDEF_FLOAT64 241 | typedef double float64; 242 | #endif 243 | 244 | /* 245 | * abstracted floating point type allows for compile time selection of 246 | * single or double precision arithmetic. Compiling with -DFLOAT32 247 | * selects single precision; the default is double precision. 248 | */ 249 | 250 | #ifndef TYPEDEF_FLOAT_T 251 | 252 | #if defined(FLOAT32) 253 | typedef float32 float_t; 254 | #else /* default to double precision floating point */ 255 | typedef float64 float_t; 256 | #endif 257 | 258 | #endif /* TYPEDEF_FLOAT_T */ 259 | 260 | /* define macro values */ 261 | 262 | #ifndef FALSE 263 | #define FALSE 0 264 | #endif 265 | 266 | #ifndef TRUE 267 | #define TRUE 1 /* TRUE */ 268 | #endif 269 | 270 | #ifndef NULL 271 | #define NULL 0 272 | #endif 273 | 274 | #ifndef OFF 275 | #define OFF 0 276 | #endif 277 | 278 | #ifndef ON 279 | #define ON 1 /* ON = 1 */ 280 | #endif 281 | 282 | #define AUTO (-1) /* Auto = -1 */ 283 | 284 | /* define PTRSZ, INLINE */ 285 | 286 | #ifndef PTRSZ 287 | #define PTRSZ sizeof(char*) 288 | #endif 289 | 290 | 291 | /* Detect compiler type. */ 292 | #if defined(__GNUC__) || defined(__lint) 293 | #define BWL_COMPILER_GNU 294 | #elif defined(__CC_ARM) && __CC_ARM 295 | #define BWL_COMPILER_ARMCC 296 | #else 297 | #error "Unknown compiler!" 298 | #endif 299 | 300 | 301 | #ifndef INLINE 302 | #if defined(BWL_COMPILER_MICROSOFT) 303 | #define INLINE __inline 304 | #elif defined(BWL_COMPILER_GNU) 305 | #define INLINE __inline__ 306 | #elif defined(BWL_COMPILER_ARMCC) 307 | #define INLINE __inline 308 | #else 309 | #define INLINE 310 | #endif 311 | #endif /* INLINE */ 312 | 313 | #undef TYPEDEF_BOOL 314 | #undef TYPEDEF_UCHAR 315 | #undef TYPEDEF_USHORT 316 | #undef TYPEDEF_UINT 317 | #undef TYPEDEF_ULONG 318 | #undef TYPEDEF_UINT8 319 | #undef TYPEDEF_UINT16 320 | #undef TYPEDEF_UINT32 321 | #undef TYPEDEF_UINT64 322 | #undef TYPEDEF_UINTPTR 323 | #undef TYPEDEF_INT8 324 | #undef TYPEDEF_INT16 325 | #undef TYPEDEF_INT32 326 | #undef TYPEDEF_INT64 327 | #undef TYPEDEF_FLOAT32 328 | #undef TYPEDEF_FLOAT64 329 | #undef TYPEDEF_FLOAT_T 330 | 331 | #endif /* USE_TYPEDEF_DEFAULTS */ 332 | 333 | /* Suppress unused parameter warning */ 334 | #define UNUSED_PARAMETER(x) (void)(x) 335 | 336 | /* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */ 337 | #define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) 338 | 339 | /* 340 | * Including the bcmdefs.h here, to make sure everyone including typedefs.h 341 | * gets this automatically 342 | */ 343 | #include 344 | #endif /* _TYPEDEFS_H_ */ 345 | --------------------------------------------------------------------------------