From 90e2f3452dc013ab8be397b1ceb0cb692b2c8751 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 25 Nov 2025 07:31:08 +0100 Subject: [PATCH] cloud_discovery: add standard FQDN fallback discovery Add discovery method that attempts to resolve a standard FQDN when DHCP discovery fails. This enables zero-touch provisioning in environments where administrators configure DNS without modifying DHCP infrastructure. The standard FQDN is configurable via STANDARD_FQDN constant (defaults to "openwifi.network"). Administrators can configure their local DNS to resolve this FQDN to their controller, allowing APs to discover the controller automatically. Discovery priority order: 1. EST enrollment (blocking) 2. DHCP discovery (Option 224/138) 3. Flash-based configuration 4. Standard FQDN resolution (NEW) 5. Cloud redirector service (internet-connected only) The implementation uses the resolv module for DNS queries, performing A record lookups. If resolution fails, discovery continues to the next method. The standard FQDN method integrates with the existing discovery block list mechanism to prevent repeated failed attempts. Note: The boguspriv dnsmasq option may prevent FQDNs from resolving to private IPs. Administrators should either use CG NAT Safe IP addresses (100.64.0.0/10) or configure dnsmasq with rebind-domain-ok exceptions. Signed-off-by: John Crispin --- .../files/usr/bin/cloud_discovery | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/feeds/tip/cloud_discovery/files/usr/bin/cloud_discovery b/feeds/tip/cloud_discovery/files/usr/bin/cloud_discovery index 3cae790d3..90ad334a2 100755 --- a/feeds/tip/cloud_discovery/files/usr/bin/cloud_discovery +++ b/feeds/tip/cloud_discovery/files/usr/bin/cloud_discovery @@ -3,6 +3,7 @@ 'use strict'; import { ulog_open, ulog, ULOG_SYSLOG, ULOG_STDIO, LOG_DAEMON, LOG_INFO } from 'log'; +import { query } from 'resolv'; import * as libubus from 'ubus'; import * as uloop from 'uloop'; import * as libuci from 'uci'; @@ -17,8 +18,12 @@ const ORPHAN = 4; const DISCOVER_DHCP = "DHCP"; const DISCOVER_FLASH = "FLASH"; +const DISCOVER_FQDN = "STANDARD_FQDN"; const DISCOVER_LOOKUP = "OpenLAN"; +const STANDARD_FQDN = "openwifi.network"; +const STANDARD_FQDN_PORT = 15002; + let ubus = libubus.connect(); let uci = libuci.cursor(); let state = DISCOVER; @@ -229,6 +234,28 @@ function discover_flash() { return 0; } +function discover_standard_fqdn() { + ulog(LOG_INFO, `Trying standard FQDN: ${STANDARD_FQDN}\n`); + + let result = query([STANDARD_FQDN], { type: ['A'] }); + if (!result || !result[STANDARD_FQDN] || !result[STANDARD_FQDN].A) { + ulog(LOG_INFO, `Failed to resolve ${STANDARD_FQDN}\n`); + return false; + } + + let address = result[STANDARD_FQDN].A[0]; + ulog(LOG_INFO, `Resolved ${STANDARD_FQDN} to ${address}\n`); + + if (gateway_write({ server: STANDARD_FQDN, port: STANDARD_FQDN_PORT, valid: false, hostname_validate: 1 })) { + ulog(LOG_INFO, `Discovered cloud via standard FQDN ${STANDARD_FQDN}\n`); + client_start(); + set_state(VALIDATING); + return true; + } + + return false; +} + function time_is_valid() { let valid = !!fs.stat('/tmp/ntp.set'); if (!valid) @@ -269,7 +296,7 @@ function interval_handler() { case DISCOVER: ulog(LOG_INFO, 'Starting discover\n'); - + if (!time_is_valid()) return; @@ -284,6 +311,10 @@ function interval_handler() { if (!is_discover_method_blacked() && !discover_flash()) return; + discovery_method = DISCOVER_FQDN; + if (!is_discover_method_blacked() && discover_standard_fqdn()) + return; + discovery_method = DISCOVER_LOOKUP; redirector_lookup();