Deleted Added
full compact
ieee80211_scan_sta.c (193655) ieee80211_scan_sta.c (195618)
1/*-
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 10 unchanged lines hidden (view full) ---

19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 10 unchanged lines hidden (view full) ---

19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_scan_sta.c 193655 2009-06-07 22:00:22Z sam $");
27__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_scan_sta.c 195618 2009-07-11 15:02:45Z rpaulo $");
28
29/*
30 * IEEE 802.11 station scanning support.
31 */
32#include "opt_wlan.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>

--- 7 unchanged lines hidden (view full) ---

43#include <net/ethernet.h>
44
45#include <net80211/ieee80211_var.h>
46#include <net80211/ieee80211_input.h>
47#include <net80211/ieee80211_regdomain.h>
48#ifdef IEEE80211_SUPPORT_TDMA
49#include <net80211/ieee80211_tdma.h>
50#endif
28
29/*
30 * IEEE 802.11 station scanning support.
31 */
32#include "opt_wlan.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>

--- 7 unchanged lines hidden (view full) ---

43#include <net/ethernet.h>
44
45#include <net80211/ieee80211_var.h>
46#include <net80211/ieee80211_input.h>
47#include <net80211/ieee80211_regdomain.h>
48#ifdef IEEE80211_SUPPORT_TDMA
49#include <net80211/ieee80211_tdma.h>
50#endif
51#ifdef IEEE80211_SUPPORT_MESH
52#include <net80211/ieee80211_mesh.h>
53#endif
51
52#include <net/bpf.h>
53
54/*
55 * Parameters for managing cache entries:
56 *
57 * o a station with STA_FAILS_MAX failures is not considered
58 * when picking a candidate

--- 48 unchanged lines hidden (view full) ---

107
108static void sta_flush_table(struct sta_table *);
109/*
110 * match_bss returns a bitmask describing if an entry is suitable
111 * for use. If non-zero the entry was deemed not suitable and it's
112 * contents explains why. The following flags are or'd to to this
113 * mask and can be used to figure out why the entry was rejected.
114 */
54
55#include <net/bpf.h>
56
57/*
58 * Parameters for managing cache entries:
59 *
60 * o a station with STA_FAILS_MAX failures is not considered
61 * when picking a candidate

--- 48 unchanged lines hidden (view full) ---

110
111static void sta_flush_table(struct sta_table *);
112/*
113 * match_bss returns a bitmask describing if an entry is suitable
114 * for use. If non-zero the entry was deemed not suitable and it's
115 * contents explains why. The following flags are or'd to to this
116 * mask and can be used to figure out why the entry was rejected.
117 */
115#define MATCH_CHANNEL 0x0001 /* channel mismatch */
116#define MATCH_CAPINFO 0x0002 /* capabilities mismatch, e.g. no ess */
117#define MATCH_PRIVACY 0x0004 /* privacy mismatch */
118#define MATCH_RATE 0x0008 /* rate set mismatch */
119#define MATCH_SSID 0x0010 /* ssid mismatch */
120#define MATCH_BSSID 0x0020 /* bssid mismatch */
121#define MATCH_FAILS 0x0040 /* too many failed auth attempts */
122#define MATCH_NOTSEEN 0x0080 /* not seen in recent scans */
123#define MATCH_RSSI 0x0100 /* rssi deemed too low to use */
124#define MATCH_CC 0x0200 /* country code mismatch */
125#define MATCH_TDMA_NOIE 0x0400 /* no TDMA ie */
126#define MATCH_TDMA_NOTMASTER 0x0800 /* not TDMA master */
127#define MATCH_TDMA_NOSLOT 0x1000 /* all TDMA slots occupied */
128#define MATCH_TDMA_LOCAL 0x2000 /* local address */
129#define MATCH_TDMA_VERSION 0x4000 /* protocol version mismatch */
118#define MATCH_CHANNEL 0x00001 /* channel mismatch */
119#define MATCH_CAPINFO 0x00002 /* capabilities mismatch, e.g. no ess */
120#define MATCH_PRIVACY 0x00004 /* privacy mismatch */
121#define MATCH_RATE 0x00008 /* rate set mismatch */
122#define MATCH_SSID 0x00010 /* ssid mismatch */
123#define MATCH_BSSID 0x00020 /* bssid mismatch */
124#define MATCH_FAILS 0x00040 /* too many failed auth attempts */
125#define MATCH_NOTSEEN 0x00080 /* not seen in recent scans */
126#define MATCH_RSSI 0x00100 /* rssi deemed too low to use */
127#define MATCH_CC 0x00200 /* country code mismatch */
128#define MATCH_TDMA_NOIE 0x00400 /* no TDMA ie */
129#define MATCH_TDMA_NOTMASTER 0x00800 /* not TDMA master */
130#define MATCH_TDMA_NOSLOT 0x01000 /* all TDMA slots occupied */
131#define MATCH_TDMA_LOCAL 0x02000 /* local address */
132#define MATCH_TDMA_VERSION 0x04000 /* protocol version mismatch */
133#define MATCH_MESH_NOID 0x10000 /* no MESHID ie */
134#define MATCH_MESHID 0x20000 /* meshid mismatch */
130static int match_bss(struct ieee80211vap *,
131 const struct ieee80211_scan_state *, struct sta_entry *, int);
132static void adhoc_age(struct ieee80211_scan_state *);
133
134static __inline int
135isocmp(const uint8_t cc1[], const uint8_t cc2[])
136{
137 return (cc1[0] == cc2[0] && cc1[1] == cc2[1]);
138}
139
140/* number of references from net80211 layer */
141static int nrefs = 0;
135static int match_bss(struct ieee80211vap *,
136 const struct ieee80211_scan_state *, struct sta_entry *, int);
137static void adhoc_age(struct ieee80211_scan_state *);
138
139static __inline int
140isocmp(const uint8_t cc1[], const uint8_t cc2[])
141{
142 return (cc1[0] == cc2[0] && cc1[1] == cc2[1]);
143}
144
145/* number of references from net80211 layer */
146static int nrefs = 0;
147/*
148 * Module glue.
149 */
150IEEE80211_SCANNER_MODULE(sta, 1);
142
143/*
144 * Attach prior to any scanning work.
145 */
146static int
147sta_attach(struct ieee80211_scan_state *ss)
148{
149 struct sta_table *st;

--- 126 unchanged lines hidden (view full) ---

276 */
277 IEEE80211_RSSI_LPF(se->se_avgrssi, rssi);
278 ise->se_rssi = IEEE80211_RSSI_GET(se->se_avgrssi);
279 ise->se_noise = noise;
280 }
281 memcpy(ise->se_tstamp.data, sp->tstamp, sizeof(ise->se_tstamp));
282 ise->se_intval = sp->bintval;
283 ise->se_capinfo = sp->capinfo;
151
152/*
153 * Attach prior to any scanning work.
154 */
155static int
156sta_attach(struct ieee80211_scan_state *ss)
157{
158 struct sta_table *st;

--- 126 unchanged lines hidden (view full) ---

285 */
286 IEEE80211_RSSI_LPF(se->se_avgrssi, rssi);
287 ise->se_rssi = IEEE80211_RSSI_GET(se->se_avgrssi);
288 ise->se_noise = noise;
289 }
290 memcpy(ise->se_tstamp.data, sp->tstamp, sizeof(ise->se_tstamp));
291 ise->se_intval = sp->bintval;
292 ise->se_capinfo = sp->capinfo;
293#ifdef IEEE80211_SUPPORT_MESH
294 if (sp->meshid != NULL && sp->meshid[1] != 0)
295 memcpy(ise->se_meshid, sp->meshid, 2+sp->meshid[1]);
296#endif
284 /*
285 * Beware of overriding se_chan for frames seen
286 * off-channel; this can cause us to attempt an
287 * association on the wrong channel.
288 */
289 if (sp->status & IEEE80211_BPARSE_OFFCHAN) {
290 struct ieee80211_channel *c;
291 /*

--- 598 unchanged lines hidden (view full) ---

890back:
891 if (okrate == 0 || ucastrate != fixedrate)
892 return badrate | IEEE80211_RATE_BASIC;
893 else
894 return RV(okrate);
895#undef RV
896}
897
297 /*
298 * Beware of overriding se_chan for frames seen
299 * off-channel; this can cause us to attempt an
300 * association on the wrong channel.
301 */
302 if (sp->status & IEEE80211_BPARSE_OFFCHAN) {
303 struct ieee80211_channel *c;
304 /*

--- 598 unchanged lines hidden (view full) ---

903back:
904 if (okrate == 0 || ucastrate != fixedrate)
905 return badrate | IEEE80211_RATE_BASIC;
906 else
907 return RV(okrate);
908#undef RV
909}
910
911static __inline int
912match_id(const uint8_t *ie, const uint8_t *val, int len)
913{
914 return (ie[1] == len && memcmp(ie+2, val, len) == 0);
915}
916
898static int
899match_ssid(const uint8_t *ie,
900 int nssid, const struct ieee80211_scan_ssid ssids[])
901{
902 int i;
903
904 for (i = 0; i < nssid; i++) {
917static int
918match_ssid(const uint8_t *ie,
919 int nssid, const struct ieee80211_scan_ssid ssids[])
920{
921 int i;
922
923 for (i = 0; i < nssid; i++) {
905 if (ie[1] == ssids[i].len &&
906 memcmp(ie+2, ssids[i].ssid, ie[1]) == 0)
924 if (match_id(ie, ssids[i].ssid, ssids[i].len))
907 return 1;
908 }
909 return 0;
910}
911
912#ifdef IEEE80211_SUPPORT_TDMA
913static int
914tdma_isfull(const struct ieee80211_tdma_param *tdma)

--- 66 unchanged lines hidden (view full) ---

981 else if (tdma_isfull(tdma))
982 fail |= MATCH_TDMA_NOSLOT;
983#if 0
984 else if (ieee80211_local_address(se->se_macaddr))
985 fail |= MATCH_TDMA_LOCAL;
986#endif
987 }
988#endif /* IEEE80211_SUPPORT_TDMA */
925 return 1;
926 }
927 return 0;
928}
929
930#ifdef IEEE80211_SUPPORT_TDMA
931static int
932tdma_isfull(const struct ieee80211_tdma_param *tdma)

--- 66 unchanged lines hidden (view full) ---

999 else if (tdma_isfull(tdma))
1000 fail |= MATCH_TDMA_NOSLOT;
1001#if 0
1002 else if (ieee80211_local_address(se->se_macaddr))
1003 fail |= MATCH_TDMA_LOCAL;
1004#endif
1005 }
1006#endif /* IEEE80211_SUPPORT_TDMA */
1007#ifdef IEEE80211_SUPPORT_MESH
1008 } else if (vap->iv_opmode == IEEE80211_M_MBSS) {
1009 const struct ieee80211_mesh_state *ms = vap->iv_mesh;
1010 /*
1011 * Mesh nodes have IBSS & ESS bits in capinfo turned off
1012 * and two special ie's that must be present.
1013 */
1014 if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS))
1015 fail |= MATCH_CAPINFO;
1016 else if (se->se_meshid == NULL)
1017 fail |= MATCH_MESH_NOID;
1018 else if (ms->ms_idlen != 0 &&
1019 match_id(se->se_meshid, ms->ms_id, ms->ms_idlen))
1020 fail |= MATCH_MESHID;
989 } else {
1021 } else {
1022#endif
990 if ((se->se_capinfo & IEEE80211_CAPINFO_ESS) == 0)
991 fail |= MATCH_CAPINFO;
992 /*
993 * If 11d is enabled and we're attempting to join a bss
994 * that advertises it's country code then compare our
995 * current settings to what we fetched from the country ie.
996 * If our country code is unspecified or different then do
997 * not attempt to join the bss. We should have already

--- 67 unchanged lines hidden (view full) ---

1065 fail & MATCH_CC ? '$' :
1066#ifdef IEEE80211_SUPPORT_TDMA
1067 fail & MATCH_TDMA_NOIE ? '&' :
1068 fail & MATCH_TDMA_VERSION ? 'v' :
1069 fail & MATCH_TDMA_NOTMASTER ? 's' :
1070 fail & MATCH_TDMA_NOSLOT ? 'f' :
1071 fail & MATCH_TDMA_LOCAL ? 'l' :
1072#endif
1023 if ((se->se_capinfo & IEEE80211_CAPINFO_ESS) == 0)
1024 fail |= MATCH_CAPINFO;
1025 /*
1026 * If 11d is enabled and we're attempting to join a bss
1027 * that advertises it's country code then compare our
1028 * current settings to what we fetched from the country ie.
1029 * If our country code is unspecified or different then do
1030 * not attempt to join the bss. We should have already

--- 67 unchanged lines hidden (view full) ---

1098 fail & MATCH_CC ? '$' :
1099#ifdef IEEE80211_SUPPORT_TDMA
1100 fail & MATCH_TDMA_NOIE ? '&' :
1101 fail & MATCH_TDMA_VERSION ? 'v' :
1102 fail & MATCH_TDMA_NOTMASTER ? 's' :
1103 fail & MATCH_TDMA_NOSLOT ? 'f' :
1104 fail & MATCH_TDMA_LOCAL ? 'l' :
1105#endif
1106 fail & MATCH_MESH_NOID ? 'm' :
1073 fail ? '-' : '+', ether_sprintf(se->se_macaddr));
1074 printf(" %s%c", ether_sprintf(se->se_bssid),
1075 fail & MATCH_BSSID ? '!' : ' ');
1076 printf(" %3d%c", ieee80211_chan2ieee(ic, se->se_chan),
1077 fail & MATCH_CHANNEL ? '!' : ' ');
1078 printf(" %+4d%c", se->se_rssi, fail & MATCH_RSSI ? '!' : ' ');
1079 printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
1080 fail & MATCH_RATE ? '!' : ' ');
1081 printf(" %4s%c",
1082 (se->se_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
1083 (se->se_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : "",
1084 fail & MATCH_CAPINFO ? '!' : ' ');
1085 printf(" %3s%c ",
1086 (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
1087 "wep" : "no",
1088 fail & MATCH_PRIVACY ? '!' : ' ');
1089 ieee80211_print_essid(se->se_ssid+2, se->se_ssid[1]);
1107 fail ? '-' : '+', ether_sprintf(se->se_macaddr));
1108 printf(" %s%c", ether_sprintf(se->se_bssid),
1109 fail & MATCH_BSSID ? '!' : ' ');
1110 printf(" %3d%c", ieee80211_chan2ieee(ic, se->se_chan),
1111 fail & MATCH_CHANNEL ? '!' : ' ');
1112 printf(" %+4d%c", se->se_rssi, fail & MATCH_RSSI ? '!' : ' ');
1113 printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
1114 fail & MATCH_RATE ? '!' : ' ');
1115 printf(" %4s%c",
1116 (se->se_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
1117 (se->se_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : "",
1118 fail & MATCH_CAPINFO ? '!' : ' ');
1119 printf(" %3s%c ",
1120 (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
1121 "wep" : "no",
1122 fail & MATCH_PRIVACY ? '!' : ' ');
1123 ieee80211_print_essid(se->se_ssid+2, se->se_ssid[1]);
1090 printf("%s\n", fail & MATCH_SSID ? "!" : "");
1124 printf("%s\n", fail & (MATCH_SSID | MATCH_MESHID) ? "!" : "");
1091 }
1092#endif
1093 return fail;
1094}
1095
1096static void
1097sta_update_notseen(struct sta_table *st)
1098{

--- 311 unchanged lines hidden (view full) ---

1410 .scan_end = sta_pick_bss,
1411 .scan_flush = sta_flush,
1412 .scan_add = sta_add,
1413 .scan_age = sta_age,
1414 .scan_iterate = sta_iterate,
1415 .scan_assoc_fail = sta_assoc_fail,
1416 .scan_assoc_success = sta_assoc_success,
1417};
1125 }
1126#endif
1127 return fail;
1128}
1129
1130static void
1131sta_update_notseen(struct sta_table *st)
1132{

--- 311 unchanged lines hidden (view full) ---

1444 .scan_end = sta_pick_bss,
1445 .scan_flush = sta_flush,
1446 .scan_add = sta_add,
1447 .scan_age = sta_age,
1448 .scan_iterate = sta_iterate,
1449 .scan_assoc_fail = sta_assoc_fail,
1450 .scan_assoc_success = sta_assoc_success,
1451};
1452IEEE80211_SCANNER_ALG(sta, IEEE80211_M_STA, sta_default);
1418
1419/*
1420 * Adhoc mode-specific support.
1421 */
1422
1423static const uint16_t adhocWorld[] = /* 36, 40, 44, 48 */
1424{ 5180, 5200, 5220, 5240 };
1425static const uint16_t adhocFcc3[] = /* 36, 40, 44, 48 145, 149, 153, 157, 161, 165 */

--- 83 unchanged lines hidden (view full) ---

1509static int
1510adhoc_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
1511{
1512 struct sta_table *st = ss->ss_priv;
1513 struct sta_entry *selbs;
1514 struct ieee80211_channel *chan;
1515
1516 KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
1453
1454/*
1455 * Adhoc mode-specific support.
1456 */
1457
1458static const uint16_t adhocWorld[] = /* 36, 40, 44, 48 */
1459{ 5180, 5200, 5220, 5240 };
1460static const uint16_t adhocFcc3[] = /* 36, 40, 44, 48 145, 149, 153, 157, 161, 165 */

--- 83 unchanged lines hidden (view full) ---

1544static int
1545adhoc_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
1546{
1547 struct sta_table *st = ss->ss_priv;
1548 struct sta_entry *selbs;
1549 struct ieee80211_channel *chan;
1550
1551 KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
1517 vap->iv_opmode == IEEE80211_M_AHDEMO,
1552 vap->iv_opmode == IEEE80211_M_AHDEMO ||
1553 vap->iv_opmode == IEEE80211_M_MBSS,
1518 ("wrong opmode %u", vap->iv_opmode));
1519
1520 if (st->st_newscan) {
1521 sta_update_notseen(st);
1522 st->st_newscan = 0;
1523 }
1524 if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {
1525 /*

--- 99 unchanged lines hidden (view full) ---

1625 .scan_flush = sta_flush,
1626 .scan_pickchan = adhoc_pick_channel,
1627 .scan_add = sta_add,
1628 .scan_age = adhoc_age,
1629 .scan_iterate = sta_iterate,
1630 .scan_assoc_fail = sta_assoc_fail,
1631 .scan_assoc_success = sta_assoc_success,
1632};
1554 ("wrong opmode %u", vap->iv_opmode));
1555
1556 if (st->st_newscan) {
1557 sta_update_notseen(st);
1558 st->st_newscan = 0;
1559 }
1560 if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {
1561 /*

--- 99 unchanged lines hidden (view full) ---

1661 .scan_flush = sta_flush,
1662 .scan_pickchan = adhoc_pick_channel,
1663 .scan_add = sta_add,
1664 .scan_age = adhoc_age,
1665 .scan_iterate = sta_iterate,
1666 .scan_assoc_fail = sta_assoc_fail,
1667 .scan_assoc_success = sta_assoc_success,
1668};
1669IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default);
1670IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default);
1633
1634static void
1635ap_force_promisc(struct ieee80211com *ic)
1636{
1637 struct ifnet *ifp = ic->ic_ifp;
1638
1639 IEEE80211_LOCK(ic);
1640 /* set interface into promiscuous mode */

--- 135 unchanged lines hidden (view full) ---

1776 .scan_flush = sta_flush,
1777 .scan_pickchan = ap_pick_channel,
1778 .scan_add = sta_add,
1779 .scan_age = adhoc_age,
1780 .scan_iterate = sta_iterate,
1781 .scan_assoc_success = sta_assoc_success,
1782 .scan_assoc_fail = sta_assoc_fail,
1783};
1671
1672static void
1673ap_force_promisc(struct ieee80211com *ic)
1674{
1675 struct ifnet *ifp = ic->ic_ifp;
1676
1677 IEEE80211_LOCK(ic);
1678 /* set interface into promiscuous mode */

--- 135 unchanged lines hidden (view full) ---

1814 .scan_flush = sta_flush,
1815 .scan_pickchan = ap_pick_channel,
1816 .scan_add = sta_add,
1817 .scan_age = adhoc_age,
1818 .scan_iterate = sta_iterate,
1819 .scan_assoc_success = sta_assoc_success,
1820 .scan_assoc_fail = sta_assoc_fail,
1821};
1822IEEE80211_SCANNER_ALG(ap, IEEE80211_M_HOSTAP, ap_default);
1784
1823
1824#ifdef IEEE80211_SUPPORT_MESH
1785/*
1825/*
1786 * Module glue.
1826 * Pick an mbss network to join or find a channel
1827 * to use to start an mbss network.
1787 */
1828 */
1788IEEE80211_SCANNER_MODULE(sta, 1);
1789IEEE80211_SCANNER_ALG(sta, IEEE80211_M_STA, sta_default);
1790IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default);
1791IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default);
1792IEEE80211_SCANNER_ALG(ap, IEEE80211_M_HOSTAP, ap_default);
1829static int
1830mesh_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
1831{
1832 struct sta_table *st = ss->ss_priv;
1833 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1834 struct sta_entry *selbs;
1835 struct ieee80211_channel *chan;
1836
1837 KASSERT(vap->iv_opmode == IEEE80211_M_MBSS,
1838 ("wrong opmode %u", vap->iv_opmode));
1839
1840 if (st->st_newscan) {
1841 sta_update_notseen(st);
1842 st->st_newscan = 0;
1843 }
1844 if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {
1845 /*
1846 * Manual/background scan, don't select+join the
1847 * bss, just return. The scanning framework will
1848 * handle notification that this has completed.
1849 */
1850 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
1851 return 1;
1852 }
1853 /*
1854 * Automatic sequencing; look for a candidate and
1855 * if found join the network.
1856 */
1857 /* NB: unlocked read should be ok */
1858 if (TAILQ_FIRST(&st->st_entry) == NULL) {
1859 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1860 "%s: no scan candidate\n", __func__);
1861 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
1862 return 0;
1863notfound:
1864 if (ms->ms_idlen != 0) {
1865 /*
1866 * No existing mbss network to join and we have
1867 * a meshid; start one up. If no channel was
1868 * specified, try to select a channel.
1869 */
1870 if (vap->iv_des_chan == IEEE80211_CHAN_ANYC ||
1871 IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
1872 struct ieee80211com *ic = vap->iv_ic;
1873
1874 chan = adhoc_pick_channel(ss, 0);
1875 if (chan != NULL)
1876 chan = ieee80211_ht_adjust_channel(ic,
1877 chan, vap->iv_flags_ht);
1878 } else
1879 chan = vap->iv_des_chan;
1880 if (chan != NULL) {
1881 ieee80211_create_ibss(vap, chan);
1882 return 1;
1883 }
1884 }
1885 /*
1886 * If nothing suitable was found decrement
1887 * the failure counts so entries will be
1888 * reconsidered the next time around. We
1889 * really want to do this only for sta's
1890 * where we've previously had some success.
1891 */
1892 sta_dec_fails(st);
1893 st->st_newscan = 1;
1894 return 0; /* restart scan */
1895 }
1896 selbs = select_bss(ss, vap, IEEE80211_MSG_SCAN);
1897 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
1898 return (selbs != NULL);
1899 if (selbs == NULL)
1900 goto notfound;
1901 chan = selbs->base.se_chan;
1902 if (selbs->se_flags & STA_DEMOTE11B)
1903 chan = demote11b(vap, chan);
1904 if (!ieee80211_sta_join(vap, chan, &selbs->base))
1905 goto notfound;
1906 return 1; /* terminate scan */
1907}
1908
1909static const struct ieee80211_scanner mesh_default = {
1910 .scan_name = "default",
1911 .scan_attach = sta_attach,
1912 .scan_detach = sta_detach,
1913 .scan_start = adhoc_start,
1914 .scan_restart = sta_restart,
1915 .scan_cancel = sta_cancel,
1916 .scan_end = mesh_pick_bss,
1917 .scan_flush = sta_flush,
1918 .scan_pickchan = adhoc_pick_channel,
1919 .scan_add = sta_add,
1920 .scan_age = adhoc_age,
1921 .scan_iterate = sta_iterate,
1922 .scan_assoc_fail = sta_assoc_fail,
1923 .scan_assoc_success = sta_assoc_success,
1924};
1925IEEE80211_SCANNER_ALG(mesh, IEEE80211_M_MBSS, mesh_default);
1926#endif /* IEEE80211_SUPPORT_MESH */