Project

General

Profile

Download (17.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	interfaces_bridge_edit.php
5

    
6
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
7
	Copyright (C) 2008 Ermal Luçi
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

    
16
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19

    
20
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31
/*
32
	pfSense_MODULE: interfaces
33
*/
34

    
35
##|+PRIV
36
##|*IDENT=page-interfaces-bridge-edit
37
##|*NAME=Interfaces: Bridge edit page
38
##|*DESCR=Allow access to the 'Interfaces: Bridge : Edit' page.
39
##|*MATCH=interfaces_bridge_edit.php*
40
##|-PRIV
41

    
42
require("guiconfig.inc");
43

    
44
if (!is_array($config['bridges']['bridged']))
45
	$config['bridges']['bridged'] = array();
46

    
47
$a_bridges = &$config['bridges']['bridged'];
48

    
49
$ifacelist = get_configured_interface_with_descr();
50

    
51
foreach ($ifacelist as $bif => $bdescr) {
52
	if (substr(get_real_interface($bif), 0, 3) == "gre") {
53
		unset($ifacelist[$bif]);
54
	}
55
}
56

    
57
if (is_numericint($_GET['id'])) {
58
	$id = $_GET['id'];
59
}
60
if (isset($_POST['id']) && is_numericint($_POST['id'])) {
61
	$id = $_POST['id'];
62
}
63

    
64
if (isset($id) && $a_bridges[$id]) {
65
	$pconfig['enablestp'] = isset($a_bridges[$id]['enablestp']);
66
	$pconfig['descr'] = $a_bridges[$id]['descr'];
67
	$pconfig['bridgeif'] = $a_bridges[$id]['bridgeif'];
68
	$pconfig['members'] = $a_bridges[$id]['members'];
69
	$pconfig['maxaddr'] = $a_bridges[$id]['maxaddr'];
70
	$pconfig['timeout'] = $a_bridges[$id]['timeout'];
71
	if ($a_bridges[$id]['static']) {
72
		$pconfig['static'] = $a_bridges[$id]['static'];
73
	}
74
	if ($a_bridges[$id]['private']) {
75
		$pconfig['private'] = $a_bridges[$id]['private'];
76
	}
77
	if (isset($a_bridges[$id]['stp'])) {
78
		$pconfig['stp'] = $a_bridges[$id]['stp'];
79
	}
80
	$pconfig['maxage'] = $a_bridges[$id]['maxage'];
81
	$pconfig['fwdelay'] = $a_bridges[$id]['fwdelay'];
82
	$pconfig['hellotime'] = $a_bridges[$id]['hellotime'];
83
	$pconfig['priority'] = $a_bridges[$id]['priority'];
84
	$pconfig['proto'] = $a_bridges[$id]['proto'];
85
	$pconfig['holdcnt'] = $a_bridges[$id]['holdcnt'];
86

    
87
	if (!empty($a_bridges[$id]['ifpriority'])) {
88
		$pconfig['ifpriority'] = explode(",", $a_bridges[$id]['ifpriority']);
89
		$ifpriority = array();
90
		foreach ($pconfig['ifpriority'] as $cfg) {
91
			list ($key, $value) = explode(":", $cfg);
92
			$embprioritycfg[$key] = $value;
93
			foreach ($embprioritycfg as $key => $value) {
94
				$ifpriority[$key] = $value;
95
			}
96
		}
97
		$pconfig['ifpriority'] = $ifpriority;
98
	}
99

    
100
	if (!empty($a_bridges[$id]['ifpathcost'])) {
101
		$pconfig['ifpathcost'] = explode(",", $a_bridges[$id]['ifpathcost']);
102
		$ifpathcost = array();
103
		foreach ($pconfig['ifpathcost'] as $cfg) {
104
			list ($key, $value) = explode(":", $cfg);
105
			$embpathcfg[$key] = $value;
106
			foreach ($embpathcfg as $key => $value) {
107
				$ifpathcost[$key] = $value;
108
			}
109
		}
110
		$pconfig['ifpathcost'] = $ifpathcost;
111
	}
112

    
113
	$pconfig['span'] = $a_bridges[$id]['span'];
114
	if (isset($a_bridges[$id]['edge'])) {
115
		$pconfig['edge'] = $a_bridges[$id]['edge'];
116
	}
117
	if (isset($a_bridges[$id]['autoedge'])) {
118
		$pconfig['autoedge'] = $a_bridges[$id]['autoedge'];
119
	}
120
	if (isset($a_bridges[$id]['ptp'])) {
121
		$pconfig['ptp'] = $a_bridges[$id]['ptp'];
122
	}
123
	if (isset($a_bridges[$id]['autoptp'])) {
124
		$pconfig['autoptp'] = $a_bridges[$id]['autoptp'];
125
	}
126
}
127

    
128
if ($_POST) {
129
	unset($input_errors);
130
	$pconfig = $_POST;
131

    
132
	/* input validation */
133
	$reqdfields = explode(" ", "members");
134
	$reqdfieldsn = array(gettext("Member Interfaces"));
135

    
136
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
137

    
138
	if ($_POST['maxage'] && !is_numeric($_POST['maxage'])) {
139
		$input_errors[] = gettext("Maxage needs to be an integer between 6 and 40.");
140
	}
141
	if ($_POST['maxaddr'] && !is_numeric($_POST['maxaddr'])) {
142
		$input_errors[] = gettext("Maxaddr needs to be an integer.");
143
	}
144
	if ($_POST['timeout'] && !is_numeric($_POST['timeout'])) {
145
		$input_errors[] = gettext("Timeout needs to be an integer.");
146
	}
147
	if ($_POST['fwdelay'] && !is_numeric($_POST['fwdelay'])) {
148
		$input_errors[] = gettext("Forward Delay needs to be an integer between 4 and 30.");
149
	}
150
	if ($_POST['hellotime'] && !is_numeric($_POST['hellotime'])) {
151
		$input_errors[] = gettext("Hello time for STP needs to be an integer between 1 and 2.");
152
	}
153
	if ($_POST['priority'] && !is_numeric($_POST['priority'])) {
154
		$input_errors[] = gettext("Priority for STP needs to be an integer between 0 and 61440.");
155
	}
156
	if ($_POST['holdcnt'] && !is_numeric($_POST['holdcnt'])) {
157
		$input_errors[] = gettext("Transmit Hold Count for STP needs to be an integer between 1 and 10.");
158
	}
159
	foreach ($ifacelist as $ifn => $ifdescr) {
160
		if ($_POST[$ifn] <> "" && !is_numeric($_POST[$ifn])) {
161
			$input_errors[] = "{$ifdescr} " . gettext("interface priority for STP needs to be an integer between 0 and 240.");
162
		}
163
	}
164

    
165
	$i = 0;
166

    
167
	foreach ($ifacelist as $ifn => $ifdescr) {
168
		if ($_POST["{$ifn}{$i}"] <> "" && !is_numeric($_POST["{$ifn}{$i}"])) {
169
			$input_errors[] = "{$ifdescr} " . gettext("interface path cost for STP needs to be an integer between 1 and 200000000.");
170
		}
171
		$i++;
172
	}
173

    
174
	if (!is_array($_POST['members']) || count($_POST['members']) < 1) {
175
		$input_errors[] = gettext("You must select at least one member interface for a bridge.");
176
	}
177

    
178
	if (is_array($_POST['members'])) {
179
		foreach ($_POST['members'] as $ifmembers) {
180
			if (empty($config['interfaces'][$ifmembers])) {
181
				$input_errors[] = gettext("A member interface passed does not exist in configuration");
182
			}
183
			if (is_array($config['interfaces'][$ifmembers]['wireless']) &&
184
			    $config['interfaces'][$ifmembers]['wireless']['mode'] != "hostap") {
185
				$input_errors[] = gettext("Bridging a wireless interface is only possible in hostap mode.");
186
			}
187
			if ($_POST['span'] != "none" && $_POST['span'] == $ifmembers) {
188
				$input_errors[] = gettext("Span interface cannot be part of the bridge. Remove the span interface from bridge members to continue.");
189
			}
190
		}
191
	}
192

    
193
	if (!$input_errors) {
194
		$bridge = array();
195
		$bridge['members'] = implode(',', $_POST['members']);
196
		$bridge['enablestp'] = $_POST['enablestp'] ? true : false;
197
		$bridge['descr'] = $_POST['descr'];
198
		$bridge['maxaddr'] = $_POST['maxaddr'];
199
		$bridge['timeout'] = $_POST['timeout'];
200
		if ($_POST['static']) {
201
			$bridge['static'] = implode(',', $_POST['static']);
202
		}
203
		if ($_POST['private']) {
204
			$bridge['private'] = implode(',', $_POST['private']);
205
		}
206
		if (isset($_POST['stp'])) {
207
			$bridge['stp'] = implode(',', $_POST['stp']);
208
		}
209
		$bridge['maxage'] = $_POST['maxage'];
210
		$bridge['fwdelay'] = $_POST['fwdelay'];
211
		$bridge['hellotime'] = $_POST['hellotime'];
212
		$bridge['priority'] = $_POST['priority'];
213
		$bridge['proto'] = $_POST['proto'];
214
		$bridge['holdcnt'] = $_POST['holdcnt'];
215
		$i = 0;
216
		$ifpriority = "";
217
		$ifpathcost = "";
218

    
219
		foreach ($ifacelist as $ifn => $ifdescr) {
220
			if ($_POST[$ifn] <> "") {
221
				if ($i > 0) {
222
					$ifpriority .= ",";
223
				}
224
				$ifpriority .= $ifn.":".$_POST[$ifn];
225
			}
226
			if ($_POST["{$ifn}0"] <> "") {
227
				if ($i > 0) {
228
					$ifpathcost .= ",";
229
				}
230
				$ifpathcost .= $ifn.":".$_POST["{$ifn}0"];
231
			}
232
			$i++;
233
		}
234

    
235
		$bridge['ifpriority'] = $ifpriority;
236
		$bridge['ifpathcost'] = $ifpathcost;
237

    
238
		if ($_POST['span'] != "none") {
239
			$bridge['span'] = $_POST['span'];
240
		} else {
241
			unset($bridge['span']);
242
		}
243
		if (isset($_POST['edge'])) {
244
			$bridge['edge'] = implode(',', $_POST['edge']);
245
		}
246
		if (isset($_POST['autoedge'])) {
247
			$bridge['autoedge'] = implode(',', $_POST['autoedge']);
248
		}
249
		if (isset($_POST['ptp'])) {
250
			$bridge['ptp'] = implode(',', $_POST['ptp']);
251
		}
252
		if (isset($_POST['autoptp'])) {
253
			$bridge['autoptp'] = implode(',', $_POST['autoptp']);
254
		}
255

    
256

    
257
		$bridge['bridgeif'] = $_POST['bridgeif'];
258
		interface_bridge_configure($bridge);
259
		if ($bridge['bridgeif'] == "" || !stristr($bridge['bridgeif'], "bridge")) {
260
			$input_errors[] = gettext("Error occurred creating interface, please retry.");
261
		} else {
262
			if (isset($id) && $a_bridges[$id]) {
263
				$a_bridges[$id] = $bridge;
264
			} else {
265
				$a_bridges[] = $bridge;
266
			}
267

    
268
			write_config();
269

    
270
			$confif = convert_real_interface_to_friendly_interface_name($bridge['bridgeif']);
271
			if ($confif <> "") {
272
				interface_configure($confif);
273
			}
274

    
275
			header("Location: interfaces_bridge.php");
276
			exit;
277
		}
278
	}
279
}
280

    
281
function build_spanport_list() {
282
	global $ifacelist;
283

    
284
	$splist = array('none' => 'None');
285

    
286
	foreach ($ifacelist as $ifn => $ifdescr)
287
		$splist[$ifn] = $ifdescr;
288

    
289
	return($splist);
290
}
291

    
292
function build_member_list() {
293
	global $pconfig, $ifacelist;
294

    
295
	$memberlist = array('list' => array(),
296
						'selected' => array());
297

    
298
	$members_array = explode(',', $pconfig['members']);
299
	foreach ($ifacelist as $ifn => $ifinfo) {
300
		$memberlist['list'][$ifn] = $ifinfo;
301

    
302
		if (in_array($ifn, $members_array))
303
		   array_push($memberlist['selected'], $ifn);
304
	}
305
	unset($members_array);
306
	return($memberlist);
307
}
308

    
309
function build_port_list($selecton) {
310
	global $pconfig, $ifacelist;
311

    
312
	$portlist = array('list' => array(),
313
						'selected' => array());
314

    
315
	foreach ($ifacelist as $ifn => $ifdescr) {
316
		$portlist['list'][$ifn] = $ifdescr;
317

    
318
		if (stristr($selecton, $ifn))
319
		   array_push($portlist['selected'], $ifn);
320
	}
321

    
322
	return($portlist);
323
}
324

    
325
$pgtitle = array(gettext("Interfaces"),gettext("Bridge"),gettext("Edit"));
326
$shortcut_section = "interfaces";
327
include("head.inc");
328

    
329
if ($input_errors)
330
	print_input_errors($input_errors);
331

    
332
require('classes/Form.class.php');
333

    
334
$form = new Form();
335

    
336
$section = new Form_Section('Bridge Configuration');
337

    
338
$memberslist = build_member_list();
339

    
340
$section->addInput(new Form_Select(
341
	'members',
342
	'Member Interfaces',
343
	$memberslist['selected'],
344
	$memberslist['list'],
345
	true // Allow multiples
346
))->setHelp('Interfaces participating in the bridge');
347

    
348
$section->addInput(new Form_Input(
349
	'Descr',
350
	'Description',
351
	'text',
352
	$pconfig['descr']
353
));
354

    
355
$section->addInput(new Form_Checkbox(
356
	'showadvanced',
357
	'Advanced',
358
	'Show advanced options',
359
	$pconfig['showadvanced']
360
))->toggles('.toggle-advanced');
361

    
362
$form->add($section);
363

    
364
$section = new Form_Section('Advanced Configuration');
365

    
366
// Set initial toggle state manually for now
367
if($pconfig['showadvanced'])
368
	$section->addClass('toggle-advanced in');
369
else
370
	$section->addClass('toggle-advanced collapse');
371

    
372
$section->addInput(new Form_Input(
373
	'maxaddr',
374
	'Cache Size',
375
	'text',
376
	$pconfig['maxaddr']
377
))->setHelp('Set the size of the bridge address cache. The default is 100 entries');
378

    
379
$section->addInput(new Form_Input(
380
	'timeout',
381
	'Cache expire time',
382
	'text',
383
	$pconfig['timeout']
384
))->setHelp('Set the timeout of address cache entries to this number of seconds. If seconds is zero, then address cache entries will not be expired. The default is 240 seconds');
385

    
386
$section->addInput(new Form_Select(
387
	'span',
388
	'Span Port',
389
	$pconfig['span'],
390
	build_spanport_list()
391
))->setHelp('Add the interface named by interface as a span port on the bridge. Span ports transmit a copy of every frame received by the bridge.' .
392
			'This is most useful for snooping a bridged network passively on another host connected to one of the span ports of the bridge. <br />' .
393
			'%sThe span interface cannot be part of the bridge member interfaces.%s', ['<strong>', '</strong>']);
394

    
395
$edgelist = build_port_list($pconfig['edge']);
396

    
397
$section->addInput(new Form_Select(
398
	'edge[]',
399
	'Edge Ports',
400
	$edgelist['selected'],
401
	$edgelist['list'],
402
	true
403
))->setHelp('Set interface as an edge port. An edge port connects directly to end stations and cannot create bridging loops in the network; this allows it to transition straight to forwarding.');
404

    
405
$edgelist = build_port_list($pconfig['autoedge']);
406

    
407
$section->addInput(new Form_Select(
408
	'autoedge[]',
409
	'Auto Edge Ports',
410
	$edgelist['selected'],
411
	$edgelist['list'],
412
	true
413
))->setHelp('Allow interface to automatically detect edge status. This is the default for all interfaces added to a bridge.' .
414
			'%sThis will disable the autoedge status of interfaces. %s', ['<strong>', '</strong>']);
415

    
416
$edgelist = build_port_list($pconfig['ptp']);
417

    
418
$section->addInput(new Form_Select(
419
	'ptp',
420
	'PTP Ports',
421
	$edgelist['selected'],
422
	$edgelist['list'],
423
	true
424
))->setHelp('Set the interface as a point-to-point link. This is required for straight transitions to forwarding and should be enabled on a direct link to another RSTP-capable switch.');
425

    
426
$edgelist = build_port_list($pconfig['autoptp']);
427

    
428
$section->addInput(new Form_Select(
429
	'autoptp[]',
430
	'Auto PTP Ports',
431
	$edgelist['selected'],
432
	$edgelist['list'],
433
	true
434
))->setHelp('Automatically detect the point-to-point status on interface by checking the full duplex link status. This is the default for interfaces added to the bridge.' .
435
			'%sThe interfaces selected here will be removed from default autoedge status. %s', ['<strong>', '</strong>']);
436

    
437
$edgelist = build_port_list($pconfig['static']);
438

    
439
$section->addInput(new Form_Select(
440
	'static[]',
441
	'Sticky Ports',
442
	$edgelist['selected'],
443
	$edgelist['list'],
444
	true
445
))->setHelp('Mark an interface as a "sticky" interface. Dynamically learned address entries are treated as static once entered into the cache. ' .
446
			'Sticky entries are never aged out of the cache or replaced, even if the address is seen on a different interface.');
447

    
448
$edgelist = build_port_list($pconfig['private']);
449

    
450
$section->addInput(new Form_Select(
451
	'private[]',
452
	'Private Ports',
453
	$edgelist['selected'],
454
	$edgelist['list'],
455
	true
456
))->setHelp('Mark an interface as a "private" interface. A private interface does not forward any traffic to any other port that is also a private interface. ');
457

    
458
//	STP section
459
// ToDo: - Should disable spanning tree section when not checked
460
$section->addInput(new Form_Checkbox(
461
	'enablestp',
462
	'Enable RSTP/STP',
463
	null,
464
	$pconfig['enablestp']
465
));
466

    
467
// Show the spanning tree section
468
$form->add($section);
469
$section = new Form_Section('RSTP/STP');
470
if($pconfig['showadvanced'])
471
	$section->addClass('toggle-advanced in');
472
else
473
	$section->addClass('toggle-advanced collapse');
474

    
475
$section->addInput(new Form_Select(
476
	'proto',
477
	'Protocol',
478
	$pconfig['proto'],
479
	array('rstp' => 'RSTP',
480
		  'stp' => 'STP')
481
))->setHelp('Protocol used for spanning tree.');
482

    
483
$edgelist = build_port_list($pconfig['stp']);
484

    
485
$section->addInput(new Form_Select(
486
	'stp[]',
487
	'STP Interfaces',
488
	$edgelist['selected'],
489
	$edgelist['list'],
490
	true
491
))->setHelp('Enable Spanning Tree Protocol on interface. The if_bridge(4) driver has support for the IEEE 802.1D Spanning Tree Protocol (STP).' .
492
			'STP is used to detect and remove loops in a network topology.');
493

    
494
$section->addInput(new Form_Input(
495
	'maxage',
496
	'Valid time',
497
	'number',
498
	$pconfig['maxage'],
499
	['placeholder' => 20, 'min' => 6, 'max' => 40]
500
))->setHelp('Set the time that a Spanning Tree Protocol configuration is valid. The default is 20 seconds. The minimum is 6 seconds and the maximum is 40 seconds.');
501

    
502
$section->addInput(new Form_Input(
503
	'fwdelay',
504
	'Forward time',
505
	'number',
506
	$pconfig['fwdelay'],
507
	['placeholder' => 15, 'min' => 4, 'max' => 30]
508
))->setHelp('Set the time that must pass before an interface begins forwarding packets when Spanning Tree is enabled. The default is 15 seconds. The minimum is 4 seconds and the maximum is 30 seconds. ');
509

    
510
$section->addInput(new Form_Input(
511
	'hellotime',
512
	'Hello time',
513
	'number',
514
	$pconfig['hellotime'],
515
	['placeholder' => 2, 'min' => 1, 'max' => 2, 'step' => '0.1']
516
))->setHelp('Set the time in seconds between broadcasting of Spanning Tree Protocol configuration messages. The hello time may only be changed when operating in legacy STP mode.' .
517
			'The default is 2 seconds. The minimum is 1 second and the maximum is 2 seconds.');
518

    
519
$section->addInput(new Form_Input(
520
	'priority',
521
	'Priority',
522
	'text',
523
	$pconfig['priority'],
524
	['placeholder' => 32768, 'min' => 0, 'max' => 61440]
525
))->setHelp('Set the bridge priority for Spanning Tree. The default is 32768. The minimum is 0 and the maximum is 61440. ');
526

    
527
$section->addInput(new Form_Input(
528
	'holdcnt',
529
	'Hold Count',
530
	'number',
531
	$pconfig['holdcnt'],
532
	['placeholder' => 6, 'min' => 1, 'max' => 10]
533
))->setHelp('Set the transmit hold count for Spanning Tree. This is the number of packets transmitted before being rate limited. The default is 6. The minimum is 1 and the maximum is 10.');
534

    
535
foreach ($ifacelist as $ifn => $ifdescr) {
536
	$section->addInput(new Form_Input(
537
		$ifn,
538
		$ifdescr . ' Priority',
539
		'number',
540
		$pconfig[$ifn],
541
		['placeholder' => 128, 'min' => 0, 'max' => 240, 'step' => 16]
542
	))->setHelp('Set the Spanning Tree priority of interface to value. The default is 128. The minimum is 0 and the maximum is 240. Increments of 16.');
543
}
544

    
545
$i = 0;
546
foreach ($ifacelist as $ifn => $ifdescr) {
547
	$section->addInput(new Form_Input(
548
		$ifn . $i,
549
		$ifdescr . ' Path cost',
550
		'number',
551
		$ifpathcost[$ifn],
552
		[ 'placeholder' => 0, 'min' => 1, 'max' => 200000000]
553
	))->setHelp('Set the Spanning Tree path cost of interface to value. The default is calculated from the link speed. '.
554
		'To change a previously selected path cost back to automatic, set the cost to 0. The minimum is 1 and the maximum is 200000000.');
555
	$i++;
556
}
557

    
558
$form->add($section);
559
print($form);
560

    
561
include("foot.inc");
(86-86/238)