On Wed, Apr 25, 2018 at 08:55:26PM +0300, Paul Irofti wrote:
> 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
Updated diff that fixes scan on hostap mode. This removes the hostap
check from SIOCG80211ALLNODES that I added by mistake.
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..53613b7cbb3 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,12 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
data)
break;
#endif
case SIOCG80211ALLNODES:
+ 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 */