net/wireless/mlme.c

Source file repositories/reference/linux-study-clean/net/wireless/mlme.c

File Facts

System
Linux kernel
Corpus path
net/wireless/mlme.c
Extension
.c
Size
39115 bytes
Lines
1435
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cfg80211_mgmt_registration {
	struct list_head list;
	struct wireless_dev *wdev;

	u32 nlportid;

	int match_len;

	__le16 frame_type;

	bool multicast_rx;

	u8 match[];
};

static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
{
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
	struct wireless_dev *tmp;
	struct cfg80211_mgmt_registration *reg;
	struct mgmt_frame_regs upd = {};

	lockdep_assert_held(&rdev->wiphy.mtx);

	spin_lock_bh(&rdev->mgmt_registrations_lock);
	if (!wdev->mgmt_registrations_need_update) {
		spin_unlock_bh(&rdev->mgmt_registrations_lock);
		return;
	}

	rcu_read_lock();
	list_for_each_entry_rcu(tmp, &rdev->wiphy.wdev_list, list) {
		list_for_each_entry(reg, &tmp->mgmt_registrations, list) {
			u32 mask = BIT(le16_to_cpu(reg->frame_type) >> 4);
			u32 mcast_mask = 0;

			if (reg->multicast_rx)
				mcast_mask = mask;

			upd.global_stypes |= mask;
			upd.global_mcast_stypes |= mcast_mask;

			if (tmp == wdev) {
				upd.interface_stypes |= mask;
				upd.interface_mcast_stypes |= mcast_mask;
			}
		}
	}
	rcu_read_unlock();

	wdev->mgmt_registrations_need_update = 0;
	spin_unlock_bh(&rdev->mgmt_registrations_lock);

	rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
}

void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
{
	struct cfg80211_registered_device *rdev;
	struct wireless_dev *wdev;

	rdev = container_of(wk, struct cfg80211_registered_device,
			    mgmt_registrations_update_wk);

	guard(wiphy)(&rdev->wiphy);

	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
		cfg80211_mgmt_registrations_update(wdev);
}

int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
				u16 frame_type, const u8 *match_data,
				int match_len, bool multicast_rx,
				struct netlink_ext_ack *extack)
{
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
	struct cfg80211_mgmt_registration *reg, *nreg;
	int err = 0;
	u16 mgmt_type;
	bool update_multicast = false;

	if (!wdev->wiphy->mgmt_stypes)
		return -EOPNOTSUPP;

	if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) {
		NL_SET_ERR_MSG(extack, "frame type not management");
		return -EINVAL;
	}

	if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) {

Annotation

Implementation Notes