[PATCH v2 3/5] pmksa: add driver callbacks and pmksa_cache_free

James Prestwood
2025-02-13T20:18:27Z

In order to support fullmac drivers the PMKSA entries must be added
and removed from the kernel. To accomplish this a set of driver
callbacks will be added to the PMKSA module. In addition a new
pmksa_cache_free API will be added whos only purpose is to handle
the removal from the kernel.
---
src/pmksa.c | 38 ++++++++++++++++++++++++++++++++++++--
src/pmksa.h | 9 +++++++++
2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/pmksa.c b/src/pmksa.c
index bb539b85..a50c8208 100644
--- a/src/pmksa.c
+++ b/src/pmksa.c
@@ -40,6 +40,9 @@

static uint64_t dot11RSNAConfigPMKLifetime = 43200ULL * L_USEC_PER_SEC;
static uint32_t pmksa_cache_capacity = 255;
+static pmksa_cache_add_func_t driver_add;
+static pmksa_cache_remove_func_t driver_remove;
+static pmksa_cache_flush_func_t driver_flush;

struct min_heap {
struct pmksa **data;
@@ -142,7 +145,7 @@ int pmksa_cache_put(struct pmksa *pmksa)
l_debug("Adding entry with PMKID: "PMKID, PMKID_STR(pmksa->pmkid));

if (cache.used == cache.capacity) {
- l_free(cache.data[0]);
+ pmksa_cache_free(cache.data[0]);
cache.data[0] = pmksa;
__minheap_sift_down(cache.data, cache.used, 0, &ops);
return 0;
@@ -152,6 +155,9 @@ int pmksa_cache_put(struct pmksa *pmksa)
__minheap_sift_up(cache.data, cache.used, &ops);
cache.used += 1;

+ if (driver_add)
+ driver_add(pmksa);
+
return 0;
}

@@ -167,7 +173,7 @@ int pmksa_cache_expire(uint64_t cutoff)

for (i = 0; i < used; i++) {
if (cache.data[i]->expiration <= cutoff) {
- l_free(cache.data[i]);
+ pmksa_cache_free(cache.data[i]);
continue;
}

@@ -190,11 +196,30 @@ int pmksa_cache_flush(void)
{
uint32_t i;

+ /*
+ * The driver flush operation is done via a single kernel API call which
+ * is why below we use l_free instead of pmksa_cache_free as to not
+ * induce a DEL_PMKSA kernel call for each entry.
+ */
+ if (driver_flush)
+ driver_flush();
+
for (i = 0; i < cache.used; i++)
l_free(cache.data[i]);

memset(cache.data, 0, cache.capacity * sizeof(struct pmksa *));
cache.used = 0;
+
+ return 0;
+}
+
+int pmksa_cache_free(struct pmksa *pmksa)
+{
+ if (driver_remove)
+ driver_remove(pmksa);
+
+ l_free(pmksa);
+
return 0;
}

@@ -217,6 +242,15 @@ void __pmksa_set_config(const struct l_settings *config)
&pmksa_cache_capacity);
}

+void __pmksa_set_driver_callbacks(pmksa_cache_add_func_t add,
+ pmksa_cache_remove_func_t remove,
+ pmksa_cache_flush_func_t flush)
+{
+ driver_add = add;
+ driver_remove = remove;
+ driver_flush = flush;
+}
+
static int pmksa_init(void)
{
cache.capacity = pmksa_cache_capacity;
diff --git a/src/pmksa.h b/src/pmksa.h
index 67879309..6a624504 100644
--- a/src/pmksa.h
+++ b/src/pmksa.h
@@ -32,6 +32,10 @@ struct pmksa {
size_t pmk_len;
};

+typedef void (*pmksa_cache_add_func_t)(const struct pmksa *pmksa);
+typedef void (*pmksa_cache_remove_func_t)(const struct pmksa *pmksa);
+typedef void (*pmksa_cache_flush_func_t)(void);
+
struct pmksa **__pmksa_cache_get_all(uint32_t *out_n_entries);

struct pmksa *pmksa_cache_get(const uint8_t spa[static 6],
@@ -41,6 +45,11 @@ struct pmksa *pmksa_cache_get(const uint8_t spa[static 6],
int pmksa_cache_put(struct pmksa *pmksa);
int pmksa_cache_expire(uint64_t cutoff);
int pmksa_cache_flush(void);
+int pmksa_cache_free(struct pmksa *pmksa);

uint64_t pmksa_lifetime(void);
void __pmksa_set_config(const struct l_settings *config);
+
+void __pmksa_set_driver_callbacks(pmksa_cache_add_func_t add,
+ pmksa_cache_remove_func_t remove,
+ pmksa_cache_flush_func_t flush);
--
2.34.1