Project

General

Profile

Download (19.5 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("openvpn.inc");
48
require_once("captiveportal.inc");
49
require_once("rrd.inc");
50
require_once("interfaces_fast.inc");
51

    
52
global $friendlyifnames;
53

    
54
global $config;
55

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

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

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

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

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

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

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

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

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

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

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

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

    
159
$ovpn_descrs = array();
160
foreach (['server', 'client'] as $openvpn_mode) {
161
	foreach (config_get_path("openvpn/openvpn-{$openvpn_mode}", []) as $openvpn_settings) {
162
		$portname = openvpn_name($openvpn_mode, $openvpn_settings);
163
		$portlist[$portname] = $openvpn_settings;
164
		$ovpn_descrs[$openvpn_settings['vpnid']] = $openvpn_settings['description'];
165
	}
166
}
167

    
168
global $ipsec_descrs;
169
$ipsec_descrs = interface_ipsec_vti_list_all();
170
foreach ($ipsec_descrs as $ifname => $ifdescr) {
171
	$portlist[$ifname] = array('descr' => $ifdescr);
172
}
173

    
174

    
175
$ifdescrs = interface_assign_description_fast($portlist,$friendlyifnames);
176

    
177
if (isset($_REQUEST['add']) && isset($_REQUEST['if_add'])) {
178
	/* Be sure this port is not being used */
179
	$portused = false;
180
	foreach (config_get_path('interfaces', []) as $ifdata) {
181
		if ($ifdata['if'] == $_REQUEST['if_add']) {
182
			$portused = true;
183
			break;
184
		}
185
	}
186

    
187
	if ($portused === false) {
188
		/* find next free optional interface number */
189
		if (!$config['interfaces']['lan']) {
190
			$newifname = "lan";
191
			$descr = "LAN";
192
		} else {
193
			for ($i = 1; $i <= count($config['interfaces']); $i++) {
194
				if (!$config['interfaces']["opt{$i}"]) {
195
					break;
196
				}
197
			}
198
			$newifname = 'opt' . $i;
199
			$descr = "OPT" . $i;
200
		}
201

    
202
		$config['interfaces'][$newifname] = array();
203
		$config['interfaces'][$newifname]['descr'] = $descr;
204
		$config['interfaces'][$newifname]['if'] = $_POST['if_add'];
205
		if (preg_match(g_get('wireless_regex'), $_POST['if_add'])) {
206
			$config['interfaces'][$newifname]['wireless'] = array();
207
			interface_sync_wireless_clones($config['interfaces'][$newifname], false);
208
		}
209

    
210

    
211
		uksort($config['interfaces'], "compare_interface_friendly_names");
212

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

    
216
		write_config("New interface assigned");
217

    
218
		filter_configure();
219

    
220
		$action_msg = gettext("Interface has been added.");
221
		$class = "success";
222
	}
223

    
224
} else if (isset($_POST['apply'])) {
225
	if (file_exists("/var/run/interface_mismatch_reboot_needed")) {
226
		system_reboot();
227
		$rebootingnow = true;
228
	} else {
229
		write_config("Interfaces assignment settings changed");
230

    
231
		$changes_applied = true;
232
		$retval = 0;
233
		$retval |= filter_configure();
234
	}
235

    
236
} else if (isset($_POST['Submit'])) {
237

    
238
	unset($input_errors);
239

    
240
	/* input validation */
241

    
242
	/* Build a list of the port names so we can see how the interfaces map */
243
	$portifmap = array();
244
	foreach ($portlist as $portname => $portinfo) {
245
		$portifmap[$portname] = array();
246
	}
247

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

    
260
	/* Deliver error message for any port with more than one assignment */
261
	foreach ($portifmap as $portname => $ifnames) {
262
		if (count($ifnames) > 1) {
263
			$errstr = sprintf(gettext('Port %1$s '.
264
				' was assigned to %2$s' .
265
				' interfaces:'), $portname, count($ifnames));
266

    
267
			foreach ($portifmap[$portname] as $ifn) {
268
				$errstr .= " " . convert_friendly_interface_to_friendly_descr(strtolower($ifn)) . " (" . $ifn . ")";
269
			}
270

    
271
			$input_errors[] = $errstr;
272
		} else if (count($ifnames) == 1 && preg_match('/^bridge[0-9]/', $portname) && is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
273
			foreach (config_get_path('bridges/bridged', []) as $bridge) {
274
				if ($bridge['bridgeif'] != $portname) {
275
					continue;
276
				}
277

    
278
				$members = explode(",", strtoupper($bridge['members']));
279
				foreach ($members as $member) {
280
					if ($member == $ifnames[0]) {
281
						$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);
282
						break;
283
					}
284
				}
285
			}
286
		}
287
	}
288

    
289
	foreach (config_get_path('vlans/vlan', []) as $vlan) {
290
		if (does_interface_exist($vlan['if']) == false) {
291
			$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']);
292
		}
293
	}
294

    
295
	if (!$input_errors) {
296
		/* No errors detected, so update the config */
297
		$filter_reload = false;
298
		foreach ($_POST as $ifname => $ifport) {
299

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

    
302
				if (!is_array($ifport)) {
303
					$reloadif = false;
304
					if (!empty($config['interfaces'][$ifname]['if']) && $config['interfaces'][$ifname]['if'] <> $ifport) {
305
						interface_bring_down($ifname);
306
						/* Mark this to be reconfigured in any case. */
307
						$reloadif = true;
308
						$filter_reload = true;
309
						$gateway_monitor_reload = true;
310
					}
311
					$config['interfaces'][$ifname]['if'] = $ifport;
312
					if (isset($portlist[$ifport]['isppp'])) {
313
						$config['interfaces'][$ifname]['ipaddr'] = $portlist[$ifport]['type'];
314
					}
315

    
316
					if ((substr($ifport, 0, 3) == 'gre') ||
317
					    (substr($ifport, 0, 5) == 'gif')) {
318
						config_del_path("interfaces/{$ifname}/ipaddr");
319
						config_del_path("interfaces/{$ifname}/subnet");
320
						config_del_path("interfaces/{$ifname}/ipaddrv6");
321
						config_del_path("interfaces/{$ifname}/subnetv6");
322
					}
323

    
324
					/* check for wireless interfaces, set or clear ['wireless'] */
325
					if (preg_match(g_get('wireless_regex'), $ifport)) {
326
						if (!is_array($config['interfaces'][$ifname]['wireless'])) {
327
							$config['interfaces'][$ifname]['wireless'] = array();
328
						}
329
					} else {
330
						config_del_path("interfaces/{$ifname}/wireless");
331
					}
332

    
333
					/* make sure there is a descr for all interfaces */
334
					if (!isset($config['interfaces'][$ifname]['descr'])) {
335
						$config['interfaces'][$ifname]['descr'] = strtoupper($ifname);
336
					}
337

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

    
359
		enable_rrd_graphing();
360
	}
361
} else {
362
	unset($delbtn);
363
	if (!empty($_POST['del'])) {
364
		$delbtn = key($_POST['del']);
365
	}
366

    
367
	if (isset($delbtn)) {
368
		$id = $delbtn;
369

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

    
386
			init_config_arr(['dhcpd', $id]);
387

    
388
			if (is_array($config['dhcpd']) && is_array($config['dhcpd'][$id])) {
389
				config_del_path("dhcpd/{$id}");
390
				services_dhcpd_configure('inet');
391
			}
392

    
393
			init_config_arr(['dhcpdv6', $id]);
394

    
395
			if (is_array($config['dhcpdv6']) && is_array($config['dhcpdv6'][$id])) {
396
				config_del_path("dhcpdv6/{$id}");
397
				services_dhcpd_configure('inet6');
398
			}
399

    
400
			init_config_arr(['filter', 'rule']);
401

    
402
			foreach (config_get_path('filter/rule', []) as $x => $rule) {
403
				if ($rule['interface'] == $id) {
404
					config_del_path("filter/rule/{$x}");
405
				}
406
			}
407

    
408
			init_config_arr(['nat', 'rule']);
409
		
410
			foreach (config_get_path('nat/rule', []) as $x => $rule) {
411
				if ($rule['interface'] == $id) {
412
					config_del_path("nat/rule/{$x}/interface");
413
				}
414
			}
415

    
416
			write_config(gettext('Interface assignment deleted'));
417

    
418
			/* If we are in firewall/routing mode (not single interface)
419
			 * then ensure that we are not running DHCP on the wan which
420
			 * will make a lot of ISPs unhappy.
421
			 */
422
			if (config_path_enabled('interfaces', 'lan')
423
				&& config_path_enabled('dhcpd', 'wan')) {
424
					config_del_path('dhcpd/wan');
425
			}
426

    
427
			link_interface_to_vlans($realid, "update");
428

    
429
			filter_configure();
430

    
431
			$action_msg = gettext("Interface has been deleted.");
432
			$class = "success";
433
		}
434
	}
435
}
436

    
437
/* Create a list of unused ports */
438
$unused_portlist = array();
439
$portArray = array_keys($portlist);
440

    
441
$ifaceArray = array_column($config['interfaces'],'if');
442
$unused = array_diff($portArray,$ifaceArray);
443
$unused = array_flip($unused);
444
$unused_portlist = array_intersect_key($portlist,$unused);//*/
445
unset($unused,$portArray,$ifaceArray);
446

    
447
include("head.inc");
448

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

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

    
476
pfSense_handle_custom_code("/usr/local/pkg/interfaces_assign/pre_input_errors");
477

    
478
if ($input_errors) {
479
	print_input_errors($input_errors);
480
}
481

    
482
$tab_array = array();
483
$tab_array[] = array(gettext("Interface Assignments"), true, "interfaces_assign.php");
484
$tab_array[] = array(gettext("Interface Groups"), false, "interfaces_groups.php");
485
$tab_array[] = array(gettext("Wireless"), false, "interfaces_wireless.php");
486
$tab_array[] = array(gettext("VLANs"), false, "interfaces_vlan.php");
487
$tab_array[] = array(gettext("QinQs"), false, "interfaces_qinq.php");
488
$tab_array[] = array(gettext("PPPs"), false, "interfaces_ppps.php");
489
$tab_array[] = array(gettext("GREs"), false, "interfaces_gre.php");
490
$tab_array[] = array(gettext("GIFs"), false, "interfaces_gif.php");
491
$tab_array[] = array(gettext("Bridges"), false, "interfaces_bridge.php");
492
$tab_array[] = array(gettext("LAGGs"), false, "interfaces_lagg.php");
493
display_top_tabs($tab_array);
494

    
495
/*Generate the port select box only once.
496
Not indenting the HTML to produce smaller code
497
and faster page load times */
498

    
499
$portselect='';
500
foreach ($portlist as $portname => $portinfo) {
501
	$portselect.='<option value="'.$portname.'"';
502
	$portselect.=">".$ifdescrs[$portname]."</option>\n";
503
}
504

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

    
575
	<button name="Submit" type="submit" class="btn btn-primary" value="<?=gettext('Save')?>"><i class="fa-solid fa-save icon-embed-btn"></i><?=gettext('Save')?></button>
576
</form>
577
<br />
578

    
579
<?php
580
print_info_box(gettext("Interfaces that are configured as members of a lagg(4) interface will not be shown.") .
581
    '<br/><br/>' .
582
    gettext("Wireless interfaces must be created on the Wireless tab before they can be assigned."), 'info', false);
583
?>
584

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