Example #1
0
bss_t *
wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid)
{
    bss_t *bss, *nextBss;

    IEEE80211_NODE_LOCK(nt);

    bss = nt->nt_node_first;

    while (bss != NULL)
    {
        nextBss = bss->ni_list_next;

        if (A_MEMCMP(bssid, bss->ni_macaddr, 6) == 0)
        {
            wlan_node_remove_core (nt, bss);
            IEEE80211_NODE_UNLOCK(nt);
            return bss;
        }

        bss = nextBss;
    }

    IEEE80211_NODE_UNLOCK(nt);
    return NULL;
}
Example #2
0
/* Update the buffer alone, not the entire node.
 * This involves,
 * 1) Freeing the buffer alone.
 * 2) Allocating a new buffer
 * 3) Update the node timestamp with the current time.
 */
A_STATUS
wlan_node_buf_update(struct ieee80211_node_table *nt, bss_t *ni, A_UINT32 len)
{
    IEEE80211_NODE_LOCK(nt);

    /* Free the ni_buf alone.
     */
    if (ni->ni_buf != NULL) {
        A_FREE(ni->ni_buf);
        ni->ni_buf = NULL;
    }

    /* Allocate ni_buf for the new length.
     */
    if (len) {
        ni->ni_buf = A_MALLOC_NOWAIT(len);
        if (ni->ni_buf == NULL) {
            IEEE80211_NODE_UNLOCK(nt);
            return A_ERROR;
        } else {
            A_MEMZERO(ni->ni_buf, len);
        }
    }

    /* Update the Node's timestamp.
     */
    wlan_node_update_timestamp(nt, ni);

    IEEE80211_NODE_UNLOCK(nt);

    return A_OK;
}
Example #3
0
/*
 * Timeout inactive nodes.  Note that we cannot hold the node
 * lock while sending a frame as this would lead to a LOR.
 * Instead we use a generation number to mark nodes that we've
 * scanned and drop the lock and restart a scan if we have to
 * time out a node.  Since we are single-threaded by virtue of
 * controlling the inactivity timer we can be sure this will
 * process each node only once.
 */
void
ieee80211_clean_nodes(struct ieee80211com *ic)
{
	struct ieee80211_node *ni, *next_ni;
	u_int gen = ic->ic_scangen++;		/* NB: ok 'cuz single-threaded*/

	IEEE80211_NODE_LOCK(ic);
	for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);
	    ni != NULL; ni = next_ni) {
		next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
		if (ic->ic_nnodes <= ic->ic_max_nnodes)
			break;
		if (ni->ni_scangen == gen)	/* previously handled */
			continue;
		ni->ni_scangen = gen;
		if (ni->ni_refcnt > 0)
			continue;
		IEEE80211_DPRINTF(("station %s purged from LRU cache\n",
		    ether_sprintf(ni->ni_macaddr)));
		/*
		 * Send a deauthenticate frame.
		 */
		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
			IEEE80211_NODE_UNLOCK(ic);
			IEEE80211_SEND_MGMT(ic, ni,
			    IEEE80211_FC0_SUBTYPE_DEAUTH,
			    IEEE80211_REASON_AUTH_EXPIRE);
			IEEE80211_NODE_LOCK(ic);
			ieee80211_node_leave(ic, ni);
		} else
			ieee80211_free_node(ic, ni);
		ic->ic_stats.is_node_timeout++;
	}
	IEEE80211_NODE_UNLOCK(ic);
}
Example #4
0
void
wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
                   void *arg)
{
    bss_t *ni;
    A_UINT32 gen;
    A_UINT32 numNodes = 0;

    gen = ++nt->nt_scangen;

    IEEE80211_NODE_LOCK (nt);
    for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
        /*if (ni->ni_scangen != gen) { */
        {
            numNodes++;
            ni->ni_scangen = gen;
            (void) ieee80211_node_incref(ni);
            (*f)(arg, ni);
            wlan_node_dec_free(ni);
        }
    }
    IEEE80211_NODE_UNLOCK (nt);

    /*RETAILMSG (1, (L"numNodes available ==> %d\n",  numNodes)); */
}
Example #5
0
/* 
 * Drivers call this, so increase the reference count before returning
 * the node.
 */
struct ieee80211_node *
ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211_frame *wh)
{
	struct ieee80211_node *ni;
	const static u_int8_t zero[IEEE80211_ADDR_LEN];
	u_int8_t *bssid;

	if (!ieee80211_needs_rxnode(ic, wh, &bssid))
		return ieee80211_ref_node(ic->ic_bss);

	IEEE80211_NODE_LOCK(ic);
	ni = ieee80211_find_node(ic, wh->i_addr2);
	IEEE80211_NODE_UNLOCK(ic);

	if (ni != NULL)
		return ieee80211_ref_node(ni);
	if (ic->ic_opmode == IEEE80211_M_HOSTAP)
		return ieee80211_ref_node(ic->ic_bss);

	/* XXX see remarks in ieee80211_find_txnode */
	/* XXX no rate negotiation; just dup */
	if ((ni = ieee80211_dup_bss(ic, wh->i_addr2)) == NULL)
		return ieee80211_ref_node(ic->ic_bss);

	IEEE80211_ADDR_COPY(ni->ni_bssid, (bssid != NULL) ? bssid : zero);

	ni->ni_rates = ic->ic_bss->ni_rates;
	if (ic->ic_newassoc)
		(*ic->ic_newassoc)(ic, ni, 1);

	IEEE80211_DPRINTF(("%s: faked-up node %p for %s\n", __func__, ni,
	    ether_sprintf(wh->i_addr2)));

	return ieee80211_ref_node(ni);
}
Example #6
0
void
wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni)
{
    IEEE80211_NODE_LOCK (nt);
    wlan_node_dec_free (ni);
    IEEE80211_NODE_UNLOCK (nt);
}
Example #7
0
static void
wlan_node_timeout(void *arg)
{
    struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg;
    bss_t *bss, *nextBss;
    A_UINT8 myBssid[IEEE80211_ADDR_LEN];

    wmi_get_current_bssid(nt->nt_wmip, myBssid);

    IEEE80211_NODE_LOCK(nt);
    bss = nt->nt_node_first;
    while (bss != NULL) {
        nextBss = bss->ni_list_next;
        if ((A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) &&
            (bss->ni_tstamp <= A_MS_TICKGET()))
        {
            /*
             * free up all but the current bss - if set
             */
            wlan_node_reclaim(nt, bss);
        }
        bss = nextBss;
    }

    IEEE80211_NODE_UNLOCK(nt);
    A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0);
}
Example #8
0
bss_t *
wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
                    A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID)
{
    bss_t   *ni = NULL;
    A_UCHAR *pIESsid = NULL;

    IEEE80211_NODE_LOCK (nt);

    for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
        pIESsid = ni->ni_cie.ie_ssid;
        if (pIESsid[1] <= 32) {

            // Step 1 : Check SSID
            if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {

//			ni->ni_macaddr //builder: check BSSID match

                //
                // Step 2.1 : Check MatchSSID is TRUE, if so, return Matched SSID
                // Profile, otherwise check whether WPA2 or WPA
                //
                if (TRUE == bMatchSSID) {
                    ieee80211_node_incref (ni);  /* mark referenced */
                    IEEE80211_NODE_UNLOCK (nt);
                    return ni;
                }

                // Step 2 : if SSID matches, check WPA or WPA2
                if (TRUE == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
                    ieee80211_node_incref (ni);  /* mark referenced */
                    IEEE80211_NODE_UNLOCK (nt);
                    return ni;
                }
                if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
                    ieee80211_node_incref(ni);  /* mark referenced */
                    IEEE80211_NODE_UNLOCK (nt);
                    return ni;
                }
            }
        }
    }

    IEEE80211_NODE_UNLOCK (nt);

    return NULL;
}
Example #9
0
bss_t *
wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr)
{
    bss_t *ni;

    IEEE80211_NODE_LOCK(nt);
    ni = _ieee80211_find_node(nt, macaddr);
    IEEE80211_NODE_UNLOCK(nt);
    return ni;
}
Example #10
0
void
ieee80211_iterate_nodes(struct ieee80211com *ic, ieee80211_iter_func *f,
    void *arg)
{
	struct ieee80211_node *ni;

	IEEE80211_NODE_LOCK(ic);
	RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree)
		(*f)(arg, ni);
	IEEE80211_NODE_UNLOCK(ic);
}
Example #11
0
void
wlan_free_allnodes(struct ieee80211_node_table *nt)
{
    bss_t *ni;

    IEEE80211_NODE_LOCK(nt);
    while ((ni = nt->nt_node_first) != NULL) {
        wlan_node_reclaim(nt, ni);
    }
    IEEE80211_NODE_UNLOCK(nt);
}
Example #12
0
void
wlan_node_ret_n_remove(struct ieee80211_node_table *nt, bss_t *ni)
{
    IEEE80211_NODE_LOCK(nt);

    ieee80211_node_decref(ni);
    if (ieee80211_node_refcnt(ni) == 0) {
        wlan_node_free(ni);
    } else {
        wlan_node_reclaim(nt, ni);
    }

    IEEE80211_NODE_UNLOCK(nt);
}
Example #13
0
bss_t *
wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr)
{
    bss_t *ni = NULL;

    if (NULL == nt || NULL == macaddr)
    {
        return ni; // NULL
    }

    IEEE80211_NODE_LOCK(nt);
    ni = _ieee80211_find_node(nt, macaddr);
    IEEE80211_NODE_UNLOCK(nt);
    return ni;
}
Example #14
0
/*
 * Reclaim a node.  If this is the last reference count then
 * do the normal free work.  Otherwise remove it from the node
 * table and mark it gone by clearing the back-reference.
 */
void
wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni)
{
    IEEE80211_NODE_LOCK(nt);

    if (ieee80211_node_dectestref(ni))
    {
        if(ni->ni_list_prev == NULL)
        {
            /* First in list so fix the list head */
            nt->nt_node_first = ni->ni_list_next;
        }
        else
        {
            ni->ni_list_prev->ni_list_next = ni->ni_list_next;
        }

        if(ni->ni_list_next == NULL)
        {
            /* Last in list so fix list tail */
            nt->nt_node_last = ni->ni_list_prev;
        }
        else
        {
            ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
        }

        if(ni->ni_hash_prev == NULL)
        {
            /* First in list so fix the list head */
            int hash;
            hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
            nt->nt_hash[hash] = ni->ni_hash_next;
        }
        else
        {
            ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
        }

        if(ni->ni_hash_next != NULL)
        {
            ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
        }
        wlan_node_free(ni);
    }
    IEEE80211_NODE_UNLOCK(nt);
}
Example #15
0
void
wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
                   void *arg)
{
    bss_t *ni;
    A_UINT32 gen;

    gen = nt->nt_scangen++;

    IEEE80211_NODE_LOCK(nt);

    for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
        if (ni->ni_scangen != gen) {
            ni->ni_scangen = gen;
            (*f)(arg, ni);
        }
    }
    IEEE80211_NODE_UNLOCK(nt);
}
Example #16
0
/*
 * Return a reference to the appropriate node for sending
 * a data frame.  This handles node discovery in adhoc networks.
 *
 * Drivers will call this, so increase the reference count before
 * returning the node.
 */
struct ieee80211_node *
ieee80211_find_txnode(struct ieee80211com *ic, u_int8_t *macaddr)
{
	struct ieee80211_node *ni;

	/*
	 * The destination address should be in the node table
	 * unless we are operating in station mode or this is a
	 * multicast/broadcast frame.
	 */
	if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))
		return ieee80211_ref_node(ic->ic_bss);

	/* XXX can't hold lock across dup_bss 'cuz of recursive locking */
	IEEE80211_NODE_LOCK(ic);
	ni = ieee80211_find_node(ic, macaddr);
	IEEE80211_NODE_UNLOCK(ic);
	if (ni == NULL) {
		if (ic->ic_opmode != IEEE80211_M_IBSS &&
		    ic->ic_opmode != IEEE80211_M_AHDEMO)
			return NULL;

		/*
		 * Fake up a node; this handles node discovery in
		 * adhoc mode.  Note that for the driver's benefit
		 * we we treat this like an association so the driver
		 * has an opportunity to setup its private state.
		 *
		 * XXX need better way to handle this; issue probe
		 *     request so we can deduce rate set, etc.
		 */
		if ((ni = ieee80211_dup_bss(ic, macaddr)) == NULL)
			return NULL;
		/* XXX no rate negotiation; just dup */
		ni->ni_rates = ic->ic_bss->ni_rates;
		if (ic->ic_newassoc)
			(*ic->ic_newassoc)(ic, ni, 1);
	}
	return ieee80211_ref_node(ni);
}
Example #17
0
struct ieee80211_node *
ieee80211_find_node_for_beacon(struct ieee80211com *ic, u_int8_t *macaddr,
    struct ieee80211_channel *chan, char *ssid, u_int8_t rssi)
{
	struct ieee80211_node *ni, *keep = NULL;
	int score = 0;

	if ((ni = ieee80211_find_node(ic, macaddr)) != NULL) {
		IEEE80211_NODE_LOCK(ic);

		if (ni->ni_chan != chan && ni->ni_rssi >= rssi)
			score++;
		if (ssid[1] == 0 && ni->ni_esslen != 0)
			score++;
		if (score > 0)
			keep = ni;

		IEEE80211_NODE_UNLOCK(ic);
	}

	return (keep);
}
Example #18
0
void
wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
                const A_UINT8 *macaddr)
{
    A_INT32 hash;

    A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
    hash = IEEE80211_NODE_HASH(macaddr);
    ieee80211_node_initref(ni);     /* mark referenced */

    ni->ni_tstamp = A_MS_TICKGET() + WLAN_NODE_INACT_TIMEOUT_MSEC;
    IEEE80211_NODE_LOCK(nt);

    /* Insert at the end of the node list */
    ni->ni_list_next = NULL;
    ni->ni_list_prev = nt->nt_node_last;
    if(nt->nt_node_last != NULL)
    {
        nt->nt_node_last->ni_list_next = ni;
    }
    nt->nt_node_last = ni;
    if(nt->nt_node_first == NULL)
    {
        nt->nt_node_first = ni;
    }
 
    /* Insert into the hash list i.e. the bucket */
    if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL)
    {
        nt->nt_hash[hash]->ni_hash_prev = ni;
    }
    ni->ni_hash_prev = NULL;
    nt->nt_hash[hash] = ni;

    IEEE80211_NODE_UNLOCK(nt);
}
Example #19
0
bss_t *
wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
                    A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode,
                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp)
{
    bss_t   *ni = NULL;
    bss_t   *best_ni = NULL;
    A_UCHAR *pIESsid = NULL;

    IEEE80211_NODE_LOCK (nt);

    for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
        pIESsid = ni->ni_cie.ie_ssid;
        if (pIESsid[1] <= 32) {

            // Step 1 : Check SSID
            if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {

                if (ni->ni_cie.ie_capInfo & 0x10)
                {

                    if ((NULL != ni->ni_cie.ie_rsn) && (WPA2_PSK_AUTH == authMode))
                    {
                        /* WPA2 */
                        if (NULL == best_ni)
                        {
                            best_ni = ni;
                        }
                        else if (ni->ni_rssi > best_ni->ni_rssi)
                        {
                            best_ni = ni;
                        }
                    }
                    else if ((NULL != ni->ni_cie.ie_wpa) && (WPA_PSK_AUTH == authMode))
                    {
                        /* WPA */
                        if (NULL == best_ni)
                        {
                            best_ni = ni;
                        }
                        else if (ni->ni_rssi > best_ni->ni_rssi)
                        {
                            best_ni = ni;
                        }
                    }
                    else if (WEP_CRYPT == pairwiseCryptoType)
                    {
                        /* WEP */
                        if (NULL == best_ni)
                        {
                            best_ni = ni;
                        }
                        else if (ni->ni_rssi > best_ni->ni_rssi)
                        {
                            best_ni = ni;
                        }
                    }
                }
                else
                {
                    /* open AP */
                    if ((OPEN_AUTH == authMode) && (NONE_CRYPT == pairwiseCryptoType))
                    {
                        if (NULL == best_ni)
                        {
                            best_ni = ni;
                        }
                        else if (ni->ni_rssi > best_ni->ni_rssi)
                        {
                            best_ni = ni;
                        }
                    }
                }
            }
        }
    }

    IEEE80211_NODE_UNLOCK (nt);

    return best_ni;
}