1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2001 Atsushi Onoe 8 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * Alternatively, this software may be distributed under the terms of the 23 * GNU General Public License ("GPL") version 2 as published by the Free 24 * Software Foundation. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #ifndef _SYS_NET80211_IMPL_H 39 #define _SYS_NET80211_IMPL_H 40 41 #include <sys/sysmacros.h> 42 #include <sys/list.h> 43 #include <sys/note.h> 44 #include <sys/net80211_proto.h> 45 #include <sys/net80211.h> 46 #include <sys/mac_wifi.h> 47 48 /* 49 * IEEE802.11 kernel support module 50 */ 51 52 #ifdef __cplusplus 53 extern "C" { 54 #endif 55 56 #define IEEE80211_TXPOWER_MAX 100 /* .5 dbM */ 57 #define IEEE80211_TXPOWER_MIN 0 /* kill radio */ 58 59 #define IEEE80211_DTIM_MAX 15 /* max DTIM period */ 60 #define IEEE80211_DTIM_MIN 1 /* min DTIM period */ 61 #define IEEE80211_DTIM_DEFAULT 1 /* default DTIM period */ 62 63 /* NB: min+max come from WiFi requirements */ 64 #define IEEE80211_BINTVAL_MAX 1000 /* max beacon interval (TU's) */ 65 #define IEEE80211_BINTVAL_MIN 25 /* min beacon interval (TU's) */ 66 #define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TU's) */ 67 68 #define IEEE80211_BMISS_MAX 2 /* maximum consecutive bmiss allowed */ 69 #define IEEE80211_SWBMISS_THRESHOLD 50 /* s/w bmiss threshold (TU's) */ 70 #define IEEE80211_HWBMISS_DEFAULT 7 /* h/w bmiss threshold (beacons) */ 71 72 #define IEEE80211_PS_SLEEP 0x1 /* STA is in power saving mode */ 73 #define IEEE80211_PS_MAX_QUEUE 50 /* maximum saved packets */ 74 75 #define IEEE80211_RTS_DEFAULT IEEE80211_RTS_MAX 76 #define IEEE80211_FRAG_DEFAULT IEEE80211_FRAG_MAX 77 78 /* 79 * The RSSI values of two node are taken as almost the same when 80 * the difference between these two node's RSSI values is within 81 * IEEE80211_RSSI_CMP_THRESHOLD 82 */ 83 #define IEEE80211_RSSI_CMP_THRESHOLD 5 84 85 /* 86 * Each ieee80211com instance has a single timer that fires once a 87 * second. This is used to initiate various work depending on the 88 * state of the instance: scanning (passive or active), ``transition'' 89 * (waiting for a response to a management frame when operating 90 * as a station), and node inactivity processing (when operating 91 * as an AP). For inactivity processing each node has a timeout 92 * set in it's in_inact field that is decremented on each timeout 93 * and the node is reclaimed when the counter goes to zero. We 94 * use different inactivity timeout values depending on whether 95 * the node is associated and authorized (either by 802.1x or 96 * open/shared key authentication) or associated but yet to be 97 * authorized. The latter timeout is shorter to more aggressively 98 * reclaim nodes that leave part way through the 802.1x exchange. 99 * 100 * IEEE80211_INACT_WAIT defines node table's inactivity interval in 101 * seconds. On timeout, node table's registered nt_timeout callback 102 * function is executed. Each node in the node table has a timeout 103 * set in its in_inact field with IEEE80211_INACT_<state>. In 104 * nt_timeout function, node table is iterated and each node's 105 * in_inact is decremented. So IEEE80211_INACT_<state> is defined in 106 * the form [inact_sec]/IEEE80211_INACT_WAIT. 107 * 108 */ 109 #define IEEE80211_INACT_WAIT 15 /* inactivity interval (secs) */ 110 #define IEEE80211_INACT_INIT (30/IEEE80211_INACT_WAIT) /* initial */ 111 #define IEEE80211_INACT_ASSOC (180/IEEE80211_INACT_WAIT) 112 /* associated but not authorized */ 113 #define IEEE80211_INACT_RUN (300/IEEE80211_INACT_WAIT) /* authorized */ 114 #define IEEE80211_INACT_PROBE (30/IEEE80211_INACT_WAIT) /* probe */ 115 #define IEEE80211_INACT_SCAN (300/IEEE80211_INACT_WAIT) /* scanned */ 116 117 #define IEEE80211_TRANS_WAIT 5 /* mgt frame tx timer (secs) */ 118 119 /* 120 * Useful combinations of channel characteristics. 121 */ 122 #define IEEE80211_CHAN_FHSS \ 123 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK) 124 #define IEEE80211_CHAN_A \ 125 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 126 #define IEEE80211_CHAN_B \ 127 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) 128 #define IEEE80211_CHAN_PUREG \ 129 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) 130 #define IEEE80211_CHAN_G \ 131 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 132 #define IEEE80211_CHAN_T \ 133 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) 134 #define IEEE80211_CHAN_108G \ 135 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) 136 137 #define IEEE80211_CHAN_ALL \ 138 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_GFSK | \ 139 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN) 140 #define IEEE80211_CHAN_ALLTURBO \ 141 (IEEE80211_CHAN_ALL | IEEE80211_CHAN_TURBO) 142 143 #define IEEE80211_IS_CHAN_FHSS(_c) \ 144 (((_c)->ich_flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS) 145 #define IEEE80211_IS_CHAN_A(_c) \ 146 (((_c)->ich_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) 147 #define IEEE80211_IS_CHAN_B(_c) \ 148 (((_c)->ich_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) 149 #define IEEE80211_IS_CHAN_PUREG(_c) \ 150 (((_c)->ich_flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) 151 #define IEEE80211_IS_CHAN_G(_c) \ 152 (((_c)->ich_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) 153 #define IEEE80211_IS_CHAN_ANYG(_c) \ 154 (IEEE80211_IS_CHAN_PUREG(_c) || IEEE80211_IS_CHAN_G(_c)) 155 #define IEEE80211_IS_CHAN_T(_c) \ 156 (((_c)->ich_flags & IEEE80211_CHAN_T) == IEEE80211_CHAN_T) 157 #define IEEE80211_IS_CHAN_108G(_c) \ 158 (((_c)->ich_flags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G) 159 160 #define IEEE80211_IS_CHAN_OFDM(_c) \ 161 ((_c)->ich_flags & IEEE80211_CHAN_OFDM) 162 #define IEEE80211_IS_CHAN_CCK(_c) \ 163 ((_c)->ich_flags & IEEE80211_CHAN_CCK) 164 #define IEEE80211_IS_CHAN_GFSK(_c) \ 165 ((_c)->ich_flags & IEEE80211_CHAN_GFSK) 166 #define IEEE80211_IS_CHAN_PASSIVE(_c) \ 167 ((_c)->ich_flags & IEEE80211_CHAN_PASSIVE) 168 169 /* ni_chan encoding for FH phy */ 170 #define IEEE80211_FH_CHANMOD 80 171 #define IEEE80211_FH_CHAN(set, pat) \ 172 (((set) - 1) * IEEE80211_FH_CHANMOD + (pat)) 173 #define IEEE80211_FH_CHANSET(chan) \ 174 ((chan) / IEEE80211_FH_CHANMOD + 1) 175 #define IEEE80211_FH_CHANPAT(chan) \ 176 ((chan) % IEEE80211_FH_CHANMOD) 177 178 #define IEEE80211_NODE_AUTH 0x0001 /* authorized for data */ 179 #define IEEE80211_NODE_QOS 0x0002 /* QoS enabled */ 180 #define IEEE80211_NODE_ERP 0x0004 /* ERP enabled */ 181 #define IEEE80211_NODE_PWR_MGT 0x0010 /* power save mode enabled */ 182 #define IEEE80211_NODE_AREF 0x0020 /* authentication ref held */ 183 184 #define IEEE80211_MAXRSSI 127 185 186 /* Debug Flags */ 187 #define IEEE80211_MSG_BRUSSELS 0x80000000 /* BRUSSELS */ 188 #define IEEE80211_MSG_DEBUG 0x40000000 /* IFF_DEBUG equivalent */ 189 #define IEEE80211_MSG_DUMPPKTS 0x20000000 /* IFF_LINK2 equivalant */ 190 #define IEEE80211_MSG_CRYPTO 0x10000000 /* crypto work */ 191 #define IEEE80211_MSG_INPUT 0x08000000 /* input handling */ 192 #define IEEE80211_MSG_XRATE 0x04000000 /* rate set handling */ 193 #define IEEE80211_MSG_ELEMID 0x02000000 /* element id parsing */ 194 #define IEEE80211_MSG_NODE 0x01000000 /* node handling */ 195 #define IEEE80211_MSG_ASSOC 0x00800000 /* association handling */ 196 #define IEEE80211_MSG_AUTH 0x00400000 /* authentication handling */ 197 #define IEEE80211_MSG_SCAN 0x00200000 /* scanning */ 198 #define IEEE80211_MSG_OUTPUT 0x00100000 /* output handling */ 199 #define IEEE80211_MSG_STATE 0x00080000 /* state machine */ 200 #define IEEE80211_MSG_POWER 0x00040000 /* power save handling */ 201 #define IEEE80211_MSG_DOT1X 0x00020000 /* 802.1x authenticator */ 202 #define IEEE80211_MSG_DOT1XSM 0x00010000 /* 802.1x state machine */ 203 #define IEEE80211_MSG_RADIUS 0x00008000 /* 802.1x radius client */ 204 #define IEEE80211_MSG_RADDUMP 0x00004000 /* dump 802.1x radius packets */ 205 #define IEEE80211_MSG_RADKEYS 0x00002000 /* dump 802.1x keys */ 206 #define IEEE80211_MSG_WPA 0x00001000 /* WPA/RSN protocol */ 207 #define IEEE80211_MSG_ACL 0x00000800 /* ACL handling */ 208 #define IEEE80211_MSG_WME 0x00000400 /* WME protocol */ 209 #define IEEE80211_MSG_SUPERG 0x00000200 /* Atheros SuperG protocol */ 210 #define IEEE80211_MSG_DOTH 0x00000100 /* 802.11h support */ 211 #define IEEE80211_MSG_INACT 0x00000080 /* inactivity handling */ 212 #define IEEE80211_MSG_ROAM 0x00000040 /* sta-mode roaming */ 213 #define IEEE80211_MSG_CONFIG 0x00000020 /* wificonfig/dladm */ 214 #define IEEE80211_MSG_ANY 0xffffffff /* anything */ 215 216 /* Error flags returned by ieee80211_match_bss */ 217 #define IEEE80211_BADCHAN 0x01 218 #define IEEE80211_BADOPMODE 0x02 219 #define IEEE80211_BADPRIVACY 0x04 220 #define IEEE80211_BADRATE 0x08 221 #define IEEE80211_BADESSID 0x10 222 #define IEEE80211_BADBSSID 0x20 223 #define IEEE80211_NODEFAIL 0x40 224 225 typedef struct ieee80211_impl { 226 struct ieee80211com *ic; 227 uint8_t im_chan_avail[IEEE80211_CHAN_BYTES]; 228 uint8_t im_chan_scan[IEEE80211_CHAN_BYTES]; 229 230 uint8_t im_bmiss_count; /* current beacon miss count */ 231 int32_t im_bmiss_max; /* max bmiss before scan */ 232 timeout_id_t im_swbmiss; 233 uint16_t im_swbmiss_count; /* beacons in last period */ 234 uint16_t im_swbmiss_period; /* s/w bmiss period */ 235 236 int32_t im_mgt_timer; /* mgmt timeout, secs */ 237 int32_t im_inact_timer; /* inactivity timer wait, sec */ 238 int32_t im_inact_init; /* initial setting */ 239 int32_t im_inact_assoc; /* assoc but not authorized */ 240 int32_t im_inact_run; /* authorized setting */ 241 int32_t im_inact_probe; /* inactive probe time */ 242 243 kcondvar_t im_scan_cv; /* wait scan complete */ 244 } ieee80211_impl_t; 245 246 /* 247 * Parameters supplied when adding/updating an entry in a 248 * scan cache. Pointer variables should be set to NULL 249 * if no data is available. Pointer references can be to 250 * local data; any information that is saved will be copied. 251 * All multi-byte values must be in host byte order. 252 */ 253 struct ieee80211_scanparams { 254 uint16_t capinfo; /* 802.11 capabilities */ 255 enum ieee80211_phytype phytype; 256 uint16_t fhdwell; /* FHSS dwell interval */ 257 uint8_t chan; 258 uint8_t bchan; 259 uint8_t fhindex; 260 uint8_t erp; 261 uint16_t bintval; 262 uint8_t timoff; 263 uint8_t *tim; 264 uint8_t *tstamp; 265 uint8_t *country; 266 uint8_t *ssid; 267 uint8_t *rates; 268 uint8_t *xrates; 269 uint8_t *wpa; 270 uint8_t *wme; 271 }; 272 273 #define IEEE80211_SEND_MGMT(_ic, _in, _type, _arg) \ 274 ((*(_ic)->ic_send_mgmt)((_ic), (_in), (_type), (_arg))) 275 276 /* Verify the existence and length of __elem or get out. */ 277 #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen, __func) do { \ 278 _NOTE(CONSTCOND) \ 279 if ((__elem) == NULL) { \ 280 ieee80211_err("ieee80211: no #__elem \n"); \ 281 __func; \ 282 } \ 283 if ((__elem)[1] > (__maxlen)) { \ 284 ieee80211_err("ieee80211: bad "#__elem " len %d\n", \ 285 (__elem)[1]); \ 286 __func; \ 287 } \ 288 _NOTE(CONSTCOND) \ 289 } while (0) 290 291 #define IEEE80211_VERIFY_LENGTH(_len, _minlen, _func) do { \ 292 _NOTE(CONSTCOND) \ 293 if ((_len) < (_minlen)) { \ 294 ieee80211_dbg(IEEE80211_MSG_ELEMID, \ 295 "ie of type %s too short", \ 296 ieee80211_mgt_subtype_name[subtype >> \ 297 IEEE80211_FC0_SUBTYPE_SHIFT]); \ 298 _func; \ 299 } \ 300 _NOTE(CONSTCOND) \ 301 } while (0) 302 303 #define IEEE80211_VERIFY_SSID(_in, _ssid, _func) do { \ 304 _NOTE(CONSTCOND) \ 305 ASSERT((_in) != NULL); \ 306 if ((_ssid)[1] != 0 && \ 307 ((_ssid)[1] != (_in)->in_esslen || \ 308 bcmp((_ssid) + 2, (_in)->in_essid, (_ssid)[1]) != 0)) { \ 309 _func; \ 310 } \ 311 _NOTE(CONSTCOND) \ 312 } while (0) 313 314 #define ieee80211_setbit(a, i) ((a)[(i)/NBBY] |= (1 << ((i)%NBBY))) 315 #define ieee80211_clrbit(a, i) ((a)[(i)/NBBY] &= ~(1 << ((i)%NBBY))) 316 #define ieee80211_isset(a, i) ((a)[(i)/NBBY] & (1 << ((i)%NBBY))) 317 #define ieee80211_isclr(a, i) (!((a)[(i)/NBBY] & (1 << ((i)%NBBY)))) 318 319 #define IEEE80211_N(a) (sizeof (a) / sizeof (a[0])) 320 321 #define IEEE80211_LOCK(_ic) \ 322 mutex_enter(&(_ic)->ic_genlock) 323 #define IEEE80211_UNLOCK(_ic) \ 324 mutex_exit(&(_ic)->ic_genlock) 325 #define IEEE80211_IS_LOCKED(_ic) \ 326 mutex_owned(&(_ic)->ic_genlock) 327 #define IEEE80211_LOCK_ASSERT(_ic) \ 328 ASSERT(mutex_owned(&(_ic)->ic_genlock)) 329 330 #define IEEE80211_NODE_LOCK(_nt) \ 331 mutex_enter(&(_nt)->nt_nodelock) 332 #define IEEE80211_NODE_UNLOCK(_nt) \ 333 mutex_exit(&(_nt)->nt_nodelock) 334 #define IEEE80211_NODE_IS_LOCKED(_nt) \ 335 mutex_owned(&(_nt)->nt_nodelock) 336 #define IEEE80211_NODE_LOCK_ASSERT(_nt) \ 337 ASSERT(mutex_owned(&(_nt)->nt_nodelock)) 338 #define ieee80211_node_hash(addr) \ 339 (((uint8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % IEEE80211_NODE_HASHSIZE) 340 341 #define IEEE80211_SCAN_LOCK(_nt) mutex_enter(&(_nt)->nt_scanlock) 342 #define IEEE80211_SCAN_UNLOCK(_nt) mutex_exit(&(_nt)->nt_scanlock) 343 344 #define IEEE80211_RV(v) ((v) & IEEE80211_RATE_VAL) 345 346 #define IEEE80211_SUBTYPE_NAME(subtype) \ 347 ieee80211_mgt_subtype_name[(subtype) >> IEEE80211_FC0_SUBTYPE_SHIFT] 348 349 extern const char *ieee80211_mgt_subtype_name[]; 350 extern const char *ieee80211_phymode_name[]; 351 352 void ieee80211_err(const int8_t *, ...); 353 void ieee80211_dbg(uint32_t, const int8_t *, ...); 354 int ieee80211_hdrspace(const void *); 355 356 void ieee80211_notify(ieee80211com_t *, wpa_event_type); 357 void ieee80211_mac_update(ieee80211com_t *); 358 359 uint64_t ieee80211_read_6(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t); 360 361 /* node */ 362 void ieee80211_node_attach(ieee80211com_t *); 363 void ieee80211_node_lateattach(ieee80211com_t *); 364 void ieee80211_node_detach(ieee80211com_t *); 365 void ieee80211_reset_bss(ieee80211com_t *); 366 void ieee80211_cancel_scan(ieee80211com_t *); 367 void ieee80211_add_scan(ieee80211com_t *, const struct ieee80211_scanparams *, 368 const struct ieee80211_frame *, int, int, int); 369 void ieee80211_init_neighbor(ieee80211_node_t *, const struct ieee80211_frame *, 370 const struct ieee80211_scanparams *); 371 ieee80211_node_t *ieee80211_add_neighbor(ieee80211com_t *, 372 const struct ieee80211_frame *, const struct ieee80211_scanparams *); 373 void ieee80211_create_ibss(ieee80211com_t *, struct ieee80211_channel *); 374 ieee80211_node_t *ieee80211_fakeup_adhoc_node(ieee80211_node_table_t *, 375 const uint8_t *); 376 ieee80211_node_t *ieee80211_tmp_node(ieee80211com_t *, const uint8_t *); 377 378 /* proto */ 379 void ieee80211_proto_attach(ieee80211com_t *); 380 int ieee80211_fix_rate(ieee80211_node_t *, int); 381 void ieee80211_setbasicrates(struct ieee80211_rateset *, 382 enum ieee80211_phymode); 383 void ieee80211_reset_erp(ieee80211com_t *); 384 void ieee80211_set_shortslottime(ieee80211com_t *, boolean_t); 385 386 /* input */ 387 int ieee80211_setup_rates(ieee80211_node_t *, const uint8_t *, 388 const uint8_t *, int); 389 void ieee80211_recv_mgmt(ieee80211com_t *, mblk_t *, ieee80211_node_t *, 390 int, int, uint32_t); 391 392 /* output */ 393 int ieee80211_send_probereq(ieee80211_node_t *, const uint8_t *, 394 const uint8_t *, const uint8_t *, const uint8_t *, size_t, const void *, 395 size_t); 396 int ieee80211_send_mgmt(ieee80211com_t *, ieee80211_node_t *, int, int); 397 int ieee80211_send_nulldata(ieee80211_node_t *); 398 399 /* crypto */ 400 struct ieee80211_key *ieee80211_crypto_getkey(ieee80211com_t *); 401 uint8_t ieee80211_crypto_getciphertype(ieee80211com_t *); 402 403 /* generic */ 404 mblk_t *ieee80211_getmgtframe(uint8_t **, int); 405 void ieee80211_notify_node_join(ieee80211com_t *, ieee80211_node_t *); 406 void ieee80211_notify_node_leave(ieee80211com_t *, ieee80211_node_t *); 407 408 #ifdef __cplusplus 409 } 410 #endif 411 412 #endif /* _SYS_NET80211_IMPL_H */ 413