Project

General

Profile

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

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

    
34
//$timealla = microtime(true);
35

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

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

    
49
global $friendlyifnames;
50

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

    
54
/*
55
	In this file, "port" refers to the physical port name,
56
	while "interface" refers to LAN, WAN, or OPTn.
57
*/
58

    
59
/* get list without VLAN interfaces */
60
$portlist = get_interface_list();
61

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

    
67
/* add wireless clone interfaces */
68
if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
69
	foreach ($config['wireless']['clone'] as $clone) {
70
		$portlist[$clone['cloneif']] = $clone;
71
		$portlist[$clone['cloneif']]['iswlclone'] = true;
72
	}
73
}
74

    
75
/* add VLAN interfaces */
76
if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
77
	//$timea = microtime(true);
78
	foreach ($config['vlans']['vlan'] as $vlan) {
79
		$portlist[$vlan['vlanif']] = $vlan;
80
		$portlist[$vlan['vlanif']]['isvlan'] = true;
81
	}
82
}
83

    
84
/* add Bridge interfaces */
85
if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
86
	foreach ($config['bridges']['bridged'] as $bridge) {
87
		$portlist[$bridge['bridgeif']] = $bridge;
88
		$portlist[$bridge['bridgeif']]['isbridge'] = true;
89
	}
90
}
91

    
92
/* add GIF interfaces */
93
if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
94
	foreach ($config['gifs']['gif'] as $gif) {
95
		$portlist[$gif['gifif']] = $gif;
96
		$portlist[$gif['gifif']]['isgif'] = true;
97
	}
98
}
99

    
100
/* add GRE interfaces */
101
if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
102
	foreach ($config['gres']['gre'] as $gre) {
103
		$portlist[$gre['greif']] = $gre;
104
		$portlist[$gre['greif']]['isgre'] = true;
105
	}
106
}
107

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

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

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

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

    
172

    
173
$ifdescrs = interface_assign_description_fast($portlist,$friendlyifnames);
174

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

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

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

    
208

    
209
		uksort($config['interfaces'], "compare_interface_friendly_names");
210

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

    
214
		write_config();
215

    
216
		$action_msg = gettext("Interface has been added.");
217
		$class = "success";
218
	}
219

    
220
} else if (isset($_POST['apply'])) {
221
	if (file_exists("/var/run/interface_mismatch_reboot_needed")) {
222
		system_reboot();
223
		$rebootingnow = true;
224
	} else {
225
		write_config();
226

    
227
		$changes_applied = true;
228
		$retval = 0;
229
		$retval |= filter_configure();
230
	}
231

    
232
} else if (isset($_POST['Submit'])) {
233

    
234
	unset($input_errors);
235

    
236
	/* input validation */
237

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

    
244
	/* Go through the list of ports selected by the user,
245
	build a list of port-to-interface mappings in portifmap */
246
	foreach ($_POST as $ifname => $ifport) {
247
		if (($ifname == 'lan') || ($ifname == 'wan') || (substr($ifname, 0, 3) == 'opt')) {
248
			$portifmap[$ifport][] = strtoupper($ifname);
249
		}
250
	}
251

    
252
	/* Deliver error message for any port with more than one assignment */
253
	foreach ($portifmap as $portname => $ifnames) {
254
		if (count($ifnames) > 1) {
255
			$errstr = sprintf(gettext('Port %1$s '.
256
				' was assigned to %2$s' .
257
				' interfaces:'), $portname, count($ifnames));
258

    
259
			foreach ($portifmap[$portname] as $ifn) {
260
				$errstr .= " " . convert_friendly_interface_to_friendly_descr(strtolower($ifn)) . " (" . $ifn . ")";
261
			}
262

    
263
			$input_errors[] = $errstr;
264
		} else if (count($ifnames) == 1 && preg_match('/^bridge[0-9]/', $portname) && is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
265
			foreach ($config['bridges']['bridged'] as $bridge) {
266
				if ($bridge['bridgeif'] != $portname) {
267
					continue;
268
				}
269

    
270
				$members = explode(",", strtoupper($bridge['members']));
271
				foreach ($members as $member) {
272
					if ($member == $ifnames[0]) {
273
						$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);
274
						break;
275
					}
276
				}
277
			}
278
		}
279
	}
280

    
281
	if (is_array($config['vlans']['vlan'])) {
282
		foreach ($config['vlans']['vlan'] as $vlan) {
283
			if (does_interface_exist($vlan['if']) == false) {
284
				$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']);
285
			}
286
		}
287
	}
288

    
289
	if (!$input_errors) {
290
		/* No errors detected, so update the config */
291
		foreach ($_POST as $ifname => $ifport) {
292

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

    
295
				if (!is_array($ifport)) {
296
					$reloadif = false;
297
					if (!empty($config['interfaces'][$ifname]['if']) && $config['interfaces'][$ifname]['if'] <> $ifport) {
298
						interface_bring_down($ifname);
299
						/* Mark this to be reconfigured in any case. */
300
						$reloadif = true;
301
					}
302
					$config['interfaces'][$ifname]['if'] = $ifport;
303
					if (isset($portlist[$ifport]['isppp'])) {
304
						$config['interfaces'][$ifname]['ipaddr'] = $portlist[$ifport]['type'];
305
					}
306

    
307
					if (substr($ifport, 0, 3) == 'gre' || substr($ifport, 0, 3) == 'gif') {
308
						unset($config['interfaces'][$ifname]['ipaddr']);
309
						unset($config['interfaces'][$ifname]['subnet']);
310
						unset($config['interfaces'][$ifname]['ipaddrv6']);
311
						unset($config['interfaces'][$ifname]['subnetv6']);
312
					}
313

    
314
					/* check for wireless interfaces, set or clear ['wireless'] */
315
					if (preg_match($g['wireless_regex'], $ifport)) {
316
						if (!is_array($config['interfaces'][$ifname]['wireless'])) {
317
							$config['interfaces'][$ifname]['wireless'] = array();
318
						}
319
					} else {
320
						unset($config['interfaces'][$ifname]['wireless']);
321
					}
322

    
323
					/* make sure there is a descr for all interfaces */
324
					if (!isset($config['interfaces'][$ifname]['descr'])) {
325
						$config['interfaces'][$ifname]['descr'] = strtoupper($ifname);
326
					}
327

    
328
					if ($reloadif == true) {
329
						if (preg_match($g['wireless_regex'], $ifport)) {
330
							interface_sync_wireless_clones($config['interfaces'][$ifname], false);
331
						}
332
						/* Reload all for the interface. */
333
						interface_configure($ifname, true);
334
					}
335
				}
336
			}
337
		}
338
		write_config();
339

    
340
		enable_rrd_graphing();
341
	}
342
} else {
343
	unset($delbtn);
344
	if (!empty($_POST['del'])) {
345
		$delbtn = key($_POST['del']);
346
	}
347

    
348
	if (isset($delbtn)) {
349
		$id = $delbtn;
350

    
351
		if (link_interface_to_group($id)) {
352
			$input_errors[] = gettext("The interface is part of a group. Please remove it from the group to continue");
353
		} else if (link_interface_to_bridge($id)) {
354
			$input_errors[] = gettext("The interface is part of a bridge. Please remove it from the bridge to continue");
355
		} else if (link_interface_to_gre($id)) {
356
			$input_errors[] = gettext("The interface is part of a gre tunnel. Please delete the tunnel to continue");
357
		} else if (link_interface_to_gif($id)) {
358
			$input_errors[] = gettext("The interface is part of a gif tunnel. Please delete the tunnel to continue");
359
		} else if (interface_has_queue($id)) {
360
			$input_errors[] = gettext("The interface has a traffic shaper queue configured.\nPlease remove all queues on the interface to continue.");
361
		} else {
362
			unset($config['interfaces'][$id]['enable']);
363
			$realid = get_real_interface($id);
364
			interface_bring_down($id);   /* down the interface */
365

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

    
368
			if (is_array($config['dhcpd']) && is_array($config['dhcpd'][$id])) {
369
				unset($config['dhcpd'][$id]);
370
				services_dhcpd_configure('inet');
371
			}
372

    
373
			if (is_array($config['dhcpdv6']) && is_array($config['dhcpdv6'][$id])) {
374
				unset($config['dhcpdv6'][$id]);
375
				services_dhcpd_configure('inet6');
376
			}
377

    
378
			if (count($config['filter']['rule']) > 0) {
379
				foreach ($config['filter']['rule'] as $x => $rule) {
380
					if ($rule['interface'] == $id) {
381
						unset($config['filter']['rule'][$x]);
382
					}
383
				}
384
			}
385
			if (is_array($config['nat']['rule']) && count($config['nat']['rule']) > 0) {
386
				foreach ($config['nat']['rule'] as $x => $rule) {
387
					if ($rule['interface'] == $id) {
388
						unset($config['nat']['rule'][$x]['interface']);
389
					}
390
				}
391
			}
392

    
393
			write_config();
394

    
395
			/* If we are in firewall/routing mode (not single interface)
396
			 * then ensure that we are not running DHCP on the wan which
397
			 * will make a lot of ISP's unhappy.
398
			 */
399
			if ($config['interfaces']['lan'] && $config['dhcpd']['wan']) {
400
				unset($config['dhcpd']['wan']);
401
			}
402

    
403
			link_interface_to_vlans($realid, "update");
404

    
405
			$action_msg = gettext("Interface has been deleted.");
406
			$class = "success";
407
		}
408
	}
409
}
410

    
411
/* Create a list of unused ports */
412
$unused_portlist = array();
413
$portArray = array_keys($portlist);
414

    
415
$ifaceArray = array_column($config['interfaces'],'if');
416
$unused = array_diff($portArray,$ifaceArray);
417
$unused = array_flip($unused);
418
$unused_portlist = array_intersect_key($portlist,$unused);//*/
419
unset($unused,$portArray,$ifaceArray);
420

    
421
include("head.inc");
422

    
423
if (file_exists("/var/run/interface_mismatch_reboot_needed")) {
424
	if ($_POST) {
425
		if ($rebootingnow) {
426
			$action_msg = gettext("The system is now rebooting. Please wait.");
427
			$class = "success";
428
		} else {
429
			$applymsg = gettext("Reboot is needed. Please apply the settings in order to reboot.");
430
			$class = "warning";
431
		}
432
	} else {
433
		$action_msg = gettext("Interface mismatch detected. Please resolve the mismatch, save and then click 'Apply Changes'. The firewall will reboot afterwards.");
434
		$class = "warning";
435
	}
436
}
437

    
438
if (file_exists("/tmp/reload_interfaces")) {
439
	echo "<p>\n";
440
	print_apply_box(gettext("The interface configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
441
	echo "<br /></p>\n";
442
} elseif ($applymsg) {
443
	print_apply_box($applymsg);
444
} elseif ($action_msg) {
445
	print_info_box($action_msg, $class);
446
} elseif ($changes_applied) {
447
	print_apply_result_box($retval);
448
}
449

    
450
pfSense_handle_custom_code("/usr/local/pkg/interfaces_assign/pre_input_errors");
451

    
452
if ($input_errors) {
453
	print_input_errors($input_errors);
454
}
455

    
456
$tab_array = array();
457
$tab_array[] = array(gettext("Interface Assignments"), true, "interfaces_assign.php");
458
$tab_array[] = array(gettext("Interface Groups"), false, "interfaces_groups.php");
459
$tab_array[] = array(gettext("Wireless"), false, "interfaces_wireless.php");
460
$tab_array[] = array(gettext("VLANs"), false, "interfaces_vlan.php");
461
$tab_array[] = array(gettext("QinQs"), false, "interfaces_qinq.php");
462
$tab_array[] = array(gettext("PPPs"), false, "interfaces_ppps.php");
463
$tab_array[] = array(gettext("GREs"), false, "interfaces_gre.php");
464
$tab_array[] = array(gettext("GIFs"), false, "interfaces_gif.php");
465
$tab_array[] = array(gettext("Bridges"), false, "interfaces_bridge.php");
466
$tab_array[] = array(gettext("LAGGs"), false, "interfaces_lagg.php");
467
display_top_tabs($tab_array);
468

    
469
/*Generate the port select box only once.
470
Not indenting the HTML to produce smaller code
471
and faster page load times */
472

    
473
$portselect='';
474
foreach ($portlist as $portname => $portinfo) {
475
	$portselect.='<option value="'.$portname.'"';
476
	$portselect.=">".$ifdescrs[$portname]."</option>\n";
477
}
478

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

    
549
	<button name="Submit" type="submit" class="btn btn-primary" value="<?=gettext('Save')?>"><i class="fa fa-save icon-embed-btn"></i><?=gettext('Save')?></button>
550
</form>
551
<br />
552

    
553
<?php
554
print_info_box(gettext("Interfaces that are configured as members of a lagg(4) interface will not be shown.") .
555
    '<br/><br/>' .
556
    gettext("Wireless interfaces must be created on the Wireless tab before they can be assigned."), 'info', false);
557
?>
558

    
559
<?php include("foot.inc")?>
(72-72/231)