[wireguard] Keep allowed IPs in a shared flash table (#20087)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
J. Nick Koston
2026-10-09 09:20:46 -10:00
committed by GitHub
co-authored by pre-commit-ci-lite[bot]
parent f7b80e6d44
commit 5cd7bf5993
5 changed files with 65 additions and 17 deletions
+11 -8
View File
@@ -121,16 +121,19 @@ async def to_code(config):
)
)
# Shared flash table ended by an empty entry, so the component stores only a pointer.
entries = [
cg.StructInitializer(
AllowedIP,
("ip", str(ip.network_address)),
("netmask", str(ip.netmask)),
)
for ip in allowed_ips
]
end = cg.StructInitializer(AllowedIP, ("ip", cg.nullptr), ("netmask", cg.nullptr))
cg.add(
var.set_allowed_ips(
[
cg.StructInitializer(
AllowedIP,
("ip", str(ip.network_address)),
("netmask", str(ip.netmask)),
)
for ip in allowed_ips
]
cg.shared_progmem_array("wireguard_allowed_ips", AllowedIP, [*entries, end])
)
)
+4 -4
View File
@@ -154,8 +154,8 @@ void Wireguard::dump_config() {
(this->preshared_key_ != nullptr ? preshared_key_masked : LOG_STR_LITERAL("NOT IN USE")));
// clang-format on
ESP_LOGCONFIG(TAG, " Peer Allowed IPs:");
for (const AllowedIP &allowed_ip : this->allowed_ips_) {
ESP_LOGCONFIG(TAG, " - %s/%s", allowed_ip.ip, allowed_ip.netmask);
for (const AllowedIP *it = this->allowed_ips_; it != nullptr && it->ip != nullptr; it++) {
ESP_LOGCONFIG(TAG, " - %s/%s", it->ip, it->netmask);
}
ESP_LOGCONFIG(TAG, " Peer Persistent Keepalive: %d%s", this->keepalive_,
(this->keepalive_ > 0 ? LOG_STR_LITERAL("s") : LOG_STR_LITERAL(" (DISABLED)")));
@@ -249,8 +249,8 @@ void Wireguard::start_connection_() {
ESP_LOGD(TAG, "Configuring allowed IPs list");
bool allowed_ips_ok = true;
for (const AllowedIP &ip : this->allowed_ips_) {
allowed_ips_ok &= (esp_wireguard_add_allowed_ip(&(this->wg_ctx_), ip.ip, ip.netmask) == ESP_OK);
for (const AllowedIP *it = this->allowed_ips_; it != nullptr && it->ip != nullptr; it++) {
allowed_ips_ok &= (esp_wireguard_add_allowed_ip(&(this->wg_ctx_), it->ip, it->netmask) == ESP_OK);
}
if (allowed_ips_ok) {
+3 -5
View File
@@ -2,7 +2,6 @@
#include "esphome/core/defines.h"
#ifdef USE_WIREGUARD
#include <ctime>
#include <initializer_list>
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
@@ -58,9 +57,8 @@ class Wireguard final : public PollingComponent {
void set_peer_public_key(const std::string &key) = delete;
void set_preshared_key(const std::string &key) = delete;
void set_allowed_ips(std::initializer_list<AllowedIP> ips) { this->allowed_ips_ = ips; }
/// Prevent accidental use of std::string which would dangle
void set_allowed_ips(std::initializer_list<std::tuple<std::string, std::string>> ips) = delete;
/// Table ended by an entry with a null ip; must outlive the component.
void set_allowed_ips(const AllowedIP *ips) { this->allowed_ips_ = ips; }
void set_keepalive(const uint16_t seconds) { this->keepalive_ = seconds; }
void set_reboot_timeout(const uint32_t seconds) { this->reboot_timeout_ = seconds; }
@@ -105,7 +103,7 @@ class Wireguard final : public PollingComponent {
const char *peer_public_key_{nullptr};
const char *preshared_key_{nullptr};
FixedVector<AllowedIP> allowed_ips_;
const AllowedIP *allowed_ips_{nullptr};
uint16_t peer_port_;
uint16_t keepalive_;
@@ -0,0 +1,26 @@
esphome:
name: test
esp32:
board: esp32dev
framework:
type: esp-idf
wifi:
ssid: test
password: password1
time:
- platform: sntp
id: sntp_time
wireguard:
time_id: sntp_time
address: 172.16.34.100
netmask: 255.255.255.0
private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8=
peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc=
peer_endpoint: wg.server.example
peer_allowed_ips:
- 172.16.34.0/24
- 192.168.0.0/16
@@ -0,0 +1,21 @@
"""Tests for the wireguard allowed IPs codegen."""
from collections.abc import Callable
from pathlib import Path
def test_allowed_ips_are_a_progmem_table(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""Allowed IPs live in a flash table ended by an empty entry instead of a heap vector."""
main_cpp = generate_main(component_config_path("allowed_ips.yaml"))
table = main_cpp.split(
"wireguard::AllowedIP wireguard_allowed_ips[] PROGMEM = ", 1
)[1]
table = table.split(";", 1)[0]
assert '.ip = "172.16.34.0"' in table
assert '.netmask = "255.255.0.0"' in table
assert ".ip = nullptr" in table
assert "->set_allowed_ips(wireguard_allowed_ips);" in main_cpp