hostapd: add radius WISPr rate control AVPs
authorJohn Crispin <john@phrozen.org>
Fri, 29 Nov 2024 07:40:08 +0000 (08:40 +0100)
committerJohn Crispin <john@phrozen.org>
Mon, 2 Dec 2024 12:55:36 +0000 (13:55 +0100)
This allows a radius server to send AVPs for client rate control inside the
accept message. Further add the ratelimits to the sta-authorized ubus
notification.

Signed-off-by: John Crispin <john@phrozen.org>
package/network/services/hostapd/patches/763-radius-wispr.patch [new file with mode: 0644]
package/network/services/hostapd/src/src/ap/ubus.c

diff --git a/package/network/services/hostapd/patches/763-radius-wispr.patch b/package/network/services/hostapd/patches/763-radius-wispr.patch
new file mode 100644 (file)
index 0000000..da81a62
--- /dev/null
@@ -0,0 +1,105 @@
+--- a/src/ap/ieee802_1x.c
++++ b/src/ap/ieee802_1x.c
+@@ -2035,6 +2035,25 @@ static int ieee802_1x_update_vlan(struct
+ }
+ #endif /* CONFIG_NO_VLAN */
++static int ieee802_1x_update_wispr(struct hostapd_data *hapd,
++                                 struct sta_info *sta,
++                                 struct radius_msg *msg)
++{
++      memset(sta->bandwidth, 0, sizeof(sta->bandwidth));
++
++      if (radius_msg_get_wispr(msg, sta->bandwidth))
++              return 0;
++
++      if (!sta->bandwidth[0] && !sta->bandwidth[1])
++              return 0;
++
++      hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
++                     HOSTAPD_LEVEL_INFO,
++                     "received wispr bandwidth from RADIUS server %d/%d",
++                     sta->bandwidth[0], sta->bandwidth[1]);
++
++      return 0;
++}
+ /**
+  * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server
+@@ -2151,6 +2170,7 @@ ieee802_1x_receive_auth(struct radius_ms
+               ieee802_1x_check_hs20(hapd, sta, msg,
+                                     session_timeout_set ?
+                                     (int) session_timeout : -1);
++              ieee802_1x_update_wispr(hapd, sta, msg);
+               break;
+       case RADIUS_CODE_ACCESS_REJECT:
+               sm->eap_if->aaaFail = true;
+--- a/src/ap/sta_info.h
++++ b/src/ap/sta_info.h
+@@ -95,6 +95,7 @@ struct sta_info {
+       u8 supported_rates[WLAN_SUPP_RATES_MAX];
+       int supported_rates_len;
+       u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
++      u32 bandwidth[2];
+ #ifdef CONFIG_MESH
+       enum mesh_plink_state plink_state;
+--- a/src/radius/radius.c
++++ b/src/radius/radius.c
+@@ -1339,6 +1339,35 @@ radius_msg_get_cisco_keys(struct radius_
+       return keys;
+ }
++#define RADIUS_VENDOR_ID_WISPR        14122
++#define RADIUS_WISPR_AV_BW_UP 7
++#define RADIUS_WISPR_AV_BW_DOWN       8
++
++int
++radius_msg_get_wispr(struct radius_msg *msg, u32 *bandwidth)
++{
++      int i;
++
++      if (msg == NULL || bandwidth == NULL)
++              return 1;
++
++      for (i = 0; i < 2; i++) {
++              size_t keylen;
++              u8 *key;
++
++              key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_WISPR,
++                                               RADIUS_WISPR_AV_BW_UP + i, &keylen);
++              if (!key)
++                      continue;
++
++              if (keylen == 4)
++                      bandwidth[i] = ntohl(*((u32 *)key));
++              os_free(key);
++      }
++
++      return 0;
++}
++
+ int radius_msg_add_mppe_keys(struct radius_msg *msg,
+                            const u8 *req_authenticator,
+--- a/src/radius/radius.h
++++ b/src/radius/radius.h
+@@ -233,6 +233,10 @@ enum {
+       RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10,
+ };
++#define RADIUS_VENDOR_ID_WISPR        14122
++#define RADIUS_WISPR_AV_BW_UP 7
++#define RADIUS_WISPR_AV_BW_DOWN       8
++
+ #ifdef _MSC_VER
+ #pragma pack(pop)
+ #endif /* _MSC_VER */
+@@ -306,6 +310,7 @@ radius_msg_get_ms_keys(struct radius_msg
+ struct radius_ms_mppe_keys *
+ radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
+                         const u8 *secret, size_t secret_len);
++int radius_msg_get_wispr(struct radius_msg *msg, u32 *bandwidth);
+ int radius_msg_add_mppe_keys(struct radius_msg *msg,
+                            const u8 *req_authenticator,
+                            const u8 *secret, size_t secret_len,
index 22567207556599fde8c324641ce5dda2b02e7ebc..b02615835770d00b1292924f23c04926f1786c40 100644 (file)
@@ -1876,6 +1876,13 @@ void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *
        blobmsg_add_string(&b, "ifname", hapd->conf->iface);
        if (auth_alg)
                blobmsg_add_string(&b, "auth-alg", auth_alg);
+       if (sta->bandwidth[0] || sta->bandwidth[1]) {
+               void *r = blobmsg_open_array(&b, "rate-limit");
+
+               blobmsg_add_u32(&b, "", sta->bandwidth[0]);
+               blobmsg_add_u32(&b, "", sta->bandwidth[1]);
+               blobmsg_close_array(&b, r);
+       }
 
        ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1);
 }