Project

General

Profile

Download (19.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * interfaces_assign.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-2022 Rubicon Communications, LLC (Netgate)
9
 * All rights reserved.
10
 *
11
 * originally based on m0n0wall (http://m0n0.ch/wall)
12
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
13
 * Written by Jim McBeath based on existing m0n0wall files
14
 * All rights reserved.
15
 *
16
 * Licensed under the Apache License, Version 2.0 (the "License");
17
 * you may not use this file except in compliance with the License.
18
 * You may obtain a copy of the License at
19
 *
20
 * http://www.apache.org/licenses/LICENSE-2.0
21
 *
22
 * Unless required by applicable law or agreed to in writing, software
23
 * distributed under the License is distributed on an "AS IS" BASIS,
24
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
 * See the License for the specific language governing permissions and
26
 * limitations under the License.
27
 */
28

    
29
##|+PRIV
30
##|*IDENT=page-interfaces-assignnetworkports
31
##|*NAME=Interfaces: Interface Assignments
32
##|*DESCR=Allow access to the 'Interfaces: Interface Assignments' page.
33
##|*MATCH=interfaces_assign.php*
34
##|-PRIV
35

    
36
//$timealla = microtime(true);
37

    
38
$pgtitle = array(gettext("Interfaces"), gettext("Interface Assignments"));
39
$shortcut_section = "interfaces";
40

    
41
require_once("guiconfig.inc");
42
require_once("functions.inc");
43
require_once("filter.inc");
44
require_once("shaper.inc");
45
require_once("ipsec.inc");
46
require_once("vpn.inc");
47
require_once("captiveportal.inc");
48
require_once("rrd.inc");
49
require_once("interfaces_fast.inc");
50

    
51
global $friendlyifnames;
52

    
53
global $config;
54

    
55
/*moved most gettext calls to here, we really don't want to be repeatedly calling gettext() within loops if it can be avoided.*/
56
$gettextArray = array('add'=>gettext('Add'),'addif'=>gettext('Add interface'),'delete'=>gettext('Delete'),'deleteif'=>gettext('Delete interface'),'edit'=>gettext('Edit'),'on'=>gettext('on'));
57

    
58
/*
59
	In this file, "port" refers to the physical port name,
60
	while "interface" refers to LAN, WAN, or OPTn.
61
*/
62

    
63
/* get list without VLAN interfaces */
64
$portlist = get_interface_list();
65

    
66
/*another *_fast function from interfaces_fast.inc. These functions are basically the same as the
67
ones they're named after, except they (usually) take an array and (always) return an array. This means that they only
68
need to be called once per script run, the returned array contains all the data necessary for repeated use */
69
$friendlyifnames = convert_real_interface_to_friendly_interface_name_fast();
70

    
71
/* add wireless clone interfaces */
72
if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
73
	foreach ($config['wireless']['clone'] as $clone) {
74
		$portlist[$clone['cloneif']] = $clone;
75
		$portlist[$clone['cloneif']]['iswlclone'] = true;
76
	}
77
}
78

    
79
/* add VLAN interfaces */
80
if (isset($config['vlans']['vlan']) && is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
81
	//$timea = microtime(true);
82
	foreach ($config['vlans']['vlan'] as $vlan) {
83
		$portlist[$vlan['vlanif']] = $vlan;
84
		$portlist[$vlan['vlanif']]['isvlan'] = true;
85
	}
86
}
87

    
88
/* add Bridge interfaces */
89
if (isset($config['bridges']['bridged']) && is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
90
	foreach ($config['bridges']['bridged'] as $bridge) {
91
		$portlist[$bridge['bridgeif']] = $bridge;
92
		$portlist[$bridge['bridgeif']]['isbridge'] = true;
93
	}
94
}
95

    
96
/* add GIF interfaces */
97
if (isset($config['gifs']['gif']) && is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
98
	foreach ($config['gifs']['gif'] as $gif) {
99
		$portlist[$gif['gifif']] = $gif;
100
		$portlist[$gif['gifif']]['isgif'] = true;
101
	}
102
}
103

    
104
/* add GRE interfaces */
105
if (isset($config['gres']['gre']) && is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
106
	foreach ($config['gres']['gre'] as $gre) {
107
		$portlist[$gre['greif']] = $gre;
108
		$portlist[$gre['greif']]['isgre'] = true;
109
	}
110
}
111

    
112
/* add LAGG interfaces */
113
if (isset($config['laggs']['lagg']) && is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
114
	foreach ($config['laggs']['lagg'] as $lagg) {
115
		$portlist[$lagg['laggif']] = $lagg;
116
		$portlist[$lagg['laggif']]['islagg'] = true;
117
		/* LAGG members cannot be assigned */
118
		$lagifs = explode(',', $lagg['members']);
119
		foreach ($lagifs as $lagif) {
120
			if (isset($portlist[$lagif])) {
121
				unset($portlist[$lagif]);
122
			}
123
		}
124
	}
125
}
126

    
127
/* add QinQ interfaces */
128
if (isset($config['qinqs']['qinqentry']) && is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
129
	foreach ($config['qinqs']['qinqentry'] as $qinq) {
130
		$portlist["{$qinq['vlanif']}"]['descr'] = "VLAN {$qinq['tag']} on {$qinq['if']}";
131
		$portlist["{$qinq['vlanif']}"]['isqinq'] = true;
132
		/* QinQ members */
133
		$qinqifs = explode(' ', $qinq['members']);
134
		foreach ($qinqifs as $qinqif) {
135
			$portlist["{$qinq['vlanif']}.{$qinqif}"]['descr'] = "QinQ {$qinqif} on VLAN {$qinq['tag']} on {$qinq['if']}";
136
			$portlist["{$qinq['vlanif']}.{$qinqif}"]['isqinq'] = true;
137
		}
138
	}
139
}
140

    
141
/* add PPP interfaces */
142
if (isset($config['ppps']['ppp']) && is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
143
	foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
144
		$portname = $ppp['if'];
145
		$portlist[$portname] = $ppp;
146
		$portlist[$portname]['isppp'] = true;
147
		$ports_base = basename($ppp['ports']);
148
		if (isset($ppp['descr'])) {
149
			$portlist[$portname]['descr'] = strtoupper($ppp['if']). "({$ports_base}) - {$ppp['descr']}";
150
		} else if (isset($ppp['username'])) {
151
			$portlist[$portname]['descr'] = strtoupper($ppp['if']). "({$ports_base}) - {$ppp['username']}";
152
		} else {
153
			$portlist[$portname]['descr'] = strtoupper($ppp['if']). "({$ports_base})";
154
		}
155
	}
156
}
157

    
158
$ovpn_descrs = array();
159
if (isset($config['openvpn']) && is_array($config['openvpn'])) {
160
	if (isset($config['openvpn']['openvpn-server']) && is_array($config['openvpn']['openvpn-server'])) {
161
		foreach ($config['openvpn']['openvpn-server'] as $s) {
162
			$portname = "ovpns{$s['vpnid']}";
163
			$portlist[$portname] = $s;
164
			$ovpn_descrs[$s['vpnid']] = $s['description'];
165
		}
166
	}
167
	if (isset($config['openvpn']['openvpn-client']) && is_array($config['openvpn']['openvpn-client'])) {
168
		foreach ($config['openvpn']['openvpn-client'] as $c) {
169
			$portname = "ovpnc{$c['vpnid']}";
170
			$portlist[$portname] = $c;
171
			$ovpn_descrs[$c['vpnid']] = $c['description'];
172
		}
173
	}
174
}
175

    
176
global $ipsec_descrs;
177
$ipsec_descrs = interface_ipsec_vti_list_all();
178
foreach ($ipsec_descrs as $ifname => $ifdescr) {
179
	$portlist[$ifname] = array('descr' => $ifdescr);
180
}
181

    
182

    
183
$ifdescrs = interface_assign_description_fast($portlist,$friendlyifnames);
184

    
185
if (isset($_REQUEST['add']) && isset($_REQUEST['if_add'])) {
186
	/* Be sure this port is not being used */
187
	$portused = false;
188
	foreach ($config['interfaces'] as $ifname => $ifdata) {
189
		if ($ifdata['if'] == $_REQUEST['if_add']) {
190
			$portused = true;
191
			break;
192
		}
193
	}
194

    
195
	if ($portused === false) {
196
		/* find next free optional interface number */
197
		if (!$config['interfaces']['lan']) {
198
			$newifname = "lan";
199
			$descr = "LAN";
200
		} else {
201
			for ($i = 1; $i <= count($config['interfaces']); $i++) {
202
				if (!$config['interfaces']["opt{$i}"]) {
203
					break;
204
				}
205
			}
206
			$newifname = 'opt' . $i;
207
			$descr = "OPT" . $i;
208
		}
209

    
210
		$config['interfaces'][$newifname] = array();
211
		$config['interfaces'][$newifname]['descr'] = $descr;
212
		$config['interfaces'][$newifname]['if'] = $_POST['if_add'];
213
		if (preg_match($g['wireless_regex'], $_POST['if_add'])) {
214
			$config['interfaces'][$newifname]['wireless'] = array();
215
			interface_sync_wireless_clones($config['interfaces'][$newifname], false);
216
		}
217

    
218

    
219
		uksort($config['interfaces'], "compare_interface_friendly_names");
220

    
221
		/* XXX: Do not remove this. */
222
		unlink_if_exists("{$g['tmp_path']}/config.cache");
223

    
224
		write_config("New interface assigned");
225

    
226
		$action_msg = gettext("Interface has been added.");
227
		$class = "success";
228
	}
229

    
230
} else if (isset($_POST['apply'])) {
231
	if (file_exists("/var/run/interface_mismatch_reboot_needed")) {
232
		system_reboot();
233
		$rebootingnow = true;
234
	} else {
235
		write_config("Interfaces assignment settings changed");
236

    
237
		$changes_applied = true;
238
		$retval = 0;
239
		$retval |= filter_configure();
240
	}
241

    
242
} else if (isset($_POST['Submit'])) {
243

    
244
	unset($input_errors);
245

    
246
	/* input validation */
247

    
248
	/* Build a list of the port names so we can see how the interfaces map */
249
	$portifmap = array();
250
	foreach ($portlist as $portname => $portinfo) {
251
		$portifmap[$portname] = array();
252
	}
253

    
254
	/* Go through the list of ports selected by the user,
255
	build a list of port-to-interface mappings in portifmap */
256
	foreach ($_POST as $ifname => $ifport) {
257
		if (($ifname == 'lan') || ($ifname == 'wan') || (substr($ifname, 0, 3) == 'opt')) {
258
			if (array_key_exists($ifport, $portlist)) {
259
				$portifmap[$ifport][] = strtoupper($ifname);
260
			} else {
261
				$input_errors[] = sprintf(gettext('Cannot set port %1$s because the submitted interface does not exist.'), $ifname);
262
			}
263
		}
264
	}
265

    
266
	/* Deliver error message for any port with more than one assignment */
267
	foreach ($portifmap as $portname => $ifnames) {
268
		if (count($ifnames) > 1) {
269
			$errstr = sprintf(gettext('Port %1$s '.
270
				' was assigned to %2$s' .
271
				' interfaces:'), $portname, count($ifnames));
272

    
273
			foreach ($portifmap[$portname] as $ifn) {
274
				$errstr .= " " . convert_friendly_interface_to_friendly_descr(strtolower($ifn)) . " (" . $ifn . ")";
275
			}
276

    
277
			$input_errors[] = $errstr;
278
		} else if (count($ifnames) == 1 && preg_match('/^bridge[0-9]/', $portname) && is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
279
			foreach ($config['bridges']['bridged'] as $bridge) {
280
				if ($bridge['bridgeif'] != $portname) {
281
					continue;
282
				}
283

    
284
				$members = explode(",", strtoupper($bridge['members']));
285
				foreach ($members as $member) {
286
					if ($member == $ifnames[0]) {
287
						$input_errors[] = sprintf(gettext('Cannot set port %1$s to interface %2$s because this interface is a member of %3$s.'), $portname, $member, $portname);
288
						break;
289
					}
290
				}
291
			}
292
		}
293
	}
294

    
295
	if (is_array($config['vlans']['vlan'])) {
296
		foreach ($config['vlans']['vlan'] as $vlan) {
297
			if (does_interface_exist($vlan['if']) == false) {
298
				$input_errors[] = sprintf(gettext('Vlan parent interface %1$s does not exist anymore so vlan id %2$s cannot be created please fix the issue before continuing.'), $vlan['if'], $vlan['tag']);
299
			}
300
		}
301
	}
302

    
303
	if (!$input_errors) {
304
		/* No errors detected, so update the config */
305
		foreach ($_POST as $ifname => $ifport) {
306

    
307
			if (($ifname == 'lan') || ($ifname == 'wan') || (substr($ifname, 0, 3) == 'opt')) {
308

    
309
				if (!is_array($ifport)) {
310
					$reloadif = false;
311
					if (!empty($config['interfaces'][$ifname]['if']) && $config['interfaces'][$ifname]['if'] <> $ifport) {
312
						interface_bring_down($ifname);
313
						/* Mark this to be reconfigured in any case. */
314
						$reloadif = true;
315
					}
316
					$config['interfaces'][$ifname]['if'] = $ifport;
317
					if (isset($portlist[$ifport]['isppp'])) {
318
						$config['interfaces'][$ifname]['ipaddr'] = $portlist[$ifport]['type'];
319
					}
320

    
321
					if ((substr($ifport, 0, 3) == 'gre') ||
322
					    (substr($ifport, 0, 5) == 'gif')) {
323
						unset($config['interfaces'][$ifname]['ipaddr']);
324
						unset($config['interfaces'][$ifname]['subnet']);
325
						unset($config['interfaces'][$ifname]['ipaddrv6']);
326
						unset($config['interfaces'][$ifname]['subnetv6']);
327
					}
328

    
329
					/* check for wireless interfaces, set or clear ['wireless'] */
330
					if (preg_match($g['wireless_regex'], $ifport)) {
331
						if (!is_array($config['interfaces'][$ifname]['wireless'])) {
332
							$config['interfaces'][$ifname]['wireless'] = array();
333
						}
334
					} else {
335
						unset($config['interfaces'][$ifname]['wireless']);
336
					}
337

    
338
					/* make sure there is a descr for all interfaces */
339
					if (!isset($config['interfaces'][$ifname]['descr'])) {
340
						$config['interfaces'][$ifname]['descr'] = strtoupper($ifname);
341
					}
342

    
343
					if ($reloadif == true) {
344
						if (preg_match($g['wireless_regex'], $ifport)) {
345
							interface_sync_wireless_clones($config['interfaces'][$ifname], false);
346
						}
347
						/* Reload all for the interface. */
348
						interface_configure($ifname, true);
349
					}
350
				}
351
			}
352
		}
353
		write_config("Interfaces assignment settings changed");
354

    
355
		enable_rrd_graphing();
356
	}
357
} else {
358
	unset($delbtn);
359
	if (!empty($_POST['del'])) {
360
		$delbtn = key($_POST['del']);
361
	}
362

    
363
	if (isset($delbtn)) {
364
		$id = $delbtn;
365

    
366
		if (link_interface_to_group($id)) {
367
			$input_errors[] = gettext("The interface is part of a group. Please remove it from the group to continue");
368
		} else if (link_interface_to_bridge($id)) {
369
			$input_errors[] = gettext("The interface is part of a bridge. Please remove it from the bridge to continue");
370
		} else if (!empty(link_interface_to_tunnelif($id, 'gre'))) {
371
			$input_errors[] = gettext("The interface is part of a gre tunnel. Please delete the tunnel to continue");
372
		} else if (!empty(link_interface_to_tunnelif($id, 'gif'))) {
373
			$input_errors[] = gettext("The interface is part of a gif tunnel. Please delete the tunnel to continue");
374
		} else if (interface_has_queue($id)) {
375
			$input_errors[] = gettext("The interface has a traffic shaper queue configured.\nPlease remove all queues on the interface to continue.");
376
		} else {
377
			unset($config['interfaces'][$id]['enable']);
378
			$realid = get_real_interface($id);
379
			interface_bring_down($id);   /* down the interface */
380

    
381
			unset($config['interfaces'][$id]);	/* delete the specified OPTn or LAN*/
382

    
383
			init_config_arr(['dhcpd', $id]);
384

    
385
			if (is_array($config['dhcpd']) && is_array($config['dhcpd'][$id])) {
386
				unset($config['dhcpd'][$id]);
387
				services_dhcpd_configure('inet');
388
			}
389

    
390
			init_config_arr(['dhcpdv6', $id]);
391

    
392
			if (is_array($config['dhcpdv6']) && is_array($config['dhcpdv6'][$id])) {
393
				unset($config['dhcpdv6'][$id]);
394
				services_dhcpd_configure('inet6');
395
			}
396

    
397
			init_config_arr(['filter', 'rule']);
398

    
399
			foreach ($config['filter']['rule'] as $x => $rule) {
400
				if ($rule['interface'] == $id) {
401
					unset($config['filter']['rule'][$x]);
402
				}
403
			}
404

    
405
			init_config_arr(['nat', 'rule']);
406
		
407
			foreach ($config['nat']['rule'] as $x => $rule) {
408
				if ($rule['interface'] == $id) {
409
					unset($config['nat']['rule'][$x]['interface']);
410
				}
411
			}
412

    
413
			write_config(gettext('Interface assignment deleted'));
414

    
415
			/* If we are in firewall/routing mode (not single interface)
416
			 * then ensure that we are not running DHCP on the wan which
417
			 * will make a lot of ISPs unhappy.
418
			 */
419
			if ($config['interfaces']['lan'] && $config['dhcpd']['wan']) {
420
				unset($config['dhcpd']['wan']);
421
			}
422

    
423
			link_interface_to_vlans($realid, "update");
424

    
425
			$action_msg = gettext("Interface has been deleted.");
426
			$class = "success";
427
		}
428
	}
429
}
430

    
431
/* Create a list of unused ports */
432
$unused_portlist = array();
433
$portArray = array_keys($portlist);
434

    
435
$ifaceArray = array_column($config['interfaces'],'if');
436
$unused = array_diff($portArray,$ifaceArray);
437
$unused = array_flip($unused);
438
$unused_portlist = array_intersect_key($portlist,$unused);//*/
439
unset($unused,$portArray,$ifaceArray);
440

    
441
include("head.inc");
442

    
443
if (file_exists("/var/run/interface_mismatch_reboot_needed")) {
444
	if ($_POST) {
445
		if ($rebootingnow) {
446
			$action_msg = gettext("The system is now rebooting. Please wait.");
447
			$class = "success";
448
		} else {
449
			$applymsg = gettext("Reboot is needed. Please apply the settings in order to reboot.");
450
			$class = "warning";
451
		}
452
	} else {
453
		$action_msg = gettext("Interface mismatch detected. Please resolve the mismatch, save and then click 'Apply Changes'. The firewall will reboot afterwards.");
454
		$class = "warning";
455
	}
456
}
457

    
458
if (file_exists("/tmp/reload_interfaces")) {
459
	echo "<p>\n";
460
	print_apply_box(gettext("The interface configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
461
	echo "<br /></p>\n";
462
} elseif ($applymsg) {
463
	print_apply_box($applymsg);
464
} elseif ($action_msg) {
465
	print_info_box($action_msg, $class);
466
} elseif ($changes_applied) {
467
	print_apply_result_box($retval);
468
}
469

    
470
pfSense_handle_custom_code("/usr/local/pkg/interfaces_assign/pre_input_errors");
471

    
472
if ($input_errors) {
473
	print_input_errors($input_errors);
474
}
475

    
476
$tab_array = array();
477
$tab_array[] = array(gettext("Interface Assignments"), true, "interfaces_assign.php");
478
$tab_array[] = array(gettext("Interface Groups"), false, "interfaces_groups.php");
479
$tab_array[] = array(gettext("Wireless"), false, "interfaces_wireless.php");
480
$tab_array[] = array(gettext("VLANs"), false, "interfaces_vlan.php");
481
$tab_array[] = array(gettext("QinQs"), false, "interfaces_qinq.php");
482
$tab_array[] = array(gettext("PPPs"), false, "interfaces_ppps.php");
483
$tab_array[] = array(gettext("GREs"), false, "interfaces_gre.php");
484
$tab_array[] = array(gettext("GIFs"), false, "interfaces_gif.php");
485
$tab_array[] = array(gettext("Bridges"), false, "interfaces_bridge.php");
486
$tab_array[] = array(gettext("LAGGs"), false, "interfaces_lagg.php");
487
display_top_tabs($tab_array);
488

    
489
/*Generate the port select box only once.
490
Not indenting the HTML to produce smaller code
491
and faster page load times */
492

    
493
$portselect='';
494
foreach ($portlist as $portname => $portinfo) {
495
	$portselect.='<option value="'.$portname.'"';
496
	$portselect.=">".$ifdescrs[$portname]."</option>\n";
497
}
498

    
499
?>
500
<form action="interfaces_assign.php" method="post">
501
	<div class="table-responsive">
502
	<table class="table table-striped table-hover">
503
	<thead>
504
		<tr>
505
			<th><?=gettext("Interface")?></th>
506
			<th><?=gettext("Network port")?></th>
507
			<th>&nbsp;</th>
508
		</tr>
509
	</thead>
510
	<tbody>
511
<?php
512
	$i=0;
513
	foreach ($config['interfaces'] as $ifname => $iface):
514
		if ($iface['descr']) {
515
			$ifdescr = $iface['descr'];
516
		} else {
517
			$ifdescr = strtoupper($ifname);
518
		}
519
?>
520
		<tr>
521
			<td><a href="/interfaces.php?if=<?=$ifname?>"><?=$ifdescr?></a></td>
522
			<td>
523
				<select name="<?=$ifname?>" id="<?=$ifname?>" class="form-control">
524
<?php
525
/*port select menu generation loop replaced with pre-prepared select menu to reduce page generation time */
526
echo str_replace('value="'.$iface['if'].'">','value="'.$iface['if'].'" selected>',$portselect);
527
?>
528
				</select>
529
			</td>
530
			<td>
531
<?php if ($ifname != 'wan'):?>
532
				<button type="submit" name="del[<?=$ifname?>]" class="btn btn-danger btn-sm" title="<?=$gettextArray['deleteif']?>">
533
					<i class="fa fa-trash icon-embed-btn"></i>
534
					<?=$gettextArray["delete"]?>
535
				</button>
536
<?php endif;?>
537
			</td>
538
		</tr>
539
<?php $i++;
540
endforeach;
541
	if (count($config['interfaces']) < count($portlist)):
542
?>
543
		<tr>
544
			<th>
545
				<?=gettext("Available network ports:")?>
546
			</th>
547
			<td>
548
				<select name="if_add" id="if_add" class="form-control">
549
<?php
550
/* HTML not indented to save on transmission/render time */
551
foreach ($unused_portlist as $portname => $portinfo):?>
552
<option value="<?=$portname?>" <?=($portname == $iface['if']) ? ' selected': ''?>><?=$ifdescrs[$portname]?></option>
553
<?php endforeach;
554
?>
555
				</select>
556
			</td>
557
			<td>
558
				<button type="submit" name="add" title="<?=gettext("Add selected interface")?>" value="add interface" class="btn btn-success btn-sm" >
559
					<i class="fa fa-plus icon-embed-btn"></i>
560
					<?=$gettextArray["add"]?>
561
				</button>
562
			</td>
563
		</tr>
564
<?php endif;?>
565
		</tbody>
566
	</table>
567
	</div>
568

    
569
	<button name="Submit" type="submit" class="btn btn-primary" value="<?=gettext('Save')?>"><i class="fa fa-save icon-embed-btn"></i><?=gettext('Save')?></button>
570
</form>
571
<br />
572

    
573
<?php
574
print_info_box(gettext("Interfaces that are configured as members of a lagg(4) interface will not be shown.") .
575
    '<br/><br/>' .
576
    gettext("Wireless interfaces must be created on the Wireless tab before they can be assigned."), 'info', false);
577
?>
578

    
579
<?php include("foot.inc")?>
(72-72/228)