Hi,
The following diff removes the functionality of the SIOCS80211SCAN ioctl.
After long discussions with stps@, mpi@, and deraadt@ we decided that
this was the correct way of fixing ifconfig scan from blocking the
network stack.
The kernel will continue scanning in the background and filling the
nodes array, but ifconfig scan commands will now basically do just a
SIOCG80211ALLNODES and pretty print the array. So the output stays the
same but is instant.
In fact, when the interface is freshly brought up, if you type fast
enough, you can see the array being filled by running multiple ifconfig
scans in sequence.
Another change that this introduces is the fact that ifconfig scan no
longer plays with UP and DOWN. If the interface is down it complains and
exits. This is needed in order to maintain the nodes list.
Currently tested on iwm(4), urtwn(4), run(4) and athn(4). We are
interested in wider testing, specially on iwn(4) and athn(4) in client
mode.
Thoughts? OKs?
Paul
diff --git sbin/ifconfig/ifconfig.c sbin/ifconfig/ifconfig.c
index 993a1ed32c8..5643c1f0219 100644
--- sbin/ifconfig/ifconfig.c
+++ sbin/ifconfig/ifconfig.c
@@ -2255,11 +2255,11 @@ ieee80211_listnodes(void)
struct ieee80211_nodereq_all na;
struct ieee80211_nodereq nr[512];
struct ifreq ifr;
- int i, down = 0;
+ int i;
if ((flags & IFF_UP) == 0) {
- down = 1;
- setifflags("up", IFF_UP);
+ printf("\t\tcan not scan, interface is down\n");
+ return;
}
bzero(&ifr, sizeof(ifr));
@@ -2268,7 +2268,7 @@ ieee80211_listnodes(void)
if (ioctl(s, SIOCS80211SCAN, (caddr_t)&ifr) != 0) {
if (errno == EPERM)
printf("\t\tno permission to scan\n");
- goto done;
+ return;
}
bzero(&na, sizeof(na));
@@ -2279,7 +2279,7 @@ ieee80211_listnodes(void)
if (ioctl(s, SIOCG80211ALLNODES, &na) != 0) {
warn("SIOCG80211ALLNODES");
- goto done;
+ return;
}
if (!na.na_nodes)
@@ -2292,10 +2292,6 @@ ieee80211_listnodes(void)
ieee80211_printnode(&nr[i]);
putchar('\n');
}
-
- done:
- if (down)
- setifflags("restore", -IFF_UP);
}
void
diff --git sys/dev/ic/athn.c sys/dev/ic/athn.c
index 54f1e668f7d..0830049a401 100644
--- sys/dev/ic/athn.c
+++ sys/dev/ic/athn.c
@@ -2917,8 +2917,6 @@ athn_stop(struct ifnet *ifp, int disable)
ifq_clr_oactive(&ifp->if_snd);
timeout_del(&sc->scan_to);
- /* In case we were scanning, release the scan "lock". */
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
diff --git sys/dev/ic/bwfm.c sys/dev/ic/bwfm.c
index 8a2f1beaddd..b05427cc0b9 100644
--- sys/dev/ic/bwfm.c
+++ sys/dev/ic/bwfm.c
@@ -463,9 +463,6 @@ bwfm_stop(struct ifnet *ifp)
ifp->if_flags &= ~IFF_RUNNING;
ifq_clr_oactive(&ifp->if_snd);
- /* In case we were scanning, release the scan "lock". */
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
-
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
bwfm_fwvar_cmd_set_int(sc, BWFM_C_DOWN, 1);
diff --git sys/dev/pci/if_ipw.c sys/dev/pci/if_ipw.c
index 57532466efd..a519af322ec 100644
--- sys/dev/pci/if_ipw.c
+++ sys/dev/pci/if_ipw.c
@@ -2024,9 +2024,6 @@ ipw_stop(struct ifnet *ifp, int disable)
for (i = 0; i < IPW_NTBD; i++)
ipw_release_sbd(sc, &sc->stbd_list[i]);
- /* in case we were scanning, release the scan "lock" */
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
-
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
}
diff --git sys/dev/pci/if_iwi.c sys/dev/pci/if_iwi.c
index f60f9113333..c3801f008df 100644
--- sys/dev/pci/if_iwi.c
+++ sys/dev/pci/if_iwi.c
@@ -2291,9 +2291,6 @@ iwi_stop(struct ifnet *ifp, int disable)
ifp->if_flags &= ~IFF_RUNNING;
ifq_clr_oactive(&ifp->if_snd);
- /* in case we were scanning, release the scan "lock" */
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
-
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
iwi_stop_master(sc);
diff --git sys/dev/pci/if_iwm.c sys/dev/pci/if_iwm.c
index fa3c1c82cc8..5a526802010 100644
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -6708,9 +6708,6 @@ iwm_stop(struct ifnet *ifp)
sc->sc_cmd_resp_pkt[i] = NULL;
sc->sc_cmd_resp_len[i] = 0;
}
- if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST)
- wakeup(&ic->ic_scan_lock);
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
ifp->if_flags &= ~IFF_RUNNING;
ifq_clr_oactive(&ifp->if_snd);
diff --git sys/dev/pci/if_iwn.c sys/dev/pci/if_iwn.c
index d26fb6a5e64..a839000a2ae 100644
--- sys/dev/pci/if_iwn.c
+++ sys/dev/pci/if_iwn.c
@@ -6633,11 +6633,6 @@ iwn_stop(struct ifnet *ifp, int disable)
ifp->if_flags &= ~IFF_RUNNING;
ifq_clr_oactive(&ifp->if_snd);
- /* In case we were scanning, release the scan "lock". */
- if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST)
- wakeup(&ic->ic_scan_lock);
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
-
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
/* Power OFF hardware. */
diff --git sys/dev/pci/if_wpi.c sys/dev/pci/if_wpi.c
index 214f1944ca3..0c5162b628c 100644
--- sys/dev/pci/if_wpi.c
+++ sys/dev/pci/if_wpi.c
@@ -3319,9 +3319,6 @@ wpi_stop(struct ifnet *ifp, int disable)
ifp->if_flags &= ~IFF_RUNNING;
ifq_clr_oactive(&ifp->if_snd);
- /* In case we were scanning, release the scan "lock". */
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
-
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
/* Power OFF hardware. */
diff --git sys/dev/usb/if_rsu.c sys/dev/usb/if_rsu.c
index fb70699874e..f55f23d79ae 100644
--- sys/dev/usb/if_rsu.c
+++ sys/dev/usb/if_rsu.c
@@ -2313,9 +2313,6 @@ rsu_stop(struct ifnet *ifp)
ifp->if_flags &= ~IFF_RUNNING;
ifq_clr_oactive(&ifp->if_snd);
- /* In case we were scanning, release the scan "lock". */
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
-
s = splusb();
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
/* Wait for all async commands to complete. */
diff --git sys/net80211/ieee80211.c sys/net80211/ieee80211.c
index da43082d70c..6f6db224727 100644
--- sys/net80211/ieee80211.c
+++ sys/net80211/ieee80211.c
@@ -143,7 +143,6 @@ ieee80211_channel_init(struct ifnet *ifp)
if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0)
ic->ic_curmode = IEEE80211_MODE_AUTO;
ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
}
void
diff --git sys/net80211/ieee80211_ioctl.c sys/net80211/ieee80211_ioctl.c
index 4c8fb30f2b0..80c471668b0 100644
--- sys/net80211/ieee80211_ioctl.c
+++ sys/net80211/ieee80211_ioctl.c
@@ -670,42 +670,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
data)
ifp->if_mtu = ifr->ifr_mtu;
break;
case SIOCS80211SCAN:
- if ((error = suser(curproc)) != 0)
- break;
-#ifndef IEEE80211_STA_ONLY
- if (ic->ic_opmode == IEEE80211_M_HOSTAP)
- break;
-#endif
- if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
- (IFF_UP | IFF_RUNNING)) {
- error = ENETDOWN;
- break;
- }
- if ((ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) == 0) {
- if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED)
- ic->ic_scan_lock |= IEEE80211_SCAN_RESUME;
- ic->ic_scan_lock |= IEEE80211_SCAN_REQUEST;
- if (ic->ic_state != IEEE80211_S_SCAN) {
- ieee80211_clean_cached(ic);
- if (ic->ic_opmode == IEEE80211_M_STA &&
- ic->ic_state == IEEE80211_S_RUN &&
- IFM_MODE(ic->ic_media.ifm_cur->ifm_media)
- == IFM_AUTO) {
- /*
- * We're already associated to an AP.
- * Make the scanning loop start off in
- * auto mode so all supported bands
- * get scanned.
- */
- ieee80211_setmode(ic,
- IEEE80211_MODE_AUTO);
- }
- ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
- }
- }
- /* Let the userspace process wait for completion */
- error = tsleep(&ic->ic_scan_lock, PCATCH, "80211scan",
- hz * IEEE80211_SCAN_TIMEOUT);
+ /* Disabled. SIOCG80211ALLNODES is enough. */
break;
case SIOCG80211NODE:
nr = (struct ieee80211_nodereq *)data;
@@ -769,6 +734,16 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
data)
break;
#endif
case SIOCG80211ALLNODES:
+#ifndef IEEE80211_STA_ONLY
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ break;
+#endif
+ if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
+ (IFF_UP | IFF_RUNNING)) {
+ error = ENETDOWN;
+ break;
+ }
+
na = (struct ieee80211_nodereq_all *)data;
na->na_nodes = i = 0;
ni = RBT_MIN(ieee80211_tree, &ic->ic_tree);
diff --git sys/net80211/ieee80211_node.c sys/net80211/ieee80211_node.c
index ae923d5beef..0c238167a42 100644
--- sys/net80211/ieee80211_node.c
+++ sys/net80211/ieee80211_node.c
@@ -245,10 +245,6 @@ ieee80211_begin_scan(struct ifnet *ifp)
{
struct ieee80211com *ic = (void *)ifp;
- if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED)
- return;
- ic->ic_scan_lock |= IEEE80211_SCAN_LOCKED;
-
/*
* In all but hostap mode scanning starts off in
* an active mode before switching to passive.
@@ -709,7 +705,7 @@ ieee80211_end_scan(struct ifnet *ifp)
break;
}
ieee80211_create_ibss(ic, &ic->ic_channels[i]);
- goto wakeup;
+ return;
}
#endif
if (ni == NULL) {
@@ -721,7 +717,7 @@ ieee80211_end_scan(struct ifnet *ifp)
(ic->ic_flags & IEEE80211_F_IBSSON) &&
ic->ic_des_esslen != 0) {
ieee80211_create_ibss(ic, ic->ic_ibss_chan);
- goto wakeup;
+ return;
}
#endif
/*
@@ -735,14 +731,8 @@ ieee80211_end_scan(struct ifnet *ifp)
*/
if (ieee80211_next_mode(ifp) == IEEE80211_MODE_AUTO ||
(ic->ic_caps & IEEE80211_C_SCANALLBAND)) {
- if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST &&
- ic->ic_scan_lock & IEEE80211_SCAN_RESUME) {
- ic->ic_scan_lock = IEEE80211_SCAN_LOCKED;
- /* Return from a user-initiated scan. */
- wakeup(&ic->ic_scan_lock);
- } else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST)
- goto wakeup;
ic->ic_scan_count++;
+ return;
}
/*
@@ -819,13 +809,13 @@ ieee80211_end_scan(struct ifnet *ifp)
if (ic->ic_bgscan_fail < IEEE80211_BGSCAN_FAIL_MAX)
ic->ic_bgscan_fail++;
ic->ic_flags &= ~IEEE80211_F_BGSCAN;
- goto wakeup;
+ return;
}
arg = malloc(sizeof(*arg), M_DEVBUF, M_NOWAIT | M_ZERO);
if (arg == NULL) {
ic->ic_flags &= ~IEEE80211_F_BGSCAN;
- goto wakeup;
+ return;
}
ic->ic_bgscan_fail = 0;
@@ -838,7 +828,7 @@ ieee80211_end_scan(struct ifnet *ifp)
IEEE80211_FC0_SUBTYPE_DEAUTH,
IEEE80211_REASON_AUTH_LEAVE) != 0) {
ic->ic_flags &= ~IEEE80211_F_BGSCAN;
- goto wakeup;
+ return;
}
/* Prevent dispatch of additional data frames to hardware. */
@@ -854,19 +844,11 @@ ieee80211_end_scan(struct ifnet *ifp)
ic->ic_bss->ni_unref_arg_size = sizeof(*arg);
ic->ic_bss->ni_unref_cb = ieee80211_node_switch_bss;
/* F_BGSCAN flag gets cleared in ieee80211_node_join_bss(). */
- goto wakeup;
+ return;
} else if (selbs == NULL)
goto notfound;
ieee80211_node_join_bss(ic, selbs);
-
- wakeup:
- if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) {
- /* Return from a user-initiated scan. */
- wakeup(&ic->ic_scan_lock);
- }
-
- ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
}
/*
diff --git sys/net80211/ieee80211_var.h sys/net80211/ieee80211_var.h
index 5b9e11179dd..0772fb32791 100644
--- sys/net80211/ieee80211_var.h
+++ sys/net80211/ieee80211_var.h
@@ -240,7 +240,6 @@ struct ieee80211com {
u_char ic_chan_scan[howmany(IEEE80211_CHAN_MAX,NBBY)];
struct mbuf_queue ic_mgtq;
struct mbuf_queue ic_pwrsaveq;
- u_int ic_scan_lock; /* user-initiated scan */
u_int8_t ic_scan_count; /* count scans */
u_int32_t ic_flags; /* state flags */
u_int32_t ic_xflags; /* more flags */