Skip to content

Commit 338b0f9

Browse files
Added /api/v1/routing/gateway/default endpoint to set the default gateways.
1 parent b076d94 commit 338b0f9

4 files changed

Lines changed: 211 additions & 0 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
// Copyright 2022 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/APIEndpoint.inc");
17+
18+
class APIRoutingGatewayDefault extends APIEndpoint {
19+
public function __construct() {
20+
$this->url = "/api/v1/routing/gateway/default";
21+
}
22+
23+
protected function put() {
24+
return (new APIRoutingGatewayDefaultUpdate())->call();
25+
}
26+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
// Copyright 2022 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+
20+
class APIRoutingGatewayDefaultUpdate extends APIModel {
21+
# Create our method constructor
22+
public function __construct() {
23+
parent::__construct();
24+
$this->privileges = ["page-all", "page-system-gateways"];
25+
$this->change_note = "Set default gateway via API";
26+
}
27+
28+
public function action() {
29+
# Set the default gateways based on the validated input
30+
$this->config["gateways"]["defaultgw4"] = $this->validated_data["defaultgw4"];
31+
$this->config["gateways"]["defaultgw6"] = $this->validated_data["defaultgw6"];
32+
33+
# Write these changes to config and apply if the client requested
34+
$this->write_config();
35+
$this->apply();
36+
return APIResponse\get(0, $this->validated_data);
37+
}
38+
39+
private function __validate_defaultgw4() {
40+
# Optionally allow clients to update the 'defaultgw4' value
41+
if (isset($this->initial_data["defaultgw4"])) {
42+
# Ensure this is a valid IPv4 gateway
43+
if (APITools\is_gateway($this->initial_data["defaultgw4"], true) === "inet") {
44+
$this->validated_data["defaultgw4"] = $this->initial_data["defaultgw4"];
45+
}
46+
# Allow client to set automatic gateway selection
47+
elseif (in_array($this->initial_data["defaultgw4"], ["", "automatic"])) {
48+
$this->validated_data["defaultgw4"] = "";
49+
}
50+
# Allow client to set no gateway
51+
elseif (in_array($this->initial_data["defaultgw4"], ["-", "none"])) {
52+
$this->validated_data["defaultgw4"] = "-";
53+
}
54+
else {
55+
$this->errors[] = APIResponse\get(6028);
56+
}
57+
}
58+
}
59+
60+
private function __validate_defaultgw6() {
61+
# Optionally allow clients to update the 'defaultgw6' value
62+
if (isset($this->initial_data["defaultgw6"])) {
63+
# Ensure this is a valid IPv6 gateway
64+
if (APITools\is_gateway($this->initial_data["defaultgw6"], true) === "inet6") {
65+
$this->validated_data["defaultgw6"] = $this->initial_data["defaultgw6"];
66+
}
67+
# Allow client to set automatic gateway selection
68+
elseif (in_array($this->initial_data["defaultgw6"], ["", "automatic"])) {
69+
$this->validated_data["defaultgw6"] = "";
70+
}
71+
# Allow client to set no gateway
72+
elseif (in_array($this->initial_data["defaultgw6"], ["-", "none"])) {
73+
$this->validated_data["defaultgw6"] = "-";
74+
}
75+
else {
76+
$this->errors[] = APIResponse\get(6028);
77+
}
78+
}
79+
}
80+
81+
public function validate_payload() {
82+
# Fetch existing default gateway values
83+
$this->validated_data = [
84+
"defaultgw4"=>$this->config["gateways"]["defaultgw4"],
85+
"defaultgw6"=>$this->config["gateways"]["defaultgw6"],
86+
];
87+
88+
# Validate client input
89+
$this->__validate_defaultgw4();
90+
$this->__validate_defaultgw6();
91+
}
92+
93+
public function apply() {
94+
# Mark the routing subsystem as changed, clear if applied
95+
mark_subsystem_dirty("staticroutes");
96+
97+
# Optionally allow clients to apply this route immediately if they passed in a true apply value
98+
# Note: this is a one-off case where this was better to default to true instead of false.
99+
if ($this->initial_data["apply"] !== false) {
100+
system_routing_configure();
101+
system_resolvconf_generate();
102+
filter_configure();
103+
setup_gateways_monitor();
104+
send_event("service reload dyndnsall");
105+
clear_subsystem_dirty("staticroutes");
106+
}
107+
}
108+
}

pfSense-pkg-API/files/usr/local/www/api/documentation/openapi.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5652,6 +5652,43 @@ paths:
56525652
summary: Update gateway
56535653
tags:
56545654
- Routing > Gateway
5655+
/api/v1/routing/gateway/default:
5656+
put:
5657+
description: 'Update the default gateways for IPv4 and/or IPv6. _Note: changing the default gateway can
5658+
prevent you from connecting to the system afterward. Proceed with caution._<br><br>
5659+
5660+
_Requires at least one of the following privileges:_ [`page-all`, `page-system-gateways`]'
5661+
requestBody:
5662+
content:
5663+
application/json:
5664+
schema:
5665+
properties:
5666+
defaultgw4:
5667+
description: >-
5668+
Set the IPv4 default gateway. This must be an existing IPv4 gateway name, `automatic` for automatic
5669+
gateway selection, or `none` for no default gateway selection for IPv4.
5670+
type: string
5671+
defaultgw6:
5672+
description: >-
5673+
Set the IPv6 default gateway. This must be an existing IPv6 gateway name, `automatic` for automatic
5674+
gateway selection, or `none` for no default gateway selection for IPv6.
5675+
type: string
5676+
apply:
5677+
default: true
5678+
description: Specify whether or not you would like this change
5679+
to be applied immediately, or simply written to the configuration
5680+
to be applied later. If set to `false` you must apply the changes
5681+
afterwards using the `/api/v1/routing/apply` endpoint.
5682+
type: boolean
5683+
type: object
5684+
responses:
5685+
200:
5686+
$ref: '#/components/responses/Success'
5687+
401:
5688+
$ref: '#/components/responses/AuthenticationFailed'
5689+
summary: Update default gateways
5690+
tags:
5691+
- Routing > Gateway > Default
56555692
/api/v1/routing/gateway/detail:
56565693
get:
56575694
description: 'Read verbose routing gateway details about both dynamic/system
@@ -9512,6 +9549,7 @@ tags:
95129549
- name: System > Reboot
95139550
- name: System > Halt
95149551
- name: Routing > Gateway
9552+
- name: Routing > Gateway > Default
95159553
- name: Routing > Gateway > Detail
95169554
- name: Routing > Static Route
95179555
- name: Routing > Apply
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2022 Jared Hendrickson
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import e2e_test_framework
16+
17+
class APIE2ETestRoutingGatewayDefault(e2e_test_framework.APIE2ETest):
18+
uri = "/api/v1/routing/gateway/default"
19+
put_tests = [
20+
{
21+
"name": "Check IPv4 gateway exists constraint",
22+
"status": 400,
23+
"return": 6028,
24+
"payload": {"defaultgw4": "INVALID"}
25+
},
26+
{
27+
"name": "Check IPv6 gateway exists constraint",
28+
"status": 400,
29+
"return": 6028,
30+
"payload": {"defaultgw6": "INVALID"}
31+
},
32+
{
33+
"name": "Check updating default gateways",
34+
"timeout": 10,
35+
"payload": {"defaultgw4": "automatic", "defaultgw6": "automatic"}
36+
}
37+
]
38+
39+
APIE2ETestRoutingGatewayDefault()

0 commit comments

Comments
 (0)