Works fine on 8265.

On Wed, May 23, 2018 at 4:31 AM, Stefan Sperling <s...@stsp.name> wrote:

> This diff implements monitor mode for iwm(4).
>
> To use it, enable 11n mode, monitor mode, and configure a channel (e.g.
> 11):
>
>         ifconfig iwm0 mode 11n mediaopt monitor
>         ifconfig iwm0 chan 11
>         ifconfig iwm0 up
>
> This command should now display wireless frames on the air:
>
>         tcpdump -n -i iwm0 -y IEEE802_11_RADIO -v
>
> Record frames with tcpdump like this (pcap file can be viewed in
> wireshark):
>
>         tcpdump -n -i iwm0 -s 4096 -y IEEE802_11_RADIO -w /tmp/iwm.pcap
>
> Note that 11n/11ac frames sent with >= 40 MHz channel width won't be
> captured. The hardware could do it but our stack is not passing the
> necessary configuration parameters to the driver, so the driver cannot
> configure the hardware appropriately (a similar problem as bwfm(4) has
> with our stack's incomplete 11n support).
> But the corresponding leading RTS and trailing BlockAck frames can be
> captured, which allows us to manually deduce the presence of such frames.
>
> Tested on a 7265 device.
>
> ok?
>
> Index: if_iwm.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
> retrieving revision 1.229
> diff -u -p -r1.229 if_iwm.c
> --- if_iwm.c    15 May 2018 19:48:23 -0000      1.229
> +++ if_iwm.c    23 May 2018 10:10:45 -0000
> @@ -426,7 +426,7 @@ uint8_t     iwm_ridx2rate(struct ieee80211_r
>  int    iwm_rval2ridx(int);
>  void   iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *);
>  void   iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
> -           struct iwm_mac_ctx_cmd *, uint32_t, int);
> +           struct iwm_mac_ctx_cmd *, uint32_t);
>  void   iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *,
>             struct iwm_mac_data_sta *, int);
>  int    iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, uint32_t,
> int);
> @@ -4446,6 +4446,7 @@ void
>  iwm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
>      struct iwm_mac_power_cmd *cmd)
>  {
> +       struct ieee80211com *ic = &sc->sc_ic;
>         struct ieee80211_node *ni = &in->in_ni;
>         int dtim_period, dtim_msec, keep_alive;
>
> @@ -4467,7 +4468,8 @@ iwm_power_build_cmd(struct iwm_softc *sc
>         keep_alive = roundup(keep_alive, 1000) / 1000;
>         cmd->keep_alive_seconds = htole16(keep_alive);
>
> -       cmd->flags = htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK);
> +       if (ic->ic_opmode != IEEE80211_M_MONITOR)
> +               cmd->flags = htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK);
>  }
>
>  int
> @@ -4494,13 +4496,15 @@ iwm_power_mac_update_mode(struct iwm_sof
>  int
>  iwm_power_update_device(struct iwm_softc *sc)
>  {
> -       struct iwm_device_power_cmd cmd = {
> -               .flags = htole16(IWM_DEVICE_POWER_
> FLAGS_POWER_SAVE_ENA_MSK),
> -       };
> +       struct iwm_device_power_cmd cmd = { };
> +       struct ieee80211com *ic = &sc->sc_ic;
>
>         if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
>                 return 0;
>
> +       if (ic->ic_opmode != IEEE80211_M_MONITOR)
> +               cmd.flags = htole16(IWM_DEVICE_POWER_
> FLAGS_POWER_SAVE_ENA_MSK);
> +
>         return iwm_send_cmd_pdu(sc,
>             IWM_POWER_TABLE_CMD, 0, sizeof(cmd), &cmd);
>  }
> @@ -4562,7 +4566,12 @@ iwm_add_sta_cmd(struct iwm_softc *sc, st
>                         add_sta_cmd.tfd_queue_msk |=
>                             htole32(1 << iwm_ac_to_tx_fifo[ac]);
>                 }
> -               IEEE80211_ADDR_COPY(&add_sta_cmd.addr,
> in->in_ni.ni_bssid);
> +               if (ic->ic_opmode == IEEE80211_M_MONITOR)
> +                       IEEE80211_ADDR_COPY(&add_sta_cmd.addr,
> +                           etherbroadcastaddr);
> +               else
> +                       IEEE80211_ADDR_COPY(&add_sta_cmd.addr,
> +                           in->in_ni.ni_bssid);
>         }
>         add_sta_cmd.add_modify = update ? 1 : 0;
>         add_sta_cmd.station_flags_msk
> @@ -5230,7 +5239,7 @@ iwm_ack_rates(struct iwm_softc *sc, stru
>
>  void
>  iwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
> -    struct iwm_mac_ctx_cmd *cmd, uint32_t action, int assoc)
> +    struct iwm_mac_ctx_cmd *cmd, uint32_t action)
>  {
>  #define IWM_EXP2(x)    ((1 << (x)) - 1)        /* CWmin = 2^ECWmin - 1 */
>         struct ieee80211com *ic = &sc->sc_ic;
> @@ -5242,12 +5251,21 @@ iwm_mac_ctxt_cmd_common(struct iwm_softc
>             in->in_color));
>         cmd->action = htole32(action);
>
> -       cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR)
> +               cmd->mac_type = htole32(IWM_FW_MAC_TYPE_LISTENER);
> +       else if (ic->ic_opmode == IEEE80211_M_STA)
> +               cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);
> +       else
> +               panic("unsupported operating mode %d\n", ic->ic_opmode);
>         cmd->tsf_id = htole32(IWM_TSF_ID_A);
>
>         IEEE80211_ADDR_COPY(cmd->node_addr, ic->ic_myaddr);
> -       IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
> +               IEEE80211_ADDR_COPY(cmd->bssid_addr, etherbroadcastaddr);
> +               return;
> +       }
>
> +       IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
>         iwm_ack_rates(sc, in, &cck_ack_rates, &ofdm_ack_rates);
>         cmd->cck_rates = htole32(cck_ack_rates);
>         cmd->ofdm_rates = htole32(ofdm_ack_rates);
> @@ -5332,6 +5350,7 @@ int
>  iwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t
> action,
>      int assoc)
>  {
> +       struct ieee80211com *ic = &sc->sc_ic;
>         struct ieee80211_node *ni = &in->in_ni;
>         struct iwm_mac_ctx_cmd cmd;
>         int active = (sc->sc_flags & IWM_FLAG_MAC_ACTIVE);
> @@ -5343,11 +5362,19 @@ iwm_mac_ctxt_cmd(struct iwm_softc *sc, s
>
>         memset(&cmd, 0, sizeof(cmd));
>
> -       iwm_mac_ctxt_cmd_common(sc, in, &cmd, action, assoc);
> +       iwm_mac_ctxt_cmd_common(sc, in, &cmd, action);
>
> -       /* Allow beacons to pass through as long as we are not associated
> or we
> -        * do not have dtim period information */
> -       if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod)
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
> +               cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_PROMISC |
> +                   IWM_MAC_FILTER_IN_CONTROL_AND_MGMT |
> +                   IWM_MAC_FILTER_IN_BEACON |
> +                   IWM_MAC_FILTER_IN_PROBE_REQUEST |
> +                   IWM_MAC_FILTER_IN_CRC32);
> +       } else if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod)
> +               /*
> +                * Allow beacons to pass through as long as we are not
> +                * associated or we do not have dtim period information.
> +                */
>                 cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_BEACON);
>         else
>                 iwm_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc);
> @@ -5564,7 +5591,10 @@ iwm_auth(struct iwm_softc *sc)
>
>         splassert(IPL_NET);
>
> -       sc->sc_phyctxt[0].channel = in->in_ni.ni_chan;
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR)
> +               sc->sc_phyctxt[0].channel = ic->ic_ibss_chan;
> +       else
> +               sc->sc_phyctxt[0].channel = in->in_ni.ni_chan;
>         err = iwm_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0], 1, 1,
>             IWM_FW_CTXT_ACTION_MODIFY, 0);
>         if (err) {
> @@ -5598,6 +5628,9 @@ iwm_auth(struct iwm_softc *sc)
>         }
>         sc->sc_flags |= IWM_FLAG_STA_ACTIVE;
>
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR)
> +               return 0;
> +
>         /*
>          * Prevent the FW from wandering off channel during association
>          * by "protecting" the session with a time event.
> @@ -5728,8 +5761,16 @@ iwm_run(struct iwm_softc *sc)
>
>         splassert(IPL_NET);
>
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
> +               /* Add a MAC context and a sniffing STA. */
> +               err = iwm_auth(sc);
> +               if (err)
> +                       return err;
> +       }
> +
>         /* Configure Rx chains for MIMO. */
> -       if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) &&
> +       if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
> +           (in->in_ni.ni_flags & IEEE80211_NODE_HT)) &&
>             !sc->sc_nvm.sku_cap_mimo_disable) {
>                 err = iwm_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0],
>                     2, 2, IWM_FW_CTXT_ACTION_MODIFY, 0);
> @@ -5797,6 +5838,11 @@ iwm_run(struct iwm_softc *sc)
>         ieee80211_amrr_node_init(&sc->sc_amrr, &in->in_amn);
>         ieee80211_mira_node_init(&in->in_mn);
>
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
> +               iwm_led_blink_start(sc);
> +               return 0;
> +       }
> +
>         /* Start at lowest available bit-rate, AMRR will raise. */
>         in->in_ni.ni_txrate = 0;
>         in->in_ni.ni_txmcs = 0;
> @@ -5817,6 +5863,9 @@ iwm_run_stop(struct iwm_softc *sc)
>
>         splassert(IPL_NET);
>
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR)
> +               iwm_led_blink_stop(sc);
> +
>         err = iwm_sf_config(sc, IWM_SF_INIT_OFF);
>         if (err)
>                 return err;
> @@ -6565,6 +6614,12 @@ iwm_init(struct ifnet *ifp)
>         ifq_clr_oactive(&ifp->if_snd);
>         ifp->if_flags |= IFF_RUNNING;
>
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
> +               ic->ic_bss->ni_chan = ic->ic_ibss_chan;
> +               ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
> +               return 0;
> +       }
> +
>         ieee80211_begin_scan(ifp);
>
>         /*
> @@ -7894,6 +7949,7 @@ iwm_attach(struct device *parent, struct
>             IEEE80211_C_RSN |           /* WPA/RSN */
>             IEEE80211_C_SCANALL |       /* device scans all channels at
> once */
>             IEEE80211_C_SCANALLBAND |   /* device scans all bands at once
> */
> +           IEEE80211_C_MONITOR |       /* monitor mode supported */
>             IEEE80211_C_SHSLOT |        /* short slot time supported */
>             IEEE80211_C_SHPREAMBLE;     /* short preamble supported */
>
>
>

Reply via email to