On Sat, May 11, 2019 at 12:27:54PM -0400, Stefan Sperling wrote:
> This fixes ifconfig 'nwflags' hiddennwid and nobridge; these flags
> currently overlap with other flags, such as the AUTO_JOIN flag and
> hence can't be used.
> 
> While here, add another flag which makes the interface ignore deauth frames.

Updated version which adds AP-side support for stayauth as well.

diff 017348fd9e151db65e509e6fb577f24587e25b0f /usr/src
blob - adc7fa737fc2f734df37a6c286e0ff50ad36425c
file + sbin/ifconfig/ifconfig.8
--- sbin/ifconfig/ifconfig.8
+++ sbin/ifconfig/ifconfig.8
@@ -969,22 +969,31 @@ Show the list of currently configured auto-join networ
 Remove all networks in the list of auto-join networks.
 .It Cm nwflag Ar flag
 Set specified flag.
-The flag name can be either
-.Ql hidenwid
-or
-.Ql nobridge .
+The flag name can be:
+.Bl -tag -width tenletters
+.It hidenwid
 The
 .Ql hidenwid
 flag will hide the network ID (ESSID) in beacon frames when operating
 in Host AP mode.
 It will also prevent responses to probe requests with an unspecified
 network ID.
+.It nobridge
 The
 .Ql nobridge
 flag will disable the direct bridging of frames between associated
 nodes when operating in Host AP mode.
 Setting this flag will block and filter direct inter-station
 communications.
+.It stayauth
+The
+.Ql stayauth
+flag will cause the interface to ignore deauth frames.
+This flag should only be used on wifi networks which are being
+attacked with spoofed deauth frames.
+It breaks interoperability with spectrum management solutions and access
+points that perform band-steering of clients.
+.El
 .Pp
 Note that the
 .Ql hidenwid
blob - 5451345b7673ff3ab88503eb534d054d796c6aad
file + sys/dev/ic/if_wi.c
--- sys/dev/ic/if_wi.c
+++ sys/dev/ic/if_wi.c
@@ -1963,8 +1963,7 @@ wi_ioctl(struct ifnet *ifp, u_long command, caddr_t da
                        }
                        sc->wi_enh_security = letoh16(wreq->wi_val[0]);
                        if (sc->wi_enh_security == WI_HIDESSID_IGNPROBES)
-                               ifr->ifr_flags |= IEEE80211_F_HIDENWID >>
-                                   IEEE80211_F_USERSHIFT;
+                               ifr->ifr_flags |= IEEE80211_F_HIDENWID;
                }
                break;
        case SIOCS80211FLAGS:
@@ -1974,7 +1973,7 @@ wi_ioctl(struct ifnet *ifp, u_long command, caddr_t da
                        error = EINVAL;
                        break;
                }
-               flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
+               flags = (u_int32_t)ifr->ifr_flags;
                if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
                        sc->wi_enh_security = (flags & IEEE80211_F_HIDENWID) ?
                            WI_HIDESSID_IGNPROBES : 0;
blob - 1c863e788dca720c3666be6387d7ea812d7a937a
file + sys/net80211/ieee80211_input.c
--- sys/net80211/ieee80211_input.c
+++ sys/net80211/ieee80211_input.c
@@ -882,7 +882,7 @@ ieee80211_deliver_data(struct ieee80211com *ic, struct
        m1 = NULL;
 #ifndef IEEE80211_STA_ONLY
        if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
-           !(ic->ic_flags & IEEE80211_F_NOBRIDGE) &&
+           !(ic->ic_userflags & IEEE80211_F_NOBRIDGE) &&
            eh->ether_type != htons(ETHERTYPE_PAE)) {
                struct ieee80211_node *ni1;
 
@@ -2418,7 +2418,9 @@ ieee80211_recv_deauth(struct ieee80211com *ic, struct 
        case IEEE80211_M_STA: {
                int bgscan = ((ic->ic_flags & IEEE80211_F_BGSCAN) &&
                    ic->ic_state == IEEE80211_S_RUN);
-               if (!bgscan) /* ignore deauth during bgscan */
+               int stay_auth = ((ic->ic_userflags & IEEE80211_F_STAYAUTH) &&
+                   ic->ic_state >= IEEE80211_S_AUTH);
+               if (!(bgscan || stay_auth))
                        ieee80211_new_state(ic, IEEE80211_S_AUTH,
                            IEEE80211_FC0_SUBTYPE_DEAUTH);
                }
@@ -2426,13 +2428,18 @@ ieee80211_recv_deauth(struct ieee80211com *ic, struct 
 #ifndef IEEE80211_STA_ONLY
        case IEEE80211_M_HOSTAP:
                if (ni != ic->ic_bss) {
+                       int stay_auth =
+                           ((ic->ic_userflags & IEEE80211_F_STAYAUTH) &&
+                           (ni->ni_state == IEEE80211_STA_AUTH ||
+                           ni->ni_state == IEEE80211_STA_ASSOC));
                        if (ic->ic_if.if_flags & IFF_DEBUG)
                                printf("%s: station %s deauthenticated "
                                    "by peer (reason %d)\n",
                                    ic->ic_if.if_xname,
                                    ether_sprintf(ni->ni_macaddr),
                                    reason);
-                       ieee80211_node_leave(ic, ni);
+                       if (!stay_auth)
+                               ieee80211_node_leave(ic, ni);
                }
                break;
 #endif
blob - f9a7edff8968924fb609ef7b829682fba923ac55
file + sys/net80211/ieee80211_ioctl.c
--- sys/net80211/ieee80211_ioctl.c
+++ sys/net80211/ieee80211_ioctl.c
@@ -903,17 +903,17 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
                }
                break;
        case SIOCG80211FLAGS:
-               flags = ic->ic_flags;
+               flags = ic->ic_userflags;
 #ifndef IEEE80211_STA_ONLY
                if (ic->ic_opmode != IEEE80211_M_HOSTAP)
 #endif
                        flags &= ~IEEE80211_F_HOSTAPMASK;
-               ifr->ifr_flags = flags >> IEEE80211_F_USERSHIFT;
+               ifr->ifr_flags = flags;
                break;
        case SIOCS80211FLAGS:
                if ((error = suser(curproc)) != 0)
                        break;
-               flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
+               flags = ifr->ifr_flags;
                if (
 #ifndef IEEE80211_STA_ONLY
                    ic->ic_opmode != IEEE80211_M_HOSTAP &&
@@ -922,7 +922,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
                        error = EINVAL;
                        break;
                }
-               ic->ic_flags = (ic->ic_flags & ~IEEE80211_F_USERMASK) | flags;
+               ic->ic_userflags = flags;
                error = ENETRESET;
                break;
        case SIOCADDMULTI:
blob - 69dbc52cbe8738b74669a4e85084512f8e0de5b3
file + sys/net80211/ieee80211_ioctl.h
--- sys/net80211/ieee80211_ioctl.h
+++ sys/net80211/ieee80211_ioctl.h
@@ -394,20 +394,21 @@ struct ieee80211_nodereq_all {
 #define SIOCG80211ALLNODES     _IOWR('i', 214, struct ieee80211_nodereq_all)
 
 /* net80211 specific interface flags */
-#define IEEE80211_F_HIDENWID   0x10000000      /* CONF: hidden ssid mode */
-#define IEEE80211_F_NOBRIDGE   0x20000000      /* CONF: no internal bridging */
-#define IEEE80211_F_HOSTAPMASK 0x30000000
-#define IEEE80211_F_USERSHIFT  28
-#define IEEE80211_F_USERBITS   "\20\01HIDENWID\02NOBRIDGE"
+#define IEEE80211_F_HIDENWID   0x00000001      /* CONF: hidden ssid mode */
+#define IEEE80211_F_NOBRIDGE   0x00000002      /* CONF: no internal bridging */
+#define IEEE80211_F_HOSTAPMASK 0x00000003
+#define IEEE80211_F_STAYAUTH   0x00000004      /* CONF: ignore deauth */
+#define IEEE80211_F_USERBITS   "\20\01HIDENWID\02NOBRIDGE\03STAYAUTH"
 
 struct ieee80211_flags {
        const char              *f_name;
        u_int                   f_flag;
 };
 
-#define IEEE80211_FLAGS        {                                               
\
-       { "hidenwid", IEEE80211_F_HIDENWID >> IEEE80211_F_USERSHIFT },  \
-       { "nobridge", IEEE80211_F_NOBRIDGE >> IEEE80211_F_USERSHIFT }   \
+#define IEEE80211_FLAGS        {                       \
+       { "hidenwid", IEEE80211_F_HIDENWID },   \
+       { "nobridge", IEEE80211_F_NOBRIDGE },   \
+       { "stayauth", IEEE80211_F_STAYAUTH }    \
 }
 
 #define SIOCG80211FLAGS                _IOWR('i', 216, struct ifreq)
blob - 2f6e0e77d2e3a668b04b12461bd690d34c8d8b92
file + sys/net80211/ieee80211_output.c
--- sys/net80211/ieee80211_output.c
+++ sys/net80211/ieee80211_output.c
@@ -1818,7 +1818,8 @@ ieee80211_beacon_alloc(struct ieee80211com *ic, struct
 
        m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
            8 + 2 + 2 +
-           2 + ((ic->ic_flags & IEEE80211_F_HIDENWID) ? 0 : ni->ni_esslen) +
+           2 + ((ic->ic_userflags & IEEE80211_F_HIDENWID) ?
+           0 : ni->ni_esslen) +
            2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
            2 + 1 +
            2 + ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 254) +
@@ -1853,7 +1854,7 @@ ieee80211_beacon_alloc(struct ieee80211com *ic, struct
        memset(frm, 0, 8); frm += 8;    /* timestamp is set by hardware */
        LE_WRITE_2(frm, ni->ni_intval); frm += 2;
        frm = ieee80211_add_capinfo(frm, ic, ni);
-       if (ic->ic_flags & IEEE80211_F_HIDENWID)
+       if (ic->ic_userflags & IEEE80211_F_HIDENWID)
                frm = ieee80211_add_ssid(frm, NULL, 0);
        else
                frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
blob - eaf7649c4dbad2884d6adfde39c9fffb0a5b2d09
file + sys/net80211/ieee80211_var.h
--- sys/net80211/ieee80211_var.h
+++ sys/net80211/ieee80211_var.h
@@ -247,6 +247,7 @@ struct ieee80211com {
        u_int8_t                ic_scan_count;  /* count scans */
        u_int32_t               ic_flags;       /* state flags */
        u_int32_t               ic_xflags;      /* more flags */
+       u_int32_t               ic_userflags;   /* yet more flags */
        u_int32_t               ic_caps;        /* capabilities */
        u_int16_t               ic_modecaps;    /* set of mode capabilities */
        u_int16_t               ic_curmode;     /* current mode */
@@ -395,7 +396,6 @@ struct ieee80211_ess {
 #define        IEEE80211_F_BGSCAN      0x08000000      /* STATUS: background 
scan */
 #define IEEE80211_F_AUTO_JOIN  0x10000000      /* CONF: auto-join active */
 #define        IEEE80211_F_VHTON       0x20000000      /* CONF: VHT enabled */
-#define IEEE80211_F_USERMASK   0xc0000000      /* CONF: ioctl flag mask */
 
 /* ic_xflags */
 #define        IEEE80211_F_TX_MGMT_ONLY 0x00000001     /* leave data frames on 
ifq */

Reply via email to