1 /* 2 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "qdf_types.h" 18 #include <net/cfg80211.h> 19 #include "wlan_cfg80211.h" 20 #include "wlan_objmgr_psoc_obj.h" 21 #include "wlan_objmgr_pdev_obj.h" 22 #include "wlan_objmgr_vdev_obj.h" 23 #include "os_if_dp_local_pkt_capture.h" 24 #include "wlan_dp_ucfg_api.h" 25 #include "wlan_dp_main.h" 26 #include "cdp_txrx_mon.h" 27 #include "wlan_policy_mgr_api.h" 28 #include <ol_defines.h> 29 #include "wlan_osif_priv.h" 30 31 /* Short name for QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE command */ 32 #define SET_MONITOR_MODE_CONFIG_MAX \ 33 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX 34 #define SET_MONITOR_MODE_INVALID \ 35 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID 36 #define SET_MONITOR_MODE_DATA_TX_FRAME_TYPE \ 37 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE 38 #define SET_MONITOR_MODE_DATA_RX_FRAME_TYPE \ 39 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE 40 #define SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE \ 41 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE 42 #define SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE \ 43 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE 44 #define SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE \ 45 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE 46 #define SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE \ 47 QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE 48 49 /* Short name for QCA_NL80211_VENDOR_SUBCMD_GET_MONITOR_MODE command */ 50 #define GET_MONITOR_MODE_CONFIG_MAX \ 51 QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_MAX 52 #define GET_MONITOR_MODE_INVALID \ 53 QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_INVALID 54 #define GET_MONITOR_MODE_STATUS \ 55 QCA_WLAN_VENDOR_ATTR_GET_MONITOR_MODE_STATUS 56 57 #define MGMT_FRAME_TYPE 0 58 #define DATA_FRAME_TYPE 1 59 #define CTRL_FRAME_TYPE 2 60 61 const struct nla_policy 62 set_monitor_mode_policy[SET_MONITOR_MODE_CONFIG_MAX + 1] = { 63 [SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] = { .type = NLA_U32 }, 64 [SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] = { .type = NLA_U32 }, 65 [SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] = { .type = NLA_U32 }, 66 [SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] = { .type = NLA_U32 }, 67 [SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] = { .type = NLA_U32 }, 68 [SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] = { .type = NLA_U32 }, 69 }; 70 71 static 72 bool os_if_local_pkt_capture_concurrency_allowed(struct wlan_objmgr_psoc *psoc) 73 { 74 uint32_t num_connections, sta_count; 75 76 num_connections = policy_mgr_get_connection_count(psoc); 77 osif_debug("Total connections %d", num_connections); 78 79 /* 80 * No connections, local packet capture is allowed 81 * Only 1 connection and its STA, then local packet capture is allowed 82 * 2+ port concurrency, local packet capture is not allowed 83 */ 84 if (!num_connections) 85 return true; 86 87 if (num_connections > 1) 88 return false; 89 90 sta_count = policy_mgr_mode_specific_connection_count(psoc, 91 PM_STA_MODE, 92 NULL); 93 osif_debug("sta_count %d", sta_count); 94 if (sta_count == 1) 95 return true; 96 97 return false; 98 } 99 100 bool os_if_lpc_mon_intf_creation_allowed(struct wlan_objmgr_psoc *psoc) 101 { 102 if (ucfg_dp_is_local_pkt_capture_enabled(psoc)) { 103 if (policy_mgr_is_mlo_sta_present(psoc)) { 104 osif_err("MLO STA present, lpc interface creation not allowed"); 105 return false; 106 } 107 108 if (!os_if_local_pkt_capture_concurrency_allowed(psoc)) { 109 osif_err("Concurrency check failed, lpc interface creation not allowed"); 110 return false; 111 } 112 } 113 114 return true; 115 } 116 117 static QDF_STATUS os_if_start_capture_allowed(struct wlan_objmgr_vdev *vdev) 118 { 119 enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev); 120 struct wlan_objmgr_psoc *psoc; 121 122 psoc = wlan_vdev_get_psoc(vdev); 123 if (!psoc) { 124 osif_err("NULL psoc"); 125 return QDF_STATUS_E_INVAL; 126 } 127 128 if (!ucfg_dp_is_local_pkt_capture_enabled(psoc)) { 129 osif_warn("local pkt capture feature not enabled"); 130 return QDF_STATUS_E_NOSUPPORT; 131 } 132 133 if (mode != QDF_MONITOR_MODE) { 134 osif_err("Operation not permitted in mode: %d", mode); 135 return QDF_STATUS_E_PERM; 136 } 137 138 /* 139 * Whether STA interface is present or not, is already checked 140 * while creating monitor interface 141 */ 142 143 if (policy_mgr_is_mlo_sta_present(psoc)) { 144 osif_err("MLO STA present, start capture is not permitted"); 145 return QDF_STATUS_E_PERM; 146 } 147 148 if (!os_if_local_pkt_capture_concurrency_allowed(psoc)) { 149 osif_err("Concurrency check failed, start capture not allowed"); 150 return QDF_STATUS_E_PERM; 151 } 152 153 return QDF_STATUS_SUCCESS; 154 } 155 156 static QDF_STATUS os_if_stop_capture_allowed(struct wlan_objmgr_vdev *vdev) 157 { 158 enum QDF_OPMODE mode; 159 struct wlan_objmgr_psoc *psoc; 160 void *soc; 161 162 soc = cds_get_context(QDF_MODULE_ID_SOC); 163 if (!soc) 164 return QDF_STATUS_E_INVAL; 165 166 psoc = wlan_vdev_get_psoc(vdev); 167 if (!psoc) { 168 osif_err("NULL psoc"); 169 return QDF_STATUS_E_INVAL; 170 } 171 172 mode = wlan_vdev_mlme_get_opmode(vdev); 173 if (mode != QDF_MONITOR_MODE) { 174 osif_warn("Operation not permitted in mode: %d", mode); 175 return QDF_STATUS_E_PERM; 176 } 177 178 if (!ucfg_dp_is_local_pkt_capture_enabled(psoc)) { 179 osif_err("local pkt capture feature not enabled"); 180 return QDF_STATUS_E_NOSUPPORT; 181 } 182 183 if (!cdp_is_local_pkt_capture_running(soc, OL_TXRX_PDEV_ID)) { 184 osif_debug("local pkt capture not running, no need to stop"); 185 return QDF_STATUS_E_PERM; 186 } 187 188 return QDF_STATUS_SUCCESS; 189 } 190 191 static 192 QDF_STATUS os_if_dp_local_pkt_capture_start(struct wlan_objmgr_vdev *vdev, 193 struct nlattr **tb) 194 { 195 QDF_STATUS status; 196 struct cdp_monitor_filter filter = {0}; 197 uint32_t pkt_type = 0, val; 198 void *soc; 199 200 status = os_if_start_capture_allowed(vdev); 201 if (QDF_IS_STATUS_ERROR(status)) 202 goto error; 203 204 soc = cds_get_context(QDF_MODULE_ID_SOC); 205 if (!soc) 206 return QDF_STATUS_E_INVAL; 207 208 if (tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]) { 209 val = nla_get_u32(tb[SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]); 210 211 if (val != QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL) { 212 osif_err("Invalid value: %d Expected: %d", 213 val, 214 QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL); 215 status = QDF_STATUS_E_INVAL; 216 goto error; 217 } 218 pkt_type |= BIT(MGMT_FRAME_TYPE); 219 } 220 221 if (tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]) { 222 val = nla_get_u32(tb[SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]); 223 224 if (val != QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL) { 225 osif_err("Invalid value: %d Expected: %d", 226 val, 227 QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL); 228 status = QDF_STATUS_E_INVAL; 229 goto error; 230 } 231 pkt_type |= BIT(MGMT_FRAME_TYPE); 232 } 233 234 if (tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]) { 235 val = nla_get_u32(tb[SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]); 236 237 if (val != QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL) { 238 osif_err("Invalid value: %d Expected: %d", 239 val, 240 QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL); 241 status = QDF_STATUS_E_INVAL; 242 goto error; 243 } 244 pkt_type |= BIT(DATA_FRAME_TYPE); 245 } 246 247 if (tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]) { 248 val = nla_get_u32(tb[SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]); 249 250 if (val != QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL) { 251 osif_err("Invalid value: %d Expected: %d", 252 val, 253 QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL); 254 status = QDF_STATUS_E_INVAL; 255 goto error; 256 } 257 pkt_type |= BIT(DATA_FRAME_TYPE); 258 } 259 260 if (tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]) { 261 val = nla_get_u32(tb[SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]); 262 263 if (val != QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL) { 264 osif_err("Invalid value: %d Expected: %d", 265 val, 266 QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL); 267 status = QDF_STATUS_E_INVAL; 268 goto error; 269 } 270 pkt_type |= BIT(CTRL_FRAME_TYPE); 271 } 272 273 if (tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]) { 274 val = nla_get_u32(tb[SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]); 275 276 if (val != QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL) { 277 osif_err("Invalid value: %d Expected: %d", 278 val, 279 QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL); 280 status = QDF_STATUS_E_INVAL; 281 goto error; 282 } 283 pkt_type |= BIT(CTRL_FRAME_TYPE); 284 } 285 286 if (pkt_type == 0) { 287 osif_err("Invalid config, pkt_type: %d", pkt_type); 288 status = QDF_STATUS_E_INVAL; 289 goto error; 290 } 291 osif_debug("start capture config pkt_type:0x%x", pkt_type); 292 293 filter.mode = MON_FILTER_PASS; 294 filter.fp_mgmt = pkt_type & BIT(MGMT_FRAME_TYPE) ? FILTER_MGMT_ALL : 0; 295 filter.fp_data = pkt_type & BIT(DATA_FRAME_TYPE) ? FILTER_DATA_ALL : 0; 296 filter.fp_ctrl = pkt_type & BIT(CTRL_FRAME_TYPE) ? FILTER_CTRL_ALL : 0; 297 298 status = cdp_start_local_pkt_capture(soc, OL_TXRX_PDEV_ID, &filter); 299 300 error: 301 return status; 302 } 303 304 QDF_STATUS os_if_dp_set_lpc_configure(struct wlan_objmgr_vdev *vdev, 305 const void *data, int data_len) 306 { 307 struct nlattr *tb[SET_MONITOR_MODE_CONFIG_MAX + 1]; 308 QDF_STATUS status = QDF_STATUS_SUCCESS; 309 310 if (wlan_cfg80211_nla_parse(tb, SET_MONITOR_MODE_CONFIG_MAX, 311 data, data_len, set_monitor_mode_policy)) { 312 osif_err("Invalid monitor attr"); 313 status = QDF_STATUS_E_INVAL; 314 goto error; 315 } 316 317 status = os_if_dp_local_pkt_capture_start(vdev, tb); 318 319 error: 320 return status; 321 } 322 323 QDF_STATUS os_if_dp_local_pkt_capture_stop(struct wlan_objmgr_vdev *vdev) 324 { 325 QDF_STATUS status; 326 void *soc; 327 328 soc = cds_get_context(QDF_MODULE_ID_SOC); 329 if (!soc || !vdev) 330 return QDF_STATUS_E_INVAL; 331 332 status = os_if_stop_capture_allowed(vdev); 333 if (QDF_IS_STATUS_ERROR(status)) 334 return status; 335 336 return cdp_stop_local_pkt_capture(soc, OL_TXRX_PDEV_ID); 337 } 338 339 QDF_STATUS os_if_dp_get_lpc_state(struct wlan_objmgr_vdev *vdev, 340 const void *data, int data_len) 341 { 342 struct wlan_objmgr_psoc *psoc; 343 struct vdev_osif_priv *osif_priv; 344 struct sk_buff *reply_skb; 345 uint32_t skb_len = NLMSG_HDRLEN, val; 346 QDF_STATUS status = QDF_STATUS_SUCCESS; 347 struct wireless_dev *wdev; 348 bool running; 349 void *soc; 350 351 psoc = wlan_vdev_get_psoc(vdev); 352 if (!psoc) 353 return QDF_STATUS_E_INVAL; 354 355 osif_priv = wlan_vdev_get_ospriv(vdev); 356 if (!osif_priv) { 357 osif_err("osif_priv is null"); 358 return QDF_STATUS_E_INVAL; 359 } 360 361 wdev = osif_priv->wdev; 362 if (!wdev) { 363 osif_err("wireless dev is null"); 364 return QDF_STATUS_E_INVAL; 365 } 366 367 soc = cds_get_context(QDF_MODULE_ID_SOC); 368 if (!soc) 369 return QDF_STATUS_E_INVAL; 370 371 /* Length of attribute QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_STATUS */ 372 skb_len += nla_total_size(sizeof(u32)); 373 374 reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wdev->wiphy, 375 skb_len); 376 if (!reply_skb) { 377 osif_err("alloc reply skb failed"); 378 return QDF_STATUS_E_NOMEM; 379 } 380 381 running = cdp_is_local_pkt_capture_running(soc, OL_TXRX_PDEV_ID); 382 val = running ? QCA_WLAN_VENDOR_MONITOR_MODE_CAPTURE_RUNNING : 383 QCA_WLAN_VENDOR_MONITOR_MODE_NO_CAPTURE_RUNNING; 384 385 if (nla_put_u32(reply_skb, GET_MONITOR_MODE_STATUS, val)) { 386 osif_err("nla put failed"); 387 status = QDF_STATUS_E_INVAL; 388 goto fail; 389 } 390 391 if (wlan_cfg80211_vendor_cmd_reply(reply_skb)) 392 status = QDF_STATUS_E_INVAL; 393 394 return status; 395 fail: 396 wlan_cfg80211_vendor_free_skb(reply_skb); 397 return status; 398 } 399 400