Project

General

Profile

Download (14.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * system_gateways.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2024 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2010 Seth Mos <seth.mos@dds.nl>
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

    
25
##|+PRIV
26
##|*IDENT=page-system-gateways
27
##|*NAME=System: Gateways
28
##|*DESCR=Allow access to the 'System: Gateways' page.
29
##|*MATCH=system_gateways.php*
30
##|-PRIV
31

    
32
require_once("guiconfig.inc");
33
require_once("functions.inc");
34
require_once("filter.inc");
35
require_once("shaper.inc");
36
require_once("gwlb.inc");
37

    
38
$simplefields = array('defaultgw4', 'defaultgw6');
39

    
40
init_config_arr(array('gateways', 'gateway_item'));
41
refresh_gateways(); // make sure we're working on a current gateway list
42
$a_gateway_item = &$config['gateways']['gateway_item'];
43

    
44
$pconfig = $_REQUEST;
45

    
46
if ($_POST['order-store']) {
47
	// Include the rules of this (the selected) interface.
48
	// If a rule is not in POST[rule], it has been deleted by the user
49
	$a_gateway_item_new = array();
50
	//print "<pre>";
51
	foreach ($_POST['row'] as $id) {
52
		//print " $id";
53
		$a_gateway_item_new[] = $a_gateway_item[$id];
54
	}
55
	//print_r($a_gateway_item);
56
	//print_r($a_gateway_item_new);
57
	//print "</pre>";
58
	$a_gateway_item = $a_gateway_item_new;
59
	//mark_subsystem_dirty('staticroutes');
60
	write_config("System - Gateways: save default gateway");
61
} else if ($_POST['save']) {
62
	unset($input_errors);
63
	$pconfig = $_POST;
64
	foreach($simplefields as $field) {
65
		$config['gateways'][$field] = $pconfig[$field];
66
	}
67
	mark_subsystem_dirty('staticroutes');
68
	write_config("System - Gateways: save default gateway");
69
}
70

    
71
if ($_POST['apply']) {
72

    
73
	$retval = 0;
74

    
75
	/* reconfigure our gateway monitor */
76
	setup_gateways_monitor();
77
	$retval |= system_routing_configure();
78
	$retval |= system_resolvconf_generate();
79
	$retval |= filter_configure();
80
	/* Dynamic DNS on gw groups may have changed */
81
	send_event("service reload dyndnsall");
82

    
83
	if ($retval == 0) {
84
		clear_subsystem_dirty('staticroutes');
85
	}
86
}
87

    
88
$a_gateways = get_gateways(GW_CACHE_INDEXED);
89

    
90
function can_delete_disable_gateway_item($id, $disable = false) {
91
	global $config, $input_errors, $a_gateways;
92

    
93
	if (!isset($a_gateways[$id])) {
94
		return false;
95
	}
96

    
97
	if (is_array($config['gateways']['gateway_group'])) {
98
		foreach (config_get_path('gateways/gateway_group', []) as $group) {
99
			foreach ($group['item'] as $item) {
100
				$items = explode("|", $item);
101
				if ($items[0] == $a_gateways[$id]['name']) {
102
					if (!$disable) {
103
						$input_errors[] = sprintf(gettext('Gateway "%1$s" cannot be deleted because it is in use on Gateway Group "%2$s"'), $a_gateways[$id]['name'], $group['name']);
104
					} else {
105
						$input_errors[] = sprintf(gettext('Gateway "%1$s" cannot be disabled because it is in use on Gateway Group "%2$s"'), $a_gateways[$id]['name'], $group['name']);
106
					}
107
				}
108
			}
109
		}
110
	}
111

    
112
	foreach (config_get_path('staticroutes/route', []) as $route) {
113
		if ($route['gateway'] == $a_gateways[$id]['name']) {
114
			if (!$disable) {
115
				// The user wants to delete this gateway, but there is a static route (enabled or disabled) that refers to the gateway.
116
				$input_errors[] = sprintf(gettext('Gateway "%1$s" cannot be deleted because it is in use on Static Route "%2$s"'), $a_gateways[$id]['name'], $route['network']);
117
			} else if (!isset($route['disabled'])) {
118
				// The user wants to disable this gateway.
119
				// But there is a static route that uses this gateway and is enabled (not disabled).
120
				$input_errors[] = sprintf(gettext('Gateway "%1$s" cannot be disabled because it is in use on Static Route "%2$s"'), $a_gateways[$id]['name'], $route['network']);
121
			}
122
		}
123
	}
124

    
125
	/* prevent removing a gateway if it's still in use by DNS servers
126
	 * see https://redmine.pfsense.org/issues/8390 */
127
	$dnsgw_counter = 1;
128
	init_config_arr(array('system', 'dnsserver'));
129
	foreach (config_get_path('system/dnsserver', []) as $dnsserver) {
130
		if (isset($config["system"]["dns{$dnsgw_counter}gw"]) &&
131
		    ($a_gateways[$id]['name'] == $config["system"]["dns{$dnsgw_counter}gw"])) {
132
				if (!$disable) {
133
					// The user wants to delete this gateway, but there is a static route to the DNS server that refers to the gateway.
134
					$input_errors[] = sprintf(gettext('Gateway "%1$s" cannot be deleted because it is in use by DNS Server "%2$s"'), $a_gateways[$id]['name'], $dnsserver);
135
				} else {
136
					// The user wants to disable this gateway, but there is a static route to the DNS server that refers to the gateway.
137
					$input_errors[] = sprintf(gettext('Gateway "%1$s" cannot be disabled because it is in use by DNS Server "%2$s"'), $a_gateways[$id]['name'], $dnsserver);
138
				}
139
		}
140
		$dnsgw_counter++;
141
	}
142

    
143
	if (isset($input_errors)) {
144
		return false;
145
	}
146

    
147
	return true;
148
}
149

    
150
function delete_gateway_item($id) {
151
	global $config, $a_gateways;
152

    
153
	if (!isset($a_gateways[$id])) {
154
		return;
155
	}
156

    
157
	/* If the removed gateway was the default route, remove the default route */
158
	if (!empty($a_gateways[$id]) && is_ipaddr($a_gateways[$id]['gateway']) &&
159
	    !isset($a_gateways[$id]['disabled']) &&
160
	    isset($a_gateways[$id]['isdefaultgw'])) {
161
		$inet = (!is_ipaddrv4($a_gateways[$id]['gateway'])
162
		    ? 'inet6' : 'inet');
163
		route_del('default', $inet);
164
	}
165

    
166
	/* NOTE: Cleanup static routes for the interface route if any */
167
	if (!empty($a_gateways[$id]) && is_ipaddr($a_gateways[$id]['gateway']) &&
168
	    $gateway['gateway'] != $a_gateways[$id]['gateway'] &&
169
	    isset($a_gateways[$id]["nonlocalgateway"])) {
170
		route_del($a_gateways[$id]['gateway']);
171
	}
172
	/* NOTE: Cleanup static routes for the monitor ip if any */
173
	if (!empty($a_gateways[$id]['monitor']) &&
174
	    $a_gateways[$id]['monitor'] != "dynamic" &&
175
	    is_ipaddr($a_gateways[$id]['monitor']) &&
176
	    $a_gateways[$id]['gateway'] != $a_gateways[$id]['monitor']) {
177
		route_del($a_gateways[$id]['monitor']);
178
	}
179

    
180
	if ($config['interfaces'][$a_gateways[$id]['friendlyiface']]['gateway'] == $a_gateways[$id]['name']) {
181
		config_del_path("interfaces/{$a_gateways[$id]['friendlyiface']}/gateway");
182
	}
183
	config_del_path("gateways/gateway_item/{$a_gateways[$id]['attribute']}");
184
}
185

    
186
unset($input_errors);
187
if ($_REQUEST['act'] == "del") {
188
	if (can_delete_disable_gateway_item($_REQUEST['id'])) {
189
		$realid = $a_gateways[$_REQUEST['id']]['attribute'];
190
		delete_gateway_item($_REQUEST['id']);
191
		write_config("Gateways: removed gateway {$realid}");
192
		mark_subsystem_dirty('staticroutes');
193
		header("Location: system_gateways.php");
194
		exit;
195
	}
196
}
197

    
198
if (isset($_REQUEST['del_x'])) {
199
	/* delete selected items */
200
	if (is_array($_REQUEST['rule']) && count($_REQUEST['rule'])) {
201
		foreach ($_REQUEST['rule'] as $rulei) {
202
			if (!can_delete_disable_gateway_item($rulei)) {
203
				break;
204
			}
205
		}
206

    
207
		if (!isset($input_errors)) {
208
			$items_deleted = "";
209
			foreach ($_REQUEST['rule'] as $rulei) {
210
				delete_gateway_item($rulei);
211
				$items_deleted .= "{$rulei} ";
212
			}
213
			if (!empty($items_deleted)) {
214
				write_config(sprintf(gettext("Gateways: removed gateways %s", $items_deleted)));
215
				mark_subsystem_dirty('staticroutes');
216
			}
217
			header("Location: system_gateways.php");
218
			exit;
219
		}
220
	}
221

    
222
} else if ($_REQUEST['act'] == "toggle" && $a_gateways[$_REQUEST['id']]) {
223
	$realid = $a_gateways[$_REQUEST['id']]['attribute'];
224
	$disable_gw = !isset($a_gateway_item[$realid]['disabled']);
225
	if ($disable_gw) {
226
		// The user wants to disable the gateway, so check if that is OK.
227
		$ok_to_toggle = can_delete_disable_gateway_item($_REQUEST['id'], $disable_gw);
228
	} else {
229
		// The user wants to enable the gateway. That is always OK.
230
		$ok_to_toggle = true;
231
	}
232
	if ($ok_to_toggle) {
233
		gateway_set_enabled($a_gateway_item[$realid]['name'], !$disable_gw);
234

    
235
		if (write_config("Gateways: enable/disable")) {
236
			mark_subsystem_dirty('staticroutes');
237
		}
238

    
239
		header("Location: system_gateways.php");
240
		exit;
241
	}
242
}
243

    
244
foreach($simplefields as $field) {
245
	$pconfig[$field] = config_get_path("gateways/{$field}");
246
}
247

    
248
$pgtitle = array(gettext("System"), gettext("Routing"), gettext("Gateways"));
249
$pglinks = array("", "@self", "@self");
250
$shortcut_section = "gateways";
251

    
252
include("head.inc");
253

    
254
if ($input_errors) {
255
	print_input_errors($input_errors);
256
}
257

    
258
if ($_POST['apply']) {
259
	print_apply_result_box($retval);
260
}
261

    
262
if (is_subsystem_dirty('staticroutes')) {
263
	print_apply_box(gettext("The gateway configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
264
}
265

    
266
$tab_array = array();
267
$tab_array[0] = array(gettext("Gateways"), true, "system_gateways.php");
268
$tab_array[1] = array(gettext("Static Routes"), false, "system_routes.php");
269
$tab_array[2] = array(gettext("Gateway Groups"), false, "system_gateway_groups.php");
270
display_top_tabs($tab_array);
271

    
272
?>
273
<form method="post">
274
<div class="panel panel-default">
275
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Gateways')?></h2></div>
276
	<div class="panel-body">
277
		<div class="table-responsive">
278
			<table id="gateways" class="table table-striped table-hover table-condensed table-rowdblclickedit">
279
				<thead>
280
					<tr>
281
						<th></th>
282
						<th></th>
283
						<th><?=gettext("Name")?></th>
284
						<th><?=gettext("Default")?></th>
285
						<th><?=gettext("Interface")?></th>
286
						<th><?=gettext("Gateway")?></th>
287
						<th><?=gettext("Monitor IP")?></th>
288
						<th><?=gettext("Description")?></th>
289
						<th><?=gettext("Actions")?></th>
290
					</tr>
291
				</thead>
292
				<tbody>
293
<?php
294
foreach ($a_gateways as $i => $gateway):
295
	if (isset($gateway['inactive'])) {
296
		$title = gettext("Gateway inactive, interface is missing");
297
		$icon = 'fa-regular fa-circle-xmark';
298
	} elseif (isset($gateway['disabled'])) {
299
		$icon = 'fa-solid fa-ban';
300
		$title = gettext("Gateway disabled");
301
	} else {
302
		$icon = 'fa-regular fa-circle-check';
303
		$title = gettext("Gateway enabled");
304
	}
305

    
306
	$gtitle = "";
307
	if (isset($gateway['isdefaultgw'])) {
308
		$gtitle = gettext("Default gateway");
309
	}
310

    
311
	$id = $gateway['attribute'];
312
?>
313
					<tr<?=($icon != 'fa-regular fa-circle-check')? ' class="disabled"' : ''?> onClick="fr_toggle(<?=$id;?>)" id="fr<?=$id;?>">
314
						<td style="white-space: nowrap;">
315
							<?php 
316
							if (is_numeric($id)) :?>
317
								<input type='checkbox' id='frc<?=$id?>' onClick='fr_toggle(<?=$id?>)' name='row[]' value='<?=$id?>'/>
318
								<a class='fa-solid fa-anchor' id='Xmove_<?=$id?>' title='"<?=gettext("Move checked entries to here")?>"'></a>
319
							<?php endif; ?>
320
						</td>
321
						<td title="<?=$title?>"><i class="<?=$icon?>"></i></td>
322
						<td title="<?=$gtitle?>">
323
						<?=htmlspecialchars($gateway['name'])?>
324
<?php
325
							if (isset($gateway['isdefaultgw'])) {
326
								echo ' <i class="fa-solid fa-globe"></i>';
327
							}
328
?>
329
						</td>
330
						<td>
331
							<?=htmlspecialchars($gateway['tiername'])?>
332
						</td>
333
						<td>
334
							<?=htmlspecialchars($gateway['friendlyifdescr'])?>
335
						</td>
336
						<td>
337
							<?=htmlspecialchars($gateway['gateway'])?>
338
						</td>
339
						<td>
340
							<?=htmlspecialchars($gateway['monitor'])?>
341
						</td>
342
						<td>
343
							<?=htmlspecialchars($gateway['descr'])?>
344
						</td>
345
						<td style="white-space: nowrap;">
346
							<a href="system_gateways_edit.php?id=<?=$i?>" class="fa-solid fa-pencil" title="<?=gettext('Edit gateway');?>"></a>
347
							<a href="system_gateways_edit.php?dup=<?=$i?>" class="fa-regular fa-clone" title="<?=gettext('Copy gateway')?>"></a>
348

    
349
<?php if (is_numeric($gateway['attribute'])): ?>
350
	<?php if (isset($gateway['disabled'])) {
351
	?>
352
							<a href="?act=toggle&amp;id=<?=$i?>" class="fa-regular fa-square-check" title="<?=gettext('Enable gateway')?>" usepost></a>
353
	<?php } else {
354
	?>
355
							<a href="?act=toggle&amp;id=<?=$i?>" class="fa-solid fa-ban" title="<?=gettext('Disable gateway')?>" usepost></a>
356
	<?php }
357
	?>
358
							<a href="system_gateways.php?act=del&amp;id=<?=$i?>" class="fa-solid fa-trash-can" title="<?=gettext('Delete gateway')?>" usepost></a>
359

    
360
<?php endif; ?>
361
						</td>
362
					</tr>
363
<?php endforeach; ?>
364
				</tbody>
365
			</table>
366
		</div>
367
	</div>
368
</div>
369

    
370
<nav class="action-buttons">
371
	<button type="submit" id="order-store" name="order-store" class="btn btn-sm btn-primary" value="store changes" disabled title="<?=gettext('Save rule order')?>">
372
		<i class="fa-solid fa-save icon-embed-btn"></i>
373
		<?=gettext("Save")?>
374
	</button>
375
	<a href="system_gateways_edit.php" role="button" class="btn btn-success">
376
		<i class="fa-solid fa-plus icon-embed-btn"></i>
377
		<?=gettext("Add");?>
378
	</a>
379
</nav>
380
</form>
381
<?php
382

    
383
$form = new Form;
384
$section = new Form_Section('Default gateway');
385

    
386
$dflts = available_default_gateways();
387

    
388
$section->addInput(new Form_Select(
389
	'defaultgw4',
390
	'Default gateway IPv4',
391
	$pconfig['defaultgw4'],
392
	$dflts['v4']
393
))->setHelp('Select a gateway or failover gateway group to use as the default gateway.');
394

    
395
$section->addInput(new Form_Select(
396
	'defaultgw6',
397
	'Default gateway IPv6',
398
	$pconfig['defaultgw6'],
399
	$dflts['v6']
400
))->setHelp('Select a gateway or failover gateway group to use as the default gateway.');
401

    
402
$form->add($section);
403
print $form;
404

    
405
?>
406
<div class="infoblock">
407
<?php
408
print_info_box(
409
	sprintf(gettext('%1$s The current default route as present in the current routing table of the operating system'), '<strong><i class="fa-solid fa-globe"></i></strong>') .
410
	sprintf(gettext('%1$s Gateway is inactive, interface is missing'), '<br /><strong><i class="fa-regular fa-circle-xmark"></i></strong>') .
411
	sprintf(gettext('%1$s Gateway disabled'), '<br /><strong><i class="fa-solid fa-ban"></i></strong>') .
412
	sprintf(gettext('%1$s Gateway enabled'), '<br /><strong><i class="fa-regular fa-circle-check"></i></strong>')
413
	);
414
?>
415
</div>
416
<script type="text/javascript">
417
//<![CDATA[
418
events.push(function() {
419
	$('#order-store').click(function () {
420
		// Check all of the rule checkboxes so that their values are posted
421
	   $('[id^=frc]').prop('checked', true);
422
	});
423

    
424
	$('[id^=Xmove_]').click(function (event) {
425
		// anchor click to move gateways around..
426
		moveRowUpAboveAnchor(event.target.id.slice(6),"gateways");
427
		return false;
428
	});
429
	$('[id^=Xmove_]').css('cursor', 'pointer');
430
});
431
	function moveRowUpAboveAnchor(rowId, tableId) {
432
		var table = $('#'+tableId);
433
		var viewcheckboxes = $('[id^=frc]input:checked', table);
434
		var rowview = $("#fr" + rowId, table);
435
		var moveabove = rowview;
436
		//var parent = moveabove[0].parentNode;
437
		
438
		viewcheckboxes.each(function( index ) {
439
			var moveid = this.value;
440
			console.log( index + ": " + this.id );
441

    
442
			var prevrowview = $("#fr" + moveid, table);
443
			prevrowview.insertBefore(moveabove);
444
			$('#order-store').removeAttr('disabled');
445
		});
446
	}
447
//]]>
448
</script>
449

    
450
<?php include("foot.inc");
(198-198/228)