Project

General

Profile

Actions

Bug #16708

open

DNS Forwarder domain overrides fail with "Cannot redeclare function String_Begins_With()" when saving 2+ entries via Nexus MIM API or GUI

Added by LTC Tech about 18 hours ago. Updated about 5 hours ago.

Status:
Feedback
Priority:
Normal
Assignee:
Category:
DNS Forwarder
Target version:
Start date:
Due date:
% Done:

100%

Estimated time:
Release Notes:
Default
Affected Plus Version:
25.11.1
Affected Architecture:

Description

Summary

Saving two or more DNS Forwarder domain overrides in a single operation via the MIM API or the Netgate Nexus GUI fails with a fatal PHP error. Only the first entry is saved. Subsequent entries trigger:

PHP ERROR: Type: 1, File: /usr/local/pfSense/include/www/services_dnsmasq.inc,
Line: 425, Message: Cannot redeclare function String_Begins_With()
(previously declared in /usr/local/pfSense/include/www/services_dnsmasq.inc:425)

Steps to Reproduce

Via Netgate Nexus MIM GUI:

1. Navigate to a managed device > Services > DNS Forwarder
2. Add a first domain override and save — succeeds
3. Add a second domain override and save — fails with the error above

Via MIM REST API:

1. Authenticate to the controller and obtain a bearer token
2. POST to /api/device/pfsense/{device_id}/api/services/dnsmasq with a config body containing 2 or more entries in the domainoverrides array
3. Receive HTTP 400 with the PHP error above

Expected Behavior

All domain overrides in the request are saved successfully.

Actual Behavior

Only the first domain override is saved. All subsequent entries fail with a fatal PHP redeclaration error. The error also prevents the MIM API from returning a success response, leaving the configuration in a partially-applied state.

Root Cause

In services_dnsmasq.inc, the function String_Begins_With() is declared inside saveDomainOverride():

function saveDomainOverride($post, $id, $json=false) {
...
function String_Begins_With($needle, $haystack) { // line 425
return (substr($haystack, 0, strlen($needle)) == $needle);
}
...
}

In PHP, a function declared inside another function is not scoped to that function. Instead, it is registered in the global namespace the first time the outer function executes. The MIM API calls saveDomainOverride() once per entry in the domainoverrides array within a single PHP process. The first call registers String_Begins_With() globally. The second call in the same process attempts to register it again and PHP fatals with "Cannot redeclare function".

This is why adding or removing a single domain override works fine (one call per HTTP request = one fresh PHP process), but any operation involving 2+ entries in a single request fails.

Fix

Move String_Begins_With() to file scope, outside of saveDomainOverride():

// File scope - declared once when the file is loaded
function String_Begins_With($needle, $haystack) {
return (substr($haystack, 0, strlen($needle)) == $needle);
}
function saveDomainOverride($post, $id, $json=false) {
// String_Begins_With() still callable here, no behavior change
...
}

A working patch is attached. It has been tested against 25.11.1 and confirmed to resolve the issue in both the Netgate Nexus GUI and the MIM REST API.

Patch

--- a/src/usr/local/pfSense/include/www/services_dnsmasq.inc
+++ b/src/usr/local/pfSense/include/www/services_dnsmasq.inc
@@ -420,20 +420,20 @@ function getDomainOverride($id, $json = false) {

 // Domain override table update
+function String_Begins_With($needle, $haystack) {
+    return (substr($haystack, 0, strlen($needle)) == $needle);
+}
+
 function saveDomainOverride($post, $id, $json=false) {
     $input_errors = array();
     $pconfig = $post;

     if (!$json) {
         /* input validation */
         $reqdfields = explode(" ", "domain ip");
         $reqdfieldsn = array(gettext("Domain"), gettext("IP address"));

         do_input_validation($post, $reqdfields, $reqdfieldsn, $input_errors);
     }

-    function String_Begins_With($needle, $haystack) {
-        return (substr($haystack, 0, strlen($needle)) == $needle);
-    }
-
     if (String_Begins_With('_msdcs', $post['domain'])) {
         $subdomainstr = substr($post['domain'], 7);

Environment

- pfSense Plus version: 25.11.1 (fully patched)
- Controller: Netgate Nexus (MIM)
- Confirmed affected: MIM GUI and MIM REST API

Actions #1

Updated by Christian McDonald about 5 hours ago

  • Assignee set to Christian McDonald
Actions #2

Updated by Christian McDonald about 5 hours ago

  • Target version set to 26.03
Actions #3

Updated by Christian McDonald about 5 hours ago

  • Assignee changed from Christian McDonald to Marcos M
Actions #4

Updated by Marcos M about 5 hours ago

  • Status changed from New to Feedback
  • % Done changed from 0 to 100
Actions

Also available in: Atom PDF