cregit-Linux how code gets into the kernel

Release 4.8 net/wireless/scan.c

Directory: net/wireless
/*
 * cfg80211 scan result handling
 *
 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 * Copyright 2016       Intel Deutschland GmbH
 */
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/nl80211.h>
#include <linux/etherdevice.h>
#include <net/arp.h>
#include <net/cfg80211.h>
#include <net/cfg80211-wext.h>
#include <net/iw_handler.h>
#include "core.h"
#include "nl80211.h"
#include "wext-compat.h"
#include "rdev-ops.h"

/**
 * DOC: BSS tree/list structure
 *
 * At the top level, the BSS list is kept in both a list in each
 * registered device (@bss_list) as well as an RB-tree for faster
 * lookup. In the RB-tree, entries can be looked up using their
 * channel, MESHID, MESHCONF (for MBSSes) or channel, BSSID, SSID
 * for other BSSes.
 *
 * Due to the possibility of hidden SSIDs, there's a second level
 * structure, the "hidden_list" and "hidden_beacon_bss" pointer.
 * The hidden_list connects all BSSes belonging to a single AP
 * that has a hidden SSID, and connects beacon and probe response
 * entries. For a probe response entry for a hidden SSID, the
 * hidden_beacon_bss pointer points to the BSS struct holding the
 * beacon's information.
 *
 * Reference counting is done for all these references except for
 * the hidden_list, so that a beacon BSS struct that is otherwise
 * not referenced has one reference for being on the bss_list and
 * one for each probe response entry that points to it using the
 * hidden_beacon_bss pointer. When a BSS struct that has such a
 * pointer is get/put, the refcount update is also propagated to
 * the referenced struct, this ensure that it cannot get removed
 * while somebody is using the probe response version.
 *
 * Note that the hidden_beacon_bss pointer never changes, due to
 * the reference counting. Therefore, no locking is needed for
 * it.
 *
 * Also note that the hidden_beacon_bss pointer is only relevant
 * if the driver uses something other than the IEs, e.g. private
 * data stored stored in the BSS struct, since the beacon IEs are
 * also linked into the probe response struct.
 */


#define IEEE80211_SCAN_RESULT_EXPIRE	(30 * HZ)


static void bss_free(struct cfg80211_internal_bss *bss) { struct cfg80211_bss_ies *ies; if (WARN_ON(atomic_read(&bss->hold))) return; ies = (void *)rcu_access_pointer(bss->pub.beacon_ies); if (ies && !bss->pub.hidden_beacon_bss) kfree_rcu(ies, rcu_head); ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies); if (ies) kfree_rcu(ies, rcu_head); /* * This happens when the module is removed, it doesn't * really matter any more save for completeness */ if (!list_empty(&bss->hidden_list)) list_del(&bss->hidden_list); kfree(bss); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg7969.30%375.00%
amitkumar karwaramitkumar karwar3530.70%125.00%
Total114100.00%4100.00%


static inline void bss_ref_get(struct cfg80211_registered_device *rdev, struct cfg80211_internal_bss *bss) { lockdep_assert_held(&rdev->bss_lock); bss->refcount++; if (bss->pub.hidden_beacon_bss) { bss = container_of(bss->pub.hidden_beacon_bss, struct cfg80211_internal_bss, pub); bss->refcount++; } }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg5996.72%266.67%
zhao gangzhao gang23.28%133.33%
Total61100.00%3100.00%


static inline void bss_ref_put(struct cfg80211_registered_device *rdev, struct cfg80211_internal_bss *bss) { lockdep_assert_held(&rdev->bss_lock); if (bss->pub.hidden_beacon_bss) { struct cfg80211_internal_bss *hbss; hbss = container_of(bss->pub.hidden_beacon_bss, struct cfg80211_internal_bss, pub); hbss->refcount--; if (hbss->refcount == 0) bss_free(hbss); } bss->refcount--; if (bss->refcount == 0) bss_free(bss); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg9097.83%266.67%
zhao gangzhao gang22.17%133.33%
Total92100.00%3100.00%


static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev, struct cfg80211_internal_bss *bss) { lockdep_assert_held(&rdev->bss_lock); if (!list_empty(&bss->hidden_list)) { /* * don't remove the beacon entry if it has * probe responses associated with it */ if (!bss->pub.hidden_beacon_bss) return false; /* * if it's a probe response entry break its * link to the other entries in the group */ list_del_init(&bss->hidden_list); } list_del_init(&bss->list); rb_erase(&bss->rbn, &rdev->bss_tree); bss_ref_put(rdev, bss); return true; }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg4853.33%360.00%
amitkumar karwaramitkumar karwar3842.22%120.00%
zhao gangzhao gang44.44%120.00%
Total90100.00%5100.00%


static void __cfg80211_bss_expire(struct cfg80211_registered_device *rdev, unsigned long expire_time) { struct cfg80211_internal_bss *bss, *tmp; bool expired = false; lockdep_assert_held(&rdev->bss_lock); list_for_each_entry_safe(bss, tmp, &rdev->bss_list, list) { if (atomic_read(&bss->hold)) continue; if (!time_after(expire_time, bss->ts)) continue; if (__cfg80211_unlink_bss(rdev, bss)) expired = true; } if (expired) rdev->bss_generation++; }

Contributors

PersonTokensPropCommitsCommitProp
sam lefflersam leffler7984.04%125.00%
johannes bergjohannes berg1010.64%250.00%
zhao gangzhao gang55.32%125.00%
Total94100.00%4100.00%


void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool send_message) { struct cfg80211_scan_request *request; struct wireless_dev *wdev; struct sk_buff *msg; #ifdef CONFIG_CFG80211_WEXT union iwreq_data wrqu; #endif ASSERT_RTNL(); if (rdev->scan_msg) { nl80211_send_scan_result(rdev, rdev->scan_msg); rdev->scan_msg = NULL; return; } request = rdev->scan_req; if (!request) return; wdev = request->wdev; /* * This must be before sending the other events! * Otherwise, wpa_supplicant gets completely confused with * wext events. */ if (wdev->netdev) cfg80211_sme_scan_done(wdev->netdev); if (!request->info.aborted && request->flags & NL80211_SCAN_FLAG_FLUSH) { /* flush entries from previous scans */ spin_lock_bh(&rdev->bss_lock); __cfg80211_bss_expire(rdev, request->scan_start); spin_unlock_bh(&rdev->bss_lock); } msg = nl80211_build_scan_msg(rdev, wdev, request->info.aborted); #ifdef CONFIG_CFG80211_WEXT if (wdev->netdev && !request->info.aborted) { memset(&wrqu, 0, sizeof(wrqu)); wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL); } #endif if (wdev->netdev) dev_put(wdev->netdev); rdev->scan_req = NULL; kfree(request); if (!send_message) rdev->scan_msg = msg; else nl80211_send_scan_result(rdev, msg); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg19981.56%1076.92%
sam lefflersam leffler3413.93%17.69%
avraham sternavraham stern62.46%17.69%
christian lamparterchristian lamparter52.05%17.69%
Total244100.00%13100.00%


void __cfg80211_scan_done(struct work_struct *wk) { struct cfg80211_registered_device *rdev; rdev = container_of(wk, struct cfg80211_registered_device, scan_done_wk); rtnl_lock(); ___cfg80211_scan_done(rdev, true); rtnl_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg40100.00%3100.00%
Total40100.00%3100.00%


void cfg80211_scan_done(struct cfg80211_scan_request *request, struct cfg80211_scan_info *info) { trace_cfg80211_scan_done(request, info); WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req); request->info = *info; request->notified = true; queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg4570.31%342.86%
avraham sternavraham stern812.50%114.29%
beni levbeni lev69.38%114.29%
alban browaeysalban browaeys34.69%114.29%
zhao gangzhao gang23.12%114.29%
Total64100.00%7100.00%

EXPORT_SYMBOL(cfg80211_scan_done);
void __cfg80211_sched_scan_results(struct work_struct *wk) { struct cfg80211_registered_device *rdev; struct cfg80211_sched_scan_request *request; rdev = container_of(wk, struct cfg80211_registered_device, sched_scan_results_wk); rtnl_lock(); request = rtnl_dereference(rdev->sched_scan_req); /* we don't have sched_scan_req anymore if the scan is stopping */ if (request) { if (request->flags & NL80211_SCAN_FLAG_FLUSH) { /* flush entries from previous scans */ spin_lock_bh(&rdev->bss_lock); __cfg80211_bss_expire(rdev, request->scan_start); spin_unlock_bh(&rdev->bss_lock); request->scan_start = jiffies; } nl80211_send_sched_scan_results(rdev, request->dev); } rtnl_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
sam lefflersam leffler5552.38%120.00%
luciano coelholuciano coelho4240.00%120.00%
johannes bergjohannes berg54.76%240.00%
jukka rissanenjukka rissanen32.86%120.00%
Total105100.00%5100.00%


void cfg80211_sched_scan_results(struct wiphy *wiphy) { trace_cfg80211_sched_scan_results(wiphy); /* ignore if we're not scanning */ if (rcu_access_pointer(wiphy_to_rdev(wiphy)->sched_scan_req)) queue_work(cfg80211_wq, &wiphy_to_rdev(wiphy)->sched_scan_results_wk); }

Contributors

PersonTokensPropCommitsCommitProp
luciano coelholuciano coelho3175.61%125.00%
beni levbeni lev512.20%125.00%
jukka rissanenjukka rissanen37.32%125.00%
zhao gangzhao gang24.88%125.00%
Total41100.00%4100.00%

EXPORT_SYMBOL(cfg80211_sched_scan_results);
void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy) { struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ASSERT_RTNL(); trace_cfg80211_sched_scan_stopped(wiphy); __cfg80211_stop_sched_scan(rdev, true); }

Contributors

PersonTokensPropCommitsCommitProp
luciano coelholuciano coelho2468.57%240.00%
eliad pellereliad peller514.29%120.00%
beni levbeni lev514.29%120.00%
zhao gangzhao gang12.86%120.00%
Total35100.00%5100.00%

EXPORT_SYMBOL(cfg80211_sched_scan_stopped_rtnl);
void cfg80211_sched_scan_stopped(struct wiphy *wiphy) { rtnl_lock(); cfg80211_sched_scan_stopped_rtnl(wiphy); rtnl_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
eliad pellereliad peller1780.95%133.33%
luciano coelholuciano coelho29.52%133.33%
johannes bergjohannes berg29.52%133.33%
Total21100.00%3100.00%

EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, bool driver_initiated) { struct cfg80211_sched_scan_request *sched_scan_req; struct net_device *dev; ASSERT_RTNL(); if (!rdev->sched_scan_req) return -ENOENT; sched_scan_req = rtnl_dereference(rdev->sched_scan_req); dev = sched_scan_req->dev; if (!driver_initiated) { int err = rdev_sched_scan_stop(rdev, dev); if (err) return err; } nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); RCU_INIT_POINTER(rdev->sched_scan_req, NULL); kfree_rcu(sched_scan_req, rcu_head); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
luciano coelholuciano coelho7673.08%342.86%
jukka rissanenjukka rissanen2120.19%114.29%
jesper juhljesper juhl43.85%114.29%
johannes bergjohannes berg21.92%114.29%
hila gonenhila gonen10.96%114.29%
Total104100.00%7100.00%


void cfg80211_bss_age(struct cfg80211_registered_device *rdev, unsigned long age_secs) { struct cfg80211_internal_bss *bss; unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); spin_lock_bh(&rdev->bss_lock); list_for_each_entry(bss, &rdev->bss_list, list) bss->ts -= age_jiffies; spin_unlock_bh(&rdev->bss_lock); }

Contributors

PersonTokensPropCommitsCommitProp
dan williamsdan williams4270.00%133.33%
johannes bergjohannes berg1423.33%133.33%
zhao gangzhao gang46.67%133.33%
Total60100.00%3100.00%


void cfg80211_bss_expire(struct cfg80211_registered_device *rdev) { __cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg1578.95%133.33%
zhao gangzhao gang210.53%133.33%
sam lefflersam leffler210.53%133.33%
Total19100.00%3100.00%


const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) { while (len > 2 && ies[0] != eid) { len -= ies[1] + 2; ies += ies[1] + 2; } if (len < 2) return NULL; if (len < 2 + ies[1]) return NULL; return ies; }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg7698.70%266.67%
bob copelandbob copeland11.30%133.33%
Total77100.00%3100.00%

EXPORT_SYMBOL(cfg80211_find_ie);
const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type, const u8 *ies, int len) { struct ieee80211_vendor_ie *ie; const u8 *pos = ies, *end = ies + len; int ie_oui; if (WARN_ON(oui_type > 0xff)) return NULL; while (pos < end) { pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos, end - pos); if (!pos) return NULL; ie = (struct ieee80211_vendor_ie *)pos; /* make sure we can access ie->len */ BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1); if (ie->len < sizeof(*ie)) goto cont; ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2]; if (ie_oui == oui && (oui_type < 0 || ie->oui_type == oui_type)) return pos; cont: pos += 2 + ie->len; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
eliad pellereliad peller13472.83%133.33%
luciano coelholuciano coelho3116.85%133.33%
emmanuel grumbachemmanuel grumbach1910.33%133.33%
Total184100.00%3100.00%

EXPORT_SYMBOL(cfg80211_find_vendor_ie);
static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, const u8 *ssid, size_t ssid_len) { const struct cfg80211_bss_ies *ies; const u8 *ssidie; if (bssid && !ether_addr_equal(a->bssid, bssid)) return false; if (!ssid) return true; ies = rcu_access_pointer(a->ies); if (!ies) return false; ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); if (!ssidie) return false; if (ssidie[1] != ssid_len) return false; return memcmp(ssidie + 2, ssid, ssid_len) == 0; }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg12498.41%480.00%
joe perchesjoe perches21.59%120.00%
Total126100.00%5100.00%

/** * enum bss_compare_mode - BSS compare mode * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find) * @BSS_CMP_HIDE_ZLEN: find hidden SSID with zero-length mode * @BSS_CMP_HIDE_NUL: find hidden SSID with NUL-ed out mode */ enum bss_compare_mode { BSS_CMP_REGULAR, BSS_CMP_HIDE_ZLEN, BSS_CMP_HIDE_NUL, };
static int cmp_bss(struct cfg80211_bss *a, struct cfg80211_bss *b, enum bss_compare_mode mode) { const struct cfg80211_bss_ies *a_ies, *b_ies; const u8 *ie1 = NULL; const u8 *ie2 = NULL; int i, r; if (a->channel != b->channel) return b->channel->center_freq - a->channel->center_freq; a_ies = rcu_access_pointer(a->ies); if (!a_ies) return -1; b_ies = rcu_access_pointer(b->ies); if (!b_ies) return 1; if (WLAN_CAPABILITY_IS_STA_BSS(a->capability)) ie1 = cfg80211_find_ie(WLAN_EID_MESH_ID, a_ies->data, a_ies->len); if (WLAN_CAPABILITY_IS_STA_BSS(b->capability)) ie2 = cfg80211_find_ie(WLAN_EID_MESH_ID, b_ies->data, b_ies->len); if (ie1 && ie2) { int mesh_id_cmp; if (ie1[1] == ie2[1]) mesh_id_cmp = memcmp(ie1 + 2, ie2 + 2, ie1[1]); else mesh_id_cmp = ie2[1] - ie1[1]; ie1 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, a_ies->data, a_ies->len); ie2 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, b_ies->data, b_ies->len); if (ie1 && ie2) { if (mesh_id_cmp) return mesh_id_cmp; if (ie1[1] != ie2[1]) return ie2[1] - ie1[1]; return memcmp(ie1 + 2, ie2 + 2, ie1[1]); } } r = memcmp(a->bssid, b->bssid, sizeof(a->bssid)); if (r) return r; ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len); ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len); if (!ie1 && !ie2) return 0; /* * Note that with "hide_ssid", the function returns a match if * the already-present BSS ("b") is a hidden SSID beacon for * the new BSS ("a"). */ /* sort missing IE before (left of) present IE */ if (!ie1) return -1; if (!ie2) return 1; switch (mode) { case BSS_CMP_HIDE_ZLEN: /* * In ZLEN mode we assume the BSS entry we're * looking for has a zero-length SSID. So if * the one we're looking at right now has that, * return 0. Otherwise, return the difference * in length, but since we're looking for the * 0-length it's really equivalent to returning * the length of the one we're looking at. * * No content comparison is needed as we assume * the content length is zero. */ return ie2[1]; case BSS_CMP_REGULAR: default: /* sort by length first, then by contents */ if (ie1[1] != ie2[1]) return ie2[1] - ie1[1]; return memcmp(ie1 + 2, ie2 + 2, ie1[1]); case BSS_CMP_HIDE_NUL: if (ie1[1] != ie2[1]) return ie2[1] - ie1[1]; /* this is equivalent to memcmp(zeroes, ie2 + 2, len) */ for (i = 0; i < ie2[1]; i++) if (ie2[i + 2]) return -1; return 0; } }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg38577.00%562.50%
dmitry tarnyagindmitry tarnyagin9819.60%112.50%
javier cardonajavier cardona91.80%112.50%
emmanuel grumbachemmanuel grumbach81.60%112.50%
Total500100.00%8100.00%


static bool cfg80211_bss_type_match(u16 capability, enum nl80211_band band, enum ieee80211_bss_type bss_type) { bool ret = true; u16 mask, val; if (bss_type == IEEE80211_BSS_TYPE_ANY) return ret; if (band == NL80211_BAND_60GHZ) { mask = WLAN_CAPABILITY_DMG_TYPE_MASK; switch (bss_type) { case IEEE80211_BSS_TYPE_ESS: val = WLAN_CAPABILITY_DMG_TYPE_AP; break; case IEEE80211_BSS_TYPE_PBSS: val = WLAN_CAPABILITY_DMG_TYPE_PBSS; break; case IEEE80211_BSS_TYPE_IBSS: val = WLAN_CAPABILITY_DMG_TYPE_IBSS; break; default: return false; } } else { mask = WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS; switch (bss_type) { case IEEE80211_BSS_TYPE_ESS: val = WLAN_CAPABILITY_ESS; break; case IEEE80211_BSS_TYPE_IBSS: val = WLAN_CAPABILITY_IBSS; break; case IEEE80211_BSS_TYPE_MBSS: val = 0; break; default: return false; } } ret = ((capability & mask) == val); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
dedy lanskydedy lansky13898.57%150.00%
johannes bergjohannes berg21.43%150.00%
Total140100.00%2100.00%

/* Returned bss is reference counted and must be cleaned up appropriately. */
struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, struct ieee80211_channel *channel, const u8 *bssid, const u8 *ssid, size_t ssid_len, enum ieee80211_bss_type bss_type, enum ieee80211_privacy privacy) { struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); struct cfg80211_internal_bss *bss, *res = NULL; unsigned long now = jiffies; int bss_privacy; trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, bss_type, privacy); spin_lock_bh(&rdev->bss_lock); list_for_each_entry(bss, &rdev->bss_list, list) { if (!cfg80211_bss_type_match(bss->pub.capability, bss->pub.channel->band, bss_type)) continue; bss_privacy = (bss->pub.capability & WLAN_CAPABILITY_PRIVACY); if ((privacy == IEEE80211_PRIVACY_ON && !bss_privacy) || (privacy == IEEE80211_PRIVACY_OFF && bss_privacy)) continue; if (channel && bss->pub.channel != channel) continue; if (!is_valid_ether_addr(bss->pub.bssid)) continue; /* Don't get expired BSS structs */ if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) && !atomic_read(&bss->hold)) continue; if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { res = bss; bss_ref_get(rdev, res); break; } } spin_unlock_bh(&rdev->bss_lock); if (!res) return NULL; trace_cfg80211_return_bss(&res->pub); return &res->pub; }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg18468.91%660.00%
dedy lanskydedy lansky5420.22%110.00%
beni levbeni lev238.61%110.00%
zhao gangzhao gang62.25%220.00%
Total267100.00%10100.00%

EXPORT_SYMBOL(cfg80211_get_bss);
static void rb_insert_bss(struct cfg80211_registered_device *rdev, struct cfg80211_internal_bss *bss) { struct rb_node **p = &rdev->bss_tree.rb_node; struct rb_node *parent = NULL; struct cfg80211_internal_bss *tbss; int cmp; while (*p) { parent = *p; tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn); cmp = cmp_bss(&bss->pub, &tbss->pub, BSS_CMP_REGULAR); if (WARN_ON(!cmp)) { /* will sort of leak this BSS */ return; } if (cmp < 0) p = &(*p)->rb_left; else p = &(*p)->rb_right; } rb_link_node(&bss->rbn, parent, p); rb_insert_color(&bss->rbn, &rdev->bss_tree); }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg14697.99%375.00%
zhao gangzhao gang32.01%125.00%
Total149100.00%4100.00%


static struct cfg80211_internal_bss * rb_find_bss(struct cfg80211_registered_device *rdev, struct cfg80211_internal_bss *res, enum bss_compare_mode mode) { struct rb_node *n = rdev->bss_tree.rb_node; struct cfg80211_internal_bss *bss; int r; while (n) { bss = rb_entry(n, struct cfg80211_internal_bss, rbn); r = cmp_bss(&res->pub, &bss->pub, mode); if (r == 0) return bss; else if (r < 0) n = n->rb_left; else n = n->rb_right; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
johannes bergjohannes berg6963.89%360.00%
dmitry tarnyagindmitry tarnyagin3734.26%120.00%
zhao gangzhao gang21.85%120.00%
Total108100.00%5100.00%


static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, struct cfg80211_internal_bss *new) { const struct cfg80211_bss_ies *ies; struct cfg80211_internal_bss *bss; const u8 *ie; int i, ssidlen; u8 fold