/* * Create a HOSTAP node on current channel based on ssid. */ int ieee80211_create_infra_bss(struct ieee80211vap *vap, const u_int8_t *essid, const u_int16_t esslen) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr); if (ni == NULL) return -ENOMEM; IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr); ni->ni_esslen = esslen; OS_MEMCPY(ni->ni_essid, essid, ni->ni_esslen); ni->ni_intval = ic->ic_intval; if (IEEE80211_VAP_IS_PRIVACY_ENABLED(vap)) { ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; ni->ni_rsn = vap->iv_rsn; /* use local RSN settings as the BSS setting */ } /* Set the node htcap to be same as ic htcap */ ni->ni_htcap = ic->ic_htcap; IEEE80211_ADD_NODE_TARGET(ni, ni->ni_vap, 1); /* copy the original bssinfo into the new ni BugID: Ev# 73905 */ ieee80211_copy_bss(ni, vap->iv_bss); return ieee80211_sta_join_bss(ni); }
/* * function to handle station joining infrastructure network. * used for AP mode vap only. */ int ieee80211_node_join(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; IEEE80211_NODE_STATE_LOCK(ni); if (ni->ni_associd == 0) { u_int16_t aid; if (vap->iv_aid_bitmap == NULL || IEEE80211_IS_TDLS_NODE(ni)) { IEEE80211_NODE_STATE_UNLOCK(ni); return -1; /* vap is being deleted */ } /* * It would be good to search the bitmap * more efficiently, but this will do for now. */ if (!IEEE80211_IS_TDLS_NODE(ni)) { for (aid = 1; aid < vap->iv_max_aid; aid++) { if (!IEEE80211_AID_ISSET(vap, aid)) break; } if (aid >= vap->iv_max_aid) { /* * Keep stats on this situation. */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "aid (%d)" " greater than max aid (%d)\n", aid, vap->iv_max_aid); IEEE80211_NODE_STATE_UNLOCK(ni); IEEE80211_NODE_LEAVE(ni); return -1; } ni->ni_associd = aid | 0xc000; IEEE80211_AID_SET(vap, ni->ni_associd); } else { /* To keep the other parts of code happy. Otherwise the code assumes * node disconnected and tries to delete it.There are no associd for * TDLS nodes. */ ni->ni_associd = vap->iv_bss->ni_associd; } vap->iv_sta_assoc++; ic->ic_sta_assoc++; /* Update bss load element in beacon */ ieee80211_vap_bssload_update_set(vap); if ((ni->ni_flags & IEEE80211_NODE_HT) && (ni->ni_flags & IEEE80211_NODE_40_INTOLERANT)) { ieee80211_change_cw(ic); } if (IEEE80211_IS_AMPDU_ENABLED(ic)) { ieee80211node_clear_flag(ni, IEEE80211_NODE_NOAMPDU); } else { ieee80211node_set_flag(ni, IEEE80211_NODE_NOAMPDU); } if (IEEE80211_NODE_USEAMPDU(ni)) { ic->ic_ht_sta_assoc++; if (ni->ni_htcap & IEEE80211_HTCAP_C_GREENFIELD) ic->ic_ht_gf_sta_assoc++; } if (ni->ni_chwidth == IEEE80211_CWM_WIDTH40) ic->ic_ht40_sta_assoc++; if ((IEEE80211_IS_CHAN_ANYG(vap->iv_bsschan) || IEEE80211_IS_CHAN_11NG(vap->iv_bsschan)) && !IEEE80211_IS_TDLS_NODE(ni)) ieee80211_node_join_11g(ni); } #if ATH_SUPPORT_WIFIPOS // Time stamp to send in status response ni->last_rx_desc_tsf = ic->ic_get_TSF32(ic); #endif ni->ni_inact_reload = ni->ni_vap->iv_inact_auth; ni->ni_inact = ni->ni_inact_reload; /* Multicast enhancement: If the entry with the node's address exists in * the snoop table, it should be removed. */ if (vap->iv_ique_ops.me_clean) { vap->iv_ique_ops.me_clean(ni); } /* * HBR / headline block removal: add the node entity to the table * for HBR purpose */ if (vap->iv_ique_ops.hbr_nodejoin) { vap->iv_ique_ops.hbr_nodejoin(vap, ni); } IEEE80211_NODE_STATE_UNLOCK(ni); IEEE80211_ADD_NODE_TARGET(ni, ni->ni_vap, 0); return 0; }
/* * Join an infrastructure network */ int ieee80211_sta_join(struct ieee80211vap *vap, ieee80211_scan_entry_t scan_entry) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node_table *nt = &ic->ic_sta; struct ieee80211_node *ni = NULL; const u_int8_t *macaddr = ieee80211_scan_entry_macaddr(scan_entry); int error = 0; ASSERT(vap->iv_opmode == IEEE80211_M_STA); ni = ieee80211_find_node(nt, macaddr); if (ni) { /* * reusing old node has a potential for several bugs . The old node may have some state info from previous association. * get rid of the old bss node and create a new bss node. */ ieee80211_sta_leave(ni); ieee80211_free_node(ni); } /* * Create a BSS node. */ ni = ieee80211_alloc_node(nt, vap, macaddr); if (ni == NULL) return -ENOMEM; /* set the maximum number frmaes to be queued when the vap is in fake sleep */ ieee80211_node_saveq_set_param(ni,IEEE80211_NODE_SAVEQ_DATA_Q_LEN,IEE80211_STA_MAX_NODE_SAVEQ_LEN); /* To become a bss node, a node need an extra reference count, which alloc node already gives */ #ifdef IEEE80211_DEBUG_REFCNT ieee80211_note(ni->ni_vap,"%s ,line %u: increase node %p <%s> refcnt to %d\n", __func__, __LINE__, ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)); #endif /* setup the bss node for association */ error = ieee80211_setup_node(ni, scan_entry); if (error != 0) { ieee80211_free_node(ni); return error; } /* copy the beacon timestamp */ OS_MEMCPY(ni->ni_tstamp.data, ieee80211_scan_entry_tsf(scan_entry), sizeof(ni->ni_tstamp)); /* * Join the BSS represented by this new node. * This function will free up the old BSS node * and use this one as the new BSS node. */ ieee80211_sta_join_bss(ni); IEEE80211_ADD_NODE_TARGET(ni, ni->ni_vap, 0); /* Save our home channel */ vap->iv_bsschan = ni->ni_chan; vap->iv_cur_mode = ieee80211_chan2mode(ni->ni_chan); /* Update the DotH falg */ ieee80211_update_spectrumrequirement(vap); /* * The OS will control our security keys. * If clear, keys will be cleared. * If static WEP, keys will be plumbed before JoinInfra. * If WPA/WPA2, ciphers will be setup, but no keys will be plumbed until * after they are negotiated. * XXX We should ASSERT that all of the foregoing is true. */ return 0; }