1+ <?php
2+ // Copyright 2021 Jared Hendrickson
3+ //
4+ // Licensed under the Apache License, Version 2.0 (the "License");
5+ // you may not use this file except in compliance with the License.
6+ // You may obtain a copy of the License at
7+ //
8+ // http://www.apache.org/licenses/LICENSE-2.0
9+ //
10+ // Unless required by applicable law or agreed to in writing, software
11+ // distributed under the License is distributed on an "AS IS" BASIS,
12+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ // See the License for the specific language governing permissions and
14+ // limitations under the License.
15+
16+ require_once ("api/framework/APIModel.inc " );
17+ require_once ("api/framework/APIResponse.inc " );
18+
19+ class APIFirewallTrafficShaperUpdate extends APIModel {
20+ private $ type_changed ;
21+
22+ # Create our method constructor
23+ public function __construct () {
24+ parent ::__construct ();
25+ $ this ->privileges = ["page-all " , "page-firewall-trafficshaper " ];
26+ $ this ->change_note = "Modified firewall traffic shaper via API " ;
27+ }
28+
29+ public function action () {
30+ # Save the updated shaper, mark the subsystem as un-applied
31+ $ this ->config ["shaper " ]["queue " ][$ this ->id ] = $ this ->validated_data ;
32+ $ this ->write_config ();
33+ mark_subsystem_dirty ('shaper ' );
34+
35+ # Only reload the filter immediately if it was requested by the client
36+ if ($ this ->initial_data ["apply " ] === true ) {
37+ # Reload the filter, reset RRD logs and mark the subsystem as applied
38+ filter_configure ();
39+ system ("rm -f /var/db/rrd/*queuedrops.rrd " );
40+ system ("rm -f /var/db/rrd/*queues.rrd " );
41+ enable_rrd_graphing ();
42+ clear_subsystem_dirty ('shaper ' );
43+ }
44+ return APIResponse \get (0 , $ this ->validated_data );
45+ }
46+
47+ public function validate_payload () {
48+ $ this ->__validate_interface ();
49+ $ this ->__validate_scheduler ();
50+ $ this ->__validate_bandwidthtype (); // Must run before __validate_bandwidth()
51+ $ this ->__validate_bandwidth ();
52+ $ this ->__validate_enabled ();
53+ $ this ->__validate_qlimit ();
54+ $ this ->__validate_tbrconfig ();
55+ }
56+
57+ private function __validate_interface () {
58+ # Check for our required `interface` payload value
59+ if (isset ($ this ->initial_data ["interface " ])) {
60+ $ this ->initial_data ["interface " ] = APITools \get_pfsense_if_id ($ this ->initial_data ["interface " ]);
61+
62+ # Check that the requested interface exists
63+ if ($ this ->initial_data ["interface " ]) {
64+ # Check that a traffic shaper does not already exist for this interface
65+ if ($ this ->get_shaper_id_by_interface ($ this ->initial_data ["interface " ], true )) {
66+ # Fetch the traffic shaper object associated with this interface
67+ $ this ->id = $ this ->get_shaper_id_by_interface ($ this ->initial_data ["interface " ]);
68+ $ this ->validated_data = $ this ->config ["shaper " ]["queue " ][$ this ->id ];
69+ } else {
70+ $ this ->errors [] = APIResponse \get (4122 );
71+ }
72+ } else {
73+ $ this ->errors [] = APIResponse \get (4111 );
74+ }
75+ } else {
76+ $ this ->errors [] = APIResponse \get (4110 );
77+ }
78+ }
79+
80+ private function __validate_scheduler () {
81+ # Check for our optional `scheduler` payload value
82+ if (isset ($ this ->initial_data ["scheduler " ])) {
83+ # Check that the scheduler type is supported
84+ if (in_array ($ this ->initial_data ["scheduler " ], ["HFSC " , "CBQ " , "FAIRQ " , "CODELQ " , "PRIQ " ])) {
85+ $ this ->validated_data ["scheduler " ] = $ this ->initial_data ["scheduler " ];
86+ } else {
87+ $ this ->errors [] = APIResponse \get (4114 );
88+ }
89+ }
90+ }
91+
92+ private function __validate_bandwidthtype () {
93+ # Check for our required `bandwidthtype` payload value
94+ if (isset ($ this ->initial_data ["bandwidthtype " ])) {
95+ # Only update the bandwidth type if it has changed
96+ if ($ this ->initial_data ["bandwidthtype " ] !== $ this ->validated_data ["bandwidthtype " ]) {
97+ # Check that the scheduler type is supported
98+ if (in_array ($ this ->initial_data ["bandwidthtype " ], ["% " , "b " , "Kb " , "Mb " , "Gb " ])) {
99+ $ this ->validated_data ["bandwidthtype " ] = $ this ->initial_data ["bandwidthtype " ];
100+ $ this ->type_changed = true ;
101+ } else {
102+ $ this ->errors [] = APIResponse \get (4116 );
103+ }
104+ }
105+ }
106+ }
107+
108+ private function __validate_bandwidth () {
109+ # Check for our optional `bandwidth` payload value
110+ if (isset ($ this ->initial_data ["bandwidth " ])) {
111+ # Check that the bandwidth is 1 or greater
112+ if (intval ($ this ->initial_data ["bandwidth " ]) >= 1 ) {
113+ # If bandwidth type % is used, enforce value to be less than 100
114+ if ($ this ->validated_data ["bandwidthtype " ] === "% " and intval ($ this ->initial_data ["bandwidth " ]) > 100 ) {
115+ $ this ->errors [] = APIResponse \get (4119 );
116+ } else {
117+ $ this ->validated_data ["bandwidth " ] = intval ($ this ->initial_data ["bandwidth " ]);
118+ }
119+ } else {
120+ $ this ->errors [] = APIResponse \get (4118 );
121+ }
122+ }
123+ # Require a new bandwidth value be specified if the type was changed
124+ elseif ($ this ->type_changed ) {
125+ $ this ->errors [] = APIResponse \get (4117 );
126+ }
127+ }
128+
129+ private function __validate_enabled () {
130+ # Enable this shaper if requested
131+ if ($ this ->initial_data ["enabled " ] === true ) {
132+ $ this ->validated_data ["enabled " ] = "on " ;
133+ }
134+ # Disabled this shaper if requested
135+ elseif ($ this ->validated_data ["enabled " ] === false ) {
136+ unset($ this ->validated_data ["enabled " ]);
137+ }
138+ }
139+
140+ private function __validate_qlimit () {
141+ # Check for our optional `qlimit` payload value
142+ if (isset ($ this ->initial_data ["qlimit " ])) {
143+ # Ensure the qlimit is 1 or greater
144+ if (is_numeric ($ this ->initial_data ["qlimit " ]) and intval ($ this ->initial_data ["qlimit " ]) >= 1 ) {
145+ $ this ->validated_data ["qlimit " ] = intval ($ this ->initial_data ["qlimit " ]);
146+ } else {
147+ $ this ->errors [] = APIResponse \get (4120 );
148+ }
149+ }
150+ }
151+
152+ private function __validate_tbrconfig () {
153+ # Check for our optional `tbrconfig` payload value
154+ if (isset ($ this ->initial_data ["tbrconfig " ])) {
155+ # Ensure the tbrconfig is 1 or greater
156+ if (is_numeric ($ this ->initial_data ["tbrconfig " ]) and intval ($ this ->initial_data ["tbrconfig " ]) >= 1 ) {
157+ $ this ->validated_data ["tbrconfig " ] = intval ($ this ->initial_data ["tbrconfig " ]);
158+ } else {
159+ $ this ->errors [] = APIResponse \get (4121 );
160+ }
161+ }
162+ }
163+
164+ public function get_shaper_id_by_interface ($ interface , $ as_bool =false ) {
165+ # Loop through each configured shaper
166+ foreach ($ this ->config ["shaper " ]["queue " ] as $ id =>$ shaper ) {
167+ # Check if this is the shaper for our interface, if so return it's ID
168+ if ($ interface === $ shaper ["interface " ]) {
169+ return ($ as_bool ) ? true : intval ($ id );
170+ }
171+ }
172+ return ($ as_bool ) ? false : null ;
173+ }
174+ }
0 commit comments