Skip to content

Commit fd95b05

Browse files
author
Jared Hendrickson
committed
Fixed bug that would revert VLAN XML to defaults, fixed issue that would rewrite interface assignments, fixed bug that incorrectly identified lagg
1 parent c0422f9 commit fd95b05

5 files changed

Lines changed: 247 additions & 119 deletions

File tree

pfSense-pkg-API/files/etc/inc/api/framework/APIResponse.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,12 @@ function get($id, $data=[], $all=false) {
822822
"return" => $id,
823823
"message" => "Interface VLAN parent required"
824824
],
825+
3056 => [
826+
"status" => "bad request",
827+
"code" => 400,
828+
"return" => $id,
829+
"message" => "Interface VLAN ID required"
830+
],
825831

826832
// 4000-4999 reserved for /firewall API calls
827833
4000 => [

pfSense-pkg-API/files/etc/inc/api/models/APIInterfaceVLANCreate.inc

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,20 @@ class APIInterfaceVLANCreate extends APIModel {
2323
parent::__construct();
2424
$this->privileges = ["page-all", "page-interfaces-vlan-edit"];
2525
$this->change_note = "Added VLAN interface via API";
26-
2726
}
2827

2928
public function action() {
30-
$this->config["vlans"]["vlan"] = [];
31-
$this->config["vlans"]["vlan"][] = $this->validated_data; // Write our configuration change
32-
interface_vlan_configure($this->validated_data); // Configure our VLAN on the backend
29+
$this->__init_config();
30+
$this->config["vlans"]["vlan"][] = $this->validated_data;
31+
interface_vlan_configure($this->validated_data);
3332
$this->write_config();
3433
return APIResponse\get(0, $this->validated_data);
3534
}
3635

37-
public function validate_payload() {
36+
private function __validate_if() {
37+
# Require clients to specify an if value to indicate which interface this VLAN will apply to
3838
if (isset($this->initial_data['if'])) {
39+
# Return an error if the requested parent interface does not exist
3940
if (!does_interface_exist($this->initial_data['if'])) {
4041
$this->errors[] = APIResponse\get(3051);
4142
} else {
@@ -44,19 +45,32 @@ class APIInterfaceVLANCreate extends APIModel {
4445
} else {
4546
$this->errors[] = APIResponse\get(3055);
4647
}
48+
}
4749

50+
private function __validate_tag() {
51+
# Require clients to specify a VLAN tag value
4852
if (isset($this->initial_data['tag'])) {
53+
# Return an error if VLAN tag is not numeric, or is not between 1 and 4096
4954
if (!is_numeric($this->initial_data['tag']) or (1 > intval($this->initial_data['tag']) or intval($this->initial_data['tag']) > 4096)) {
5055
$this->errors[] = APIResponse\get(3052);
51-
} else {
52-
$this->validated_data["tag"] = intval(trim($this->initial_data['tag']));
53-
$str_tag = strval($this->validated_data["tag"]);
56+
}
57+
# Return an error if this VLAN already exists on this interface
58+
elseif ($this->__is_vlan($this->validated_data["if"], $this->initial_data["tag"])) {
59+
$this->errors[] = APIResponse\get(3054);
60+
}
61+
# Otherwise, store our tag value as validated
62+
else {
63+
$this->validated_data["tag"] = $this->initial_data['tag'];
5464
}
5565
} else {
5666
$this->errors[] = APIResponse\get(3048);
5767
}
68+
}
5869

70+
private function __validate_pcp() {
71+
# Optionally allow client to specify a VLAN PCP value. Default if not set.
5972
if (isset($this->initial_data['pcp'])) {
73+
# Return error if PCP value is not between 0 and 7
6074
if (0 > $this->initial_data['pcp'] or $this->initial_data['pcp'] > 7) {
6175
$this->errors[] = APIResponse\get(3053);
6276
} else {
@@ -65,25 +79,43 @@ class APIInterfaceVLANCreate extends APIModel {
6579
} else {
6680
$this->validated_data["pcp"] = "";
6781
}
82+
}
6883

84+
private function __validate__descr() {
85+
# Optionally allow client to specify a VLAN description. Default if not set.
6986
if (isset($this->initial_data['descr'])) {
7087
$this->validated_data["descr"] = $this->initial_data['descr'];
7188
} else {
7289
$this->validated_data["descr"] = "";
7390
}
91+
}
92+
93+
public function validate_payload() {
94+
$this->__validate_if();
95+
$this->__validate_tag();
96+
$this->__validate_pcp();
97+
$this->__validate__descr();
98+
$this->validated_data["vlanif"] = $this->validated_data["if"].".".$this->initial_data['tag'];
99+
}
74100

75-
// Check if our VLAN is already in use
76-
if (is_array($this->config["vlans"]["vlan"])) {
77-
foreach ($this->config["vlans"]["vlan"] as $vle) {
78-
if ($this->validated_data["if"] === $vle["if"] and $str_tag === $vle["tag"]) {
79-
$this->errors[] = APIResponse\get(3054);
80-
}
101+
private function __is_vlan($if, $tag) {
102+
# Check if our VLAN already exists
103+
foreach ($this->config["vlans"]["vlan"] as $vle) {
104+
if ($if === $vle["if"] and strval($tag) === $vle["tag"]) {
105+
return true;
81106
}
82-
} else {
83-
$this->config["vlans"] = [];
84-
$this->config["vlans"]["vlan"] = [];
85107
}
86-
$this->validated_data["vlanif"] = $this->validated_data["if"].".".$this->initial_data['tag'];
108+
return false;
109+
}
87110

111+
private function __init_config() {
112+
# Ensure our VLANs config section is an array
113+
if (!is_array($this->config["vlans"])) {
114+
$this->config["vlans"] = [];
115+
}
116+
# Ensure our VLAN config section is an array
117+
if (!is_array($this->config["vlans"]["vlan"])) {
118+
$this->config["vlan"] = [];
119+
}
88120
}
89-
}
121+
}

pfSense-pkg-API/files/etc/inc/api/models/APIInterfaceVLANDelete.inc

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,40 +27,48 @@ class APIInterfaceVLANDelete extends APIModel {
2727
}
2828

2929
public function action() {
30-
$del_ent = $this->config["vlans"]["vlan"][$this->validated_data["id"]]; // Save our deleted VLAN
31-
pfSense_interface_destroy($this->config["vlans"]["vlan"][$this->validated_data["id"]]["vlanif"]); // delete our VLAN on the backend
32-
unset($this->config["vlans"]["vlan"][$this->validated_data["id"]]); // Remove our VLAN configuration
30+
pfSense_interface_destroy($this->validated_data["vlanif"]); // delete our VLAN on the backend
31+
unset($this->config["vlans"]["vlan"][$this->id]); // Remove our VLAN configuration
3332
$this->write_config();
34-
return APIResponse\get(0, $del_ent);
33+
return APIResponse\get(0, $this->validated_data);
3534
}
3635

37-
public function validate_payload() {
38-
$curr_vlans = $this->config["vlans"]["vlan"]; // Save our current VLANs
39-
if (isset($this->initial_data['vlanif'])) {
40-
$this->validated_data["vlanif"] = $this->initial_data['vlanif'];
41-
}
42-
elseif (isset($this->initial_data['id'])) {
43-
$this->validated_data["id"] = $this->initial_data['id'];
44-
} else {
45-
$this->errors[] = APIResponse\get(3048);
46-
}
47-
// Ensure we have a vlanif and id regardless of which input selector was provided
48-
if (isset($this->validated_data["vlanif"])) {
49-
foreach ($curr_vlans as $ind => $cve) {
50-
if ($this->validated_data["vlanif"] === $cve["vlanif"]) {
51-
$this->validated_data["id"] = $ind;
52-
break;
53-
}
36+
private function __validate_id() {
37+
# Check if the given ID exists. Also allow vlanif for backward compatibility
38+
if (isset($this->initial_data["id"]) or isset($this->initial_data["vlanif"])) {
39+
# Allow user to locate the VLAN by vlanif
40+
if (!is_null($this->__get_vlan_id_from_vlanif($this->initial_data["vlanif"]))) {
41+
$this->id = $this->__get_vlan_id_from_vlanif($this->initial_data["vlanif"]);
42+
$this->validated_data = $this->config["vlans"]["vlan"][$this->id];
43+
}
44+
# Try to locate our ID by configuration index ID
45+
elseif (array_key_exists($this->initial_data["id"], $this->config["vlans"]["vlan"])) {
46+
$this->id = $this->initial_data["id"];
47+
$this->validated_data = $this->config["vlans"]["vlan"][$this->id];
48+
}
49+
else {
50+
$this->errors[] = APIResponse\get(3050);
51+
}
52+
53+
# Lastly check that our interface is not in use currently
54+
if (APITools\get_pfsense_if_id($this->validated_data["vlanif"])) {
55+
$this->errors[] = APIResponse\get(3049);
5456
}
5557
} else {
56-
$this->validated_data["vlanif"] = $curr_vlans[$this->validated_data["id"]]["vlanif"];
58+
$this->errors[] = APIResponse\get(3056);
5759
}
58-
// Check that our interface is not in use currently
59-
if (convert_real_interface_to_friendly_interface_name($this->validated_data["vlanif"])) {
60-
$this->errors[] = APIResponse\get(3049);
61-
}
62-
if (empty($this->config["vlans"]["vlan"][$this->validated_data["id"]])) {
63-
$this->errors[] = APIResponse\get(3050);
60+
}
61+
62+
public function validate_payload() {
63+
$this->__validate_id();
64+
}
65+
66+
private function __get_vlan_id_from_vlanif($vlanif) {
67+
# Loop through each VLAN and return it's ID if it matches
68+
foreach ($this->config["vlans"]["vlan"] as $id => $vlan) {
69+
if ($vlanif === $vlan["vlanif"]) {
70+
return $id;
71+
}
6472
}
6573
}
6674
}

0 commit comments

Comments
 (0)