Project

General

Profile

Download (19.6 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-2023 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 $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 $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_get('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
		filter_configure();
227

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

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

    
239
		$changes_applied = true;
240
		$retval = 0;
241
		$retval |= filter_configure();
242
	}
243

    
244
} else if (isset($_POST['Submit'])) {
245

    
246
	unset($input_errors);
247

    
248
	/* input validation */
249

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

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

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

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

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

    
286
				$members = explode(",", strtoupper($bridge['members']));
287
				foreach ($members as $member) {
288
					if ($member == $ifnames[0]) {
289
						$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);
290
						break;
291
					}
292
				}
293
			}
294
		}
295
	}
296

    
297
	foreach (config_get_path('vlans/vlan', []) as $vlan) {
298
		if (does_interface_exist($vlan['if']) == false) {
299
			$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']);
300
		}
301
	}
302

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

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

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

    
324
					if ((substr($ifport, 0, 3) == 'gre') ||
325
					    (substr($ifport, 0, 5) == 'gif')) {
326
						config_del_path("interfaces/{$ifname}/ipaddr");
327
						config_del_path("interfaces/{$ifname}/subnet");
328
						config_del_path("interfaces/{$ifname}/ipaddrv6");
329
						config_del_path("interfaces/{$ifname}/subnetv6");
330
					}
331

    
332
					/* check for wireless interfaces, set or clear ['wireless'] */
333
					if (preg_match(g_get('wireless_regex'), $ifport)) {
334
						if (!is_array($config['interfaces'][$ifname]['wireless'])) {
335
							$config['interfaces'][$ifname]['wireless'] = array();
336
						}
337
					} else {
338
						config_del_path("interfaces/{$ifname}/wireless");
339
					}
340

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

    
346
					if ($reloadif == true) {
347
						if (preg_match(g_get('wireless_regex'), $ifport)) {
348
							interface_sync_wireless_clones($config['interfaces'][$ifname], false);
349
						}
350
						/* Reload all for the interface. */
351
						interface_configure($ifname, true);
352
						$filter_reload = true;
353
					}
354
				}
355
			}
356
		}
357
		/* regenerated ruleset after re-assigning the interface,
358
		 * see https://redmine.pfsense.org/issues/12949 */
359
		if ($filter_reload) {
360
			filter_configure();
361
		}
362
		if ($gateway_monitor_reload) {
363
			setup_gateways_monitor();
364
		}
365
		write_config("Interfaces assignment settings changed");
366

    
367
		enable_rrd_graphing();
368
	}
369
} else {
370
	unset($delbtn);
371
	if (!empty($_POST['del'])) {
372
		$delbtn = key($_POST['del']);
373
	}
374

    
375
	if (isset($delbtn)) {
376
		$id = $delbtn;
377

    
378
		if (link_interface_to_group($id)) {
379
			$input_errors[] = gettext("The interface is part of a group. Please remove it from the group to continue");
380
		} else if (link_interface_to_bridge($id)) {
381
			$input_errors[] = gettext("The interface is part of a bridge. Please remove it from the bridge to continue");
382
		} else if (!empty(link_interface_to_tunnelif($id, 'gre'))) {
383
			$input_errors[] = gettext("The interface is part of a gre tunnel. Please delete the tunnel to continue");
384
		} else if (!empty(link_interface_to_tunnelif($id, 'gif'))) {
385
			$input_errors[] = gettext("The interface is part of a gif tunnel. Please delete the tunnel to continue");
386
		} else if (interface_has_queue($id)) {
387
			$input_errors[] = gettext("The interface has a traffic shaper queue configured.\nPlease remove all queues on the interface to continue.");
388
		} else {
389
			config_del_path("interfaces/{$id}/enable");
390
			$realid = get_real_interface($id);
391
			interface_bring_down($id);
392
			config_del_path("interfaces/{$id}");	/* delete the specified OPTn or LAN*/
393

    
394
			init_config_arr(['dhcpd', $id]);
395

    
396
			if (is_array($config['dhcpd']) && is_array($config['dhcpd'][$id])) {
397
				config_del_path("dhcpd/{$id}");
398
				services_dhcpd_configure('inet');
399
			}
400

    
401
			init_config_arr(['dhcpdv6', $id]);
402

    
403
			if (is_array($config['dhcpdv6']) && is_array($config['dhcpdv6'][$id])) {
404
				config_del_path("dhcpdv6/{$id}");
405
				services_dhcpd_configure('inet6');
406
			}
407

    
408
			init_config_arr(['filter', 'rule']);
409

    
410
			foreach ($config['filter']['rule'] as $x => $rule) {
411
				if ($rule['interface'] == $id) {
412
					config_del_path("filter/rule/{$x}");
413
				}
414
			}
415

    
416
			init_config_arr(['nat', 'rule']);
417
		
418
			foreach ($config['nat']['rule'] as $x => $rule) {
419
				if ($rule['interface'] == $id) {
420
					config_del_path("nat/rule/{$x}/interface");
421
				}
422
			}
423

    
424
			write_config(gettext('Interface assignment deleted'));
425

    
426
			/* If we are in firewall/routing mode (not single interface)
427
			 * then ensure that we are not running DHCP on the wan which
428
			 * will make a lot of ISPs unhappy.
429
			 */
430
			if (config_path_enabled('interfaces', 'lan')
431
				&& config_path_enabled('dhcpd', 'wan')) {
432
					config_del_path('dhcpd/wan');
433
			}
434

    
435
			link_interface_to_vlans($realid, "update");
436

    
437
			filter_configure();
438

    
439
			$action_msg = gettext("Interface has been deleted.");
440
			$class = "success";
441
		}
442
	}
443
}
444

    
445
/* Create a list of unused ports */
446
$unused_portlist = array();
447
$portArray = array_keys($portlist);
448

    
449
$ifaceArray = array_column($config['interfaces'],'if');
450
$unused = array_diff($portArray,$ifaceArray);
451
$unused = array_flip($unused);
452
$unused_portlist = array_intersect_key($portlist,$unused);//*/
453
unset($unused,$portArray,$ifaceArray);
454

    
455
include("head.inc");
456

    
457
if (file_exists("/var/run/interface_mismatch_reboot_needed")) {
458
	if ($_POST) {
459
		if ($rebootingnow) {
460
			$action_msg = gettext("The system is now rebooting. Please wait.");
461
			$class = "success";
462
		} else {
463
			$applymsg = gettext("Reboot is needed. Please apply the settings in order to reboot.");
464
			$class = "warning";
465
		}
466
	} else {
467
		$action_msg = gettext("Interface mismatch detected. Please resolve the mismatch, save and then click 'Apply Changes'. The firewall will reboot afterwards.");
468
		$class = "warning";
469
	}
470
}
471

    
472
if (file_exists("/tmp/reload_interfaces")) {
473
	echo "<p>\n";
474
	print_apply_box(gettext("The interface configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
475
	echo "<br /></p>\n";
476
} elseif ($applymsg) {
477
	print_apply_box($applymsg);
478
} elseif ($action_msg) {
479
	print_info_box($action_msg, $class);
480
} elseif ($changes_applied) {
481
	print_apply_result_box($retval);
482
}
483

    
484
pfSense_handle_custom_code("/usr/local/pkg/interfaces_assign/pre_input_errors");
485

    
486
if ($input_errors) {
487
	print_input_errors($input_errors);
488
}
489

    
490
$tab_array = array();
491
$tab_array[] = array(gettext("Interface Assignments"), true, "interfaces_assign.php");
492
$tab_array[] = array(gettext("Interface Groups"), false, "interfaces_groups.php");
493
$tab_array[] = array(gettext("Wireless"), false, "interfaces_wireless.php");
494
$tab_array[] = array(gettext("VLANs"), false, "interfaces_vlan.php");
495
$tab_array[] = array(gettext("QinQs"), false, "interfaces_qinq.php");
496
$tab_array[] = array(gettext("PPPs"), false, "interfaces_ppps.php");
497
$tab_array[] = array(gettext("GREs"), false, "interfaces_gre.php");
498
$tab_array[] = array(gettext("GIFs"), false, "interfaces_gif.php");
499
$tab_array[] = array(gettext("Bridges"), false, "interfaces_bridge.php");
500
$tab_array[] = array(gettext("LAGGs"), false, "interfaces_lagg.php");
501
display_top_tabs($tab_array);
502

    
503
/*Generate the port select box only once.
504
Not indenting the HTML to produce smaller code
505
and faster page load times */
506

    
507
$portselect='';
508
foreach ($portlist as $portname => $portinfo) {
509
	$portselect.='<option value="'.$portname.'"';
510
	$portselect.=">".$ifdescrs[$portname]."</option>\n";
511
}
512

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

    
583
	<button name="Submit" type="submit" class="btn btn-primary" value="<?=gettext('Save')?>"><i class="fa fa-save icon-embed-btn"></i><?=gettext('Save')?></button>
584
</form>
585
<br />
586

    
587
<?php
588
print_info_box(gettext("Interfaces that are configured as members of a lagg(4) interface will not be shown.") .
589
    '<br/><br/>' .
590
    gettext("Wireless interfaces must be created on the Wireless tab before they can be assigned."), 'info', false);
591
?>
592

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