/* SPDX-License-Identifier: GPL-3.0-only */ /* Versioned persistent configuration for the station mDNS hostname. */ #include "mdns_config.h" #include #include #include "esp_mac.h" #include "nvs.h" #include "nvs_flash.h" _Static_assert(sizeof(mdns_config_t) == MDNS_CONFIG_BLOB_SIZE, "mDNS config schema size changed"); static bool suffix_character_is_valid(char character) { return (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9') || character == '-'; } void mdns_config_defaults(mdns_config_t *config) { static const char hex[] = "0123456789abcdef"; uint8_t mac[6] = {0}; if (config == NULL) { return; } memset(config, 0, sizeof(*config)); config->schema_version = MDNS_CONFIG_SCHEMA_VERSION; config->blob_size = MDNS_CONFIG_BLOB_SIZE; if (esp_read_mac(mac, ESP_MAC_WIFI_STA) != ESP_OK) { return; } for (size_t index = 0U; index < sizeof(mac); ++index) { config->suffix[index * 2U] = hex[mac[index] >> 4U]; config->suffix[index * 2U + 1U] = hex[mac[index] & 0x0fU]; } config->suffix_len = sizeof(mac) * 2U; } esp_err_t mdns_config_validate(const mdns_config_t *config) { if (config == NULL || config->schema_version != MDNS_CONFIG_SCHEMA_VERSION || config->blob_size != MDNS_CONFIG_BLOB_SIZE || config->suffix_len == 0U || config->suffix_len > MDNS_CONFIG_SUFFIX_MAX_LEN || config->reserved != 0U || config->suffix[config->suffix_len] != '\0') { return ESP_ERR_INVALID_ARG; } if (config->suffix[0] == '-' || config->suffix[config->suffix_len - 1U] == '-') { return ESP_ERR_INVALID_ARG; } for (size_t index = 0U; index < MDNS_CONFIG_SUFFIX_MAX_LEN; ++index) { if (index < config->suffix_len) { if (!suffix_character_is_valid(config->suffix[index])) { return ESP_ERR_INVALID_ARG; } } else if (config->suffix[index] != '\0') { return ESP_ERR_INVALID_ARG; } } return ESP_OK; } esp_err_t mdns_config_load(mdns_config_t *config, bool *used_stored_config) { if (config == NULL || used_stored_config == NULL) { return ESP_ERR_INVALID_ARG; } mdns_config_defaults(config); *used_stored_config = false; if (mdns_config_validate(config) != ESP_OK) { return ESP_FAIL; } esp_err_t error = nvs_flash_init(); if (error != ESP_OK) { return error; } nvs_handle_t handle; error = nvs_open(MDNS_CONFIG_NVS_NAMESPACE, NVS_READONLY, &handle); if (error == ESP_ERR_NVS_NOT_FOUND) { return ESP_OK; } if (error != ESP_OK) { return error; } size_t size = 0U; error = nvs_get_blob(handle, MDNS_CONFIG_NVS_BLOB_KEY, NULL, &size); if (error == ESP_ERR_NVS_NOT_FOUND || error == ESP_ERR_NVS_TYPE_MISMATCH || (error == ESP_OK && size != sizeof(*config))) { nvs_close(handle); return ESP_OK; } if (error != ESP_OK) { nvs_close(handle); return error; } mdns_config_t stored = {0}; error = nvs_get_blob(handle, MDNS_CONFIG_NVS_BLOB_KEY, &stored, &size); nvs_close(handle); if (error == ESP_ERR_NVS_INVALID_LENGTH) { return ESP_OK; } if (error != ESP_OK) { return error; } if (size == sizeof(stored) && mdns_config_validate(&stored) == ESP_OK) { *config = stored; *used_stored_config = true; } return ESP_OK; } esp_err_t mdns_config_save(const mdns_config_t *config) { esp_err_t error = mdns_config_validate(config); if (error != ESP_OK) { return error; } error = nvs_flash_init(); if (error != ESP_OK) { return error; } nvs_handle_t handle; error = nvs_open(MDNS_CONFIG_NVS_NAMESPACE, NVS_READWRITE, &handle); if (error != ESP_OK) { return error; } error = nvs_set_blob(handle, MDNS_CONFIG_NVS_BLOB_KEY, config, sizeof(*config)); if (error == ESP_OK) { error = nvs_commit(handle); } nvs_close(handle); return error; } esp_err_t mdns_config_reset_storage(void) { mdns_config_t config; mdns_config_defaults(&config); return mdns_config_save(&config); }