Project

General

Profile

Bug #16540 ยป cppatch_25.07.1.txt

Marcos M, 11/19/2025 08:23 PM

 
1
diff --git a/src/etc/inc/captiveportal.inc b/src/etc/inc/captiveportal.inc
2
index fb8086444b..4f95e5df48 100644
3
--- a/src/etc/inc/captiveportal.inc
4
+++ b/src/etc/inc/captiveportal.inc
5
@@ -1020,6 +1020,7 @@ function captiveportal_passthrumac_delete_entry($macent) {
6
 	if ($macent['action'] == 'pass') {
7
 		$pipes = captiveportal_get_dn_passthru_pipes($macent['mac']);
8
 		if (!empty($pipes)) {
9
+			// passthrumac should always have 2 pipes, one each for 'ether in' and 'ether out'.
10
 			captiveportal_pipes_delete($pipes);
11
 		}
12
 	} else {
13
@@ -1088,6 +1089,14 @@ function captiveportal_ether_delete_entry($hostent, $anchor = 'allowedhosts') {
14
 
15
 	$pipes = pfSense_pf_cp_get_eth_pipes("{$cpzoneprefix}_{$anchor}/{$host}");
16
 	if (!empty($pipes)) {
17
+		// 2 pipes are reserved per entry; keep the reservation list aligned when a rule is created for a single direction.
18
+		if (count($pipes) == 1) {
19
+			if ($hostent['dir'] == 'to') {
20
+				$pipes[array_key_last($pipes) + 1] = $pipes[array_key_last($pipes)] + 1;
21
+			} elseif ($hostent['dir'] == 'from') {
22
+				$pipes[array_key_last($pipes) + 1] = $pipes[array_key_last($pipes)] - 1;
23
+			}
24
+		}
25
 		captiveportal_pipes_delete($pipes);
26
 	}
27
 	/* flush anchor rules */
28
@@ -2590,6 +2599,14 @@ function captiveportal_allowedhostname_cleanup() {
29
 		$pipes = pfSense_pf_cp_get_eth_pipes("{$cpzoneprefix}_allowedhosts/hostname_{$id}");
30
 		pfSense_pf_cp_flush("{$cpzoneprefix}_allowedhosts/hostname_{$id}", "ether");
31
 		if (!empty($pipes)) {
32
+			// 2 pipes are reserved per entry; keep the reservation list aligned when a rule is created for a single direction.
33
+			if (count($pipes) == 1) {
34
+				if ($hostnameent['dir'] == 'to') {
35
+					$pipes[array_key_last($pipes) + 1] = $pipes[array_key_last($pipes)] + 1;
36
+				} elseif ($hostnameent['dir'] == 'from') {
37
+					$pipes[array_key_last($pipes) + 1] = $pipes[array_key_last($pipes)] - 1;
38
+				}
39
+			}
40
 			captiveportal_pipes_delete($pipes);
41
 		}
42
 	}
43
diff --git a/src/etc/inc/system.inc b/src/etc/inc/system.inc
44
index f78531488e..d93089267d 100644
45
--- a/src/etc/inc/system.inc
46
+++ b/src/etc/inc/system.inc
47
@@ -3051,18 +3051,21 @@ function system_reboot_cleanup() {
48
 	mwexec("/usr/local/bin/beep.sh stop");
49
 	require_once("captiveportal.inc");
50
 	$cps = config_get_path('captiveportal', []);
51
+	$preservedb = false;
52
 	foreach ($cps as $cpzone=>$cp) {
53
 		if (!isset($cp['preservedb'])) {
54
 			/* send Accounting-Stop packet for all clients, termination cause 'Admin-Reboot' */
55
 			captiveportal_radius_stop_all(7); // Admin-Reboot
56
 			unlink_if_exists("{$g['vardb_path']}/captiveportal{$cpzone}.db");
57
 			captiveportal_free_dnrules();
58
+		} else {
59
+			$preservedb = true;
60
 		}
61
 		/* Send Accounting-Off packet to the RADIUS server */
62
 		captiveportal_send_server_accounting('off');
63
 	}
64
 
65
-	if (count($cps)> 0) {
66
+	if (!$preservedb) {
67
 		/* Remove the pipe database */
68
 		unlink_if_exists("{$g['vardb_path']}/captiveportaldn.rules");
69
 	}
70
diff --git a/src/etc/rc.carpmaster b/src/etc/rc.carpmaster
71
index fde3e22054..cf8f251f8b 100755
72
--- a/src/etc/rc.carpmaster
73
+++ b/src/etc/rc.carpmaster
74
@@ -149,7 +149,11 @@ if (!empty(config_get_path('captiveportal')) &&
75
 		}
76
 	}
77
 
78
-	foreach (array_keys(config_get_path('captiveportal', [])) as $cpzone) {
79
+	foreach (config_get_path('captiveportal', []) as $cpzone => $cpzone_config) {
80
+		if ($cpzone_config['interface'] != $friendly) {
81
+			// Ignore CARP events for unrelated interfaces.
82
+			continue;
83
+		}
84
 		$rpc_client = new pfsense_xmlrpc_client();
85
 		$rpc_client->setConnectionData(config_get_path('hasync/synchronizetoip'), $xmlrpc_port, $xmlrpc_username, config_get_path('hasync/password'));
86
 		$resp = $rpc_client->xmlrpc_method('captive_portal_sync', array('op' => 'get_databases', 'zone' => $cpzone));
87
@@ -169,7 +173,8 @@ if (!empty(config_get_path('captiveportal')) &&
88
 			if (!empty($unsetindexes)) {
89
 				captiveportal_remove_entries($unsetindexes, true); // true: prevent carp loop
90
 			}
91
-			captiveportal_free_dnrules();
92
+			// Make sure the passthrumac, ip, and hostname entries are added; clear the rest.
93
+			captiveportal_init_rules(true);
94
 
95
 			foreach ($connected_users as $user) {
96
 				if (!is_array($user) || empty($user)) {
97
diff --git a/src/usr/local/www/services_captiveportal_ip_edit.php b/src/usr/local/www/services_captiveportal_ip_edit.php
98
index e1de2da60e..b8ce3f88bb 100644
99
--- a/src/usr/local/www/services_captiveportal_ip_edit.php
100
+++ b/src/usr/local/www/services_captiveportal_ip_edit.php
101
@@ -135,15 +135,7 @@ if ($_POST['save']) {
102
 			$ip['bw_down'] = $_POST['bw_down'];
103
 		}
104
 
105
-		$oldip = array();
106
 		if ($this_allowedip_config) {
107
-			$oldip['ip'] = $this_allowedip_config['ip'];
108
-			if (!empty($this_allowedip_config['sn'])) {
109
-				$oldip['sn'] = $this_allowedip_config['sn'];
110
-			} else {
111
-				$oldip['sn'] = 32;
112
-			}
113
-
114
 			config_set_path("captiveportal/{$cpzone}/allowedip/{$id}", $ip);
115
 		} else {
116
 			config_set_path("captiveportal/{$cpzone}/allowedip/", $ip);
117
@@ -154,8 +146,8 @@ if ($_POST['save']) {
118
 		write_config("Captive portal allowed IPs added");
119
 
120
 		if (config_path_enabled("captiveportal/{$cpzone}")) {
121
-			if (!empty($oldip)) {
122
-				captiveportal_ether_delete_entry($oldip, 'allowedhosts');
123
+			if ($this_allowedip_config) {
124
+				captiveportal_ether_delete_entry($this_allowedip_config, 'allowedhosts');
125
 			}
126
 			captiveportal_allowedip_configure_entry($ip);
127
 		}
    (1-1/1)