]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
GAS: Prefer unique dialog token value across all pending queries
authorJouni Malinen <jouni.malinen@oss.qualcomm.com>
Wed, 27 Aug 2025 09:58:24 +0000 (12:58 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 27 Aug 2025 09:58:24 +0000 (12:58 +0300)
Previously, the dialog token for a new GAS query was selected in a
manner that would be random and unique for the specific peer. However,
with the introduction of support for AP MLDs, multiple different
addresses could have ended up using the same dialog token value for the
same peer.

Make duplicate dialog token uses for AP MLDs less likely by first trying
to find a random dialog token value that is not used in any pending GAS
query for any peer. Only if that does not succeed, fall back to unique
value for the specific peer address to maintain previous behavior.

Signed-off-by: Jouni Malinen <jouni.malinen@oss.qualcomm.com>
wpa_supplicant/gas_query.c

index b3ebac1689946b59add4d6026fb8faca3d8eeac1..63424505f32e35a57f5af4625b59b6f40343c68d 100644 (file)
@@ -685,7 +685,7 @@ static int gas_query_dialog_token_available(struct gas_query *gas,
 {
        struct gas_query_pending *q;
        dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
-               if (ether_addr_equal(dst, q->addr) &&
+               if ((!dst || ether_addr_equal(dst, q->addr)) &&
                    dialog_token == q->dialog_token)
                        return 0;
        }
@@ -756,6 +756,18 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
         * token by checking random values. Use a limit on the number of
         * iterations to handle the unexpected case of large number of pending
         * queries cleanly. */
+       for (i = 0; i < 256; i++) {
+               /* Get a random number and check if it is not used in any
+                * pending entry for any peer. */
+               if (os_get_random(&dialog_token, sizeof(dialog_token)) < 0)
+                       break;
+               if (gas_query_dialog_token_available(gas, NULL, dialog_token))
+                       return dialog_token;
+       }
+
+       /* In the highly unlikely case there were so many pending queries that
+        * no available unused dialog token was available. Try to find one that
+        * is unique for this specific peer. */
        for (i = 0; i < 256; i++) {
                /* Get a random number and check if the slot is available */
                if (os_get_random(&dialog_token, sizeof(dialog_token)) < 0)