Message ID | 20221209152836.1667196-1-alvin@pqrs.dk (mailing list archive) |
---|---|
State | Awaiting Upstream |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [next] wifi: nl80211: emit CMD_START_AP on multicast group when an AP is started | expand |
On Fri, 2022-12-09 at 16:28 +0100, Alvin Šipraga wrote: > > This is problematic because it is possible that the network > configuration that should be applied is a function of the AP's > properties such as SSID (cf. SSID= in systemd.network(5)). As > illustrated in the above diagram, it may be that the AP with SSID "bar" > ends up being configured as though it had SSID "foo". > You might not care if you want the SSID, but it still seems wrong: > +static void nl80211_send_ap_started(struct wireless_dev *wdev) > +{ > + struct wiphy *wiphy = wdev->wiphy; > + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); > + struct sk_buff *msg; > + void *hdr; > + > + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); > + if (!msg) > + return; > + > + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_START_AP); > + if (!hdr) > + goto out; > + > + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || > + nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || > + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), > + NL80211_ATTR_PAD) || > + (wdev->u.ap.ssid_len && > + nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len, > + wdev->u.ap.ssid))) > + goto out; > + > + genlmsg_end(msg, hdr); > + > + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, > + NL80211_MCGRP_MLME, GFP_KERNEL); > + return; > +out: > + nlmsg_free(msg); > +} This has no indication of the link, but with multi-link you could actually be sending this event multiple times to userspace on the same netdev. > static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) > { > struct cfg80211_registered_device *rdev = info->user_ptr[0]; > @@ -6050,6 +6083,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) > > if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) > wdev->conn_owner_nlportid = info->snd_portid; > + > + nl80211_send_ap_started(wdev); > } because this can be called multiple times, once for each link. Seems like you should include the link ID or something? johannes
Hi Johannes, On Wed, Jan 18, 2023 at 05:26:19PM +0100, Johannes Berg wrote: > On Fri, 2022-12-09 at 16:28 +0100, Alvin Šipraga wrote: > > > > This is problematic because it is possible that the network > > configuration that should be applied is a function of the AP's > > properties such as SSID (cf. SSID= in systemd.network(5)). As > > illustrated in the above diagram, it may be that the AP with SSID "bar" > > ends up being configured as though it had SSID "foo". > > > > You might not care if you want the SSID, but it still seems wrong: > > > +static void nl80211_send_ap_started(struct wireless_dev *wdev) > > +{ > > + struct wiphy *wiphy = wdev->wiphy; > > + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); > > + struct sk_buff *msg; > > + void *hdr; > > + > > + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); > > + if (!msg) > > + return; > > + > > + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_START_AP); > > + if (!hdr) > > + goto out; > > + > > + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || > > + nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || > > + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), > > + NL80211_ATTR_PAD) || > > + (wdev->u.ap.ssid_len && > > + nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len, > > + wdev->u.ap.ssid))) > > + goto out; > > + > > + genlmsg_end(msg, hdr); > > + > > + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, > > + NL80211_MCGRP_MLME, GFP_KERNEL); > > + return; > > +out: > > + nlmsg_free(msg); > > +} > > This has no indication of the link, but with multi-link you could > actually be sending this event multiple times to userspace on the same > netdev. > > > static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) > > { > > struct cfg80211_registered_device *rdev = info->user_ptr[0]; > > @@ -6050,6 +6083,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) > > > > if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) > > wdev->conn_owner_nlportid = info->snd_portid; > > + > > + nl80211_send_ap_started(wdev); > > } > > because this can be called multiple times, once for each link. > > Seems like you should include the link ID or something? Thanks for your review, you are quite right. I didn't give much thought to MLO as I am not too familiar with it. Is something like the below what you are looking for? Speaking of which: I drew inspiration from nl80211_send_ap_stopped() which see also doesn't include the link ID. Would you like me to include a second patch in v2 which adds the link ID to that function along the same lines? Kind regards, Alvin -------------->8---------------------------------- diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ba4965f035b2..5720ffcbecc4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5770,7 +5770,7 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, } } -static void nl80211_send_ap_started(struct wireless_dev *wdev) +static void nl80211_send_ap_started(struct wireless_dev *wdev, unsigned int link_id) { struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); @@ -5791,7 +5791,9 @@ static void nl80211_send_ap_started(struct wireless_dev *wdev) NL80211_ATTR_PAD) || (wdev->u.ap.ssid_len && nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len, - wdev->u.ap.ssid))) + wdev->u.ap.ssid)) || + (wdev->valid_links && + nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))) goto out; genlmsg_end(msg, hdr); @@ -6084,7 +6086,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) wdev->conn_owner_nlportid = info->snd_portid; - nl80211_send_ap_started(wdev); + nl80211_send_ap_started(wdev, link_id); } out_unlock: wdev_unlock(wdev);
Hi, > > Seems like you should include the link ID or something? > > Thanks for your review, you are quite right. I didn't give much thought > to MLO as I am not too familiar with it. Is something like the below > what you are looking for? Yes, that looks good. > Speaking of which: I drew inspiration from nl80211_send_ap_stopped() > which see also doesn't include the link ID. Would you like me to include > a second patch in v2 which adds the link ID to that function along the > same lines? Maybe have that as a separate patch, but yeah, good idea - thanks for looking! johannes
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 33a82ecab9d5..323b7e40d855 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5770,6 +5770,39 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, } } +static void nl80211_send_ap_started(struct wireless_dev *wdev) +{ + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_START_AP); + if (!hdr) + goto out; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD) || + (wdev->u.ap.ssid_len && + nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len, + wdev->u.ap.ssid))) + goto out; + + genlmsg_end(msg, hdr); + + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, + NL80211_MCGRP_MLME, GFP_KERNEL); + return; +out: + nlmsg_free(msg); +} + static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -6050,6 +6083,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) wdev->conn_owner_nlportid = info->snd_portid; + + nl80211_send_ap_started(wdev); } out_unlock: wdev_unlock(wdev);