Project

General

Profile

Download (159 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	interfaces.inc
4
	Copyright (C) 2004-2008 Scott Ullrich
5
	Copyright (C) 2008-2009 Ermal Lu?i
6
	All rights reserved.
7

    
8
	function interfaces_wireless_configure is
9
	Copyright (C) 2005 Espen Johansen
10
	All rights reserved.
11

    
12
	originally part of m0n0wall (http://m0n0.ch/wall)
13
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
14
	All rights reserved.
15

    
16
	Redistribution and use in source and binary forms, with or without
17
	modification, are permitted provided that the following conditions are met:
18

    
19
	1. Redistributions of source code must retain the above copyright notices,
20
	   this list of conditions and the following disclaimer.
21

    
22
	2. Redistributions in binary form must reproduce the above copyright
23
	   notices, this list of conditions and the following disclaimer in the
24
	   documentation and/or other materials provided with the distribution.
25

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

    
37
	pfSense_BUILDER_BINARIES:	/sbin/dhclient	/bin/sh	/usr/bin/grep	/usr/bin/xargs	/usr/bin/awk	/usr/local/sbin/choparp
38
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig	/sbin/route	/usr/sbin/ngctl	/usr/sbin/arp	/bin/kill	/usr/local/sbin/mpd5
39
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dhcp6c
40
	pfSense_MODULE:	interfaces
41

    
42
*/
43

    
44
/* include all configuration functions */
45
require_once("globals.inc");
46
require_once("util.inc");
47
require_once("gwlb.inc");
48

    
49
function interfaces_bring_up($interface) {
50
	if(!$interface) {
51
		log_error(gettext("interfaces_bring_up() was called but no variable defined."));
52
		log_error( "Backtrace: " . debug_backtrace() );
53
		return;
54
	}
55
	pfSense_interface_flags($interface, IFF_UP);
56
}
57

    
58
/*
59
 * Return the interface array
60
 */
61
function get_interface_arr($flush = false) {
62
	global $interface_arr_cache;
63

    
64
	/* If the cache doesn't exist, build it */
65
	if (!isset($interface_arr_cache) or $flush)
66
		$interface_arr_cache = pfSense_interface_listget();
67

    
68
	return $interface_arr_cache;
69
}
70

    
71
/*
72
 * does_interface_exist($interface): return true or false if a interface is
73
 * detected.
74
 */
75
function does_interface_exist($interface, $flush = true) {
76
	global $config;
77

    
78
	if(!$interface)
79
		return false;
80

    
81
	$ints = get_interface_arr($flush);
82
	if (in_array($interface, $ints))
83
		return true;
84
	else
85
		return false;
86
}
87

    
88
/*
89
 * does_vip_exist($vip): return true or false if a vip is
90
 * configured.
91
 */
92
function does_vip_exist($vip) {
93
	global $config;
94

    
95
	if(!$vip)
96
		return false;
97

    
98

    
99
	switch ($vip['mode']) {
100
	case "carp":
101
	case "ipalias":
102
		/* XXX: Make proper checks? */
103
		$realif = get_real_interface($vip['interface']);
104
		if (!does_interface_exist($realif)) {
105
			return false;
106
		}
107
		break;
108
	case "proxyarp":
109
		/* XXX: Implement this */
110
	default:
111
		return false;
112
	}
113

    
114
	$ifacedata = pfSense_getall_interface_addresses($realif);
115
	foreach ($ifacedata as $vipips) {
116
		if ($vipips == "{$vip['subnet']}/{$vip['subnet_bits']}")
117
			return true;
118
	}
119

    
120
	return false;
121
}
122

    
123
function interface_netgraph_needed($interface = "wan") {
124
	global $config;
125

    
126
	$found = false;
127
	if (!empty($config['pptpd']) &&
128
		$config['pptpd']['mode'] == "server")
129
		$found = true;
130
	if ($found == false && !empty($config['l2tp']) &&
131
		$config['l2tp']['mode'] == "server")
132
		$found = true;
133
	if ($found == false && is_array($config['pppoes']['pppoe'])) {
134
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
135
			if ($pppoe['mode'] != "server")
136
				continue;
137
			if ($pppoe['interface'] == $interface) {
138
				$found = true;
139
				break;
140
			}
141
		}
142
	}
143
	if ($found == false)
144
		$found = interface_isppp_type($interface);
145

    
146
	if ($found == false) {
147
		$realif = get_real_interface($interface);
148
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
149
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
150
				$ports = explode(',',$ppp['ports']);
151
				foreach($ports as $pid => $port){
152
					$port = get_real_interface($port);
153
					if ($realif == $port) {
154
						$found = true;
155
						break;
156
					}
157
					/* Find the parent interfaces of the vlans in the MLPPP configs
158
					* there should be only one element in the array here
159
					* -- this could be better . . . */
160
					$parent_if = get_parent_interface($port);
161
					if ($realif == $parent_if[0]) {
162
						$found = true;
163
						break;
164
					}
165
				}
166
			}
167
		}
168
	}
169

    
170
	if ($found == false) {
171
		$realif = get_real_interface($interface);
172
		pfSense_ngctl_detach("{$realif}:", $realif);
173
	}
174
	/* NOTE: We make sure for this on interface_ppps_configure()
175
	 *	no need to do it here again.
176
	 *	else
177
	 *		pfSense_ngctl_attach(".", $realif);
178
	 */
179
}
180

    
181
function interfaces_loopback_configure() {
182
	global $g;
183

    
184
	if ($g['platform'] == 'jail')
185
		return;
186
	if (platform_booting())
187
		echo gettext("Configuring loopback interface...");
188
	pfSense_interface_setaddress("lo0", "127.0.0.1");
189
	interfaces_bring_up("lo0");
190
	if (platform_booting())
191
		echo gettext("done.") . "\n";
192
	return 0;
193
}
194

    
195
function interfaces_vlan_configure($realif = "") {
196
	global $config, $g;
197
	if (platform_booting())
198
		echo gettext("Configuring VLAN interfaces...");
199
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
200
		foreach ($config['vlans']['vlan'] as $vlan) {
201
			if (empty($vlan['vlanif']))
202
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
203
			if (!empty($realif) && $realif != $vlan['vlanif'])
204
				continue;
205

    
206
			/* XXX: Maybe we should report any errors?! */
207
			interface_vlan_configure($vlan);
208
		}
209
	}
210
	if (platform_booting())
211
		echo gettext("done.") . "\n";
212
}
213

    
214
function interface_vlan_configure(&$vlan) {
215
	global $config, $g;
216

    
217
	if (!is_array($vlan)) {
218
		log_error(gettext("VLAN: called with wrong options. Problems with config!"));
219
		return;
220
	}
221
	$if = $vlan['if'];
222
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
223
	$tag = $vlan['tag'];
224

    
225
	if (empty($if)) {
226
		log_error(gettext("interface_vlan_configure called with if undefined."));
227
		return;
228
	}
229

    
230
	/* make sure the parent interface is up */
231
	interfaces_bring_up($if);
232
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
233
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
234

    
235
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
236
		interface_bring_down($vlanif, true);
237
	} else {
238
		$tmpvlanif = pfSense_interface_create("vlan");
239
		pfSense_interface_rename($tmpvlanif, $vlanif);
240
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
241
	}
242

    
243
	pfSense_vlan_create($vlanif, $if, $tag);
244

    
245
	interfaces_bring_up($vlanif);
246

    
247
	/* invalidate interface cache */
248
	get_interface_arr(true);
249

    
250
	/* XXX: ermal -- for now leave it here at the moment it does not hurt. */
251
	interfaces_bring_up($if);
252

    
253
	return $vlanif;
254
}
255

    
256
function interface_qinq_configure(&$vlan, $fd = NULL) {
257
	global $config, $g;
258

    
259
	if (!is_array($vlan)) {
260
		log_error(sprintf(gettext("QinQ compat VLAN: called with wrong options. Problems with config!%s"), "\n"));
261
		return;
262
	}
263

    
264
	$qinqif = $vlan['if'];
265
	$tag = $vlan['tag'];
266
	if(empty($qinqif)) {
267
		log_error(sprintf(gettext("interface_qinq_configure called with if undefined.%s"), "\n"));
268
		return;
269
	}
270

    
271
	if(!does_interface_exist($qinqif)) {
272
		log_error(sprintf(gettext("interface_qinq_configure called with invalid if.%s"), "\n"));
273
		return;
274
	}
275

    
276
	$vlanif = interface_vlan_configure($vlan);
277

    
278
	if ($fd == NULL) {
279
		$exec = true;
280
		$fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
281
	} else
282
		$exec = false;
283
	/* make sure the parent is converted to ng_vlan(4) and is up */
284
	interfaces_bring_up($qinqif);
285

    
286
	pfSense_ngctl_attach(".", $qinqif);
287
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
288
		fwrite($fd, "shutdown {$qinqif}qinq:\n");
289
		exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
290
		if (empty($result)) {
291
			fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
292
			fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
293
			fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
294
		}
295
	} else {
296
		fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
297
		fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
298
		fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
299
	}
300

    
301
	/* invalidate interface cache */
302
	get_interface_arr(true);
303

    
304
	if (!stristr($qinqif, "_vlan"))
305
		mwexec("/sbin/ifconfig {$qinqif} promisc\n");
306

    
307
	$macaddr = get_interface_mac($qinqif);
308
	if (!empty($vlan['members'])) {
309
		$members = explode(" ", $vlan['members']);
310
		foreach ($members as $qtag) {
311
			$qinq = array();
312
			$qinq['tag'] = $qtag;
313
			$qinq['if'] = $vlanif;
314
			interface_qinq2_configure($qinq, $fd, $macaddr);
315
		}
316
	}
317
	if ($exec == true) {
318
		fclose($fd);
319
		mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
320
	}
321

    
322
	interfaces_bring_up($qinqif);
323
	if (!empty($vlan['members'])) {
324
		$members = explode(" ", $vlan['members']);
325
		foreach ($members as $qif)
326
			interfaces_bring_up("{$vlanif}_{$qif}");
327
	}
328

    
329
	return $vlanif;
330
}
331

    
332
function interfaces_qinq_configure() {
333
	global $config, $g;
334
	if (platform_booting())
335
		echo gettext("Configuring QinQ interfaces...");
336
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
337
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
338
			/* XXX: Maybe we should report any errors?! */
339
			interface_qinq_configure($qinq);
340
		}
341
	}
342
	if (platform_booting())
343
		echo gettext( "done.") . "\n";
344
}
345

    
346
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
347
	global $config, $g;
348

    
349
	if (!is_array($qinq)) {
350
		log_error(sprintf(gettext("QinQ compat VLAN: called with wrong options. Problems with config!%s"), "\n"));
351
		return;
352
	}
353

    
354
	$if = $qinq['if'];
355
	$tag = $qinq['tag'];
356
	$vlanif = "{$if}_{$tag}";
357
	if(empty($if)) {
358
		log_error(sprintf(gettext("interface_qinq2_configure called with if undefined.%s"), "\n"));
359
		return;
360
	}
361

    
362
	fwrite($fd, "shutdown {$if}h{$tag}:\n");
363
	fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
364
	fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
365
	fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
366
	fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
367
	fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
368

    
369
	/* invalidate interface cache */
370
	get_interface_arr(true);
371

    
372
	return $vlanif;
373
}
374

    
375
function interfaces_create_wireless_clones() {
376
	global $config, $g;
377

    
378
	if (platform_booting())
379
		echo gettext("Creating wireless clone interfaces...");
380

    
381
	$iflist = get_configured_interface_list();
382

    
383
	foreach ($iflist as $if) {
384
		$realif = $config['interfaces'][$if]['if'];
385
		if (is_interface_wireless($realif))
386
			interface_wireless_clone(interface_get_wireless_clone($realif), $config['interfaces'][$if]);
387
	}
388

    
389
	if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
390
		foreach ($config['wireless']['clone'] as $clone) {
391
			if(empty($clone['cloneif']))
392
				continue;
393
			if(does_interface_exist($clone['cloneif']))
394
				continue;
395
			/* XXX: Maybe we should report any errors?! */
396
			interface_wireless_clone($clone['cloneif'], $clone);
397
		}
398
	}
399
	if (platform_booting())
400
		echo gettext("done.") . "\n";
401

    
402
}
403

    
404
function interfaces_bridge_configure($checkmember = 0, $realif = "") {
405
	global $config;
406

    
407
	$i = 0;
408
	if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
409
		foreach ($config['bridges']['bridged'] as $bridge) {
410
			if (empty($bridge['bridgeif']))
411
				$bridge['bridgeif'] = "bridge{$i}";
412
			if (!empty($realif) && $realif != $bridge['bridgeif'])
413
				continue;
414

    
415
			if ($checkmember == 1) {
416
				if (strstr($bridge['if'], "_vip"))
417
					continue;
418
				$members = explode(',', $bridge['members']);
419
				foreach ($members as $member) {
420
					if (!empty($config['interfaces'][$bridge['if']]) && $config['interfaces'][$bridge['if']]['ipaddrv6'] == "track6")
421
						continue 2;
422
				}
423
			}
424
			else if ($checkmember == 2) {
425
				$members = explode(',', $bridge['members']);
426
				foreach ($members as $member) {
427
					if (empty($config['interfaces'][$bridge['if']]) || $config['interfaces'][$bridge['if']]['ipaddrv6'] != "track6")
428
						continue 2;
429
				}
430
			}
431
			/* XXX: Maybe we should report any errors?! */
432
			interface_bridge_configure($bridge, $checkmember);
433
			$i++;
434
		}
435
	}
436
}
437

    
438
function interface_bridge_configure(&$bridge, $checkmember = 0) {
439
	global $config, $g;
440

    
441
	if (!is_array($bridge))
442
		return;
443

    
444
	if (empty($bridge['members'])) {
445
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
446
		return;
447
	}
448

    
449
	$members = explode(',', $bridge['members']);
450
	if (!count($members))
451
		return;
452

    
453
	/* Calculate smaller mtu and enforce it */
454
	$smallermtu = 0;
455
	$commonrx = true;
456
	$commontx = true;
457
	$foundgif = false;
458
	foreach ($members as $member) {
459
		$realif = get_real_interface($member);
460
		$mtu = get_interface_mtu($realif);
461
		if (substr($realif, 0, 3) == "gif") {
462
			$foundgif = true;
463
			if ($checkmember == 1)
464
				return;
465
			if ($mtu <= 1500)
466
				continue;
467
		}
468
		if ($smallermtu == 0 && !empty($mtu))
469
			$smallermtu = $mtu;
470
		else if (!empty($mtu) && $mtu < $smallermtu)
471
			$smallermtu = $mtu;
472
	}
473
	if ($foundgif == false && $checkmember == 2)
474
		return;
475

    
476
	/* Just in case anything is not working well */
477
	if ($smallermtu == 0)
478
		$smallermtu = 1500;
479

    
480
	if (platform_booting() || !empty($bridge['bridgeif'])) {
481
		pfSense_interface_destroy($bridge['bridgeif']);
482
		pfSense_interface_create($bridge['bridgeif']);
483
		$bridgeif = escapeshellarg($bridge['bridgeif']);
484
	} else {
485
		$bridgeif = pfSense_interface_create("bridge");
486
		$bridge['bridgeif'] = $bridgeif;
487
	}
488

    
489
	$bridgemtu = interface_find_child_cfgmtu($bridge['bridgeif']);
490
	if ($bridgemtu > $smallermtu)
491
		$smallermtu = $bridgemtu;
492

    
493
	$checklist = get_configured_interface_list();
494

    
495
	/* Add interfaces to bridge */
496
	foreach ($members as $member) {
497
		if (empty($checklist[$member]))
498
			continue;
499
		$realif = get_real_interface($member);
500
		if (!$realif) {
501
			log_error(gettext("realif not defined in interfaces bridge - up"));
502
			continue;
503
		}
504
		/* make sure the parent interface is up */
505
		pfSense_interface_mtu($realif, $smallermtu);
506
		interfaces_bring_up($realif);
507
		enable_hardware_offloading($member);
508
		pfSense_bridge_add_member($bridge['bridgeif'], $realif);
509
	}
510

    
511
	if (isset($bridge['enablestp'])) {
512
		/* Choose spanning tree proto */
513
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
514

    
515
		if (!empty($bridge['stp'])) {
516
			$stpifs = explode(',', $bridge['stp']);
517
			foreach ($stpifs as $stpif) {
518
				$realif = get_real_interface($stpif);
519
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
520
			}
521
		}
522
		if (!empty($bridge['maxage']))
523
			mwexec("/sbin/ifconfig {$bridgeif} maxage " . escapeshellarg($bridge['maxage']));
524
		if (!empty($bridge['fwdelay']))
525
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay " . escapeshellarg($bridge['fwdelay']));
526
		if (!empty($bridge['hellotime']))
527
			mwexec("/sbin/ifconfig {$bridgeif} hellotime " . escapeshellarg($bridge['hellotime']));
528
		if (!empty($bridge['priority']))
529
			mwexec("/sbin/ifconfig {$bridgeif} priority " . escapeshellarg($bridge['priority']));
530
		if (!empty($bridge['holdcnt']))
531
			mwexec("/sbin/ifconfig {$bridgeif} holdcnt " . escapeshellarg($bridge['holdcnt']));
532
		if (!empty($bridge['ifpriority'])) {
533
			$pconfig = explode(",", $bridge['ifpriority']);
534
			$ifpriority = array();
535
			foreach ($pconfig as $cfg) {
536
				$embcfg = explode_assoc(":", $cfg);
537
				foreach ($embcfg as $key => $value)
538
					$ifpriority[$key] = $value;
539
			}
540
			foreach ($ifpriority as $key => $value) {
541
				$realif = get_real_interface($key);
542
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} " . escapeshellarg($value));
543
			}
544
		}
545
		if (!empty($bridge['ifpathcost'])) {
546
			$pconfig = explode(",", $bridge['ifpathcost']);
547
			$ifpathcost = array();
548
			foreach ($pconfig as $cfg) {
549
				$embcfg = explode_assoc(":", $cfg);
550
				foreach ($embcfg as $key => $value)
551
					$ifpathcost[$key] = $value;
552
			}
553
			foreach ($ifpathcost as $key => $value) {
554
				$realif = get_real_interface($key);
555
				mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} " . escapeshellarg($value));
556
			}
557
		}
558
	}
559

    
560
	if ($bridge['maxaddr'] <> "")
561
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr " . escapeshellarg($bridge['maxaddr']));
562
	if ($bridge['timeout'] <> "")
563
		mwexec("/sbin/ifconfig {$bridgeif} timeout " . escapeshellarg($bridge['timeout']));
564
	if ($bridge['span'] <> "") {
565
		$realif = get_real_interface($bridge['span']);
566
		mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
567
	}
568
	if (!empty($bridge['edge'])) {
569
		$edgeifs = explode(',', $bridge['edge']);
570
		foreach ($edgeifs as $edgeif) {
571
			$realif = get_real_interface($edgeif);
572
			mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
573
		}
574
	}
575
	if (!empty($bridge['autoedge'])) {
576
		$edgeifs = explode(',', $bridge['autoedge']);
577
		foreach ($edgeifs as $edgeif) {
578
			$realif = get_real_interface($edgeif);
579
			mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
580
		}
581
	}
582
	if (!empty($bridge['ptp'])) {
583
		$ptpifs = explode(',', $bridge['ptp']);
584
		foreach ($ptpifs as $ptpif) {
585
			$realif = get_real_interface($ptpif);
586
			mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
587
		}
588
	}
589
	if (!empty($bridge['autoptp'])) {
590
		$ptpifs = explode(',', $bridge['autoptp']);
591
		foreach ($ptpifs as $ptpif) {
592
			$realif = get_real_interface($ptpif);
593
			mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
594
		}
595
	}
596
	if (!empty($bridge['static'])) {
597
		$stickyifs = explode(',', $bridge['static']);
598
		foreach ($stickyifs as $stickyif) {
599
			$realif = get_real_interface($stickyif);
600
			mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
601
		}
602
	}
603
	if (!empty($bridge['private'])) {
604
		$privateifs = explode(',', $bridge['private']);
605
		foreach ($privateifs as $privateif) {
606
			$realif = get_real_interface($privateif);
607
			mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
608
		}
609
	}
610

    
611
	if ($bridge['bridgeif'])
612
		interfaces_bring_up($bridge['bridgeif']);
613
	else
614
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
615
}
616

    
617
function interface_bridge_add_member($bridgeif, $interface, $flagsapplied = false) {
618

    
619
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
620
		return;
621

    
622
	if ($flagsapplied == false) {
623
		$mtu = get_interface_mtu($bridgeif);
624
		$mtum = get_interface_mtu($interface);
625
		if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
626
			pfSense_interface_mtu($interface, $mtu);
627

    
628
		hardware_offloading_applyflags($interface);
629
		interfaces_bring_up($interface);
630
	}
631

    
632
	pfSense_bridge_add_member($bridgeif, $interface);
633
}
634

    
635
function interfaces_lagg_configure($realif = "") {
636
	global $config, $g;
637
	if (platform_booting())
638
		echo gettext("Configuring LAGG interfaces...");
639
	$i = 0;
640
	if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
641
		foreach ($config['laggs']['lagg'] as $lagg) {
642
			if(empty($lagg['laggif']))
643
				$lagg['laggif'] = "lagg{$i}";
644
			if (!empty($realif) && $realif != $lagg['laggif'])
645
				continue;
646
			/* XXX: Maybe we should report any errors?! */
647
			interface_lagg_configure($lagg);
648
			$i++;
649
		}
650
	}
651
	if (platform_booting())
652
		echo gettext("done.") . "\n";
653
}
654

    
655
function interface_lagg_configure($lagg) {
656
	global $config, $g;
657

    
658
	if (!is_array($lagg))
659
		return -1;
660

    
661
	$members = explode(',', $lagg['members']);
662
	if (!count($members))
663
		return -1;
664

    
665
	if (platform_booting() || !(empty($lagg['laggif']))) {
666
		pfSense_interface_destroy($lagg['laggif']);
667
		pfSense_interface_create($lagg['laggif']);
668
		$laggif = $lagg['laggif'];
669
	} else
670
		$laggif = pfSense_interface_create("lagg");
671

    
672
	/* Check if MTU was defined for this lagg interface */
673
	$lagg_mtu = interface_find_child_cfgmtu($laggif);
674
	if ($lagg_mtu == 0) {
675
		/* Calculate smaller mtu and enforce it */
676
		$smallermtu = 0;
677
		foreach ($members as $member) {
678
			$mtu = get_interface_mtu($member);
679
			if ($smallermtu == 0 && !empty($mtu))
680
				$smallermtu = $mtu;
681
			else if (!empty($mtu) && $mtu < $smallermtu)
682
				$smallermtu = $mtu;
683
		}
684
		$lagg_mtu = $smallermtu;
685
	}
686

    
687
	/* Just in case anything is not working well */
688
	if ($lagg_mtu == 0)
689
		$lagg_mtu = 1500;
690

    
691
	foreach ($members as $member) {
692
		if (!does_interface_exist($member))
693
			continue;
694
		/* make sure the parent interface is up */
695
		pfSense_interface_mtu($member, $lagg_mtu);
696
		interfaces_bring_up($member);
697
		hardware_offloading_applyflags($member);
698
		mwexec("/sbin/ifconfig " . escapeshellarg($laggif) . " laggport " . escapeshellarg($member));
699
	}
700
	pfSense_interface_capabilities($laggif, -$flags_off);
701
	pfSense_interface_capabilities($laggif, $flags_on);
702

    
703
	mwexec("/sbin/ifconfig {$laggif} laggproto " . escapeshellarg($lagg['proto']));
704

    
705
	interfaces_bring_up($laggif);
706

    
707
	return $laggif;
708
}
709

    
710
function interfaces_gre_configure($checkparent = 0, $realif = "") {
711
	global $config;
712

    
713
	if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
714
		foreach ($config['gres']['gre'] as $i => $gre) {
715
			if (empty($gre['greif']))
716
				$gre['greif'] = "gre{$i}";
717
			if (!empty($realif) && $realif != $gre['greif'])
718
				continue;
719

    
720
			if ($checkparent == 1) {
721
				if (strstr($gre['if'], "_vip"))
722
					continue;
723
				if (!empty($config['interfaces'][$gre['if']]) && $config['interfaces'][$gre['if']]['ipaddrv6'] == "track6")
724
					continue;
725
			}
726
			else if ($checkparent == 2) {
727
				if (!strstr($gre['if'], "_vip") && (empty($config['interfaces'][$gre['if']]) || $config['interfaces'][$gre['if']]['ipaddrv6'] != "track6"))
728
					continue;
729
			}
730
			/* XXX: Maybe we should report any errors?! */
731
			interface_gre_configure($gre);
732
		}
733
	}
734
}
735

    
736
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
737
function interface_gre_configure(&$gre, $grekey = "") {
738
	global $config, $g;
739

    
740
	if (!is_array($gre))
741
		return -1;
742

    
743
	$realif = get_real_interface($gre['if']);
744
	$realifip = get_interface_ip($gre['if']);
745

    
746
	/* make sure the parent interface is up */
747
	interfaces_bring_up($realif);
748

    
749
	if (platform_booting() || !(empty($gre['greif']))) {
750
		pfSense_interface_destroy($gre['greif']);
751
		pfSense_interface_create($gre['greif']);
752
		$greif = $gre['greif'];
753
	} else
754
		$greif = pfSense_interface_create("gre");
755

    
756
	/* Do not change the order here for more see gre(4) NOTES section. */
757
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} " . escapeshellarg($gre['remote-addr']));
758
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
759
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
760
		//mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gre['tunnel-remote-net']));
761
		mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen 128");
762
	} else {
763
		mwexec("/sbin/ifconfig {$greif} " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
764
	}
765
	if (isset($gre['link0']))
766
		pfSense_interface_flags($greif, IFF_LINK0);
767
	if (isset($gre['link1']))
768
		pfSense_interface_flags($greif, IFF_LINK1);
769
	if (isset($gre['link2']))
770
		pfSense_interface_flags($greif, IFF_LINK2);
771

    
772
	if($greif)
773
		interfaces_bring_up($greif);
774
	else
775
		log_error(gettext("Could not bring greif up -- variable not defined."));
776

    
777
	if (isset($gre['link1']) && $gre['link1'])
778
		mwexec("/sbin/route add " . escapeshellarg($gre['tunnel-remote-addr']) . "/" . escapeshellarg($gre['tunnel-remote-net']) . " " . escapeshellarg($gre['tunnel-local-addr']));
779
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
780
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
781
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
782
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
783

    
784
	interfaces_bring_up($greif);
785

    
786
	return $greif;
787
}
788

    
789
function interfaces_gif_configure($checkparent = 0, $realif = "") {
790
	global $config;
791

    
792
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
793
		foreach ($config['gifs']['gif'] as $i => $gif) {
794
			if (empty($gif['gifif']))
795
				$gre['gifif'] = "gif{$i}";
796
			if (!empty($realif) && $realif != $gif['gifif'])
797
				continue;
798

    
799
			if ($checkparent == 1) {
800
				if (strstr($gif['if'], "_vip"))
801
					continue;
802
				if (!empty($config['interfaces'][$gif['if']]) && $config['interfaces'][$gif['if']]['ipaddrv6'] == "track6")
803
					continue;
804
			}
805
			else if ($checkparent == 2) {
806
				if (!strstr($gif['if'], "_vip") && (empty($config['interfaces'][$gif['if']]) || $config['interfaces'][$gif['if']]['ipaddrv6'] != "track6"))
807
					continue;
808
			}
809
			/* XXX: Maybe we should report any errors?! */
810
			interface_gif_configure($gif);
811
		}
812
	}
813
}
814

    
815
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
816
function interface_gif_configure(&$gif, $gifkey = "") {
817
	global $config, $g;
818

    
819
	if (!is_array($gif))
820
		return -1;
821

    
822
	$realif = get_real_interface($gif['if']);
823
	$ipaddr = $gif['ipaddr'];
824

    
825
	if (is_ipaddrv4($gif['remote-addr'])) {
826
		if (is_ipaddrv4($ipaddr))
827
			$realifip = $ipaddr;
828
		else
829
			$realifip = get_interface_ip($gif['if']);
830
		$realifgw = get_interface_gateway($gif['if']);
831
	} else if (is_ipaddrv6($gif['remote-addr'])) {
832
		if (is_ipaddrv6($ipaddr))
833
			$realifip = $ipaddr;
834
		else
835
			$realifip = get_interface_ipv6($gif['if']);
836
		$realifgw = get_interface_gateway_v6($gif['if']);
837
	}
838
	/* make sure the parent interface is up */
839
	if($realif)
840
		interfaces_bring_up($realif);
841
	else
842
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
843

    
844
	if (platform_booting() || !(empty($gif['gifif']))) {
845
		pfSense_interface_destroy($gif['gifif']);
846
		pfSense_interface_create($gif['gifif']);
847
		$gifif = $gif['gifif'];
848
	} else
849
		$gifif = pfSense_interface_create("gif");
850

    
851
	/* Do not change the order here for more see gif(4) NOTES section. */
852
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} " . escapeshellarg($gif['remote-addr']));
853
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
854
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
855
		//mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gif['tunnel-remote-net']));
856
		mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen 128");
857
	} else {
858
		mwexec("/sbin/ifconfig {$gifif} " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
859
	}
860
	if (isset($gif['link0']))
861
		pfSense_interface_flags($gifif, IFF_LINK0);
862
	if (isset($gif['link1']))
863
		pfSense_interface_flags($gifif, IFF_LINK1);
864
	if($gifif)
865
		interfaces_bring_up($gifif);
866
	else
867
		log_error(gettext("could not bring gifif up -- variable not defined"));
868

    
869
	if (!platform_booting()) {
870
		$iflist = get_configured_interface_list();
871
		foreach($iflist as $ifname) {
872
			if($config['interfaces'][$ifname]['if'] == $gifif) {
873
				if(get_interface_gateway($ifname)) {
874
					system_routing_configure($ifname);
875
					break;
876
				}
877
				if(get_interface_gateway_v6($ifname)) {
878
					system_routing_configure($ifname);
879
					break;
880
				}
881
			}
882
		}
883
	}
884

    
885

    
886
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
887
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
888
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
889
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
890

    
891
	if (is_ipaddrv4($realifgw)) {
892
		mwexec("/sbin/route change -host " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
893
	}
894
	if (is_ipaddrv6($realifgw)) {
895
		mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
896
	}
897

    
898
	interfaces_bring_up($gifif);
899

    
900
	return $gifif;
901
}
902

    
903
function interfaces_configure() {
904
	global $config, $g;
905

    
906
	if ($g['platform'] == 'jail')
907
		return;
908

    
909
	/* Set up our loopback interface */
910
	interfaces_loopback_configure();
911

    
912
	/* create the unconfigured wireless clones */
913
	interfaces_create_wireless_clones();
914

    
915
	/* set up LAGG virtual interfaces */
916
	interfaces_lagg_configure();
917

    
918
	/* set up VLAN virtual interfaces */
919
	interfaces_vlan_configure();
920

    
921
	interfaces_qinq_configure();
922

    
923
	$iflist = get_configured_interface_with_descr();
924
	$delayed_list = array();
925
	$bridge_list = array();
926
	$track6_list = array();
927

    
928
	/* This is needed to speedup interfaces on bootup. */
929
	$reload = false;
930
	if (!platform_booting())
931
		$reload = true;
932

    
933
	foreach($iflist as $if => $ifname) {
934
		$realif = $config['interfaces'][$if]['if'];
935
		if (strstr($realif, "bridge"))
936
			$bridge_list[$if] = $ifname;
937
		else if (strstr($realif, "gre"))
938
			$delayed_list[$if] = $ifname;
939
		else if (strstr($realif, "gif"))
940
			$delayed_list[$if] = $ifname;
941
		else if (strstr($realif, "ovpn")) {
942
			//echo "Delaying OpenVPN interface configuration...done.\n";
943
			continue;
944
		} else if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
945
			$track6_list[$if] = $ifname;
946
		} else {
947
			if (platform_booting())
948
				printf(gettext("Configuring %s interface..."), $ifname);
949

    
950
			if($g['debug'])
951
				log_error(sprintf(gettext("Configuring %s"), $ifname));
952
			interface_configure($if, $reload);
953
			if (platform_booting())
954
				echo gettext( "done.") . "\n";
955
		}
956
	}
957

    
958
	/*
959
	 * NOTE: The following function parameter consists of
960
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
961
	 *	2 - Do load gre/gif/bridge with parent/member as vip
962
	 */
963

    
964
	/* set up GRE virtual interfaces */
965
	interfaces_gre_configure(1);
966

    
967
	/* set up GIF virtual interfaces */
968
	interfaces_gif_configure(1);
969

    
970
	/* set up BRIDGe virtual interfaces */
971
	interfaces_bridge_configure(1);
972

    
973
	foreach ($track6_list as $if => $ifname) {
974
		if (platform_booting())
975
			printf(gettext("Configuring %s interface..."), $ifname);
976
		if ($g['debug'])
977
			log_error(sprintf(gettext("Configuring %s"), $ifname));
978

    
979
		interface_configure($if, $reload);
980

    
981
		if (platform_booting())
982
			echo gettext("done.") . "\n";
983
	}
984

    
985
	/* bring up vip interfaces */
986
	interfaces_vips_configure();
987

    
988
	/* set up GRE virtual interfaces */
989
	interfaces_gre_configure(2);
990

    
991
	/* set up GIF virtual interfaces */
992
	interfaces_gif_configure(2);
993

    
994
	foreach ($delayed_list as $if => $ifname) {
995
		if (platform_booting())
996
			printf(gettext("Configuring %s interface..."), $ifname);
997
		if ($g['debug'])
998
			log_error(sprintf(gettext("Configuring %s"), $ifname));
999

    
1000
		interface_configure($if, $reload);
1001

    
1002
		if (platform_booting())
1003
			echo gettext("done.") . "\n";
1004
	}
1005

    
1006
	/* set up BRIDGe virtual interfaces */
1007
	interfaces_bridge_configure(2);
1008

    
1009
	foreach ($bridge_list as $if => $ifname) {
1010
		if (platform_booting())
1011
			printf(gettext("Configuring %s interface..."), $ifname);
1012
		if($g['debug'])
1013
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1014

    
1015
		interface_configure($if, $reload);
1016

    
1017
		if (platform_booting())
1018
			echo gettext("done.") . "\n";
1019
	}
1020

    
1021
	/* configure interface groups */
1022
	interfaces_group_setup();
1023

    
1024
	if (!platform_booting()) {
1025
		/* reconfigure static routes (kernel may have deleted them) */
1026
		system_routing_configure();
1027

    
1028
		/* reload IPsec tunnels */
1029
		vpn_ipsec_configure();
1030

    
1031
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1032
		services_dhcpd_configure();
1033

    
1034
		/* restart dnsmasq or unbound */
1035
		if (isset($config['dnsmasq']['enable']))
1036
			services_dnsmasq_configure();
1037
		elseif (isset($config['unbound']['enable']))
1038
			services_unbound_configure();
1039
	}
1040

    
1041
	return 0;
1042
}
1043

    
1044
function interface_reconfigure($interface = "wan", $reloadall = false) {
1045
	interface_bring_down($interface);
1046
	interface_configure($interface, $reloadall);
1047
}
1048

    
1049
function interface_vip_bring_down($vip) {
1050
	global $g;
1051

    
1052
	if (strpos($vip['interface'], '_vip')) {
1053
		if (is_ipaddrv6($vip['subnet']))
1054
			$family = 'inet6';
1055
		else
1056
			$family = 'inet';
1057

    
1058
		$carpvip = get_configured_carp_interface_list($vip['interface'], $family, 'vip');
1059
		$iface = $carpvip['interface'];
1060
	} else
1061
		$iface = $vip['interface'];
1062

    
1063
	$vipif = get_real_interface($iface);
1064
	switch ($vip['mode']) {
1065
	case "proxyarp":
1066
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1067
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1068
		break;
1069
	case "ipalias":
1070
		if (does_interface_exist($vipif)) {
1071
			if (is_ipaddrv6($vip['subnet']))
1072
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " -alias");
1073
			else
1074
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1075
		}
1076
		break;
1077
	case "carp":
1078
		/* XXX: Is enough to delete ip address? */
1079
		if (does_interface_exist($vipif)) {
1080
			if (is_ipaddrv6($vip['subnet']))
1081
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " delete");
1082
			else
1083
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1084
		}
1085
		break;
1086
	}
1087
}
1088

    
1089
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1090
	global $config, $g;
1091

    
1092
	if (!isset($config['interfaces'][$interface]))
1093
		return;
1094

    
1095
	if ($g['debug'])
1096
		log_error("Calling interface down for interface {$interface}, destroy is " . (($destroy) ? 'true' : 'false'));
1097

    
1098
	/*
1099
	 * NOTE: The $realifv6 is needed when WANv4 is type PPP and v6 is DHCP and the option v6 from v4 is used.
1100
	 * In this case the real $realif of v4 is different from that of v6 for operation.
1101
	 * Keep this in mind while doing changes here!
1102
	 */
1103
	if ($ifacecfg === false) {
1104
		$ifcfg = $config['interfaces'][$interface];
1105
		$ppps = $config['ppps']['ppp'];
1106
		$realif = get_real_interface($interface);
1107
		$realifv6 = get_real_interface($interface, "inet6", true);
1108
	} elseif (!is_array($ifacecfg)) {
1109
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1110
		$ifcfg = $config['interfaces'][$interface];
1111
		$ppps = $config['ppps']['ppp'];
1112
		$realif = get_real_interface($interface);
1113
		$realifv6 = get_real_interface($interface, "inet6", true);
1114
	} else {
1115
		$ifcfg = $ifacecfg['ifcfg'];
1116
		$ppps = $ifacecfg['ppps'];
1117
		if (isset($ifacecfg['ifcfg']['realif'])) {
1118
			$realif = $ifacecfg['ifcfg']['realif'];
1119
			/* XXX: Any better way? */
1120
			$realifv6 = $realif;
1121
		} else {
1122
			$realif = get_real_interface($interface);
1123
			$realifv6 = get_real_interface($interface, "inet6", true);
1124
		}
1125
	}
1126

    
1127
	switch ($ifcfg['ipaddr']) {
1128
	case "ppp":
1129
	case "pppoe":
1130
	case "pptp":
1131
	case "l2tp":
1132
		if (is_array($ppps) && count($ppps)) {
1133
			foreach ($ppps as $pppid => $ppp) {
1134
				if ($realif == $ppp['if']) {
1135
					if (isset($ppp['ondemand']) && !$destroy){
1136
						send_event("interface reconfigure {$interface}");
1137
						break;
1138
					}
1139
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1140
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1141
						sleep(2);
1142
					}
1143
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1144
					break;
1145
				}
1146
			}
1147
		}
1148
		break;
1149
	case "dhcp":
1150
		kill_dhclient_process($realif);
1151
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1152
		if(does_interface_exist("$realif")) {
1153
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1154
			interface_ipalias_cleanup($interface);
1155
			if ($destroy == true)
1156
				pfSense_interface_flags($realif, -IFF_UP);
1157
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1158
		}
1159
		break;
1160
	default:
1161
		if(does_interface_exist("$realif")) {
1162
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1163
			interface_ipalias_cleanup($interface);
1164
			if ($destroy == true)
1165
				pfSense_interface_flags($realif, -IFF_UP);
1166
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1167
		}
1168
		break;
1169
	}
1170

    
1171
	$track6 = array();
1172
	switch ($ifcfg['ipaddrv6']) {
1173
		case "slaac":
1174
		case "dhcp6":
1175
			$pidv6 = find_dhcp6c_process($realif);
1176
			if ($pidv6) {
1177
				posix_kill($pidv6, SIGTERM);
1178
			}
1179
			sleep(3);
1180
			unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1181
			if (does_interface_exist($realifv6)) {
1182
				$ip6 = find_interface_ipv6($realifv6);
1183
				if (is_ipaddrv6($ip6) && $ip6 != "::") {
1184
					mwexec("/sbin/ifconfig " . escapeshellarg($realifv6) . " inet6 {$ip6} delete", true);
1185
				}
1186
				interface_ipalias_cleanup($interface, "inet6");
1187
				if ($destroy == true) {
1188
					pfSense_interface_flags($realif, -IFF_UP);
1189
				}
1190
				//mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1191
			}
1192
			$track6 = link_interface_to_track6($interface);
1193
			break;
1194
		case "6rd":
1195
		case "6to4":
1196
			$realif = "{$interface}_stf";
1197
			if (does_interface_exist("$realif")) {
1198
				/* destroy stf interface if tunnel is being disabled or tunnel type is being changed */
1199
				if (($ifcfg['ipaddrv6'] == '6rd' && (!isset($config['interfaces'][$interface]['ipaddrv6']) || $config['interfaces'][$interface]['ipaddrv6'] != '6rd')) ||
1200
					($ifcfg['ipaddrv6'] == '6to4' && (!isset($config['interfaces'][$interface]['ipaddrv6']) || $config['interfaces'][$interface]['ipaddrv6'] != '6to4'))) {
1201
					$destroy = true;
1202
				} else {
1203
					/* get_interface_ipv6() returns empty value if interface is being disabled */
1204
					$ip6 = get_interface_ipv6($interface);
1205
					if (is_ipaddrv6($ip6))
1206
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1207
				}
1208
				interface_ipalias_cleanup($interface, "inet6");
1209
				if ($destroy == true) {
1210
					pfSense_interface_flags($realif, -IFF_UP);
1211
				}
1212
			}
1213
			$track6 = link_interface_to_track6($interface);
1214
			break;
1215
		default:
1216
			if (does_interface_exist("$realif")) {
1217
				$ip6 = get_interface_ipv6($interface);
1218
				if (is_ipaddrv6($ip6)) {
1219
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1220
				}
1221
				if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6'])) {
1222
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1223
				}
1224
				interface_ipalias_cleanup($interface, "inet6");
1225
				if ($destroy == true) {
1226
					pfSense_interface_flags($realif, -IFF_UP);
1227
				}
1228
				//mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1229
			}
1230
			$track6 = link_interface_to_track6($interface);
1231
			break;
1232
	}
1233

    
1234
	if (!empty($track6) && is_array($track6)) {
1235
		if (!function_exists('services_dhcpd_configure'))
1236
			require_once('services.inc');
1237
		/* Bring down radvd and dhcp6 on these interfaces */
1238
		services_dhcpd_configure('inet6', $track6);
1239
	}
1240

    
1241
	$old_router = '';
1242
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1243
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1244

    
1245
	/* remove interface up file if it exists */
1246
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1247
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1248
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1249
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1250
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1251
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1252
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1253

    
1254
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1255
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1256
	if (is_array($ifcfg['wireless'])) {
1257
		kill_hostapd($realif);
1258
		mwexec(kill_wpasupplicant($realif));
1259
	}
1260

    
1261
	if ($destroy == true) {
1262
		if (preg_match("/^[a-z0-9]+^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1263
			pfSense_interface_destroy($realif);
1264
	}
1265

    
1266
	return;
1267
}
1268

    
1269
function interfaces_carp_set_maintenancemode($carp_maintenancemode){
1270
	global $config;
1271
	if (isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == false) {
1272
		unset($config["virtualip_carp_maintenancemode"]);
1273
		write_config("Leave CARP maintenance mode");
1274
	} else
1275
	if (!isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == true) {
1276
		$config["virtualip_carp_maintenancemode"] = true;
1277
		write_config("Enter CARP maintenance mode");
1278
	}
1279

    
1280
	$viparr = &$config['virtualip']['vip'];
1281
	foreach ($viparr as $vip) {
1282
		if ($vip['mode'] == "carp") {
1283
			interface_carp_configure($vip);
1284
		}
1285
	}
1286
}
1287

    
1288
function interface_isppp_type($interface) {
1289
	global $config;
1290

    
1291
	if (!is_array($config['interfaces'][$interface]))
1292
		return false;
1293

    
1294
	switch ($config['interfaces'][$interface]['ipaddr']) {
1295
	case 'pptp':
1296
	case 'l2tp':
1297
	case 'pppoe':
1298
	case 'ppp':
1299
		return true;
1300
		break;
1301
	default:
1302
		return false;
1303
		break;
1304
	}
1305
}
1306

    
1307
function interfaces_ptpid_used($ptpid) {
1308
	global $config;
1309

    
1310
	if (is_array($config['ppps']['ppp']))
1311
		foreach ($config['ppps']['ppp'] as & $settings)
1312
			if ($ptpid == $settings['ptpid'])
1313
				return true;
1314

    
1315
	return false;
1316
}
1317

    
1318
function interfaces_ptpid_next() {
1319

    
1320
	$ptpid = 0;
1321
	while(interfaces_ptpid_used($ptpid))
1322
		$ptpid++;
1323

    
1324
	return $ptpid;
1325
}
1326

    
1327
function getMPDCRONSettings($pppif) {
1328
	global $config;
1329

    
1330
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1331
	if (is_array($config['cron']['item'])) {
1332
		foreach ($config['cron']['item'] as $i => $item) {
1333
			if (stripos($item['command'], $cron_cmd_file) !== false)
1334
				return array("ID" => $i, "ITEM" => $item);
1335
		}
1336
	}
1337

    
1338
	return NULL;
1339
}
1340

    
1341
function handle_pppoe_reset($post_array) {
1342
	global $config, $g;
1343

    
1344
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1345
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1346

    
1347
	if (!is_array($config['cron']['item']))
1348
		$config['cron']['item'] = array();
1349

    
1350
	$itemhash = getMPDCRONSettings($pppif);
1351

    
1352
	// reset cron items if necessary and return
1353
	if (empty($post_array['pppoe-reset-type'])) {
1354
		if (isset($itemhash))
1355
			unset($config['cron']['item'][$itemhash['ID']]);
1356
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1357
		return;
1358
	}
1359

    
1360
	if (empty($itemhash))
1361
		$itemhash = array();
1362
	$item = array();
1363
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1364
		$item['minute'] = $post_array['pppoe_resetminute'];
1365
		$item['hour'] = $post_array['pppoe_resethour'];
1366
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1367
			$date = explode("/", $post_array['pppoe_resetdate']);
1368
			$item['mday'] = $date[1];
1369
			$item['month'] = $date[0];
1370
		} else {
1371
			$item['mday'] = "*";
1372
			$item['month'] = "*";
1373
		}
1374
		$item['wday'] = "*";
1375
		$item['who'] = "root";
1376
		$item['command'] = $cron_cmd_file;
1377
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1378
		switch ($post_array['pppoe_pr_preset_val']) {
1379
		case "monthly":
1380
			$item['minute'] = "0";
1381
			$item['hour'] = "0";
1382
			$item['mday'] = "1";
1383
			$item['month'] = "*";
1384
			$item['wday'] = "*";
1385
			break;
1386
		case "weekly":
1387
			$item['minute'] = "0";
1388
			$item['hour'] = "0";
1389
			$item['mday'] = "*";
1390
			$item['month'] = "*";
1391
			$item['wday'] = "0";
1392
			break;
1393
		case "daily":
1394
			$item['minute'] = "0";
1395
			$item['hour'] = "0";
1396
			$item['mday'] = "*";
1397
			$item['month'] = "*";
1398
			$item['wday'] = "*";
1399
			break;
1400
		case "hourly":
1401
			$item['minute'] = "0";
1402
			$item['hour'] = "*";
1403
			$item['mday'] = "*";
1404
			$item['month'] = "*";
1405
			$item['wday'] = "*";
1406
			break;
1407
		} // end switch
1408
		$item['who'] = "root";
1409
		$item['command'] = $cron_cmd_file;
1410
	}
1411
	if (empty($item))
1412
		return;
1413
	if (isset($itemhash['ID']))
1414
		$config['cron']['item'][$itemhash['ID']] = $item;
1415
	else
1416
		$config['cron']['item'][] = $item;
1417
}
1418

    
1419
/*
1420
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1421
 * It writes the mpd config file to /var/etc every time the link is opened.
1422
 */
1423
function interface_ppps_configure($interface) {
1424
	global $config, $g;
1425

    
1426
	/* Return for unassigned interfaces. This is a minimum requirement. */
1427
	if (empty($config['interfaces'][$interface]))
1428
		return 0;
1429
	$ifcfg = $config['interfaces'][$interface];
1430
	if (!isset($ifcfg['enable']))
1431
		return 0;
1432

    
1433
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1434
	if(!is_dir("/var/spool/lock")) {
1435
		mkdir("/var/spool/lock", 0777, true);
1436
	}
1437
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1438
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1439
		@symlink("/usr/local/sbin/mpd.script", "{$g['varetc_path']}/mpd.script");
1440

    
1441
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1442
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1443
			if ($ifcfg['if'] == $ppp['if'])
1444
				break;
1445
		}
1446
	}
1447
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1448
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1449
		return 0;
1450
	}
1451
	$pppif = $ifcfg['if'];
1452
	if ($ppp['type'] == "ppp")
1453
		$type = "modem";
1454
	else
1455
		$type = $ppp['type'];
1456
	$upper_type = strtoupper($ppp['type']);
1457

    
1458
	/* XXX: This does not make sense and may create trouble
1459
	 * comment it for now to be removed later on.
1460
	if (platform_booting()) {
1461
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1462
		echo "starting {$pppif} link...";
1463
		if(isvalidpid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1464
			return 0;
1465
	}
1466
	*/
1467

    
1468
	$ports = explode(',',$ppp['ports']);
1469
	if ($type != "modem") {
1470
		foreach ($ports as $pid => $port) {
1471
			$ports[$pid] = get_real_interface($port);
1472
			if (empty($ports[$pid]))
1473
				return 0;
1474
		}
1475
	}
1476
	$localips = explode(',',$ppp['localip']);
1477
	$gateways = explode(',',$ppp['gateway']);
1478
	$subnets = explode(',',$ppp['subnet']);
1479

    
1480
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1481
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1482
	 */
1483
	foreach($ports as $pid => $port){
1484
		switch ($ppp['type']) {
1485
			case "pppoe":
1486
				/* Bring the parent interface up */
1487
				interfaces_bring_up($port);
1488
				pfSense_ngctl_attach(".", $port);
1489
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1490
				mwexec("ngctl msg {$port}: setautosrc 1");
1491
				break;
1492
			case "pptp":
1493
			case "l2tp":
1494
				/* configure interface */
1495
				if(is_ipaddr($localips[$pid])){
1496
					// Manually configure interface IP/subnet
1497
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1498
					interfaces_bring_up($port);
1499
				} else if (empty($localips[$pid]))
1500
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1501

    
1502
				if(!is_ipaddr($localips[$pid])){
1503
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure. Using 0.0.0.0 ip!");
1504
					$localips[$pid] = "0.0.0.0";
1505
				}
1506
				if(!is_ipaddr($gateways[$pid])){
1507
					log_error(sprintf(gettext('Could not get a PPTP/L2TP Remote IP address from %1$s for %2$s in interfaces_ppps_configure.'), $dhcp_gateway, $gway));
1508
					return 0;
1509
				}
1510
				pfSense_ngctl_attach(".", $port);
1511
				break;
1512
			case "ppp":
1513
				if (!file_exists("{$port}")) {
1514
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1515
					return 0;
1516
				}
1517
				break;
1518
			default:
1519
				log_error(sprintf(gettext("Unknown %s configured as ppp interface."), $type));
1520
				break;
1521
		}
1522
	}
1523

    
1524
	if (is_array($ports) && count($ports) > 1)
1525
		$multilink = "enable";
1526
	else
1527
		$multilink = "disable";
1528

    
1529
	if ($type == "modem"){
1530
		if (is_ipaddr($ppp['localip']))
1531
			$localip = $ppp['localip'];
1532
		else
1533
			$localip = '0.0.0.0';
1534

    
1535
		if (is_ipaddr($ppp['gateway']))
1536
			$gateway = $ppp['gateway'];
1537
		else
1538
			$gateway = "10.64.64.{$pppid}";
1539
		$ranges = "{$localip}/0 {$gateway}/0";
1540

    
1541
		if (empty($ppp['apnum']))
1542
			$ppp['apnum'] = 1;
1543
	} else
1544
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1545

    
1546
	if (isset($ppp['ondemand']))
1547
		$ondemand = "enable";
1548
	else
1549
		$ondemand = "disable";
1550
	if (!isset($ppp['idletimeout']))
1551
		$ppp['idletimeout'] = 0;
1552

    
1553
	if (empty($ppp['username']) && $type == "modem"){
1554
		$ppp['username'] = "user";
1555
		$ppp['password'] = "none";
1556
	}
1557
	if (empty($ppp['password']) && $type == "modem")
1558
		$passwd = "none";
1559
	else
1560
		$passwd = base64_decode($ppp['password']);
1561

    
1562
	$bandwidths = explode(',',$ppp['bandwidth']);
1563
	$defaultmtu = "1492";
1564
	if (!empty($ifcfg['mtu']))
1565
		$defaultmtu = intval($ifcfg['mtu']);
1566
	$mtus = explode(',',$ppp['mtu']);
1567
	$mrus = explode(',',$ppp['mru']);
1568

    
1569
	if (isset($ppp['mrru']))
1570
		$mrrus = explode(',',$ppp['mrru']);
1571

    
1572
	// Construct the mpd.conf file
1573
	$mpdconf = <<<EOD
1574
startup:
1575
	# configure the console
1576
	set console close
1577
	# configure the web server
1578
	set web close
1579

    
1580
default:
1581
{$ppp['type']}client:
1582
	create bundle static {$interface}
1583
	set bundle enable ipv6cp
1584
	set iface name {$pppif}
1585

    
1586
EOD;
1587
	$setdefaultgw = false;
1588
	$founddefaultgw = false;
1589
	if (is_array($config['gateways']['gateway_item'])) {
1590
		foreach($config['gateways']['gateway_item'] as $gateway) {
1591
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1592
				$setdefaultgw = true;
1593
				break;
1594
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1595
				$founddefaultgw = true;
1596
				break;
1597
			}
1598
		}
1599
	}
1600

    
1601
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1602
		$setdefaultgw = true;
1603
		$mpdconf .= <<<EOD
1604
	set iface route default
1605

    
1606
EOD;
1607
	}
1608
	$mpdconf .= <<<EOD
1609
	set iface {$ondemand} on-demand
1610
	set iface idle {$ppp['idletimeout']}
1611

    
1612
EOD;
1613

    
1614
	if (isset($ppp['ondemand']))
1615
		$mpdconf .= <<<EOD
1616
	set iface addrs 10.10.1.1 10.10.1.2
1617

    
1618
EOD;
1619

    
1620
	if (isset($ppp['tcpmssfix']))
1621
		$tcpmss = "disable";
1622
	else
1623
		$tcpmss = "enable";
1624
		$mpdconf .= <<<EOD
1625
	set iface {$tcpmss} tcpmssfix
1626

    
1627
EOD;
1628

    
1629
	$mpdconf .= <<<EOD
1630
	set iface up-script /usr/local/sbin/ppp-linkup
1631
	set iface down-script /usr/local/sbin/ppp-linkdown
1632
	set ipcp ranges {$ranges}
1633

    
1634
EOD;
1635
	if (isset($ppp['vjcomp']))
1636
		$mpdconf .= <<<EOD
1637
	set ipcp no vjcomp
1638

    
1639
EOD;
1640

    
1641
	if (isset($config['system']['dnsallowoverride']))
1642
		$mpdconf .= <<<EOD
1643
	set ipcp enable req-pri-dns
1644
	set ipcp enable req-sec-dns
1645

    
1646
EOD;
1647
	if (!isset($ppp['verbose_log']))
1648
		$mpdconf .= <<<EOD
1649
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1650

    
1651
EOD;
1652
	foreach($ports as $pid => $port){
1653
		$port = get_real_interface($port);
1654
		$mpdconf .= <<<EOD
1655

    
1656
	create link static {$interface}_link{$pid} {$type}
1657
	set link action bundle {$interface}
1658
	set link {$multilink} multilink
1659
	set link keep-alive 10 60
1660
	set link max-redial 0
1661

    
1662
EOD;
1663
		if (isset($ppp['shortseq']))
1664
			$mpdconf .= <<<EOD
1665
	set link no shortseq
1666

    
1667
EOD;
1668

    
1669
		if (isset($ppp['acfcomp']))
1670
			$mpdconf .= <<<EOD
1671
	set link no acfcomp
1672

    
1673
EOD;
1674

    
1675
		if (isset($ppp['protocomp']))
1676
			$mpdconf .= <<<EOD
1677
	set link no protocomp
1678

    
1679
EOD;
1680

    
1681
		$mpdconf .= <<<EOD
1682
	set link disable chap pap
1683
	set link accept chap pap eap
1684
	set link disable incoming
1685

    
1686
EOD;
1687

    
1688

    
1689
		if (!empty($bandwidths[$pid]))
1690
			$mpdconf .= <<<EOD
1691
	set link bandwidth {$bandwidths[$pid]}
1692

    
1693
EOD;
1694

    
1695
		if (empty($mtus[$pid]))
1696
			$mtus[$pid] = $defaultmtu;
1697
			$mpdconf .= <<<EOD
1698
	set link mtu {$mtus[$pid]}
1699

    
1700
EOD;
1701

    
1702
		if (!empty($mrus[$pid]))
1703
			$mpdconf .= <<<EOD
1704
	set link mru {$mrus[$pid]}
1705

    
1706
EOD;
1707

    
1708
		if (!empty($mrrus[$pid]))
1709
			$mpdconf .= <<<EOD
1710
	set link mrru {$mrrus[$pid]}
1711

    
1712
EOD;
1713

    
1714
		$mpdconf .= <<<EOD
1715
	set auth authname "{$ppp['username']}"
1716
	set auth password {$passwd}
1717

    
1718
EOD;
1719
		if ($type == "modem") {
1720
			$mpdconf .= <<<EOD
1721
	set modem device {$ppp['ports']}
1722
	set modem script DialPeer
1723
	set modem idle-script Ringback
1724
	set modem watch -cd
1725
	set modem var \$DialPrefix "DT"
1726
	set modem var \$Telephone "{$ppp['phone']}"
1727

    
1728
EOD;
1729
		}
1730
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1731
			$mpdconf .= <<<EOD
1732
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1733

    
1734
EOD;
1735
		}
1736
		if (isset($ppp['initstr']) && $type == "modem") {
1737
			$initstr = base64_decode($ppp['initstr']);
1738
			$mpdconf .= <<<EOD
1739
	set modem var \$InitString "{$initstr}"
1740

    
1741
EOD;
1742
		}
1743
		if (isset($ppp['simpin']) && $type == "modem") {
1744
			if($ppp['pin-wait'] == "")
1745
				$ppp['pin-wait'] = 0;
1746
			$mpdconf .= <<<EOD
1747
	set modem var \$SimPin "{$ppp['simpin']}"
1748
	set modem var \$PinWait "{$ppp['pin-wait']}"
1749

    
1750
EOD;
1751
		}
1752
		if (isset($ppp['apn']) && $type == "modem") {
1753
			$mpdconf .= <<<EOD
1754
	set modem var \$APN "{$ppp['apn']}"
1755
	set modem var \$APNum "{$ppp['apnum']}"
1756

    
1757
EOD;
1758
		}
1759
		if ($type == "pppoe") {
1760
			// Send a null service name if none is set.
1761
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1762
			$mpdconf .= <<<EOD
1763
	set pppoe service "{$provider}"
1764

    
1765
EOD;
1766
		}
1767
		if ($type == "pppoe")
1768
			$mpdconf .= <<<EOD
1769
	set pppoe iface {$port}
1770

    
1771
EOD;
1772

    
1773
		if ($type == "pptp" || $type == "l2tp") {
1774
			$mpdconf .= <<<EOD
1775
	set {$type} self {$localips[$pid]}
1776
	set {$type} peer {$gateways[$pid]}
1777

    
1778
EOD;
1779
		}
1780

    
1781
		$mpdconf .= "\topen\n";
1782
	} //end foreach($port)
1783

    
1784

    
1785
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1786
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1787
		@symlink("{$g['conf_path']}/mpd_{$interface}.conf", "{$g['varetc_path']}/mpd_{$interface}.conf");
1788
	else {
1789
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1790
		if (!$fd) {
1791
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1792
			return 0;
1793
		}
1794
		// Write out mpd_ppp.conf
1795
		fwrite($fd, $mpdconf);
1796
		fclose($fd);
1797
		unset($mpdconf);
1798
	}
1799

    
1800
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1801
	if (isset($ppp['uptime'])) {
1802
		if (!file_exists("/conf/{$pppif}.log")) {
1803
			conf_mount_rw();
1804
			file_put_contents("/conf/{$pppif}.log", '');
1805
			conf_mount_ro();
1806
		}
1807
	} else {
1808
		if (file_exists("/conf/{$pppif}.log")) {
1809
			conf_mount_rw();
1810
			@unlink("/conf/{$pppif}.log");
1811
			conf_mount_ro();
1812
		}
1813
	}
1814

    
1815
	/* clean up old lock files */
1816
	foreach($ports as $port) {
1817
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1818
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1819
	}
1820

    
1821
	/* fire up mpd */
1822
	mwexec("/usr/local/sbin/mpd5 -b -k -d {$g['varetc_path']} -f mpd_{$interface}.conf -p {$g['varrun_path']}/" .
1823
		escapeshellarg($ppp['type']) . "_{$interface}.pid -s ppp " . escapeshellarg($ppp['type']) . "client");
1824

    
1825
	// Check for PPPoE periodic reset request
1826
	if ($type == "pppoe") {
1827
		if (!empty($ppp['pppoe-reset-type']))
1828
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1829
		else
1830
			interface_setup_pppoe_reset_file($ppp['if']);
1831
	}
1832
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1833
	$i = 0;
1834
	while($i < 3) {
1835
		sleep(10);
1836
		if (does_interface_exist($ppp['if'], true))
1837
			break;
1838
		$i++;
1839
	}
1840

    
1841
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1842
	/* We should be able to launch the right version for each modem */
1843
	/* We can also guess the mondev from the manufacturer */
1844
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1845
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1846
	foreach($ports as $port) {
1847
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1848
			$mondev  = substr(basename($port), 0, -1);
1849
			$devlist = glob("/dev/{$mondev}?");
1850
			$mondev = basename(end($devlist));
1851
		}
1852
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1853
			$mondev  = substr(basename($port), 0, -1) . "1";
1854
		}
1855
		if($mondev != '') {
1856
			log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1857
			mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1858
		}
1859
	}
1860

    
1861
	return 1;
1862
}
1863

    
1864
function interfaces_sync_setup() {
1865
	global $g, $config;
1866

    
1867
	if (isset($config['system']['developerspew'])) {
1868
		$mt = microtime();
1869
		echo "interfaces_sync_setup() being called $mt\n";
1870
	}
1871

    
1872
	if (platform_booting()) {
1873
		echo gettext("Configuring CARP settings...");
1874
		mute_kernel_msgs();
1875
	}
1876

    
1877
	/* suck in configuration items */
1878
	if ($config['hasync']) {
1879
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1880
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1881
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1882
	} else {
1883
		unset($pfsyncinterface);
1884
		unset($pfsyncenabled);
1885
	}
1886

    
1887
	set_sysctl(array(
1888
		"net.inet.carp.preempt" => "1",
1889
		"net.inet.carp.log" => "1")
1890
	);
1891

    
1892
	if (!empty($pfsyncinterface))
1893
		$carp_sync_int = get_real_interface($pfsyncinterface);
1894
	else
1895
		unset($carp_sync_int);
1896

    
1897
	/* setup pfsync interface */
1898
	if (isset($carp_sync_int) and isset($pfsyncenabled)) {
1899
		if (is_ipaddr($pfsyncpeerip))
1900
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1901
		else
1902
			$syncpeer = "-syncpeer";
1903

    
1904
		mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} {$syncpeer} up", false);
1905

    
1906
		sleep(1);
1907

    
1908
		/* XXX: Handle an issue with pfsync(4) and carp(4). In a cluster carp will come up before pfsync(4) has updated and so will cause issues
1909
		 * for existing sessions.
1910
		 */
1911
		log_error("waiting for pfsync...");
1912
		$i = 0;
1913
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1914
			$i++;
1915
			sleep(1);
1916
		}
1917
		log_error("pfsync done in $i seconds.");
1918
		log_error("Configuring CARP settings finalize...");
1919
	} else {
1920
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1921
	}
1922

    
1923
	if($config['virtualip']['vip'])
1924
		set_single_sysctl("net.inet.carp.allow", "1");
1925
	else
1926
		set_single_sysctl("net.inet.carp.allow", "0");
1927

    
1928
	if (platform_booting()) {
1929
		unmute_kernel_msgs();
1930
		echo gettext("done.") . "\n";
1931
	}
1932
}
1933

    
1934
function interface_proxyarp_configure($interface = "") {
1935
	global $config, $g;
1936
	if(isset($config['system']['developerspew'])) {
1937
		$mt = microtime();
1938
		echo "interface_proxyarp_configure() being called $mt\n";
1939
	}
1940

    
1941
	/* kill any running choparp */
1942
	if (empty($interface))
1943
		killbyname("choparp");
1944
	else {
1945
		$vipif = get_real_interface($interface);
1946
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1947
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1948
	}
1949

    
1950
	$paa = array();
1951
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1952

    
1953
		/* group by interface */
1954
		foreach ($config['virtualip']['vip'] as $vipent) {
1955
			if ($vipent['mode'] === "proxyarp") {
1956
				if ($vipent['interface'])
1957
					$proxyif = $vipent['interface'];
1958
				else
1959
					$proxyif = "wan";
1960

    
1961
				if (!empty($interface) && $interface != $proxyif)
1962
					continue;
1963

    
1964
				if (!is_array($paa[$proxyif]))
1965
					$paa[$proxyif] = array();
1966

    
1967
				$paa[$proxyif][] = $vipent;
1968
			}
1969
		}
1970
	}
1971

    
1972
	if (!empty($interface)) {
1973
		if (is_array($paa[$interface])) {
1974
			$paaifip = get_interface_ip($interface);
1975
			if (!is_ipaddr($paaifip))
1976
				return;
1977
			$args = get_real_interface($interface) . " auto";
1978
			foreach ($paa[$interface] as $paent) {
1979
				if (isset($paent['subnet']))
1980
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1981
				else if (isset($paent['range']))
1982
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1983
			}
1984
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1985
		}
1986
	} else if (count($paa) > 0) {
1987
		foreach ($paa as $paif => $paents)  {
1988
			$paaifip = get_interface_ip($paif);
1989
			if (!is_ipaddr($paaifip))
1990
				continue;
1991
			$args = get_real_interface($paif) . " auto";
1992
			foreach ($paents as $paent) {
1993
				if (isset($paent['subnet']))
1994
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1995
				else if (isset($paent['range']))
1996
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1997
			}
1998
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1999
		}
2000
	}
2001
}
2002

    
2003
function interface_ipalias_cleanup($interface, $inet = "inet4") {
2004
	global $g, $config;
2005

    
2006
	if (is_array($config['virtualip']['vip'])) {
2007
		foreach ($config['virtualip']['vip'] as $vip) {
2008
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
2009
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
2010
					interface_vip_bring_down($vip);
2011
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
2012
					interface_vip_bring_down($vip);
2013
			}
2014
		}
2015
	}
2016
}
2017

    
2018
function interfaces_vips_configure($interface = "") {
2019
	global $g, $config;
2020
	if(isset($config['system']['developerspew'])) {
2021
		$mt = microtime();
2022
		echo "interfaces_vips_configure() being called $mt\n";
2023
	}
2024
	$paa = array();
2025
	if(is_array($config['virtualip']['vip'])) {
2026
		$carp_setuped = false;
2027
		$anyproxyarp = false;
2028
		foreach ($config['virtualip']['vip'] as $vip) {
2029
			switch ($vip['mode']) {
2030
			case "proxyarp":
2031
				/* nothing it is handled on interface_proxyarp_configure() */
2032
				if ($interface <> "" && $vip['interface'] <> $interface)
2033
					continue;
2034
				$anyproxyarp = true;
2035
				break;
2036
			case "ipalias":
2037
				if ($interface <> "" && $vip['interface'] <> $interface)
2038
					continue;
2039
				interface_ipalias_configure($vip);
2040
				break;
2041
			case "carp":
2042
				if ($interface <> "" && $vip['interface'] <> $interface)
2043
					continue;
2044
				if ($carp_setuped == false)
2045
					$carp_setuped = true;
2046
				interface_carp_configure($vip);
2047
				break;
2048
			}
2049
		}
2050
		if ($carp_setuped == true)
2051
			interfaces_sync_setup();
2052
		if ($anyproxyarp == true)
2053
			interface_proxyarp_configure();
2054
	}
2055
}
2056

    
2057
function interface_ipalias_configure(&$vip) {
2058
	global $config;
2059

    
2060
	if ($vip['mode'] != 'ipalias')
2061
		return;
2062

    
2063
	if ($vip['interface'] != 'lo0' && stripos($vip['interface'], '_vip') === false) {
2064
		if (!isset($config['interfaces'][$vip['interface']]))
2065
			return;
2066

    
2067
		if (!isset($config['interfaces'][$vip['interface']]['enable']))
2068
			return;
2069
	}
2070

    
2071
	$af = 'inet';
2072
	if(is_ipaddrv6($vip['subnet']))
2073
		$af = 'inet6';
2074
	$iface = $vip['interface'];
2075
	$vipadd = '';
2076
	if (strpos($vip['interface'], '_vip')) {
2077
		$carpvip = get_configured_carp_interface_list($vip['interface'], $af, 'vip');
2078
		$iface = $carpvip['interface'];
2079
		$vipadd = "vhid {$carpvip['vhid']}";
2080
	}
2081
	$if = get_real_interface($iface);
2082
	mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias {$vipadd}");
2083
	unset($iface, $af, $if, $carpvip, $vipadd);
2084
}
2085

    
2086
function interface_reload_carps($cif) {
2087
	global $config;
2088

    
2089
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2090
	if (empty($carpifs))
2091
		return;
2092

    
2093
	$carps = explode(" ", $carpifs);
2094
	if(is_array($config['virtualip']['vip'])) {
2095
		$viparr = &$config['virtualip']['vip'];
2096
		foreach ($viparr as $vip) {
2097
			if (in_array($vip['carpif'], $carps)) {
2098
				switch ($vip['mode']) {
2099
				case "carp":
2100
					interface_vip_bring_down($vip);
2101
					sleep(1);
2102
					interface_carp_configure($vip);
2103
					break;
2104
				case "ipalias":
2105
					interface_vip_bring_down($vip);
2106
					sleep(1);
2107
					interface_ipalias_configure($vip);
2108
					break;
2109
				}
2110
			}
2111
		}
2112
	}
2113
}
2114

    
2115
function interface_carp_configure(&$vip) {
2116
	global $config, $g;
2117
	if(isset($config['system']['developerspew'])) {
2118
		$mt = microtime();
2119
		echo "interface_carp_configure() being called $mt\n";
2120
	}
2121

    
2122
	if ($vip['mode'] != "carp")
2123
		return;
2124

    
2125
	/* NOTE: Maybe its useless nowadays */
2126
	$realif = get_real_interface($vip['interface']);
2127
	if (!does_interface_exist($realif)) {
2128
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2129
		return;
2130
	}
2131

    
2132
	$vip_password = $vip['password'];
2133
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2134
	if ($vip['password'] != "")
2135
		$password = " pass {$vip_password}";
2136

    
2137
	$advbase = "";
2138
	if (!empty($vip['advbase']))
2139
		$advbase = "advbase " . escapeshellarg($vip['advbase']);
2140

    
2141
	$carp_maintenancemode = isset($config["virtualip_carp_maintenancemode"]);
2142
	if ($carp_maintenancemode)
2143
		$advskew = "advskew 254";
2144
	else
2145
		$advskew = "advskew " . escapeshellarg($vip['advskew']);
2146
	
2147
	mwexec("/sbin/ifconfig {$realif} vhid " . escapeshellarg($vip['vhid']) . " {$advskew} {$advbase} {$password}");
2148

    
2149
	if (is_ipaddrv4($vip['subnet']))
2150
		mwexec("/sbin/ifconfig {$realif} " . escapeshellarg($vip['subnet']) . "/" . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2151
	else if (is_ipaddrv6($vip['subnet']))
2152
		mwexec("/sbin/ifconfig {$realif} inet6 " . escapeshellarg($vip['subnet']) . " prefixlen " . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2153

    
2154
	return $realif;
2155
}
2156

    
2157
function interface_wireless_clone($realif, $wlcfg) {
2158
	global $config, $g;
2159
	/*   Check to see if interface has been cloned as of yet.
2160
	 *   If it has not been cloned then go ahead and clone it.
2161
	 */
2162
	$needs_clone = false;
2163
	if(is_array($wlcfg['wireless']))
2164
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2165
	else
2166
		$wlcfg_mode = $wlcfg['mode'];
2167
	switch($wlcfg_mode) {
2168
	case "hostap":
2169
		$mode = "wlanmode hostap";
2170
		break;
2171
	case "adhoc":
2172
		$mode = "wlanmode adhoc";
2173
		break;
2174
	default:
2175
		$mode = "";
2176
		break;
2177
	}
2178
	$baseif = interface_get_wireless_base($wlcfg['if']);
2179
	if(does_interface_exist($realif)) {
2180
		exec("/sbin/ifconfig " . escapeshellarg($realif), $output, $ret);
2181
		$ifconfig_str = implode($output);
2182
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2183
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2184
			$needs_clone = true;
2185
		}
2186
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2187
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2188
			$needs_clone = true;
2189
		}
2190
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2191
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2192
			$needs_clone = true;
2193
		}
2194
	} else {
2195
		$needs_clone = true;
2196
	}
2197

    
2198
	if($needs_clone == true) {
2199
		/* remove previous instance if it exists */
2200
		if(does_interface_exist($realif))
2201
			pfSense_interface_destroy($realif);
2202

    
2203
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2204
		// Create the new wlan interface. FreeBSD returns the new interface name.
2205
		// example:  wlan2
2206
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2207
		if($ret <> 0) {
2208
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2209
			return false;
2210
		}
2211
		$newif = trim($out[0]);
2212
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2213
		pfSense_interface_rename($newif, $realif);
2214
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2215
	}
2216
	return true;
2217
}
2218

    
2219
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2220
	global $config, $g;
2221

    
2222
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2223
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2224
				 'regdomain', 'regcountry', 'reglocation');
2225

    
2226
	if(!is_interface_wireless($ifcfg['if']))
2227
		return;
2228

    
2229
	$baseif = interface_get_wireless_base($ifcfg['if']);
2230

    
2231
	// Sync shared settings for assigned clones
2232
	$iflist = get_configured_interface_list(false, true);
2233
	foreach ($iflist as $if) {
2234
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2235
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2236
				foreach ($shared_settings as $setting) {
2237
					if ($sync_changes) {
2238
						if (isset($ifcfg['wireless'][$setting]))
2239
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2240
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2241
							unset($config['interfaces'][$if]['wireless'][$setting]);
2242
					} else {
2243
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2244
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2245
						else if (isset($ifcfg['wireless'][$setting]))
2246
							unset($ifcfg['wireless'][$setting]);
2247
					}
2248
				}
2249
				if (!$sync_changes)
2250
					break;
2251
			}
2252
		}
2253
	}
2254

    
2255
	// Read or write settings at shared area
2256
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2257
		foreach ($shared_settings as $setting) {
2258
			if ($sync_changes) {
2259
				if (isset($ifcfg['wireless'][$setting]))
2260
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2261
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2262
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2263
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2264
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2265
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2266
				else if (isset($ifcfg['wireless'][$setting]))
2267
					unset($ifcfg['wireless'][$setting]);
2268
			}
2269
		}
2270
	}
2271

    
2272
	// Sync the mode on the clone creation page with the configured mode on the interface
2273
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2274
		foreach ($config['wireless']['clone'] as &$clone) {
2275
			if ($clone['cloneif'] == $ifcfg['if']) {
2276
				if ($sync_changes) {
2277
					$clone['mode'] = $ifcfg['wireless']['mode'];
2278
				} else {
2279
					$ifcfg['wireless']['mode'] = $clone['mode'];
2280
				}
2281
				break;
2282
			}
2283
		}
2284
		unset($clone);
2285
	}
2286
}
2287

    
2288
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2289
	global $config, $g;
2290

    
2291
	/*    open up a shell script that will be used to output the commands.
2292
	 *    since wireless is changing a lot, these series of commands are fragile
2293
	 *    and will sometimes need to be verified by a operator by executing the command
2294
	 *    and returning the output of the command to the developers for inspection.  please
2295
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2296
	 */
2297

    
2298
	// Remove script file
2299
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2300

    
2301
	// Clone wireless nic if needed.
2302
	interface_wireless_clone($if, $wl);
2303

    
2304
	// Reject inadvertent changes to shared settings in case the interface hasn't been configured.
2305
	interface_sync_wireless_clones($wl, false);
2306

    
2307
	$fd_set = fopen("{$g['tmp_path']}/{$if}_setup.sh","w");
2308
	fwrite($fd_set, "#!/bin/sh\n");
2309
	fwrite($fd_set, "# {$g['product_name']} wireless configuration script.\n\n");
2310
	
2311
	$wlan_setup_log = fopen("{$g['tmp_path']}/{$if}_setup.log","w");
2312

    
2313
	/* set values for /path/program */
2314
	$hostapd = "/usr/sbin/hostapd";
2315
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2316
	$ifconfig = "/sbin/ifconfig";
2317
	$sysctl = "/sbin/sysctl";
2318
	$killall = "/usr/bin/killall";
2319

    
2320
	/* Set all wireless ifconfig variables (split up to get rid of needed checking) */
2321

    
2322
	$wlcmd = array();
2323
	$wl_sysctl = array();
2324
	/* Make sure it's up */
2325
	$wlcmd[] = "up";
2326
	/* Set a/b/g standard */
2327
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2328
	$wlcmd[] = "mode " . escapeshellarg($standard);
2329

    
2330
	/* XXX: Disable ampdu for now on mwl when running in 11n mode
2331
	 * to prevent massive packet loss under certain conditions. */
2332
	if(preg_match("/^mwl/i", $if) && ($standard == "11ng" || $standard == "11na"))
2333
		$wlcmd[] = "-ampdu";
2334

    
2335
	/* Set ssid */
2336
	if($wlcfg['ssid'])
2337
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2338

    
2339
	/* Set 802.11g protection mode */
2340
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2341

    
2342
	/* set wireless channel value */
2343
	if(isset($wlcfg['channel'])) {
2344
		if($wlcfg['channel'] == "0") {
2345
			$wlcmd[] = "channel any";
2346
		} else {
2347
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2348
		}
2349
	}
2350

    
2351
	/* Set antenna diversity value */
2352
	if(isset($wlcfg['diversity']))
2353
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2354

    
2355
	/* Set txantenna value */
2356
	if(isset($wlcfg['txantenna']))
2357
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2358

    
2359
	/* Set rxantenna value */
2360
	if(isset($wlcfg['rxantenna']))
2361
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2362

    
2363
	/* set Distance value */
2364
	if($wlcfg['distance'])
2365
		$distance = escapeshellarg($wlcfg['distance']);
2366

    
2367
	/* Set wireless hostap mode */
2368
	if ($wlcfg['mode'] == "hostap") {
2369
		$wlcmd[] = "mediaopt hostap";
2370
	} else {
2371
		$wlcmd[] = "-mediaopt hostap";
2372
	}
2373

    
2374
	/* Set wireless adhoc mode */
2375
	if ($wlcfg['mode'] == "adhoc") {
2376
		$wlcmd[] = "mediaopt adhoc";
2377
	} else {
2378
		$wlcmd[] = "-mediaopt adhoc";
2379
	}
2380

    
2381
	/* Not necessary to set BSS mode as this is default if adhoc and/or hostap is NOT set */
2382

    
2383
	/* handle hide ssid option */
2384
	if(isset($wlcfg['hidessid']['enable'])) {
2385
		$wlcmd[] = "hidessid";
2386
	} else {
2387
		$wlcmd[] = "-hidessid";
2388
	}
2389

    
2390
	/* handle pureg (802.11g) only option */
2391
	if(isset($wlcfg['pureg']['enable'])) {
2392
		$wlcmd[] = "mode 11g pureg";
2393
	} else {
2394
		$wlcmd[] = "-pureg";
2395
	}
2396

    
2397
	/* handle puren (802.11n) only option */
2398
	if(isset($wlcfg['puren']['enable'])) {
2399
		$wlcmd[] = "puren";
2400
	} else {
2401
		$wlcmd[] = "-puren";
2402
	}
2403

    
2404
	/* enable apbridge option */
2405
	if(isset($wlcfg['apbridge']['enable'])) {
2406
		$wlcmd[] = "apbridge";
2407
	} else {
2408
		$wlcmd[] = "-apbridge";
2409
	}
2410

    
2411
	/* handle turbo option */
2412
	if(isset($wlcfg['turbo']['enable'])) {
2413
		$wlcmd[] = "mediaopt turbo";
2414
	} else {
2415
		$wlcmd[] = "-mediaopt turbo";
2416
	}
2417

    
2418
	/* handle txpower setting */
2419
	if($wlcfg['txpower'] <> "" && is_numeric($wlcfg['txpower'])) {
2420
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2421
	}
2422
	
2423
	/* handle wme option */
2424
	if(isset($wlcfg['wme']['enable'])) {
2425
		$wlcmd[] = "wme";
2426
	} else {
2427
		$wlcmd[] = "-wme";
2428
	}
2429

    
2430
	/* set up wep if enabled */
2431
	$wepset = "";
2432
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2433
		switch($wlcfg['wpa']['auth_algs']) {
2434
			case "1":
2435
				$wepset .= "authmode open wepmode on ";
2436
				break;
2437
			case "2":
2438
				$wepset .= "authmode shared wepmode on ";
2439
				break;
2440
			case "3":
2441
				$wepset .= "authmode mixed wepmode on ";
2442
		}
2443
		$i = 1;
2444
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2445
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2446
			if (isset($wepkey['txkey'])) {
2447
				$wlcmd[] = "weptxkey {$i} ";
2448
			}
2449
			$i++;
2450
		}
2451
		$wlcmd[] = $wepset;
2452
	} else if (isset($wlcfg['wpa']['enable'])) {
2453
		$wlcmd[] = "authmode wpa wepmode off ";
2454
	} else {
2455
		$wlcmd[] = "authmode open wepmode off ";
2456
	}
2457

    
2458
	kill_hostapd($if);
2459
	mwexec(kill_wpasupplicant("{$if}"));
2460

    
2461
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2462
	conf_mount_rw();
2463

    
2464
	switch ($wlcfg['mode']) {
2465
	case 'bss':
2466
		if (isset($wlcfg['wpa']['enable'])) {
2467
			$wpa .= <<<EOD
2468
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2469
ctrl_interface_group=0
2470
ap_scan=1
2471
#fast_reauth=1
2472
network={
2473
ssid="{$wlcfg['ssid']}"
2474
scan_ssid=1
2475
priority=5
2476
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2477
psk="{$wlcfg['wpa']['passphrase']}"
2478
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2479
group={$wlcfg['wpa']['wpa_pairwise']}
2480
}
2481
EOD;
2482

    
2483
			@file_put_contents("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", $wpa);
2484
			unset($wpa);
2485
		}
2486
		break;
2487
	case 'hostap':
2488
		if (!empty($wlcfg['wpa']['passphrase']))
2489
			$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2490
		else
2491
			$wpa_passphrase = "";
2492
		if (isset($wlcfg['wpa']['enable'])) {
2493
			$wpa .= <<<EOD
2494
interface={$if}
2495
driver=bsd
2496
logger_syslog=-1
2497
logger_syslog_level=0
2498
logger_stdout=-1
2499
logger_stdout_level=0
2500
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2501
ctrl_interface={$g['varrun_path']}/hostapd
2502
ctrl_interface_group=wheel
2503
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2504
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2505
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2506
ssid={$wlcfg['ssid']}
2507
debug={$wlcfg['wpa']['debug_mode']}
2508
auth_algs={$wlcfg['wpa']['auth_algs']}
2509
wpa={$wlcfg['wpa']['wpa_mode']}
2510
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2511
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2512
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2513
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2514
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2515
{$wpa_passphrase}
2516

    
2517
EOD;
2518

    
2519
			if (isset($wlcfg['wpa']['rsn_preauth'])) {
2520
				$wpa .= <<<EOD
2521
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2522
rsn_preauth=1
2523
rsn_preauth_interfaces={$if}
2524

    
2525
EOD;
2526
			}
2527
			if (is_array($wlcfg['wpa']['ieee8021x']) && isset($wlcfg['wpa']['ieee8021x']['enable'])) {
2528
				$wpa .= "ieee8021x=1\n";
2529

    
2530
			if (!empty($wlcfg['auth_server_addr']) && !empty($wlcfg['auth_server_shared_secret'])) {
2531
				$auth_server_port = "1812";
2532
				if (!empty($wlcfg['auth_server_port']) && is_numeric($wlcfg['auth_server_port']))
2533
					$auth_server_port = intval($wlcfg['auth_server_port']);
2534
				$wpa .= <<<EOD
2535

    
2536
auth_server_addr={$wlcfg['auth_server_addr']}
2537
auth_server_port={$auth_server_port}
2538
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2539

    
2540
EOD;
2541
				if (!empty($wlcfg['auth_server_addr2']) && !empty($wlcfg['auth_server_shared_secret2'])) {
2542
					$auth_server_port2 = "1812";
2543
					if (!empty($wlcfg['auth_server_port2']) && is_numeric($wlcfg['auth_server_port2']))
2544
						$auth_server_port2 = intval($wlcfg['auth_server_port2']);
2545

    
2546
					$wpa .= <<<EOD
2547
auth_server_addr={$wlcfg['auth_server_addr2']}
2548
auth_server_port={$auth_server_port2}
2549
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2550

    
2551
EOD;
2552
					}
2553
				}
2554
			}
2555

    
2556
			@file_put_contents("{$g['varetc_path']}/hostapd_{$if}.conf", $wpa);
2557
			unset($wpa);
2558
		}
2559
		break;
2560
	}
2561

    
2562
	/*
2563
	 *    all variables are set, lets start up everything
2564
	 */
2565

    
2566
	$baseif = interface_get_wireless_base($if);
2567
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2568
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2569

    
2570
	/* set sysctls for the wireless interface */
2571
	if (!empty($wl_sysctl)) {
2572
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2573
		foreach ($wl_sysctl as $wl_sysctl_line) {
2574
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2575
		}
2576
	}
2577

    
2578
	/* set ack timers according to users preference (if he/she has any) */
2579
	if($distance) {
2580
		fwrite($fd_set, "# Enable ATH distance settings\n");
2581
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2582
	}
2583

    
2584
	if (isset($wlcfg['wpa']['enable'])) {
2585
		if ($wlcfg['mode'] == "bss") {
2586
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2587
		}
2588
		if ($wlcfg['mode'] == "hostap") {
2589
			/* add line to script to restore old mac to make hostapd happy */
2590
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2591
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2592
				if (is_macaddr($if_oldmac))
2593
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2594
						" link " . escapeshellarg($if_oldmac) . "\n");
2595
			}
2596

    
2597
			fwrite($fd_set, "{$hostapd} -B -P {$g['varrun_path']}/hostapd_{$if}.pid {$g['varetc_path']}/hostapd_{$if}.conf\n");
2598

    
2599
			/* add line to script to restore spoofed mac after running hostapd */
2600
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2601
				if ($wl['spoofmac'])
2602
					$if_curmac = $wl['spoofmac'];
2603
				else
2604
					$if_curmac = get_interface_mac($if);
2605
				if (is_macaddr($if_curmac))
2606
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2607
						" link " . escapeshellarg($if_curmac) . "\n");
2608
			}
2609
		}
2610
	}
2611

    
2612
	fclose($fd_set);
2613
	conf_mount_ro();
2614

    
2615
	/* Making sure regulatory settings have actually changed
2616
	 * before applying, because changing them requires bringing
2617
	 * down all wireless networks on the interface. */
2618
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2619
	$ifconfig_str = implode($output);
2620
	unset($output);
2621
	$reg_changing = false;
2622

    
2623
	/* special case for the debug country code */
2624
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2625
		$reg_changing = true;
2626
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2627
		$reg_changing = true;
2628
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2629
		$reg_changing = true;
2630
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2631
		$reg_changing = true;
2632
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2633
		$reg_changing = true;
2634

    
2635
	if ($reg_changing) {
2636
		/* set regulatory domain */
2637
		if($wlcfg['regdomain'])
2638
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2639

    
2640
		/* set country */
2641
		if($wlcfg['regcountry'])
2642
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2643

    
2644
		/* set location */
2645
		if($wlcfg['reglocation'])
2646
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2647

    
2648
		$wlregcmd_args = implode(" ", $wlregcmd);
2649

    
2650
		/* build a complete list of the wireless clones for this interface */
2651
		$clone_list = array();
2652
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2653
			$clone_list[] = interface_get_wireless_clone($baseif);
2654
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2655
			foreach ($config['wireless']['clone'] as $clone) {
2656
				if ($clone['if'] == $baseif)
2657
					$clone_list[] = $clone['cloneif'];
2658
			}
2659
		}
2660

    
2661
		/* find which clones are up and bring them down */
2662
		$clones_up = array();
2663
		foreach ($clone_list as $clone_if) {
2664
			$clone_status = pfSense_get_interface_addresses($clone_if);
2665
			if ($clone_status['status'] == 'up') {
2666
				$clones_up[] = $clone_if;
2667
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2668
			}
2669
		}
2670

    
2671
		/* apply the regulatory settings */
2672
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2673
		fwrite($wlan_setup_log, "$ifconfig" . escapeshellarg($if) . "$wlregcmd_args \n");
2674

    
2675
		/* bring the clones back up that were previously up */
2676
		foreach ($clones_up as $clone_if) {
2677
			interfaces_bring_up($clone_if);
2678

    
2679
			/*
2680
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2681
			 * is in infrastructure mode, and WPA is enabled.
2682
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2683
			 */
2684
			if ($clone_if != $if) {
2685
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2686
				if ( !empty($friendly_if)
2687
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2688
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2689
					mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($clone_if) . "_setup.sh");
2690
				}
2691
			}
2692
		}
2693
	}
2694

    
2695
	/* The mode must be specified in a separate command before ifconfig
2696
	 * will allow the mode and channel at the same time in the next. */
2697
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " mode " . escapeshellarg($standard));
2698
	fwrite($wlan_setup_log, "/sbin/ifconfig " . escapeshellarg($if) . " mode " . escapeshellarg($standard) . "\n");
2699

    
2700
	/* configure wireless */
2701
	$wlcmd_args = implode(" ", $wlcmd);
2702
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $wlcmd_args, false);
2703
	fwrite($wlan_setup_log, "/sbin/ifconfig " . escapeshellarg($if) . " " . "$wlcmd_args \n");
2704
	fclose($wlan_setup_log);
2705
	
2706
	unset($wlcmd_args, $wlcmd);
2707

    
2708

    
2709
	sleep(1);
2710
	/* execute hostapd and wpa_supplicant if required in shell */
2711
	mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($if) . "_setup.sh");
2712

    
2713
	return 0;
2714

    
2715
}
2716

    
2717
function kill_hostapd($interface) {
2718
	global $g;
2719

    
2720
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2721
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2722
}
2723

    
2724
function kill_wpasupplicant($interface) {
2725
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2726
}
2727

    
2728
function find_dhclient_process($interface) {
2729
	if ($interface)
2730
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2731
	else
2732
		$pid = 0;
2733

    
2734
	return intval($pid);
2735
}
2736

    
2737
function kill_dhclient_process($interface) {
2738
	if (empty($interface) || !does_interface_exist($interface))
2739
		return;
2740

    
2741
	$i = 0;
2742
	while ((($pid = find_dhclient_process($interface)) != 0) && ($i < 3)) {
2743
		/* 3rd time make it die for sure */
2744
		$sig = ($i == 2 ? SIGKILL : SIGTERM);
2745
		posix_kill($pid, $sig);
2746
		sleep(1);
2747
		$i++;
2748
	}
2749
	unset($i);
2750
}
2751

    
2752
function find_dhcp6c_process($interface) {
2753
	global $g;
2754

    
2755
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2756
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2757
	else
2758
		return(false);
2759

    
2760
	return intval($pid);
2761
}
2762

    
2763
function interface_virtual_create($interface) {
2764
	global $config;
2765

    
2766
	if (strstr($interface, "_vlan")) {
2767
		interfaces_vlan_configure($vlan);
2768
	} else if (substr($interface, 0, 3) == "gre") {
2769
		interfaces_gre_configure(0, $interface);
2770
	} else if (substr($interface, 0, 3) == "gif") {
2771
		interfaces_gif_configure(0, $interface);
2772
	} else if (substr($interface, 0, 5) == "ovpns") {
2773
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-server'])) {
2774
			foreach ($config['openvpn']['openvpn-server'] as $server) {
2775
				if ($interface == "ovpns{$server['vpnid']}") {
2776
					if (!function_exists('openvpn_resync'))
2777
						require_once('openvpn.inc');
2778
					log_error("OpenVPN: Resync server {$server['description']}");
2779
					openvpn_resync('server', $server);
2780
				}
2781
			}
2782
			unset($server);
2783
		}
2784
	} else if (substr($interface, 0, 5) == "ovpnc") {
2785
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-client'])) {
2786
			foreach ($config['openvpn']['openvpn-client'] as $client) {
2787
				if ($interface == "ovpnc{$client['vpnid']}") {
2788
					if (!function_exists('openvpn_resync'))
2789
						require_once('openvpn.inc');
2790
					log_error("OpenVPN: Resync server {$client['description']}");
2791
					openvpn_resync('client', $client);
2792
				}
2793
			}
2794
			unset($client);
2795
		}
2796
	} else if (substr($interface, 0, 4) == "lagg") {
2797
		interfaces_lagg_configure($interface);
2798
	} else if (substr($interface, 0, 6) == "bridge") {
2799
		interfaces_bridge_configure(0, $interface);
2800
	}
2801
}
2802

    
2803
function interface_vlan_mtu_configured($realhwif, $mtu) {
2804
	global $config;
2805

    
2806
	if (is_array($config['vlans']) && is_array($config['vlans']['vlan'])) {
2807
		foreach ($config['vlans']['vlan'] as $vlan) {
2808
			if ($vlan['if'] != $realhwif)
2809
				continue;
2810
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2811
			if (!empty($assignedport) && !empty($config['interfaces'][$assignedport]['mtu'])) {
2812
				if (intval($config['interfaces'][$assignedport]['mtu']) > $mtu)
2813
					$mtu = $config['interfaces'][$assignedport]['mtu'];
2814
			}
2815
		}
2816
	}
2817

    
2818
	return $mtu;
2819
}
2820

    
2821
function interface_vlan_adapt_mtu($vlanifs, $mtu) {
2822
	global $config;
2823

    
2824
	if (!is_array($vlanifs))
2825
		return;
2826

    
2827
	/* All vlans need to use the same mtu value as their parent. */
2828
	foreach ($vlanifs as $vlan) {
2829
		$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2830
		if (!empty($assignedport)) {
2831
			if (!empty($config['interfaces'][$assignedport]['mtu'])) {
2832
				pfSense_interface_mtu($vlan['vlanif'], $config['interfaces'][$assignedport]['mtu']);
2833
			} else {
2834
				if (get_interface_mtu($vlan['vlanif']) != $mtu)
2835
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
2836
			}
2837
		} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
2838
			pfSense_interface_mtu($vlan['vlanif'], $mtu);
2839
	}
2840
}
2841

    
2842
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2843
	global $config, $g;
2844
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2845
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2846

    
2847
	$wancfg = $config['interfaces'][$interface];
2848

    
2849
	if (!isset($wancfg['enable']))
2850
		return;
2851

    
2852
	$realif = get_real_interface($interface);
2853
	$realhwif_array = get_parent_interface($interface);
2854
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2855
	$realhwif = $realhwif_array[0];
2856

    
2857
	if (!platform_booting() && !(substr($realif, 0, 4) == "ovpn")) {
2858
		/* remove all IPv4 and IPv6 addresses */
2859
		$tmpifaces = pfSense_getall_interface_addresses($realif);
2860
		if (is_array($tmpifaces)) {
2861
			foreach ($tmpifaces as $tmpiface) {
2862
				if (is_ipaddrv6($tmpiface) || is_subnetv6($tmpiface)) {
2863
					if (!is_linklocal($tmpiface))
2864
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$tmpiface} delete");
2865
				} else {
2866
					if (is_subnetv4($tmpiface)) {
2867
						$tmpip = explode('/', $tmpiface);
2868
						$tmpip = $tmpip[0];
2869
					} else
2870
						$tmpip = $tmpiface;
2871
					pfSense_interface_deladdress($realif, $tmpip);
2872
				}
2873
			}
2874
		}
2875

    
2876
		/* only bring down the interface when both v4 and v6 are set to NONE */
2877
		if (empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6']))
2878
			interface_bring_down($interface);
2879
	}
2880

    
2881
	$interface_to_check = $realif;
2882
	if (interface_isppp_type($interface))
2883
		$interface_to_check = $realhwif;
2884

    
2885
	/* Need to check that the interface exists or not in the case where its coming back from disabled state see #3270 */
2886
	if (!platform_booting() && (in_array(substr($realif, 0, 3), array("gre", "gif")) || !does_interface_exist($interface_to_check)))
2887
		interface_virtual_create($interface_to_check);
2888

    
2889
	/* Disable Accepting router advertisements unless specifically requested */
2890
	if ($g['debug'])
2891
		log_error("Deny router advertisements for interface {$interface}");
2892
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv", true);
2893

    
2894
	/* wireless configuration? */
2895
	if (is_array($wancfg['wireless']))
2896
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2897

    
2898
	$mac = get_interface_mac($realhwif);
2899
	/*
2900
	 * Don't try to reapply the spoofed MAC if it's already applied.
2901
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2902
	 * the interface config again, which attempts to spoof the MAC again,
2903
	 * which cycles the link again...
2904
	 */
2905
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2906
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2907
			" link " . escapeshellarg($wancfg['spoofmac']));
2908
	}  else {
2909

    
2910
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2911
			/*   this is not a valid mac address.  generate a
2912
			 *   temporary mac address so the machine can get online.
2913
			 */
2914
			echo gettext("Generating new MAC address.");
2915
			$random_mac = generate_random_mac_address();
2916
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2917
				" link " . escapeshellarg($random_mac));
2918
			$wancfg['spoofmac'] = $random_mac;
2919
			write_config();
2920
			file_notice("MAC Address altered", sprintf(gettext('The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface %1$s has been automatically replaced with %2$s'), $realif, $random_mac), "Interfaces");
2921
		}
2922
	}
2923

    
2924
	/* media */
2925
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2926
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2927
		if ($wancfg['media'])
2928
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2929
		if ($wancfg['mediaopt'])
2930
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2931
		mwexec($cmd);
2932
	}
2933

    
2934
	/* Apply hw offloading policies as configured */
2935
	enable_hardware_offloading($interface);
2936

    
2937
	/* invalidate interface/ip/sn cache */
2938
	get_interface_arr(true);
2939
	unset($interface_ip_arr_cache[$realif]);
2940
	unset($interface_sn_arr_cache[$realif]);
2941
	unset($interface_ipv6_arr_cache[$realif]);
2942
	unset($interface_snv6_arr_cache[$realif]);
2943

    
2944
	$tunnelif = substr($realif, 0, 3);
2945

    
2946
	if (does_interface_exist($wancfg['if']))
2947
		interfaces_bring_up($wancfg['if']);
2948

    
2949
	if (!empty($wancfg['mtu'])) {
2950
		if (stristr($realif, "_vlan")) {
2951
			$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2952
			if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu'])) {
2953
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
2954
				if ($wancfg['mtu'] > $parentmtu)
2955
					log_error("There is a conflict on MTU between parent {$realhwif} and VLAN({$realif})");
2956
			} else
2957
				$parentmtu = 0;
2958

    
2959
			$parentmtu = interface_vlan_mtu_configured($realhwif, $parentmtu);
2960

    
2961
			if (get_interface_mtu($realhwif) != $parentmtu)
2962
				pfSense_interface_mtu($realhwif, $parentmtu);
2963

    
2964
			/* All vlans need to use the same mtu value as their parent. */
2965
			interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $parentmtu);
2966
		} else if (substr($realif, 0, 4) == 'lagg') {
2967
			/* LAGG interface must be destroyed and re-created to change MTU */
2968
			if ($wancfg['mtu'] != get_interface_mtu($realif)) {
2969
				if (isset($config['laggs']['lagg']) && is_array($config['laggs']['lagg'])) {
2970
					foreach ($config['laggs']['lagg'] as $lagg) {
2971
						if ($lagg['laggif'] == $realif) {
2972
							interface_lagg_configure($lagg);
2973
							break;
2974
						}
2975
					}
2976
				}
2977
			}
2978
		} else {
2979
			if ($wancfg['mtu'] != get_interface_mtu($realif))
2980
				pfSense_interface_mtu($realif, $wancfg['mtu']);
2981

    
2982
			/* This case is needed when the parent of vlans is being configured */
2983
			$vlans = link_interface_to_vlans($realif);
2984
			if (is_array($vlans))
2985
				interface_vlan_adapt_mtu($vlans, $wancfg['mtu']);
2986
			unset($vlans);
2987
		}
2988
		/* XXX: What about gre/gif/.. ? */
2989
	}
2990

    
2991
	switch ($wancfg['ipaddr']) {
2992
	case 'dhcp':
2993
		interface_dhcp_configure($interface);
2994
		break;
2995
	case 'pppoe':
2996
	case 'l2tp':
2997
	case 'pptp':
2998
	case 'ppp':
2999
		interface_ppps_configure($interface);
3000
		break;
3001
	default:
3002
		/* XXX: Kludge for now related to #3280 */
3003
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
3004
			if (is_ipaddrv4($wancfg['ipaddr']) && $wancfg['subnet'] <> "")
3005
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
3006
		}
3007
		break;
3008
	}
3009

    
3010
	switch ($wancfg['ipaddrv6']) {
3011
	case 'slaac':
3012
	case 'dhcp6':
3013
		interface_dhcpv6_configure($interface, $wancfg);
3014
		break;
3015
	case '6rd':
3016
		interface_6rd_configure($interface, $wancfg);
3017
		break;
3018
	case '6to4':
3019
		interface_6to4_configure($interface, $wancfg);
3020
		break;
3021
	case 'track6':
3022
		interface_track6_configure($interface, $wancfg, $linkupevent);
3023
		break;
3024
	default:
3025
		/* XXX: Kludge for now related to #3280 */
3026
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
3027
			if (is_ipaddrv6($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
3028
				//pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
3029
				// FIXME: Add IPv6 Support to the pfSense module
3030
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$wancfg['ipaddrv6']} prefixlen " . escapeshellarg($wancfg['subnetv6']));
3031
			}
3032
		}
3033
		break;
3034
	}
3035

    
3036
	interface_netgraph_needed($interface);
3037

    
3038
	if (!platform_booting()) {
3039
		link_interface_to_vips($interface, "update");
3040

    
3041
		if ($tunnelif != 'gre') {
3042
			unset($gre);
3043
			$gre = link_interface_to_gre($interface);
3044
			if (!empty($gre))
3045
				array_walk($gre, 'interface_gre_configure');
3046
		}
3047

    
3048
		if ($tunnelif != 'gif') {
3049
			unset($gif);
3050
			$gif = link_interface_to_gif($interface);
3051
			if (!empty($gif))
3052
				array_walk($gif, 'interface_gif_configure');
3053
		}
3054

    
3055
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3056
			unset($bridgetmp);
3057
			$bridgetmp = link_interface_to_bridge($interface);
3058
			if (!empty($bridgetmp))
3059
				interface_bridge_add_member($bridgetmp, $realif);
3060
		}
3061

    
3062
		$grouptmp = link_interface_to_group($interface);
3063
		if (!empty($grouptmp))
3064
			array_walk($grouptmp, 'interface_group_add_member');
3065

    
3066
		if ($interface == "lan")
3067
			/* make new hosts file */
3068
			system_hosts_generate();
3069

    
3070
		if ($reloadall == true) {
3071

    
3072
			/* reconfigure static routes (kernel may have deleted them) */
3073
			system_routing_configure($interface);
3074

    
3075
			/* reload ipsec tunnels */
3076
			send_event("service reload ipsecdns");
3077

    
3078
			/* restart dnsmasq or unbound */
3079
			if (isset($config['dnsmasq']['enable']))
3080
				services_dnsmasq_configure();
3081
			elseif (isset($config['unbound']['enable']))
3082
				services_unbound_configure();
3083

    
3084
			/* update dyndns */
3085
			send_event("service reload dyndns {$interface}");
3086

    
3087
			/* reload captive portal */
3088
			if (!function_exists('captiveportal_init_rules_byinterface'))
3089
				require_once('captiveportal.inc');
3090
			captiveportal_init_rules_byinterface($interface);
3091
		}
3092
	}
3093

    
3094
	interfaces_staticarp_configure($interface);
3095
	return 0;
3096
}
3097

    
3098
function interface_track6_configure($interface = "lan", $wancfg, $linkupevent = false) {
3099
	global $config, $g;
3100

    
3101
	if (!is_array($wancfg))
3102
		return;
3103

    
3104
	if (!isset($wancfg['enable']))
3105
		return;
3106

    
3107
	/* If the interface is not configured via another, exit */
3108
	if (empty($wancfg['track6-interface']))
3109
		return;
3110

    
3111
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3112
	$realif = get_real_interface($interface);
3113
	$linklocal = find_interface_ipv6_ll($realif);
3114
	if (!empty($linklocal))
3115
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3116
	/* XXX: This might break for good on a carp installation using link-local as network ips */
3117
	/* XXX: Probably should remove? */
3118
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3119

    
3120
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3121
	if (!isset($trackcfg['enable'])) {
3122
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3123
		return;
3124
	}
3125

    
3126
	switch($trackcfg['ipaddrv6']) {
3127
	case "6to4":
3128
		if ($g['debug'])
3129
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3130
		interface_track6_6to4_configure($interface, $wancfg);
3131
		break;
3132
	case "6rd":
3133
		if ($g['debug'])
3134
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3135
		interface_track6_6rd_configure($interface, $wancfg);
3136
		break;
3137
	case "dhcp6":
3138
		if ($linkupevent == true) {
3139
			/* 
3140
			 * NOTE: Usually come here from rc.linkup calling so just call directly instead of generating event
3141
			 * 	Instead of disrupting all other v4 configuration just restart DHCPv6 client for now
3142
			 *
3143
			 * XXX: Probably DHCPv6 client should handle this automagically itself?
3144
			 */
3145
			$parentrealif = get_real_interface($wancfg['track6-interface']);
3146
			$pidv6 = find_dhcp6c_process($parentrealif);
3147
			if($pidv6)
3148
				posix_kill($pidv6, SIGHUP);
3149
		}
3150
		break;
3151
	}
3152

    
3153
	if ($linkupevent == false) {
3154
		if (!function_exists('services_dhcpd_configure'))
3155
			require_once("services.inc");
3156

    
3157
		if (isset($config['unbound']['enable']))
3158
			services_unbound_configure();
3159

    
3160
		services_dhcpd_configure("inet6");
3161
	}
3162

    
3163
	return 0;
3164
}
3165

    
3166
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3167
	global $config, $g;
3168
	global $interface_ipv6_arr_cache;
3169
	global $interface_snv6_arr_cache;
3170

    
3171
	if (!is_array($lancfg))
3172
		return;
3173

    
3174
	/* If the interface is not configured via another, exit */
3175
	if (empty($lancfg['track6-interface']))
3176
		return;
3177

    
3178
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3179
	if (empty($wancfg)) {
3180
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3181
		return;
3182
	}
3183

    
3184
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3185
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3186
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not valid, not configuring 6RD tunnel");
3187
		return;
3188
	}
3189
	$hexwanv4 = return_hex_ipv4($ip4address);
3190

    
3191
	/* create the long prefix notation for math, save the prefix length */
3192
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3193
	$rd6prefixlen = $rd6prefix[1];
3194
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3195

    
3196
	/* binary presentation of the prefix for all 128 bits. */
3197
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3198

    
3199
	/* just save the left prefix length bits */
3200
	$rd6lanbin = substr($rd6lanbin, 0, $rd6prefixlen);
3201
	/* add the v4 address, offset n bits from the left */
3202
	$rd6lanbin .= substr(sprintf("%032b", hexdec($hexwanv4)), (0 + $wancfg['prefix-6rd-v4plen']), 32);
3203

    
3204
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3205
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3206
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3207
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3208
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3209
	/* fill the rest out with zeros */
3210
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);
3211

    
3212
	/* convert the 128 bits for the lan address back into a valid IPv6 address */
3213
	$rd6lan = convert_128bit_to_ipv6($rd6lanbin) ."1";
3214

    
3215
	$lanif = get_real_interface($interface);
3216
	$oip = find_interface_ipv6($lanif);
3217
	if (is_ipaddrv6($oip))
3218
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3219
	unset($interface_ipv6_arr_cache[$lanif]);
3220
	unset($interface_snv6_arr_cache[$lanif]);
3221
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3222
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3223

    
3224
	return 0;
3225
}
3226

    
3227
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3228
	global $config, $g;
3229
	global $interface_ipv6_arr_cache;
3230
	global $interface_snv6_arr_cache;
3231

    
3232
	if (!is_array($lancfg))
3233
		return;
3234

    
3235
	/* If the interface is not configured via another, exit */
3236
	if (empty($lancfg['track6-interface']))
3237
		return;
3238

    
3239
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3240
	if (empty($wancfg)) {
3241
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3242
		return;
3243
	}
3244

    
3245
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3246
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3247
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3248
		return;
3249
	}
3250
	$hexwanv4 = return_hex_ipv4($ip4address);
3251

    
3252
	/* create the long prefix notation for math, save the prefix length */
3253
	$sixto4prefix = "2002::";
3254
	$sixto4prefixlen = 16;
3255
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3256

    
3257
	/* binary presentation of the prefix for all 128 bits. */
3258
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3259

    
3260
	/* just save the left prefix length bits */
3261
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3262
	/* add the v4 address */
3263
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3264
	/* add the custom prefix id */
3265
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3266
	/* fill the rest out with zeros */
3267
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);
3268

    
3269
	/* convert the 128 bits for the lan address back into a valid IPv6 address */
3270
	$sixto4lan = convert_128bit_to_ipv6($sixto4lanbin) ."1";
3271

    
3272
	$lanif = get_real_interface($interface);
3273
	$oip = find_interface_ipv6($lanif);
3274
	if (is_ipaddrv6($oip))
3275
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3276
	unset($interface_ipv6_arr_cache[$lanif]);
3277
	unset($interface_snv6_arr_cache[$lanif]);
3278
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3279
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3280

    
3281
	return 0;
3282
}
3283

    
3284
function interface_6rd_configure($interface = "wan", $wancfg) {
3285
	global $config, $g;
3286

    
3287
	/* because this is a tunnel interface we can only function
3288
	 *	with a public IPv4 address on the interface */
3289

    
3290
	if (!is_array($wancfg))
3291
		return;
3292

    
3293
	if (!is_module_loaded('if_stf.ko'))
3294
		mwexec('/sbin/kldload if_stf.ko');
3295

    
3296
	$wanif = get_real_interface($interface);
3297
	$ip4address = find_interface_ip($wanif);
3298
	if (!is_ipaddrv4($ip4address)) {
3299
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3300
		return false;
3301
	}
3302
	$hexwanv4 = return_hex_ipv4($ip4address);
3303

    
3304
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3305
		$wancfg['prefix-6rd-v4plen'] = 0;
3306

    
3307
	/* create the long prefix notation for math, save the prefix length */
3308
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3309
	$rd6prefixlen = $rd6prefix[1];
3310
	$brgw = explode('.', $wancfg['gateway-6rd']);
3311
	$rd6brgw = substr(Net_IPv6::_ip2Bin($rd6prefix[0]), 0, $rd6prefixlen);
3312
	$rd6brgw .= str_pad(decbin($brgw[0]), 8, '0', STR_PAD_LEFT) . str_pad(decbin($brgw[1]), 8, '0', STR_PAD_LEFT) . str_pad(decbin($brgw[2]), 8, '0', STR_PAD_LEFT) . str_pad(decbin($brgw[3]), 8, '0', STR_PAD_LEFT);
3313
	if (strlen($rd6brgw) < 128)
3314
		$rd6brgw = str_pad($rd6brgw, 128, '0', STR_PAD_RIGHT);
3315
	$rd6brgw = Net_IPv6::compress(Net_IPv6::_bin2Ip($rd6brgw));
3316
	unset($brgw);
3317
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3318

    
3319
	/* binary presentation of the prefix for all 128 bits. */
3320
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3321

    
3322
	/* just save the left prefix length bits */
3323
	$rd6prefixbin = substr($rd6prefixbin, 0, $rd6prefixlen);
3324
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3325
	$rd6prefixbin .= substr(sprintf("%032b", hexdec($hexwanv4)), $wancfg['prefix-6rd-v4plen'], 32);
3326
	/* fill out the rest with 0's */
3327
	$rd6prefixbin = str_pad($rd6prefixbin, 128, "0", STR_PAD_RIGHT);
3328

    
3329
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3330
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3331

    
3332

    
3333
	/* XXX: need to extend to support variable prefix size for v4 */
3334
	if (!is_module_loaded("if_stf"))
3335
		mwexec("/sbin/kldload if_stf.ko");
3336
	$stfiface = "{$interface}_stf";
3337
	if (does_interface_exist($stfiface))
3338
		pfSense_interface_destroy($stfiface);
3339
	$tmpstfiface = pfSense_interface_create("stf");
3340
	pfSense_interface_rename($tmpstfiface, $stfiface);
3341
	pfSense_interface_flags($stfiface, IFF_LINK2);
3342
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3343
	mwexec("/sbin/ifconfig {$stfiface} stfv4br " . escapeshellarg($wancfg['gateway-6rd']));
3344
	if ($wancfg['prefix-6rd-v4plen'] >= 0 && $wancfg['prefix-6rd-v4plen'] <= 32)
3345
		mwexec("/sbin/ifconfig {$stfiface} stfv4net {$ip4address}/" . escapeshellarg($wancfg['prefix-6rd-v4plen']));
3346
	if ($g['debug'])
3347
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3348

    
3349
	/* write out a default router file */
3350
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3351
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3352

    
3353
	$ip4gateway = get_interface_gateway($interface);
3354
	if (is_ipaddrv4($ip4gateway))
3355
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3356

    
3357
	/* configure dependent interfaces */
3358
	if (!platform_booting())
3359
		link_interface_to_track6($interface, "update");
3360

    
3361
	return 0;
3362
}
3363

    
3364
function interface_6to4_configure($interface = "wan", $wancfg){
3365
	global $config, $g;
3366

    
3367
	/* because this is a tunnel interface we can only function
3368
	 *	with a public IPv4 address on the interface */
3369

    
3370
	if (!is_array($wancfg))
3371
		return;
3372

    
3373
	$wanif = get_real_interface($interface);
3374
	$ip4address = find_interface_ip($wanif);
3375
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3376
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3377
		return false;
3378
	}
3379

    
3380
	/* create the long prefix notation for math, save the prefix length */
3381
	$stfprefixlen = 16;
3382
	$stfprefix = Net_IPv6::uncompress("2002::");
3383
	$stfarr = explode(":", $stfprefix);
3384
	$v4prefixlen = "0";
3385

    
3386
	/* we need the hex form of the interface IPv4 address */
3387
	$ip4arr = explode(".", $ip4address);
3388
	$hexwanv4 = "";
3389
	foreach($ip4arr as $octet)
3390
		$hexwanv4 .= sprintf("%02x", $octet);
3391

    
3392
	/* we need the hex form of the broker IPv4 address */
3393
	$ip4arr = explode(".", "192.88.99.1");
3394
	$hexbrv4 = "";
3395
	foreach($ip4arr as $octet)
3396
		$hexbrv4 .= sprintf("%02x", $octet);
3397

    
3398
	/* binary presentation of the prefix for all 128 bits. */
3399
	$stfprefixbin = "";
3400
	foreach($stfarr as $element) {
3401
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3402
	}
3403
	/* just save the left prefix length bits */
3404
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3405

    
3406
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3407
	$stfbrokerbin = substr(sprintf("%032b", hexdec($hexbrv4)), $v4prefixlen, 32);
3408
	$stfbrokerbin = str_pad($stfprefixstartbin . $stfbrokerbin, 128, "0", STR_PAD_RIGHT);
3409

    
3410
	/* for the local subnet too. */
3411
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3412
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);
3413

    
3414
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3415
	$stfbrarr = array();
3416
	$stfbrbinarr = array();
3417
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3418
	foreach($stfbrbinarr as $bin)
3419
		$stfbrarr[] = dechex(bindec($bin));
3420
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3421

    
3422
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3423
	$stflanarr = array();
3424
	$stflanbinarr = array();
3425
	$stflanbinarr = str_split($stflanbin, 16);
3426
	foreach($stflanbinarr as $bin)
3427
		$stflanarr[] = dechex(bindec($bin));
3428
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3429
	$stflanarr[7] = 1;
3430
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3431

    
3432
	/* setup the stf interface */
3433
	if (!is_module_loaded("if_stf"))
3434
		mwexec("/sbin/kldload if_stf.ko");
3435
	$stfiface = "{$interface}_stf";
3436
	if (does_interface_exist($stfiface))
3437
		pfSense_interface_destroy($stfiface);
3438
	$tmpstfiface = pfSense_interface_create("stf");
3439
	pfSense_interface_rename($tmpstfiface, $stfiface);
3440
	pfSense_interface_flags($stfiface, IFF_LINK2);
3441
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3442

    
3443
	if ($g['debug'])
3444
		log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for {$stfiface}, route {$stfbrgw}");
3445

    
3446
	/* write out a default router file */
3447
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3448
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3449

    
3450
	$ip4gateway = get_interface_gateway($interface);
3451
	if (is_ipaddrv4($ip4gateway))
3452
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3453

    
3454
	if (!platform_booting())
3455
		link_interface_to_track6($interface, "update");
3456

    
3457
	return 0;
3458
}
3459

    
3460
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3461
	global $config, $g;
3462

    
3463
	if (!is_array($wancfg))
3464
		return;
3465

    
3466
	$wanif = get_real_interface($interface, "inet6");
3467
	$dhcp6cconf = "";
3468
	$dhcp6cconf .= "interface {$wanif} {\n";
3469

    
3470
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3471
	if($wancfg['ipaddrv6'] == "slaac") {
3472
		$dhcp6cconf .= "	information-only;\n";
3473
		$dhcp6cconf .= "	request domain-name-servers;\n";
3474
		$dhcp6cconf .= "	request domain-name;\n";
3475
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3476
		$dhcp6cconf .= "};\n";
3477
	} else {
3478
		$trackiflist = array();
3479
		$iflist = link_interface_to_track6($interface);
3480
		foreach ($iflist as $ifname => $ifcfg) {
3481
			if (is_numeric($ifcfg['track6-prefix-id']))
3482
				$trackiflist[$ifname] = $ifcfg;
3483
		}
3484

    
3485
		/* skip address request if this is set */
3486
		if(!isset($wancfg['dhcp6prefixonly']))
3487
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3488
		if(is_numeric($wancfg['dhcp6-ia-pd-len']) && !empty($trackiflist))
3489
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3490

    
3491
		$dhcp6cconf .= "\trequest domain-name-servers;\n";
3492
		$dhcp6cconf .= "\trequest domain-name;\n";
3493
		$dhcp6cconf .= "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3494

    
3495
		$dhcp6cconf .= "};\n";
3496

    
3497
		if(!isset($wancfg['dhcp6prefixonly']))
3498
			$dhcp6cconf .= "id-assoc na 0 { };\n";
3499

    
3500
		if(is_numeric($wancfg['dhcp6-ia-pd-len']) && !empty($trackiflist)) {
3501
			/* Setup the prefix delegation */
3502
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3503
			$preflen = 64 - $wancfg['dhcp6-ia-pd-len'];
3504
			if (isset($wancfg['dhcp6-ia-pd-send-hint']))
3505
				$dhcp6cconf .= "	prefix ::/{$preflen} infinity;\n";
3506
			foreach ($trackiflist as $friendly => $ifcfg) {
3507
				if ($g['debug'])
3508
					log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3509
				$realif = get_real_interface($friendly);
3510
				$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3511
				$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3512
				$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3513
				$dhcp6cconf .= "	};\n";
3514
			}
3515
			unset($preflen, $iflist, $ifcfg, $ifname);
3516
			$dhcp6cconf .= "};\n";
3517
		}
3518
		unset($trackiflist);
3519
	}
3520

    
3521
	// DHCP6 Config File Advanced
3522
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3523

    
3524
	// DHCP6 Config File Override
3525
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3526

    
3527
	/* wide-dhcp6c works for now. */
3528
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3529
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3530
		unset($dhcp6cconf);
3531
		return 1;
3532
	}
3533
	unset($dhcp6cconf);
3534

    
3535
	$dhcp6cscript = "#!/bin/sh\n";
3536
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3537
	$dhcp6cscript .= "dmips=\${new_domain_name_servers}\n";
3538
	$dhcp6cscript .= "dmnames=\${new_domain_name}\n";
3539
	$dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
3540
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3541
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3542
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3543
		unset($dhcp6cscript);
3544
		return 1;
3545
	}
3546
	unset($dhcp6cscript);
3547
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3548

    
3549
	$rtsoldscript = "#!/bin/sh\n";
3550
	$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
3551
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
3552
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_defaultgwv6\n";
3553
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Recieved RA specifying route \$2 for interface {$interface}({$wanif})\"\n";
3554
	$rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
3555
	$rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
3556
	$rtsoldscript .= "\t/bin/sleep 1\n";
3557
	$rtsoldscript .= "fi\n";
3558
	$rtsoldscript .= "/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
3559
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Starting dhcp6 client for interface {$interface}({$wanif})\"\n";
3560
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3561
	if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) {
3562
		printf("Error: cannot open rtsold_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3563
		unset($rtsoldscript);
3564
		return 1;
3565
	}
3566
	unset($rtsoldscript);
3567
	@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
3568

    
3569
	/* accept router advertisements for this interface */
3570
	set_single_sysctl("net.inet6.ip6.accept_rtadv", "1");
3571
	log_error("Accept router advertisements on interface {$wanif} ");
3572
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3573

    
3574
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3575
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3576
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3577
		sleep(2);
3578
	}
3579
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3580

    
3581
	/* NOTE: will be called from rtsold invoked script
3582
	 * link_interface_to_track6($interface, "update");
3583
	 */
3584

    
3585
	return 0;
3586
}
3587

    
3588
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3589
	global $g;
3590

    
3591
	$send_options = "";
3592
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3593
		$options = explode(',', $wancfg['adv_dhcp6_interface_statement_send_options']);
3594
		foreach ($options as $option) {
3595
			$send_options .= "\tsend " . trim($option) . ";\n";
3596
		}
3597
	}
3598

    
3599
	$request_options = "";
3600
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3601
		$options = explode(',', $wancfg['adv_dhcp6_interface_statement_request_options']);
3602
		foreach ($options as $option) {
3603
			$request_options .= "\trequest " . trim($option) . ";\n";
3604
		}
3605
	}
3606

    
3607
	$information_only = "";
3608
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3609
		$information_only = "\tinformation-only;\n";
3610

    
3611
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3612
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3613
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3614

    
3615
	$interface_statement  = "interface";
3616
	$interface_statement .= " {$wanif}";
3617
	$interface_statement .= " {\n";
3618
	$interface_statement .= "$send_options";
3619
	$interface_statement .= "$request_options";
3620
	$interface_statement .= "$information_only";
3621
	$interface_statement .= "$script";
3622
	$interface_statement .= "};\n";
3623

    
3624
	$id_assoc_statement_address = "";
3625
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3626
		$id_assoc_statement_address .= "id-assoc";
3627
		$id_assoc_statement_address .= " na";
3628
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3629
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3630
		$id_assoc_statement_address .= " { ";
3631

    
3632
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3633
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3634
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3635
			$id_assoc_statement_address .= "\n\taddress";
3636
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3637
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3638
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3639
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3640
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3641
			$id_assoc_statement_address .= ";\n";
3642
		}
3643

    
3644
		$id_assoc_statement_address  .= "};\n";
3645
	}
3646

    
3647
	$id_assoc_statement_prefix = "";
3648
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3649
		$id_assoc_statement_prefix .= "id-assoc";
3650
		$id_assoc_statement_prefix .= " pd";
3651
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3652
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3653
		$id_assoc_statement_prefix .= " { ";
3654

    
3655
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3656
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3657
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3658
			$id_assoc_statement_prefix .= "\n\tprefix";
3659
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3660
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3661
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3662
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3663
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3664
			$id_assoc_statement_prefix .= ";";
3665
		}
3666

    
3667
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3668
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3669
			$id_assoc_statement_prefix .= " {$wanif}";
3670
			$id_assoc_statement_prefix .= " {\n";
3671
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3672
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3673
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3674
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3675
			$id_assoc_statement_prefix .= "\t};";
3676
		}
3677

    
3678
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3679
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3680
			$id_assoc_statement_prefix .= "\n";
3681
		}
3682

    
3683
		$id_assoc_statement_prefix  .= "};\n";
3684
	}
3685

    
3686
	$authentication_statement = "";
3687
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3688
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3689
		$authentication_statement .= "authentication";
3690
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3691
		$authentication_statement .= " {\n";
3692
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3693
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3694
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3695
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3696
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3697
		$authentication_statement .= "};\n";
3698
	}
3699

    
3700
	$key_info_statement = "";
3701
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3702
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3703
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3704
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3705
		$key_info_statement .= "keyinfo";
3706
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3707
		$key_info_statement .= " {\n";
3708
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3709
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3710
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3711
		if (preg_match("/((([0-9]{4}-)?[0-9]{2}[0-9]{2} )?[0-9]{2}:[0-9]{2})||(foreever)/", $wancfg['adv_dhcp6_key_info_statement_expire'])) 
3712
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3713
		$key_info_statement .= "};\n";
3714
	}
3715

    
3716
	$dhcp6cconf  = $interface_statement;
3717
	$dhcp6cconf .= $id_assoc_statement_address;
3718
	$dhcp6cconf .= $id_assoc_statement_prefix;
3719
	$dhcp6cconf .= $authentication_statement;
3720
	$dhcp6cconf .= $key_info_statement;
3721

    
3722
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3723

    
3724
	return $dhcp6cconf;
3725
}
3726

    
3727

    
3728
function DHCP6_Config_File_Override($wancfg, $wanif) {
3729

    
3730
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3731
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3732

    
3733
	return $dhcp6cconf;
3734
}
3735

    
3736

    
3737
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3738

    
3739
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3740

    
3741
	return $dhcp6cconf;
3742
}
3743

    
3744

    
3745
function interface_dhcp_configure($interface = "wan") {
3746
	global $config, $g;
3747

    
3748
	$wancfg = $config['interfaces'][$interface];
3749
	$wanif = $wancfg['if'];
3750
	if (empty($wancfg))
3751
		$wancfg = array();
3752

    
3753
	/* generate dhclient_wan.conf */
3754
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3755
	if (!$fd) {
3756
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3757
		return 1;
3758
	}
3759

    
3760
	if ($wancfg['dhcphostname']) {
3761
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3762
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3763
	} else {
3764
		$dhclientconf_hostname = "";
3765
	}
3766

    
3767
	$wanif = get_real_interface($interface);
3768
	if (empty($wanif)) {
3769
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3770
		return 0;
3771
	}
3772
	$dhclientconf = "";
3773

    
3774
	$dhclientconf .= <<<EOD
3775
interface "{$wanif}" {
3776
timeout 60;
3777
retry 15;
3778
select-timeout 0;
3779
initial-interval 1;
3780
	{$dhclientconf_hostname}
3781
	script "/sbin/dhclient-script";
3782
EOD;
3783

    
3784
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3785
	$dhclientconf .= <<<EOD
3786

    
3787
	reject {$wancfg['dhcprejectfrom']};
3788
EOD;
3789
}
3790
	$dhclientconf .= <<<EOD
3791

    
3792
}
3793

    
3794
EOD;
3795

    
3796
	// DHCP Config File Advanced
3797
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3798

    
3799
if(is_ipaddr($wancfg['alias-address'])) {
3800
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3801
	$dhclientconf .= <<<EOD
3802
alias {
3803
	interface  "{$wanif}";
3804
	fixed-address {$wancfg['alias-address']};
3805
	option subnet-mask {$subnetmask};
3806
}
3807

    
3808
EOD;
3809
}
3810

    
3811
	// DHCP Config File Override
3812
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3813

    
3814
	fwrite($fd, $dhclientconf);
3815
	fclose($fd);
3816

    
3817
	/* bring wan interface up before starting dhclient */
3818
	if($wanif)
3819
		interfaces_bring_up($wanif);
3820
	else
3821
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3822

    
3823
	/* Make sure dhclient is not running */
3824
	kill_dhclient_process($wanif);
3825

    
3826
	/* fire up dhclient */
3827
	mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$interface}.conf {$wanif} > {$g['tmp_path']}/{$wanif}_output 2> {$g['tmp_path']}/{$wanif}_error_output");
3828

    
3829
	return 0;
3830
}
3831

    
3832
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3833

    
3834
	$hostname = "";
3835
	if ($wancfg['dhcphostname'] != '') {
3836
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3837
	}
3838

    
3839
	/* DHCP Protocol Timings */
3840
	$protocol_timings = array ('adv_dhcp_pt_timeout' => "timeout", 'adv_dhcp_pt_retry' => "retry", 'adv_dhcp_pt_select_timeout' => "select-timeout", 'adv_dhcp_pt_reboot' => "reboot", 'adv_dhcp_pt_backoff_cutoff' => "backoff-cutoff", 'adv_dhcp_pt_initial_interval' => "initial-interval");
3841
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3842
		$pt_variable = "{$Protocol_Timing}";
3843
		${$pt_variable} = "";
3844
		if ($wancfg[$Protocol_Timing] != "") {
3845
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3846
		}
3847
	}
3848

    
3849
	$send_options = "";
3850
	if ($wancfg['adv_dhcp_send_options'] != '') {
3851
		$options = explode(',', $wancfg['adv_dhcp_send_options']);
3852
		foreach ($options as $option) {
3853
			$send_options .= "\tsend " . trim($option) . ";\n";
3854
		}
3855
	}
3856

    
3857
	$request_options = "";
3858
	if ($wancfg['adv_dhcp_request_options'] != '') {
3859
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3860
	}
3861

    
3862
	$required_options = "";
3863
	if ($wancfg['adv_dhcp_required_options'] != '') {
3864
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3865
	}
3866

    
3867
	$option_modifiers = "";
3868
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3869
		$modifiers = explode(',', $wancfg['adv_dhcp_option_modifiers']);
3870
		foreach ($modifiers as $modifier) {
3871
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3872
		}
3873
	}
3874

    
3875
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3876
 	$dhclientconf .= "\n";
3877
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3878
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3879
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3880
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3881
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3882
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3883
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3884
 	$dhclientconf .= "\n";
3885
 	$dhclientconf .= "# DHCP Protocol Options\n";
3886
 	$dhclientconf .= "{$hostname}";
3887
 	$dhclientconf .= "{$send_options}";
3888
 	$dhclientconf .= "{$request_options}";
3889
 	$dhclientconf .= "{$required_options}";
3890
 	$dhclientconf .= "{$option_modifiers}";
3891
 	$dhclientconf .= "\n";
3892
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3893
 	$dhclientconf .= "}\n";
3894

    
3895
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3896

    
3897
	return $dhclientconf;
3898
}
3899

    
3900

    
3901
function DHCP_Config_File_Override($wancfg, $wanif) {
3902

    
3903
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3904
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3905

    
3906
	return $dhclientconf;
3907
}
3908

    
3909

    
3910
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3911

    
3912
	/* Apply Interface Substitutions */
3913
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3914

    
3915
	/* Apply Hostname Substitutions */
3916
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3917

    
3918
	/* Arrays of MAC Address Types, Cases, Delimiters */
3919
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3920
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3921
	$various_mac_cases      = array("U", "L");
3922
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3923

    
3924
	/* Apply MAC Address Substitutions */
3925
	foreach ($various_mac_types as $various_mac_type) {
3926
		foreach ($various_mac_cases as $various_mac_case) {
3927
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3928

    
3929
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3930
				if ($res !== false) {
3931

    
3932
					/* Get MAC Address as ASCII String With Colon (:) delimiters */
3933
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3934
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3935

    
3936
					if ("$various_mac_type" == "mac_addr_hex") {
3937
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3938
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3939
						$dhcpclientconf_mac_hex = "";
3940
						$delimiter = "";
3941
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3942
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3943
							$delimiter = ":";
3944
						}
3945
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3946
					}
3947

    
3948
					/* MAC Address Delimiter Substitutions */
3949
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3950

    
3951
					/* Apply MAC Address Substitutions */
3952
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
3953
				}
3954
			}
3955
		}
3956
	}
3957

    
3958
	return $dhclientconf;
3959
}
3960

    
3961
function interfaces_group_setup() {
3962
	global $config;
3963

    
3964
	if (!is_array($config['ifgroups']['ifgroupentry']))
3965
		return;
3966

    
3967
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3968
		interface_group_setup($groupar);
3969

    
3970
	return;
3971
}
3972

    
3973
function interface_group_setup(&$groupname /* The parameter is an array */) {
3974
	global $config;
3975

    
3976
	if (!is_array($groupname))
3977
		return;
3978
	$members = explode(" ", $groupname['members']);
3979
	foreach($members as $ifs) {
3980
		$realif = get_real_interface($ifs);
3981
		if ($realif && does_interface_exist($realif))
3982
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3983
	}
3984

    
3985
	return;
3986
}
3987

    
3988
function is_interface_group($if) {
3989
	global $config;
3990

    
3991
	if (is_array($config['ifgroups']['ifgroupentry']))
3992
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
3993
			if ($groupentry['ifname'] === $if)
3994
				return true;
3995
		}
3996

    
3997
	return false;
3998
}
3999

    
4000
function interface_group_add_member($interface, $groupname) {
4001
	$interface = get_real_interface($interface);
4002
	if (does_interface_exist($interface))
4003
		mwexec("/sbin/ifconfig {$interface} group " . escapeshellarg($groupname), true);
4004
}
4005

    
4006
/* COMPAT Function */
4007
function convert_friendly_interface_to_real_interface_name($interface) {
4008
	return get_real_interface($interface);
4009
}
4010

    
4011
/* COMPAT Function */
4012
function get_real_wan_interface($interface = "wan") {
4013
	return get_real_interface($interface);
4014
}
4015

    
4016
/* COMPAT Function */
4017
function get_current_wan_address($interface = "wan") {
4018
	return get_interface_ip($interface);
4019
}
4020

    
4021
/*
4022
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
4023
 */
4024
function convert_real_interface_to_friendly_interface_name($interface = "wan", $checkparent = false) {
4025
	global $config;
4026

    
4027
	if (stripos($interface, "_vip")) {
4028
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
4029
			if ($vip['mode'] == "carp")  {
4030
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4031
				return $vip['interface'];
4032
			}
4033
		}
4034
	}
4035

    
4036
	/* XXX: For speed reasons reference directly the interface array */
4037
	$ifdescrs = &$config['interfaces'];
4038
	//$ifdescrs = get_configured_interface_list(false, true);
4039

    
4040
	foreach ($ifdescrs as $if => $ifname) {
4041
		if ($if == $interface || $ifname['if'] == $interface)
4042
			return $if;
4043

    
4044
		if (get_real_interface($if) == $interface)
4045
			return $if;
4046

    
4047
		if ($checkparent == false)
4048
			continue;
4049

    
4050
		$int = get_parent_interface($if, true);
4051
		if (is_array($int)) {
4052
			foreach ($int as $iface) {
4053
				if ($iface == $interface)
4054
					return $if;
4055
			}
4056
		}
4057
	}
4058

    
4059
	if ($interface == "enc0")
4060
		return 'IPsec';
4061
}
4062

    
4063
/* attempt to resolve interface to friendly descr */
4064
function convert_friendly_interface_to_friendly_descr($interface) {
4065
	global $config;
4066

    
4067
	switch ($interface) {
4068
	case "l2tp":
4069
		$ifdesc = "L2TP";
4070
		break;
4071
	case "pptp":
4072
		$ifdesc = "PPTP";
4073
		break;
4074
	case "pppoe":
4075
		$ifdesc = "PPPoE";
4076
		break;
4077
	case "openvpn":
4078
		$ifdesc = "OpenVPN";
4079
		break;
4080
	case "enc0":
4081
	case "ipsec":
4082
	case "IPsec":
4083
		$ifdesc = "IPsec";
4084
		break;
4085
	default:
4086
		if (isset($config['interfaces'][$interface])) {
4087
			if (empty($config['interfaces'][$interface]['descr']))
4088
				$ifdesc = strtoupper($interface);
4089
			else
4090
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4091
			break;
4092
		} else if (stristr($interface, "_vip")) {
4093
			if (is_array($config['virtualip']['vip'])) {
4094
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4095
					if ($vip['mode'] == "carp")  {
4096
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4097
							return "{$vip['subnet']} - {$vip['descr']}";
4098
					}
4099
				}
4100
			}
4101
		} else {
4102
			/* if list */
4103
			$ifdescrs = get_configured_interface_with_descr(false, true);
4104
			foreach ($ifdescrs as $if => $ifname) {
4105
				if ($if == $interface || $ifname == $interface)
4106
					return $ifname;
4107
			}
4108
		}
4109
		break;
4110
	}
4111

    
4112
	return $ifdesc;
4113
}
4114

    
4115
function convert_real_interface_to_friendly_descr($interface) {
4116

    
4117
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4118

    
4119
	if (!empty($ifdesc))
4120
		return convert_friendly_interface_to_friendly_descr($ifdesc);
4121

    
4122
	return $interface;
4123
}
4124

    
4125
/*
4126
 *  get_parent_interface($interface):
4127
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4128
 *				or virtual interface (i.e. vlan)
4129
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4130
 *			-- returns $interface passed in if $interface parent is not found
4131
 *			-- returns empty array if an invalid interface is passed
4132
 *	(Only handles ppps and vlans now.)
4133
 */
4134
function get_parent_interface($interface, $avoidrecurse = false) {
4135
	global $config;
4136

    
4137
	$parents = array();
4138
	//Check that we got a valid interface passed
4139
	$realif = get_real_interface($interface);
4140
	if ($realif == NULL)
4141
		return $parents;
4142

    
4143
	// If we got a real interface, find it's friendly assigned name
4144
	if ($interface == $realif && $avoidrecurse == false)
4145
		$interface = convert_real_interface_to_friendly_interface_name($interface);
4146

    
4147
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4148
		$ifcfg = $config['interfaces'][$interface];
4149
		switch ($ifcfg['ipaddr']) {
4150
			case "ppp":
4151
			case "pppoe":
4152
			case "pptp":
4153
			case "l2tp":
4154
				if (empty($parents))
4155
					if (is_array($config['ppps']['ppp']))
4156
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4157
							if ($ifcfg['if'] == $ppp['if']) {
4158
								$ports = explode(',', $ppp['ports']);
4159
								foreach ($ports as $pid => $parent_if)
4160
									$parents[$pid] = get_real_interface($parent_if);
4161
								break;
4162
							}
4163
						}
4164
				break;
4165
			case "dhcp":
4166
			case "static":
4167
			default:
4168
				// Handle _vlans
4169
				if (strpos($realif, '_vlan') !== FALSE) {
4170
					if (is_array($config['vlans']['vlan'])) {
4171
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan) {
4172
							if ($ifcfg['if'] == $vlan['vlanif']) {
4173
								$parents[0] = $vlan['if'];
4174
								break;
4175
							}
4176
						}
4177
					}
4178
				}
4179
				break;
4180
		}
4181
	}
4182

    
4183
	if (empty($parents))
4184
		$parents[0] = $realif;
4185

    
4186
	return $parents;
4187
}
4188

    
4189
function interface_is_wireless_clone($wlif) {
4190
	if(!stristr($wlif, "_wlan")) {
4191
		return false;
4192
	} else {
4193
		return true;
4194
	}
4195
}
4196

    
4197
function interface_get_wireless_base($wlif) {
4198
	if(!stristr($wlif, "_wlan")) {
4199
		return $wlif;
4200
	} else {
4201
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4202
	}
4203
}
4204

    
4205
function interface_get_wireless_clone($wlif) {
4206
	if(!stristr($wlif, "_wlan")) {
4207
		return $wlif . "_wlan0";
4208
	} else {
4209
		return $wlif;
4210
	}
4211
}
4212

    
4213
function get_real_interface($interface = "wan", $family = "all", $realv6iface = false, $flush = true) {
4214
	global $config, $g;
4215

    
4216
	$wanif = NULL;
4217

    
4218
	switch ($interface) {
4219
	case "l2tp":
4220
		$wanif = "l2tp";
4221
		break;
4222
	case "pptp":
4223
		$wanif = "pptp";
4224
		break;
4225
	case "pppoe":
4226
		$wanif = "pppoe";
4227
		break;
4228
	case "openvpn":
4229
		$wanif = "openvpn";
4230
		break;
4231
	case "ipsec":
4232
	case "enc0":
4233
		$wanif = "enc0";
4234
		break;
4235
	case "ppp":
4236
		$wanif = "ppp";
4237
		break;
4238
	default:
4239
		// If a real interface was already passed simply
4240
		// pass the real interface back.  This encourages
4241
		// the usage of this function in more cases so that
4242
		// we can combine logic for more flexibility.
4243
		if(does_interface_exist($interface, $flush)) {
4244
			$wanif = $interface;
4245
			break;
4246
		}
4247

    
4248
		if (empty($config['interfaces'][$interface]))
4249
			break;
4250

    
4251
		$cfg = &$config['interfaces'][$interface];
4252

    
4253
		if ($family == "inet6") {
4254
			switch ($cfg['ipaddrv6']) {
4255
			case "6rd":
4256
			case "6to4":
4257
				$wanif = "{$interface}_stf";
4258
				break;
4259
			case 'pppoe':
4260
			case 'ppp':
4261
			case 'l2tp':
4262
			case 'pptp':
4263
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4264
					$wanif = interface_get_wireless_clone($cfg['if']);
4265
				else
4266
					$wanif = $cfg['if'];
4267
				break;
4268
			default:
4269
				switch ($cfg['ipaddr']) {
4270
				case 'pppoe':
4271
				case 'ppp':
4272
				case 'l2tp':
4273
				case 'pptp':
4274
					if (isset($cfg['dhcp6usev4iface']) && $realv6iface === false)
4275
						$wanif = $cfg['if'];
4276
					else {
4277
						$parents = get_parent_interface($interface);
4278
						if (!empty($parents[0]))
4279
							$wanif = $parents[0];
4280
						else
4281
							$wanif = $cfg['if'];
4282
					}
4283
					break;
4284
				default:
4285
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4286
						$wanif = interface_get_wireless_clone($cfg['if']);
4287
					else
4288
						$wanif = $cfg['if'];
4289
					break;
4290
				}
4291
				break;
4292
			}
4293
		} else {
4294
			// Wireless cloned NIC support (FreeBSD 8+)
4295
			// interface name format: $parentnic_wlanparentnic#
4296
			// example: ath0_wlan0
4297
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4298
				$wanif = interface_get_wireless_clone($cfg['if']);
4299
			else
4300
				$wanif = $cfg['if'];
4301
		}
4302
		break;
4303
	}
4304

    
4305
	return $wanif;
4306
}
4307

    
4308
/* Guess the physical interface by providing a IP address */
4309
function guess_interface_from_ip($ipaddress) {
4310

    
4311
	$family = '';
4312
	if(is_ipaddrv4($ipaddress))
4313
		$family = 'inet';
4314
	if (empty($family) && is_ipaddrv6($ipaddress))
4315
		$family = 'inet6';
4316

    
4317
	if (empty($family))
4318
		return false;
4319

    
4320
	/* create a route table we can search */
4321
	$output = '';
4322
	$_gb = exec("/sbin/route -n get -{$family} " . escapeshellarg($ipaddress) . " | /usr/bin/awk '/interface/ { print \$2; };'", $output);
4323
	$output[0] = trim($output[0], " \n");
4324
	if (!empty($output[0]))
4325
		return $output[0];
4326

    
4327
	return false;
4328
}
4329

    
4330
/*
4331
 * find_ip_interface($ip): return the interface where an ip is defined
4332
 *   (or if $bits is specified, where an IP within the subnet is defined)
4333
 */
4334
function find_ip_interface($ip, $bits = null) {
4335
	if (!is_ipaddr($ip))
4336
		return false;
4337

    
4338
	$isv6ip = is_ipaddrv6($ip);
4339

    
4340
	/* if list */
4341
	$ifdescrs = get_configured_interface_list();
4342

    
4343
	foreach ($ifdescrs as $ifdescr => $ifname) {
4344
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4345
		if (is_null($ifip))
4346
			continue;
4347
		if (is_null($bits)) {
4348
			if ($ip == $ifip) {
4349
				$int = get_real_interface($ifname);
4350
				return $int;
4351
			}
4352
		}
4353
		else {
4354
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4355
				$int = get_real_interface($ifname);
4356
				return $int;
4357
			}
4358
		}
4359
	}
4360

    
4361
	return false;
4362
}
4363

    
4364
/*
4365
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4366
 *   (or if $bits is specified, where an IP within the subnet is found)
4367
 */
4368
function find_virtual_ip_alias($ip, $bits = null) {
4369
	global $config;
4370

    
4371
	if (!is_array($config['virtualip']['vip'])) {
4372
		return false;
4373
	}
4374
	if (!is_ipaddr($ip))
4375
		return false;
4376

    
4377
	$isv6ip = is_ipaddrv6($ip);
4378

    
4379
	foreach ($config['virtualip']['vip'] as $vip) {
4380
		if ($vip['mode'] === "ipalias") {
4381
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4382
				continue;
4383
			if (is_null($bits)) {
4384
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4385
					return $vip;
4386
				}
4387
			}
4388
			else {
4389
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4390
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4391
					return $vip;
4392
				}
4393
			}
4394
		}
4395
	}
4396
	return false;
4397
}
4398

    
4399
/*
4400
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4401
 */
4402
function find_number_of_created_carp_interfaces() {
4403
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4404
}
4405

    
4406
/*
4407
 * find_carp_interface($ip): return the carp interface where an ip is defined
4408
 */
4409
function find_carp_interface($ip) {
4410
	global $config;
4411
	if (is_array($config['virtualip']['vip'])) {
4412
		foreach ($config['virtualip']['vip'] as $vip) {
4413
			if ($vip['mode'] == "carp") {
4414
				if(is_ipaddrv4($ip)) {
4415
					$carp_ip = get_interface_ip($vip['interface']);
4416
				}
4417
				if(is_ipaddrv6($ip)) {
4418
					$carp_ip = get_interface_ipv6($vip['interface']);
4419
				}
4420
				exec("/sbin/ifconfig", $output, $return);
4421
				foreach($output as $line) {
4422
					$elements = preg_split("/[ ]+/i", $line);
4423
					if(strstr($elements[0], "vip"))
4424
						$curif = str_replace(":", "", $elements[0]);
4425
					if(stristr($line, $ip)) {
4426
						$if = $curif;
4427
						continue;
4428
					}
4429
				}
4430

    
4431
				if ($if)
4432
					return $if;
4433
			}
4434
		}
4435
	}
4436
}
4437

    
4438
function link_carp_interface_to_parent($interface) {
4439
	global $config;
4440

    
4441
	if (empty($interface))
4442
		return;
4443

    
4444
	$carp_ip = get_interface_ip($interface);
4445
	$carp_ipv6 = get_interface_ipv6($interface);
4446

    
4447
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4448
		return;
4449

    
4450
	/* if list */
4451
	$ifdescrs = get_configured_interface_list();
4452
	foreach ($ifdescrs as $ifdescr => $ifname) {
4453
		/* check IPv4 */
4454
		if(is_ipaddrv4($carp_ip)) {
4455
			$interfaceip = get_interface_ip($ifname);
4456
			$subnet_bits = get_interface_subnet($ifname);
4457
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4458
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4459
				return $ifname;
4460
		}
4461
		/* Check IPv6 */
4462
		if(is_ipaddrv6($carp_ipv6)) {
4463
			$interfaceipv6 = get_interface_ipv6($ifname);
4464
			$prefixlen = get_interface_subnetv6($ifname);
4465
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4466
				return $ifname;
4467
		}
4468
	}
4469
	return "";
4470
}
4471

    
4472

    
4473
/****f* interfaces/link_ip_to_carp_interface
4474
 * NAME
4475
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4476
 * INPUTS
4477
 *   $ip
4478
 * RESULT
4479
 *   $carp_ints
4480
 ******/
4481
function link_ip_to_carp_interface($ip) {
4482
	global $config;
4483

    
4484
	if (!is_ipaddr($ip))
4485
		return;
4486

    
4487
	$carp_ints = "";
4488
	if (is_array($config['virtualip']['vip'])) {
4489
		$first = 0;
4490
		$carp_int = array();
4491
		foreach ($config['virtualip']['vip'] as $vip) {
4492
			if ($vip['mode'] == "carp") {
4493
				$carp_ip = $vip['subnet'];
4494
				$carp_sn = $vip['subnet_bits'];
4495
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4496
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4497
					$carp_int[] = get_real_interface($vip['interface']);
4498
				}
4499
			}
4500
		}
4501
		if (!empty($carp_int))
4502
			$carp_ints = implode(" ", array_unique($carp_int));
4503
	}
4504

    
4505
	return $carp_ints;
4506
}
4507

    
4508
function link_interface_to_track6($int, $action = "") {
4509
	global $config;
4510

    
4511
	if (empty($int))
4512
		return;
4513

    
4514
	if (is_array($config['interfaces'])) {
4515
		$list = array();
4516
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4517
			if (!isset($ifcfg['enable']))
4518
				continue;
4519
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4520
				if ($action == "update")
4521
					interface_track6_configure($ifname, $ifcfg);
4522
				else if ($action == "")
4523
					$list[$ifname] = $ifcfg;
4524
			}
4525
		}
4526
		return $list;
4527
	}
4528
}
4529

    
4530
function interface_find_child_cfgmtu($realiface) {
4531
	global $config;
4532

    
4533
	$interface = convert_real_interface_to_friendly_interface_name($realiface);
4534
	$vlans = link_interface_to_vlans($realiface);
4535
	$bridge = link_interface_to_bridge($realiface);
4536
	if (!empty($interface)) {
4537
		$gifs = link_interface_to_gif($interface);
4538
		$gres = link_interface_to_gre($interface);
4539
	} else {
4540
		$gifs = array();
4541
		$gres = array();
4542
	}
4543

    
4544
	$mtu = 0;
4545
	if (is_array($vlans)) {
4546
		foreach ($vlans as $vlan) {
4547
			$ifass = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
4548
			if (empty($ifass))
4549
				continue;
4550
			if (!empty($config['interfaces'][$ifass]['mtu'])) {
4551
				if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4552
					$mtu = intval($config['interfaces'][$ifass]['mtu']);
4553
			}
4554
		}
4555
	}
4556
	if (is_array($gifs)) {
4557
		foreach ($gifs as $vlan) {
4558
			$ifass = convert_real_interface_to_friendly_interface_name($vlan['gifif']);
4559
			if (empty($ifass))
4560
				continue;
4561
			if (!empty($config['interfaces'][$ifass]['mtu'])) {
4562
				if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4563
					$mtu = intval($config['interfaces'][$ifass]['mtu']);
4564
			}
4565
		}
4566
	}
4567
	if (is_array($gres)) {
4568
		foreach ($gres as $vlan) {
4569
			$ifass = convert_real_interface_to_friendly_interface_name($vlan['greif']);
4570
			if (empty($ifass))
4571
				continue;
4572
			if (!empty($config['interfaces'][$ifass]['mtu'])) {
4573
				if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4574
					$mtu = intval($config['interfaces'][$ifass]['mtu']);
4575
			}
4576
		}
4577
	}
4578
	$ifass = convert_real_interface_to_friendly_interface_name($bridge);
4579
	if (!empty($ifass) && !empty($config['interfaces'][$ifass]['mtu'])) {
4580
		if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4581
			$mtu = intval($config['interfaces'][$ifass]['mtu']);
4582
	}
4583
	unset($vlans, $bridge, $gifs, $gres, $ifass, $vlan);
4584

    
4585
	return $mtu;
4586
}
4587

    
4588
function link_interface_to_vlans($int, $action = "") {
4589
	global $config;
4590

    
4591
	if (empty($int))
4592
		return;
4593

    
4594
	if (is_array($config['vlans']['vlan'])) {
4595
		$ifaces = array();
4596
		foreach ($config['vlans']['vlan'] as $vlan) {
4597
			if ($int == $vlan['if']) {
4598
				if ($action == "update") {
4599
					interfaces_bring_up($int);
4600
				} else
4601
					$ifaces[$vlan['tag']] = $vlan;
4602
			}
4603
		}
4604
		if (!empty($ifaces))
4605
			return $ifaces;
4606
	}
4607
}
4608

    
4609
function link_interface_to_vips($int, $action = "") {
4610
	global $config;
4611

    
4612
	if (is_array($config['virtualip']['vip'])) {
4613
		$result = array();
4614
		foreach ($config['virtualip']['vip'] as $vip) {
4615
			if ($int == $vip['interface']) {
4616
				if ($action == "update")
4617
					interfaces_vips_configure($int);
4618
				else
4619
					$result[] = $vip;
4620
			}
4621
		}
4622
		return $result;
4623
	}
4624
}
4625

    
4626
/****f* interfaces/link_interface_to_bridge
4627
 * NAME
4628
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4629
 * INPUTS
4630
 *   $ip
4631
 * RESULT
4632
 *   bridge[0-99]
4633
 ******/
4634
function link_interface_to_bridge($int) {
4635
	global $config;
4636

    
4637
	if (is_array($config['bridges']['bridged'])) {
4638
		foreach ($config['bridges']['bridged'] as $bridge) {
4639
			if (in_array($int, explode(',', $bridge['members'])))
4640
				return "{$bridge['bridgeif']}";
4641
		}
4642
	}
4643
}
4644

    
4645
function link_interface_to_group($int) {
4646
	global $config;
4647

    
4648
	$result = array();
4649

    
4650
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4651
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4652
			if (in_array($int, explode(" ", $group['members'])))
4653
				$result[$group['ifname']] = $int;
4654
		}
4655
	}
4656

    
4657
	return $result;
4658
}
4659

    
4660
function link_interface_to_gre($interface) {
4661
	global $config;
4662

    
4663
	$result = array();
4664

    
4665
	if (is_array($config['gres']['gre'])) {
4666
		foreach ($config['gres']['gre'] as $gre)
4667
			if($gre['if'] == $interface)
4668
				$result[] = $gre;
4669
	}
4670

    
4671
	return $result;
4672
}
4673

    
4674
function link_interface_to_gif($interface) {
4675
	global $config;
4676

    
4677
	$result = array();
4678

    
4679
	if (is_array($config['gifs']['gif'])) {
4680
		foreach ($config['gifs']['gif'] as $gif)
4681
			if($gif['if'] == $interface)
4682
				$result[] = $gif;
4683
	}
4684

    
4685
	return $result;
4686
}
4687

    
4688
/*
4689
 * find_interface_ip($interface): return the interface ip (first found)
4690
 */
4691
function find_interface_ip($interface, $flush = false) {
4692
	global $interface_ip_arr_cache;
4693
	global $interface_sn_arr_cache;
4694

    
4695
	$interface = str_replace("\n", "", $interface);
4696

    
4697
	if (!does_interface_exist($interface))
4698
		return;
4699

    
4700
	/* Setup IP cache */
4701
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4702
		$ifinfo = pfSense_get_interface_addresses($interface);
4703
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4704
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4705
	}
4706

    
4707
	return $interface_ip_arr_cache[$interface];
4708
}
4709

    
4710
/*
4711
 * find_interface_ipv6($interface): return the interface ip (first found)
4712
 */
4713
function find_interface_ipv6($interface, $flush = false) {
4714
	global $interface_ipv6_arr_cache;
4715
	global $interface_snv6_arr_cache;
4716
	global $config;
4717

    
4718
	$interface = trim($interface);
4719
	$interface = get_real_interface($interface);
4720

    
4721
	if (!does_interface_exist($interface))
4722
		return;
4723

    
4724
	/* Setup IP cache */
4725
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4726
		$ifinfo = pfSense_get_interface_addresses($interface);
4727
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4728
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4729
	}
4730

    
4731
	return $interface_ipv6_arr_cache[$interface];
4732
}
4733

    
4734
/*
4735
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4736
 */
4737
function find_interface_ipv6_ll($interface, $flush = false) {
4738
	global $interface_llv6_arr_cache;
4739
	global $config;
4740

    
4741
	$interface = str_replace("\n", "", $interface);
4742

    
4743
	if (!does_interface_exist($interface))
4744
		return;
4745

    
4746
	/* Setup IP cache */
4747
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4748
		$ifinfo = pfSense_getall_interface_addresses($interface);
4749
		foreach($ifinfo as $line) {
4750
			if (strstr($line, ":")) {
4751
				$parts = explode("/", $line);
4752
				if(is_linklocal($parts[0])) {
4753
					$ifinfo['linklocal'] = $parts[0];
4754
				}
4755
			}
4756
		}
4757
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4758
	}
4759
	return $interface_llv6_arr_cache[$interface];
4760
}
4761

    
4762
function find_interface_subnet($interface, $flush = false) {
4763
	global $interface_sn_arr_cache;
4764
	global $interface_ip_arr_cache;
4765

    
4766
	$interface = str_replace("\n", "", $interface);
4767
	if (does_interface_exist($interface) == false)
4768
		return;
4769

    
4770
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4771
		$ifinfo = pfSense_get_interface_addresses($interface);
4772
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4773
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4774
	}
4775

    
4776
	return $interface_sn_arr_cache[$interface];
4777
}
4778

    
4779
function find_interface_subnetv6($interface, $flush = false) {
4780
	global $interface_snv6_arr_cache;
4781
	global $interface_ipv6_arr_cache;
4782

    
4783
	$interface = str_replace("\n", "", $interface);
4784
	if (does_interface_exist($interface) == false)
4785
		return;
4786

    
4787
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4788
		$ifinfo = pfSense_get_interface_addresses($interface);
4789
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4790
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4791
	}
4792

    
4793
	return $interface_snv6_arr_cache[$interface];
4794
}
4795

    
4796
function ip_in_interface_alias_subnet($interface, $ipalias) {
4797
	global $config;
4798

    
4799
	if (empty($interface) || !is_ipaddr($ipalias))
4800
		return false;
4801
	if (is_array($config['virtualip']['vip'])) {
4802
		foreach ($config['virtualip']['vip'] as $vip) {
4803
			switch ($vip['mode']) {
4804
			case "ipalias":
4805
				if ($vip['interface'] <> $interface)
4806
					break;
4807
				$subnet = is_ipaddrv6($ipalias) ? gen_subnetv6($vip['subnet'], $vip['subnet_bits']) : gen_subnet($vip['subnet'], $vip['subnet_bits']);
4808
				if (ip_in_subnet($ipalias, $subnet . "/" . $vip['subnet_bits']))
4809
					return true;
4810
				break;
4811
			}
4812
		}
4813
	}
4814

    
4815
	return false;
4816
}
4817

    
4818
function get_interface_ip($interface = "wan") {
4819
	
4820
	$realif = get_failover_interface($interface);
4821
	if (empty($realif)) {
4822
		if (strstr($interface, "_vip"))
4823
			return get_configured_carp_interface_list($interface);
4824
		else
4825
			return null;
4826
	}
4827

    
4828
	$curip = find_interface_ip($realif);
4829
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4830
		return $curip;
4831
	else
4832
		return null;
4833
}
4834

    
4835
function get_interface_ipv6($interface = "wan", $flush = false) {
4836
	global $config;
4837

    
4838
	$realif = get_failover_interface($interface, "inet6");
4839
	if (empty($realif)) {
4840
		if (strstr($interface, "_vip"))
4841
			return get_configured_carp_interface_list($interface, "inet6");
4842
		else
4843
			return null;
4844
	}
4845

    
4846
	/*
4847
	 * NOTE: On the case when only the prefix is requested,
4848
	 * the communication on WAN will be done over link-local.
4849
	 */
4850
	if (is_array($config['interfaces'][$interface])) {
4851
		switch ($config['interfaces'][$interface]['ipaddr']) {
4852
		case 'pppoe':
4853
		case 'l2tp':
4854
		case 'pptp':
4855
		case 'ppp':
4856
			if ($config['interfaces'][$interface]['ipaddrv6'] == 'dhcp6')
4857
				$realif = get_real_interface($interface, "inet6", true);
4858
			break;
4859
		}
4860
		if (isset($config['interfaces'][$interface]['dhcp6prefixonly'])) {
4861
			$curip = find_interface_ipv6_ll($realif, $flush);
4862
			if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4863
				return $curip;
4864
		}
4865
	}
4866

    
4867
	$curip = find_interface_ipv6($realif, $flush);
4868
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4869
		return $curip;
4870
	else
4871
		return null;
4872
}
4873

    
4874
function get_interface_linklocal($interface = "wan") {
4875

    
4876
	$realif = get_failover_interface($interface, "inet6");
4877
	if (!$realif) {
4878
		if (strstr($interface, "_vip")) {
4879
			list($interface, $vhid) = explode("_vip", $interface);
4880
			$realif = get_real_interface($interface);
4881
		} else
4882
			return null;
4883
	}
4884

    
4885
	$curip = find_interface_ipv6_ll($realif);
4886
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4887
		return $curip;
4888
	else
4889
		return null;
4890
}
4891

    
4892
function get_interface_subnet($interface = "wan") {
4893
	$realif = get_real_interface($interface);
4894
	if (empty($realif)) {
4895
		if (strstr($interface, "_vip")) {
4896
			return get_configured_carp_interface_list($interface, 'inet', 'subnet');
4897
		} else
4898
			return null;
4899
	}
4900

    
4901
	$cursn = find_interface_subnet($realif);
4902
	if (!empty($cursn))
4903
		return $cursn;
4904

    
4905
	return null;
4906
}
4907

    
4908
function get_interface_subnetv6($interface = "wan") {
4909
	global $config;
4910

    
4911
	$realif = get_real_interface($interface, "inet6");
4912
	if (empty($realif)) {
4913
		if (strstr($interface, "_vip")) {
4914
			return get_configured_carp_interface_list($interface, 'inet6', 'subnet');
4915
		} else
4916
			return null;
4917
	}
4918

    
4919
	$cursn = find_interface_subnetv6($realif);
4920
	if (!empty($cursn))
4921
		return $cursn;
4922

    
4923
	return null;
4924
}
4925

    
4926
/* return outside interfaces with a gateway */
4927
function get_interfaces_with_gateway() {
4928
	global $config;
4929

    
4930
	$ints = array();
4931

    
4932
	/* loop interfaces, check config for outbound */
4933
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4934
		switch ($ifname['ipaddr']) {
4935
			case "dhcp":
4936
			case "ppp";
4937
			case "pppoe":
4938
			case "pptp":
4939
			case "l2tp":
4940
			case "ppp";
4941
				$ints[$ifdescr] = $ifdescr;
4942
			break;
4943
			default:
4944
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4945
				    !empty($ifname['gateway']))
4946
					$ints[$ifdescr] = $ifdescr;
4947
			break;
4948
		}
4949
	}
4950
	return $ints;
4951
}
4952

    
4953
/* return true if interface has a gateway */
4954
function interface_has_gateway($friendly) {
4955
	global $config;
4956

    
4957
	if (!empty($config['interfaces'][$friendly])) {
4958
		$ifname = &$config['interfaces'][$friendly];
4959
		switch ($ifname['ipaddr']) {
4960
			case "dhcp":
4961
			case "pppoe":
4962
			case "pptp":
4963
			case "l2tp":
4964
			case "ppp";
4965
				return true;
4966
			break;
4967
			default:
4968
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4969
					return true;
4970
				$tunnelif = substr($ifname['if'], 0, 3);
4971
				if ($tunnelif == "gif" || $tunnelif == "gre")
4972
					return true;
4973
				if (!empty($ifname['gateway']))
4974
					return true;
4975
			break;
4976
		}
4977
	}
4978

    
4979
	return false;
4980
}
4981

    
4982
/* return true if interface has a gateway */
4983
function interface_has_gatewayv6($friendly) {
4984
	global $config;
4985

    
4986
	if (!empty($config['interfaces'][$friendly])) {
4987
		$ifname = &$config['interfaces'][$friendly];
4988
		switch ($ifname['ipaddrv6']) {
4989
			case "slaac":
4990
			case "dhcp6":
4991
			case "6to4":
4992
			case "6rd":
4993
				return true;
4994
				break;
4995
			default:
4996
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4997
					return true;
4998
				$tunnelif = substr($ifname['if'], 0, 3);
4999
				if ($tunnelif == "gif" || $tunnelif == "gre")
5000
					return true;
5001
				if (!empty($ifname['gatewayv6']))
5002
					return true;
5003
				break;
5004
		}
5005
	}
5006

    
5007
	return false;
5008
}
5009

    
5010
/****f* interfaces/is_altq_capable
5011
 * NAME
5012
 *   is_altq_capable - Test if interface is capable of using ALTQ
5013
 * INPUTS
5014
 *   $int            - string containing interface name
5015
 * RESULT
5016
 *   boolean         - true or false
5017
 ******/
5018

    
5019
function is_altq_capable($int) {
5020
	/* Per:
5021
	 * http://www.freebsd.org/cgi/man.cgi?query=altq&apropos=0&sektion=0&manpath=FreeBSD+8.3-RELEASE&arch=default&format=html
5022
	 * Only the following drivers have ALTQ support
5023
	 */
5024
	$capable = array("ae", "age", "alc", "ale", "an", "ath", "aue", "axe", "awi", "bce",
5025
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "epair", "et", "fxp", "gem",
5026
			"hme", "hn", "igb", "ipw", "iwi", "ixgbe", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
5027
			"nge", "npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sge", "sis", "sk",
5028
			"ste", "stge", "ti", "txp", "udav", "ural", "vge", "vmx", "vr", "vte", "wi", "xl",
5029
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
5030
			"l2tp", "ppp", "vtnet");
5031

    
5032
	$int_family = remove_ifindex($int);
5033

    
5034
	if (in_array($int_family, $capable))
5035
		return true;
5036
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
5037
		return true;
5038
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
5039
		return true;
5040
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
5041
		return true;
5042
	else
5043
		return false;
5044
}
5045

    
5046
/****f* interfaces/is_interface_wireless
5047
 * NAME
5048
 *   is_interface_wireless - Returns if an interface is wireless
5049
 * RESULT
5050
 *   $tmp       - Returns if an interface is wireless
5051
 ******/
5052
function is_interface_wireless($interface) {
5053
	global $config, $g;
5054

    
5055
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
5056
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
5057
		if (preg_match($g['wireless_regex'], $interface)) {
5058
			if (isset($config['interfaces'][$friendly]))
5059
				$config['interfaces'][$friendly]['wireless'] = array();
5060
			return true;
5061
		}
5062
		return false;
5063
	} else
5064
		return true;
5065
}
5066

    
5067
function get_wireless_modes($interface) {
5068
	/* return wireless modes and channels */
5069
	$wireless_modes = array();
5070

    
5071
	$cloned_interface = get_real_interface($interface);
5072

    
5073
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5074
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
5075
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5076
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
5077

    
5078
		$interface_channels = "";
5079
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5080
		$interface_channel_count = count($interface_channels);
5081

    
5082
		$c = 0;
5083
		while ($c < $interface_channel_count) {
5084
			$channel_line = explode(",", $interface_channels["$c"]);
5085
			$wireless_mode = trim($channel_line[0]);
5086
			$wireless_channel = trim($channel_line[1]);
5087
			if(trim($wireless_mode) != "") {
5088
				/* if we only have 11g also set 11b channels */
5089
				if($wireless_mode == "11g") {
5090
					if(!isset($wireless_modes["11b"]))
5091
						$wireless_modes["11b"] = array();
5092
				} else if($wireless_mode == "11g ht") {
5093
					if(!isset($wireless_modes["11b"]))
5094
						$wireless_modes["11b"] = array();
5095
					if(!isset($wireless_modes["11g"]))
5096
						$wireless_modes["11g"] = array();
5097
					$wireless_mode = "11ng";
5098
				} else if($wireless_mode == "11a ht") {
5099
					if(!isset($wireless_modes["11a"]))
5100
						$wireless_modes["11a"] = array();
5101
					$wireless_mode = "11na";
5102
				}
5103
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
5104
			}
5105
			$c++;
5106
		}
5107
	}
5108
	return($wireless_modes);
5109
}
5110

    
5111
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5112
function get_wireless_channel_info($interface) {
5113
	$wireless_channels = array();
5114

    
5115
	$cloned_interface = get_real_interface($interface);
5116

    
5117
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5118
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5119
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5120
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5121

    
5122
		$interface_channels = "";
5123
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5124

    
5125
		foreach ($interface_channels as $channel_line) {
5126
			$channel_line = explode(",", $channel_line);
5127
			if(!isset($wireless_channels[$channel_line[0]]))
5128
				$wireless_channels[$channel_line[0]] = $channel_line;
5129
		}
5130
	}
5131
	return($wireless_channels);
5132
}
5133

    
5134
/****f* interfaces/get_interface_mtu
5135
 * NAME
5136
 *   get_interface_mtu - Return the mtu of an interface
5137
 * RESULT
5138
 *   $tmp       - Returns the mtu of an interface
5139
 ******/
5140
function get_interface_mtu($interface) {
5141
	$mtu = pfSense_interface_getmtu($interface);
5142
	return $mtu['mtu'];
5143
}
5144

    
5145
function get_interface_mac($interface) {
5146

    
5147
	$macinfo = pfSense_get_interface_addresses($interface);
5148
	return $macinfo["macaddr"];
5149
}
5150

    
5151
/****f* pfsense-utils/generate_random_mac_address
5152
 * NAME
5153
 *   generate_random_mac - generates a random mac address
5154
 * INPUTS
5155
 *   none
5156
 * RESULT
5157
 *   $mac - a random mac address
5158
 ******/
5159
function generate_random_mac_address() {
5160
	$mac = "02";
5161
	for($x=0; $x<5; $x++)
5162
		$mac .= ":" . dechex(rand(16, 255));
5163
	return $mac;
5164
}
5165

    
5166
/****f* interfaces/is_jumbo_capable
5167
 * NAME
5168
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5169
 * INPUTS
5170
 *   $int             - string containing interface name
5171
 * RESULT
5172
 *   boolean          - true or false
5173
 ******/
5174
function is_jumbo_capable($iface) {
5175
	$iface = trim($iface);
5176
	$capable = pfSense_get_interface_addresses($iface);
5177

    
5178
	if (isset($capable['caps']['vlanmtu']))
5179
		return true;
5180

    
5181
	// hack for some lagg modes missing vlanmtu, but work fine w/VLANs
5182
	if (substr($iface, 0, 4) == "lagg")
5183
		return true;
5184

    
5185
	return false;
5186
}
5187

    
5188
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5189
	global $g;
5190

    
5191
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5192

    
5193
	if(!empty($iface) && !empty($pppif)){
5194
		$cron_cmd = <<<EOD
5195
#!/bin/sh
5196
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5197
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5198

    
5199
EOD;
5200

    
5201
		@file_put_contents($cron_file, $cron_cmd);
5202
		chmod($cron_file, 0755);
5203
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5204
	} else
5205
		unlink_if_exists($cron_file);
5206
}
5207

    
5208
function get_interface_default_mtu($type = "ethernet") {
5209
	switch ($type) {
5210
	case "gre":
5211
		return 1476;
5212
		break;
5213
	case "gif":
5214
		return 1280;
5215
		break;
5216
	case "tun":
5217
	case "vlan":
5218
	case "tap":
5219
	case "ethernet":
5220
	default:
5221
		return 1500;
5222
		break;
5223
	}
5224

    
5225
	/* Never reached */
5226
	return 1500;
5227
}
5228

    
5229
function get_vip_descr($ipaddress) {
5230
	global $config;
5231

    
5232
	foreach ($config['virtualip']['vip'] as $vip) {
5233
		if ($vip['subnet'] == $ipaddress) {
5234
			return ($vip['descr']);
5235
		}
5236
	}
5237
	return "";
5238
}
5239

    
5240
function interfaces_staticarp_configure($if) {
5241
	global $config, $g;
5242
	if(isset($config['system']['developerspew'])) {
5243
		$mt = microtime();
5244
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5245
	}
5246

    
5247
	$ifcfg = $config['interfaces'][$if];
5248

    
5249
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5250
		return 0;
5251

    
5252
	/* Enable staticarp, if enabled */
5253
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5254
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5255
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5256
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5257

    
5258
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5259
				mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5260

    
5261
			}
5262

    
5263
		}
5264
	} else {
5265
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5266
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5267
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5268
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5269
				if (isset($arpent['arp_table_static_entry'])) {
5270
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5271
				}
5272
			}
5273
		}
5274
	}
5275

    
5276
	return 0;
5277
}
5278

    
5279
function get_failover_interface($interface, $family = "all") {
5280
	global $config;
5281

    
5282
	/* shortcut to get_real_interface if we find it in the config */
5283
	if (is_array($config['interfaces'][$interface])) {
5284
		return get_real_interface($interface, $family);
5285
	}
5286

    
5287
	/* compare against gateway groups */
5288
	$a_groups = return_gateway_groups_array();
5289
	if (is_array($a_groups[$interface])) {
5290
		/* we found a gateway group, fetch the interface or vip */
5291
		if ($a_groups[$interface][0]['vip'] <> "")
5292
			return $a_groups[$interface][0]['vip'];
5293
		else
5294
			return $a_groups[$interface][0]['int'];
5295
	}
5296
	/* fall through to get_real_interface */
5297
	/* XXX: Really needed? */
5298
	return get_real_interface($interface, $family);
5299
}
5300

    
5301
function remove_ifindex($ifname) {
5302
	return preg_replace("/[0-9]+$/", "", $ifname);
5303
}
5304

    
5305
?>
(26-26/68)