📄 ieee80211_proto.c
字号:
switch (nstate) { case IEEE80211_S_INIT: switch (ostate) { case IEEE80211_S_INIT: break; case IEEE80211_S_RUN: switch (vap->iv_opmode) { case IEEE80211_M_STA: IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC, IEEE80211_REASON_ASSOC_LEAVE); ieee80211_sta_leave(ni); break; case IEEE80211_M_HOSTAP: ieee80211_iterate_nodes(&ic->ic_sta, sta_disassoc, vap); break; default: break; } goto reset; case IEEE80211_S_ASSOC: switch (vap->iv_opmode) { case IEEE80211_M_STA: IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_LEAVE); break; case IEEE80211_M_HOSTAP: ieee80211_iterate_nodes(&ic->ic_sta, sta_deauth, vap); break; default: break; } goto reset; case IEEE80211_S_SCAN: ieee80211_cancel_scan(vap); goto reset; case IEEE80211_S_AUTH: reset: ieee80211_reset_bss(vap); break; } if (vap->iv_auth->ia_detach != NULL) vap->iv_auth->ia_detach(vap); break; case IEEE80211_S_SCAN: switch (ostate) { case IEEE80211_S_INIT: createibss: if ((vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_AHDEMO) && vap->iv_des_chan != IEEE80211_CHAN_ANYC) { /* * AP operation and we already have a channel; * bypass the scan and startup immediately. */ ieee80211_create_ibss(vap, vap->iv_des_chan); } else { ieee80211_check_scan(vap, IEEE80211_SCAN_ACTIVE | IEEE80211_SCAN_FLUSH, IEEE80211_SCAN_FOREVER, vap->iv_des_nssid, vap->iv_des_ssid, NULL); } break; case IEEE80211_S_SCAN: case IEEE80211_S_AUTH: case IEEE80211_S_ASSOC: /* * These can happen either because of a timeout * on an assoc/auth response or because of a * change in state that requires a reset. For * the former we're called with a non-zero arg * that is the cause for the failure; pass this * to the scan code so it can update state. * Otherwise trigger a new scan unless we're in * manual roaming mode in which case an application * must issue an explicit scan request. */ if (arg != 0) ieee80211_scan_assoc_fail(ic, vap->iv_bss->ni_macaddr, arg); if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) ieee80211_check_scan(vap, IEEE80211_SCAN_ACTIVE, IEEE80211_SCAN_FOREVER, vap->iv_des_nssid, vap->iv_des_ssid, NULL); break; case IEEE80211_S_RUN: /* beacon miss */ if (vap->iv_opmode == IEEE80211_M_STA) { ieee80211_sta_leave(ni); vap->iv_flags &= ~IEEE80211_F_SIBSS; /* XXX */ if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) ieee80211_check_scan(vap, IEEE80211_SCAN_ACTIVE, IEEE80211_SCAN_FOREVER, vap->iv_des_nssid, vap->iv_des_ssid, NULL); } else { ieee80211_iterate_nodes(&ic->ic_sta, sta_disassoc, vap); goto createibss; } break; } break; case IEEE80211_S_AUTH: KASSERT(vap->iv_opmode == IEEE80211_M_STA, ("switch to %s state when operating in mode %u", ieee80211_state_name[nstate], vap->iv_opmode)); switch (ostate) { case IEEE80211_S_INIT: case IEEE80211_S_SCAN: IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, 1); break; case IEEE80211_S_AUTH: case IEEE80211_S_ASSOC: switch (arg) { case IEEE80211_FC0_SUBTYPE_AUTH: /* ??? */ IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, 2); break; case IEEE80211_FC0_SUBTYPE_DEAUTH: IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, 1); break; } break; case IEEE80211_S_RUN: switch (arg) { case IEEE80211_FC0_SUBTYPE_AUTH: IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, 2); vap->iv_state = ostate; /* stay RUN */ break; case IEEE80211_FC0_SUBTYPE_DEAUTH: ieee80211_sta_leave(ni); if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { /* try to reauth */ IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, 1); } break; } break; } break; case IEEE80211_S_ASSOC: KASSERT(vap->iv_opmode == IEEE80211_M_STA, ("switch to %s state when operating in mode %u", ieee80211_state_name[nstate], vap->iv_opmode)); switch (ostate) { case IEEE80211_S_INIT: case IEEE80211_S_SCAN: IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: invalid transition\n", __func__); break; case IEEE80211_S_AUTH: case IEEE80211_S_ASSOC: IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); break; case IEEE80211_S_RUN: ieee80211_sta_leave(ni); if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { /* NB: caller specifies ASSOC/REASSOC by arg */ IEEE80211_SEND_MGMT(ni, arg ? IEEE80211_FC0_SUBTYPE_REASSOC_REQ : IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); } break; } break; case IEEE80211_S_RUN: if (vap->iv_flags & IEEE80211_F_WPA) { /* XXX validate prerequisites */ } switch (ostate) { case IEEE80211_S_INIT: if (vap->iv_opmode == IEEE80211_M_MONITOR || vap->iv_opmode == IEEE80211_M_WDS || vap->iv_opmode == IEEE80211_M_HOSTAP) { /* * Already have a channel; bypass the * scan and startup immediately. */ ieee80211_create_ibss(vap, ic->ic_curchan); /* * In wds mode allocate and initialize peer node */ if (vap->iv_opmode == IEEE80211_M_WDS) { struct ieee80211_node *wds_ni; wds_ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->wds_mac); if (wds_ni != NULL) { if (ieee80211_add_wds_addr(&ic->ic_sta, wds_ni, vap->wds_mac, 1) == 0) { ieee80211_node_authorize(wds_ni); wds_ni->ni_chan = vap->iv_bss->ni_chan; wds_ni->ni_capinfo = ni->ni_capinfo; wds_ni->ni_associd = 1; wds_ni->ni_ath_flags = vap->iv_ath_cap; } } } break; } /* fall thru... */ case IEEE80211_S_AUTH: IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: invalid transition\n", __func__); break; case IEEE80211_S_RUN: break; case IEEE80211_S_SCAN: /* adhoc/hostap mode */ case IEEE80211_S_ASSOC: /* infra mode */ KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates, ("%s: bogus xmit rate %u setup\n", __func__, ni->ni_txrate));#ifdef IEEE80211_DEBUG if (ieee80211_msg_debug(vap)) { ieee80211_note(vap, "%s with %s ssid ", (vap->iv_opmode == IEEE80211_M_STA ? "associated" : "synchronized "), ether_sprintf(ni->ni_bssid)); ieee80211_print_essid(vap->iv_bss->ni_essid, ni->ni_esslen); printf(" channel %d start %uMb\n", ieee80211_chan2ieee(ic, ic->ic_curchan), IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate])); }#endif if (vap->iv_opmode == IEEE80211_M_STA) { ieee80211_scan_assoc_success(ic, ni->ni_macaddr); ieee80211_notify_node_join(ni, (arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP) | \ (arg == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)); } break; } /* WDS/Repeater: Start software beacon timer for STA */ if (ostate != IEEE80211_S_RUN && (vap->iv_opmode == IEEE80211_M_STA && vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) { vap->iv_swbmiss.function = ieee80211_sta_swbmiss; vap->iv_swbmiss.data = (unsigned long) vap; vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES( IEEE80211_SWBMISS_THRESHOLD * ni->ni_intval); mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period); } /* * Start/stop the authenticator when operating as an * AP. We delay until here to allow configuration to * happen out of order. */ /* XXX WDS? */ if (vap->iv_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */ vap->iv_auth->ia_attach != NULL) { /* XXX check failure */ vap->iv_auth->ia_attach(vap); } else if (vap->iv_auth->ia_detach != NULL) vap->iv_auth->ia_detach(vap); /* * When 802.1x is not in use mark the port authorized * at this point so traffic can flow. */ if (ni->ni_authmode != IEEE80211_AUTH_8021X) ieee80211_node_authorize(ni);#ifdef ATH_SUPERG_XR /* * fire a timer to bring up XR vap if configured. */ if (ostate != IEEE80211_S_RUN && vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR)) { vap->iv_xrvapstart.function = ieee80211_start_xrvap; vap->iv_xrvapstart.data = (unsigned long) vap->iv_xrvap; mod_timer(&vap->iv_xrvapstart,jiffies+HZ); /* start xr vap on next second */ /* * do not let the normal vap automatically bring up XR vap. * let the timer handler start the XR vap. if you let the * normal vap automatically start the XR vap normal vap will not * have the bssid initialized and the XR vap will use the * invalid bssid in XRIE of its beacon. */ if (vap->iv_xrvap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING) vap->iv_xrvap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_PENDING; } /* * when an XR vap transitions to RUN state, * normal vap needs to update the XR IE * with the xr vaps MAC address. */ if (vap->iv_flags & IEEE80211_F_XR) vap->iv_xrvap->iv_flags |= IEEE80211_F_XRUPDATE; #endif break; } return 0;}static intieee80211_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg){ struct ieee80211com *ic = vap->iv_ic; enum ieee80211_state ostate; struct ieee80211vap *tmpvap; ostate = vap->iv_state; switch (nstate) { case IEEE80211_S_SCAN: if (ostate == IEEE80211_S_INIT) { int nrunning, nscanning; nrunning = nscanning = 0; TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { if (vap != tmpvap) { if (tmpvap->iv_state == IEEE80211_S_RUN) nrunning++; else if (tmpvap->iv_state == IEEE80211_S_SCAN || tmpvap->iv_state == IEEE80211_S_AUTH || /* STA in WDS/Repeater */ tmpvap->iv_state == IEEE80211_S_ASSOC) nscanning++; } } KASSERT(!(nscanning && nrunning), ("SCAN and RUN can't happen at the same time\n")); if (!nscanning && !nrunning) { /* when no one is running or scanning, start a new scan */ __ieee80211_newstate(vap, nstate, arg); } else if (!nscanning && nrunning) { /* when no one is scanning but someone is running, bypass * scan and go to run state immediately */ __ieee80211_newstate(vap, IEEE80211_S_RUN, arg); } else if (nscanning && !nrunning) { /* when someone is scanning and no one is running, set * the scan pending flag. Don't go through state machine */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s with SCAN_PENDING\n", __func__, ieee80211_state_name[ostate], ieee80211_state_name[nstate]); vap->iv_flags_ext |= IEEE80211_FEXT_SCAN_PENDING; } } else { /* the VAP is forced to scan, we need to change all other vap's state * to INIT and pend for the scan completion */ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { if (vap != tmpvap && tmpvap->iv_state != IEEE80211_S_INIT) { tmpvap->iv_newstate(tmpvap, IEEE80211_S_INIT, 0); tmpvap->iv_flags_ext |= IEEE80211_FEXT_SCAN_PENDING; } } /* start the new scan */ __ieee80211_newstate(vap, nstate, arg); } break; case IEEE80211_S_RUN: if (ostate == IEEE80211_S_SCAN || /* AP coming out of scan */ vap->iv_opmode == IEEE80211_M_STA) { /* STA in WDS/Repeater needs to bring up other VAPs */ __ieee80211_newstate(vap, nstate, arg); /* bring up all other vaps pending on the scan*/ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { if (vap != tmpvap) { if (tmpvap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING) { tmpvap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_PENDING; tmpvap->iv_newstate(tmpvap, IEEE80211_S_RUN, 0); } } } } else __ieee80211_newstate(vap, nstate, arg); break; case IEEE80211_S_INIT: if (ostate == IEEE80211_S_INIT && vap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING) vap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_PENDING; /* fall through */ default: __ieee80211_newstate(vap, nstate, arg); } return 0;}#ifdef ATH_SUPERG_XR/* * start the XR vap . * called from a timer when normal vap enters RUN state . */static voidieee80211_start_xrvap(unsigned long data){ struct ieee80211vap *vap = (struct ieee80211vap *)data; /* make sure that the normal vap is still in RUN state */ if (vap->iv_xrvap->iv_state == IEEE80211_S_RUN) ieee80211_init(vap->iv_dev, 0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -