From a6b6d837bd9288c184deda99c78d74fd5c941534 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 21 Jul 2026 07:31:20 -0700 Subject: [PATCH] Add dscp field to FirewallRule model The pfSense webConfigurator supports matching firewall rules on a DSCP value (config field 'dscp', rendered as 'tos ' in rules.debug), but the FirewallRule model did not define the field. API clients that submitted 'dscp' had the value silently discarded: the rule was created without the DSCP match, which for policy-routing rules meant matching far more traffic than intended. Adds the field with pfSense's canonical choice list (guiconfig.inc $firewall_rules_dscp_types) and a test asserting the value reaches the generated pfctl rule. --- .../local/pkg/RESTAPI/Models/FirewallRule.inc | 7 +++++ .../Tests/APIModelsFirewallRuleTestCase.inc | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/FirewallRule.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/FirewallRule.inc index 8e89850f..e9880c96 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/FirewallRule.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/FirewallRule.inc @@ -191,6 +191,13 @@ class FirewallRule extends Model { verbose_name: 'Log', help_text: 'Enable or disable logging of traffic that matches this rule.', ); + $this->dscp = new StringField( + default: '', + choices: ['af11', 'af12', 'af13', 'af21', 'af22', 'af23', 'af31', 'af32', 'af33', 'af41', 'af42', 'af43', 'VA', 'EF', 'cs1', 'cs2', 'cs3', 'cs4', 'cs5', 'cs6', 'cs7', '0x01', '0x02', '0x04'], + allow_empty: true, + verbose_name: 'DSCP', + help_text: 'The DSCP value this firewall rule should match.', + ); $this->tag = new StringField( default: '', allow_empty: true, diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsFirewallRuleTestCase.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsFirewallRuleTestCase.inc index e0d7d922..4598f34e 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsFirewallRuleTestCase.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsFirewallRuleTestCase.inc @@ -331,6 +331,33 @@ class APIModelsFirewallRuleTestCase extends TestCase { $rule->delete(apply: true); } + /** + * Checks that the `dscp` field is properly set in the pfctl rule + */ + public function test_dscp() { + # Create a firewall rule to test with + $rule = new FirewallRule( + data: [ + 'type' => 'pass', + 'interface' => ['lan'], + 'ipprotocol' => 'inet', + 'protocol' => 'tcp', + 'source' => 'any', + 'destination' => 'any', + 'dscp' => 'af11', + ], + async: false, + ); + $rule->create(apply: true); + + # Ensure the pfctl rule with this rule object's tracker matches the requested DSCP value + $pfctl_rules = file_get_contents('/tmp/rules.debug'); + $this->assert_str_contains($pfctl_rules, "tos af11 ridentifier {$rule->tracker->value}"); + + # Delete the firewall rule + $rule->delete(apply: true); + } + /** * Checks that firewall rules with `log` enabled have the log flag set in pfctl */