Project

General

Profile

Download (158 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
	if ($found == false) {
143
		if (!empty($config['interfaces'][$interface])) {
144
			switch ($config['interfaces'][$interface]['ipaddr']) {
145
			case "ppp":
146
			case "pppoe":
147
			case "l2tp":
148
			case "pptp":
149
				$found = true;
150
				break;
151
			default:
152
				$found = false;
153
				break;
154
			}
155
		}
156
	}
157
	if ($found == false) {
158
		$realif = get_real_interface($interface);
159
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
160
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
161

    
162
/* This if block doesn't do anything. It can be deleted.
163
PPP interfaces are found above in the previous if ($found == false) block.
164
This block of code is only entered for OPTx interfaces that are configured for PPPoE modem access, so $realif != $ppp['if']
165

    
166
				if ($realif == $ppp['if']) {
167
					$found = true;
168
					break;
169
				}
170
*/
171
				$ports = explode(',',$ppp['ports']);
172
				foreach($ports as $pid => $port){
173
					$port = get_real_interface($port);
174
					if ($realif == $port) {
175
						$found = true;
176
						break;
177
					}
178
					/* Find the parent interfaces of the vlans in the MLPPP configs
179
					* there should be only one element in the array here
180
					* -- this could be better . . . */
181
					$parent_if = get_parent_interface($port);
182
					if ($realif == $parent_if[0]) {
183
						$found = true;
184
						break;
185
					}
186
				}
187
			}
188
		}
189
	}
190

    
191
	if ($found == false) {
192
		$realif = get_real_interface($interface);
193
		pfSense_ngctl_detach("{$realif}:", $realif);
194
	}
195
	/* NOTE: We make sure for this on interface_ppps_configure()
196
	 *	no need to do it here agan.
197
	 *	else
198
	 *		pfSense_ngctl_attach(".", $realif);
199
	 */
200
}
201

    
202
function interfaces_loopback_configure() {
203
	global $g;
204

    
205
	if ($g['platform'] == 'jail')
206
		return;
207
	if($g['booting'])
208
		echo gettext("Configuring loopback interface...");
209
	pfSense_interface_setaddress("lo0", "127.0.0.1");
210
	interfaces_bring_up("lo0");
211
	if($g['booting'])
212
		echo gettext("done.") . "\n";
213
	return 0;
214
}
215

    
216
function interfaces_vlan_configure($realif = "") {
217
	global $config, $g;
218
	if($g['booting'])
219
		echo gettext("Configuring VLAN interfaces...");
220
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
221
		foreach ($config['vlans']['vlan'] as $vlan) {
222
			if (empty($vlan['vlanif']))
223
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
224
			if (!empty($realif) && $realif != $vlan['vlanif'])
225
				continue;
226

    
227
			/* XXX: Maybe we should report any errors?! */
228
			interface_vlan_configure($vlan);
229
		}
230
	}
231
	if($g['booting'])
232
		echo gettext("done.") . "\n";
233
}
234

    
235
function interface_vlan_configure(&$vlan) {
236
	global $config, $g;
237

    
238
	if (!is_array($vlan)) {
239
		log_error(gettext("VLAN: called with wrong options. Problems with config!"));
240
		return;
241
	}
242
	$if = $vlan['if'];
243
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
244
	$tag = $vlan['tag'];
245

    
246
	if (empty($if)) {
247
		log_error(gettext("interface_vlan_configure called with if undefined."));
248
		return;
249
	}
250

    
251
	/* make sure the parent interface is up */
252
	interfaces_bring_up($if);
253
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
254
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
255

    
256
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
257
		interface_bring_down($vlanif, true);
258
	} else {
259
		$tmpvlanif = pfSense_interface_create("vlan");
260
		pfSense_interface_rename($tmpvlanif, $vlanif);
261
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
262
	}
263

    
264
	pfSense_vlan_create($vlanif, $if, $tag);
265

    
266
	interfaces_bring_up($vlanif);
267

    
268
	/* invalidate interface cache */
269
	get_interface_arr(true);
270

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

    
274
	return $vlanif;
275
}
276

    
277
function interface_qinq_configure(&$vlan, $fd = NULL) {
278
	global $config, $g;
279

    
280
	if (!is_array($vlan)) {
281
		log_error(sprintf(gettext("QinQ compat VLAN: called with wrong options. Problems with config!%s"), "\n"));
282
		return;
283
	}
284

    
285
	$qinqif = $vlan['if'];
286
	$tag = $vlan['tag'];
287
	if(empty($qinqif)) {
288
		log_error(sprintf(gettext("interface_qinq_configure called with if undefined.%s"), "\n"));
289
		return;
290
	}
291

    
292
	if(!does_interface_exist($qinqif)) {
293
		log_error(sprintf(gettext("interface_qinq_configure called with invalid if.%s"), "\n"));
294
		return;
295
	}
296

    
297
	$vlanif = interface_vlan_configure($vlan);
298

    
299
	if ($fd == NULL) {
300
		$exec = true;
301
		$fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
302
	} else
303
		$exec = false;
304
	/* make sure the parent is converted to ng_vlan(4) and is up */
305
	interfaces_bring_up($qinqif);
306

    
307
	pfSense_ngctl_attach(".", $qinqif);
308
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
309
		fwrite($fd, "shutdown {$qinqif}qinq:\n");
310
		exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
311
		if (empty($result)) {
312
			fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
313
			fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
314
			fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
315
		}
316
	} else {
317
		fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
318
		fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
319
		fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
320
	}
321

    
322
	/* invalidate interface cache */
323
	get_interface_arr(true);
324

    
325
	if (!stristr($qinqif, "_vlan"))
326
		mwexec("/sbin/ifconfig {$qinqif} promisc\n");
327

    
328
	$macaddr = get_interface_mac($qinqif);
329
	if (!empty($vlan['members'])) {
330
		$members = explode(" ", $vlan['members']);
331
		foreach ($members as $qtag) {
332
			$qinq = array();
333
			$qinq['tag'] = $qtag;
334
			$qinq['if'] = $vlanif;
335
			interface_qinq2_configure($qinq, $fd, $macaddr);
336
		}
337
	}
338
	if ($exec == true) {
339
		fclose($fd);
340
		mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
341
	}
342

    
343
	interfaces_bring_up($qinqif);
344
	if (!empty($vlan['members'])) {
345
		$members = explode(" ", $vlan['members']);
346
		foreach ($members as $qif)
347
			interfaces_bring_up("{$vlanif}_{$qif}");
348
	}
349

    
350
	return $vlanif;
351
}
352

    
353
function interfaces_qinq_configure() {
354
	global $config, $g;
355
	if($g['booting'])
356
		echo gettext("Configuring QinQ interfaces...");
357
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
358
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
359
			/* XXX: Maybe we should report any errors?! */
360
			interface_qinq_configure($qinq);
361
		}
362
	}
363
	if($g['booting'])
364
		echo gettext( "done.") . "\n";
365
}
366

    
367
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
368
	global $config, $g;
369

    
370
	if (!is_array($qinq)) {
371
		log_error(sprintf(gettext("QinQ compat VLAN: called with wrong options. Problems with config!%s"), "\n"));
372
		return;
373
	}
374

    
375
	$if = $qinq['if'];
376
	$tag = $qinq['tag'];
377
	$vlanif = "{$if}_{$tag}";
378
	if(empty($if)) {
379
		log_error(sprintf(gettext("interface_qinq2_configure called with if undefined.%s"), "\n"));
380
		return;
381
	}
382

    
383
	fwrite($fd, "shutdown {$if}h{$tag}:\n");
384
	fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
385
	fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
386
	fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
387
	fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
388
	fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
389

    
390
	/* invalidate interface cache */
391
	get_interface_arr(true);
392

    
393
	return $vlanif;
394
}
395

    
396
function interfaces_create_wireless_clones() {
397
	global $config, $g;
398

    
399
	if($g['booting'])
400
		echo gettext("Creating wireless clone interfaces...");
401

    
402
	$iflist = get_configured_interface_list();
403

    
404
	foreach ($iflist as $if) {
405
		$realif = $config['interfaces'][$if]['if'];
406
		if (is_interface_wireless($realif))
407
			interface_wireless_clone(interface_get_wireless_clone($realif), $config['interfaces'][$if]);
408
	}
409

    
410
	if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
411
		foreach ($config['wireless']['clone'] as $clone) {
412
			if(empty($clone['cloneif']))
413
				continue;
414
			if(does_interface_exist($clone['cloneif']))
415
				continue;
416
			/* XXX: Maybe we should report any errors?! */
417
			interface_wireless_clone($clone['cloneif'], $clone);
418
		}
419
	}
420
	if($g['booting'])
421
		echo gettext("done.") . "\n";
422

    
423
}
424

    
425
function interfaces_bridge_configure($checkmember = 0, $realif = "") {
426
	global $config;
427

    
428
	$i = 0;
429
	if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
430
		foreach ($config['bridges']['bridged'] as $bridge) {
431
			if (empty($bridge['bridgeif']))
432
				$bridge['bridgeif'] = "bridge{$i}";
433
			if (!empty($realif) && $realif != $bridge['bridgeif'])
434
				continue;
435

    
436
			if ($checkmember == 1) {
437
				if (strstr($bridge['if'], "_vip"))
438
					continue;
439
				$members = explode(',', $bridge['members']);
440
				foreach ($members as $member) {
441
					if (!empty($config['interfaces'][$bridge['if']]) && $config['interfaces'][$bridge['if']]['ipaddrv6'] == "track6")
442
						continue 2;
443
				}
444
			}
445
			else if ($checkmember == 2) {
446
				if (strstr($bridge['if'], "_vip"))
447
					continue;
448
				$members = explode(',', $bridge['members']);
449
				foreach ($members as $member) {
450
					if (empty($config['interfaces'][$bridge['if']]) || $config['interfaces'][$bridge['if']]['ipaddrv6'] != "track6")
451
						continue 2;
452
				}
453
			}
454
			/* XXX: Maybe we should report any errors?! */
455
			interface_bridge_configure($bridge, $checkmember);
456
			$i++;
457
		}
458
	}
459
}
460

    
461
function interface_bridge_configure(&$bridge, $checkmember = 0) {
462
	global $config, $g;
463

    
464
	if (!is_array($bridge))
465
		return;
466

    
467
	if (empty($bridge['members'])) {
468
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
469
		return;
470
	}
471

    
472
	$members = explode(',', $bridge['members']);
473
	if (!count($members))
474
		return;
475

    
476
	/* Calculate smaller mtu and enforce it */
477
	$smallermtu = 0;
478
	$commonrx = true;
479
	$commontx = true;
480
	$foundgif = false;
481
	foreach ($members as $member) {
482
		$realif = get_real_interface($member);
483
		$opts = pfSense_get_interface_addresses($realif);
484
		$mtu = $opts['mtu'];
485
		if (substr($realif, 0, 3) == "gif") {
486
			$foundgif = true;
487
			if ($checkmember == 1)
488
				return;
489
			if ($mtu <= 1500)
490
				continue;
491
		}
492
		if ($smallermtu == 0 && !empty($mtu))
493
			$smallermtu = $mtu;
494
		else if (!empty($mtu) && $mtu < $smallermtu)
495
			$smallermtu = $mtu;
496
	}
497
	if ($foundgif == false && $checkmember == 2)
498
		return;
499

    
500
	/* Just in case anything is not working well */
501
	if ($smallermtu == 0)
502
		$smallermtu = 1500;
503

    
504
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
505
		pfSense_interface_destroy($bridge['bridgeif']);
506
		pfSense_interface_create($bridge['bridgeif']);
507
		$bridgeif = escapeshellarg($bridge['bridgeif']);
508
	} else {
509
		$bridgeif = pfSense_interface_create("bridge");
510
		$bridge['bridgeif'] = $bridgeif;
511
	}
512

    
513
	$bridgemtu = interface_find_child_cfgmtu($bridge['bridgeif']);
514
	if ($bridgemtu > $smallermtu)
515
		$smallermtu = $bridgemtu;
516

    
517
	$checklist = get_configured_interface_list();
518

    
519
	/* Add interfaces to bridge */
520
	foreach ($members as $member) {
521
		if (empty($checklist[$member]))
522
			continue;
523
		$realif = get_real_interface($member);
524
		if (!$realif) {
525
			log_error(gettext("realif not defined in interfaces bridge - up"));
526
			continue;
527
		}
528
		/* make sure the parent interface is up */
529
		pfSense_interface_mtu($realif, $smallermtu);
530
		interfaces_bring_up($realif);
531
		enable_hardware_offloading($member);
532
		pfSense_bridge_add_member($bridge['bridgeif'], $realif);
533
	}
534

    
535
	if (isset($bridge['enablestp'])) {
536
		/* Choose spanning tree proto */
537
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
538

    
539
		if (!empty($bridge['stp'])) {
540
			$stpifs = explode(',', $bridge['stp']);
541
			foreach ($stpifs as $stpif) {
542
				$realif = get_real_interface($stpif);
543
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
544
			}
545
		}
546
		if (!empty($bridge['maxage']))
547
			mwexec("/sbin/ifconfig {$bridgeif} maxage " . escapeshellarg($bridge['maxage']));
548
		if (!empty($bridge['fwdelay']))
549
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay " . escapeshellarg($bridge['fwdelay']));
550
		if (!empty($bridge['hellotime']))
551
			mwexec("/sbin/ifconfig {$bridgeif} hellotime " . escapeshellarg($bridge['hellotime']));
552
		if (!empty($bridge['priority']))
553
			mwexec("/sbin/ifconfig {$bridgeif} priority " . escapeshellarg($bridge['priority']));
554
		if (!empty($bridge['holdcnt']))
555
			mwexec("/sbin/ifconfig {$bridgeif} holdcnt " . escapeshellarg($bridge['holdcnt']));
556
		if (!empty($bridge['ifpriority'])) {
557
			$pconfig = explode(",", $bridge['ifpriority']);
558
			$ifpriority = array();
559
			foreach ($pconfig as $cfg) {
560
				$embcfg = explode_assoc(":", $cfg);
561
				foreach ($embcfg as $key => $value)
562
					$ifpriority[$key] = $value;
563
			}
564
			foreach ($ifpriority as $key => $value) {
565
				$realif = get_real_interface($key);
566
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} " . escapeshellarg($value));
567
			}
568
		}
569
		if (!empty($bridge['ifpathcost'])) {
570
			$pconfig = explode(",", $bridge['ifpathcost']);
571
			$ifpathcost = array();
572
			foreach ($pconfig as $cfg) {
573
				$embcfg = explode_assoc(":", $cfg);
574
				foreach ($embcfg as $key => $value)
575
					$ifpathcost[$key] = $value;
576
			}
577
			foreach ($ifpathcost as $key => $value) {
578
				$realif = get_real_interface($key);
579
				mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} " . escapeshellarg($value));
580
			}
581
		}
582
	}
583

    
584
	if ($bridge['maxaddr'] <> "")
585
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr " . escapeshellarg($bridge['maxaddr']));
586
	if ($bridge['timeout'] <> "")
587
		mwexec("/sbin/ifconfig {$bridgeif} timeout " . escapeshellarg($bridge['timeout']));
588
	if ($bridge['span'] <> "") {
589
		$realif = get_real_interface($bridge['span']);
590
		mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
591
	}
592
	if (!empty($bridge['edge'])) {
593
		$edgeifs = explode(',', $bridge['edge']);
594
		foreach ($edgeifs as $edgeif) {
595
			$realif = get_real_interface($edgeif);
596
			mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
597
		}
598
	}
599
	if (!empty($bridge['autoedge'])) {
600
		$edgeifs = explode(',', $bridge['autoedge']);
601
		foreach ($edgeifs as $edgeif) {
602
			$realif = get_real_interface($edgeif);
603
			mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
604
		}
605
	}
606
	if (!empty($bridge['ptp'])) {
607
		$ptpifs = explode(',', $bridge['ptp']);
608
		foreach ($ptpifs as $ptpif) {
609
			$realif = get_real_interface($ptpif);
610
			mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
611
		}
612
	}
613
	if (!empty($bridge['autoptp'])) {
614
		$ptpifs = explode(',', $bridge['autoptp']);
615
		foreach ($ptpifs as $ptpif) {
616
			$realif = get_real_interface($ptpif);
617
			mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
618
		}
619
	}
620
	if (!empty($bridge['static'])) {
621
		$stickyifs = explode(',', $bridge['static']);
622
		foreach ($stickyifs as $stickyif) {
623
			$realif = get_real_interface($stickyif);
624
			mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
625
		}
626
	}
627
	if (!empty($bridge['private'])) {
628
		$privateifs = explode(',', $bridge['private']);
629
		foreach ($privateifs as $privateif) {
630
			$realif = get_real_interface($privateif);
631
			mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
632
		}
633
	}
634

    
635
	if ($bridge['bridgeif'])
636
		interfaces_bring_up($bridge['bridgeif']);
637
	else
638
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
639
}
640

    
641
function interface_bridge_add_member($bridgeif, $interface, $flagsapplied = false) {
642

    
643
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
644
		return;
645

    
646
	if ($flagsapplied == false) {
647
		$mtu = get_interface_mtu($bridgeif);
648
		$mtum = get_interface_mtu($interface);
649
		if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
650
			pfSense_interface_mtu($interface, $mtu);
651

    
652
		hardware_offloading_applyflags($interface);
653
		interfaces_bring_up($interface);
654
	}
655

    
656
	pfSense_bridge_add_member($bridgeif, $interface);
657
}
658

    
659
function interfaces_lagg_configure($realif = "") {
660
	global $config, $g;
661
	if($g['booting'])
662
		echo gettext("Configuring LAGG interfaces...");
663
	$i = 0;
664
	if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
665
		foreach ($config['laggs']['lagg'] as $lagg) {
666
			if(empty($lagg['laggif']))
667
				$lagg['laggif'] = "lagg{$i}";
668
			if (!empty($realif) && $realif != $lagg['laggif'])
669
				continue;
670
			/* XXX: Maybe we should report any errors?! */
671
			interface_lagg_configure($lagg);
672
			$i++;
673
		}
674
	}
675
	if($g['booting'])
676
		echo gettext("done.") . "\n";
677
}
678

    
679
function interface_lagg_configure($lagg) {
680
	global $config, $g;
681

    
682
	if (!is_array($lagg))
683
		return -1;
684

    
685
	$members = explode(',', $lagg['members']);
686
	if (!count($members))
687
		return -1;
688

    
689
	if ($g['booting'] || !(empty($lagg['laggif']))) {
690
		pfSense_interface_destroy($lagg['laggif']);
691
		pfSense_interface_create($lagg['laggif']);
692
		$laggif = $lagg['laggif'];
693
	} else
694
		$laggif = pfSense_interface_create("lagg");
695

    
696
	/* Check if MTU was defined for this lagg interface */
697
	$lagg_mtu = interface_find_child_cfgmtu($laggif);
698
	if ($lagg_mtu == 0) {
699
		/* Calculate smaller mtu and enforce it */
700
		$smallermtu = 0;
701
		foreach ($members as $member) {
702
			$opts = pfSense_get_interface_addresses($member);
703
			$mtu = $opts['mtu'];
704
			if ($smallermtu == 0 && !empty($mtu))
705
				$smallermtu = $mtu;
706
			else if (!empty($mtu) && $mtu < $smallermtu)
707
				$smallermtu = $mtu;
708
		}
709
		$lagg_mtu = $smallermtu;
710
	}
711

    
712
	/* Just in case anything is not working well */
713
	if ($lagg_mtu == 0)
714
		$lagg_mtu = 1500;
715

    
716
	foreach ($members as $member) {
717
		if (!does_interface_exist($member))
718
			continue;
719
		/* make sure the parent interface is up */
720
		pfSense_interface_mtu($member, $lagg_mtu);
721
		interfaces_bring_up($member);
722
		hardware_offloading_applyflags($member);
723
		mwexec("/sbin/ifconfig " . escapeshellarg($laggif) . " laggport " . escapeshellarg($member));
724
	}
725
	pfSense_interface_capabilities($laggif, -$flags_off);
726
	pfSense_interface_capabilities($laggif, $flags_on);
727

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

    
730
	interfaces_bring_up($laggif);
731

    
732
	return $laggif;
733
}
734

    
735
function interfaces_gre_configure($checkparent = 0, $realif = "") {
736
	global $config;
737

    
738
	if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
739
		foreach ($config['gres']['gre'] as $i => $gre) {
740
			if (empty($gre['greif']))
741
				$gre['greif'] = "gre{$i}";
742
			if (!empty($realif) && $realif != $gre['greif'])
743
				continue;
744

    
745
			if ($checkparent == 1) {
746
				if (strstr($gre['if'], "_vip"))
747
					continue;
748
				if (!empty($config['interfaces'][$gre['if']]) && $config['interfaces'][$gre['if']]['ipaddrv6'] == "track6")
749
					continue;
750
			}
751
			else if ($checkparent == 2) {
752
				if (strstr($gre['if'], "_vip"))
753
					continue;
754
				if (empty($config['interfaces'][$gre['if']]) || $config['interfaces'][$gre['if']]['ipaddrv6'] != "track6")
755
					continue;
756
			}
757
			/* XXX: Maybe we should report any errors?! */
758
			interface_gre_configure($gre);
759
		}
760
	}
761
}
762

    
763
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
764
function interface_gre_configure(&$gre, $grekey = "") {
765
	global $config, $g;
766

    
767
	if (!is_array($gre))
768
		return -1;
769

    
770
	$realif = get_real_interface($gre['if']);
771
	$realifip = get_interface_ip($gre['if']);
772

    
773
	/* make sure the parent interface is up */
774
	interfaces_bring_up($realif);
775

    
776
	if ($g['booting'] || !(empty($gre['greif']))) {
777
		pfSense_interface_destroy($gre['greif']);
778
		pfSense_interface_create($gre['greif']);
779
		$greif = $gre['greif'];
780
	} else
781
		$greif = pfSense_interface_create("gre");
782

    
783
	/* Do not change the order here for more see gre(4) NOTES section. */
784
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} " . escapeshellarg($gre['remote-addr']));
785
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
786
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
787
		//mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gre['tunnel-remote-net']));
788
		mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen 128");
789
	} else {
790
		mwexec("/sbin/ifconfig {$greif} " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
791
	}
792
	if (isset($gre['link0']))
793
		pfSense_interface_flags($greif, IFF_LINK0);
794
	if (isset($gre['link1']))
795
		pfSense_interface_flags($greif, IFF_LINK1);
796
	if (isset($gre['link2']))
797
		pfSense_interface_flags($greif, IFF_LINK2);
798

    
799
	if($greif)
800
		interfaces_bring_up($greif);
801
	else
802
		log_error(gettext("Could not bring greif up -- variable not defined."));
803

    
804
	if (isset($gre['link1']) && $gre['link1'])
805
		mwexec("/sbin/route add " . escapeshellarg($gre['tunnel-remote-addr']) . "/" . escapeshellarg($gre['tunnel-remote-net']) . " " . escapeshellarg($gre['tunnel-local-addr']));
806
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
807
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
808
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
809
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
810

    
811
	interfaces_bring_up($greif);
812

    
813
	return $greif;
814
}
815

    
816
function interfaces_gif_configure($checkparent = 0, $realif = "") {
817
	global $config;
818

    
819
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
820
		foreach ($config['gifs']['gif'] as $i => $gif) {
821
			if (empty($gif['gifif']))
822
				$gre['gifif'] = "gif{$i}";
823
			if (!empty($realif) && $realif != $gif['gifif'])
824
				continue;
825

    
826
			if ($checkparent == 1) {
827
				if (strstr($gif['if'], "_vip"))
828
					continue;
829
				if (!empty($config['interfaces'][$gif['if']]) && $config['interfaces'][$gif['if']]['ipaddrv6'] == "track6")
830
					continue;
831
			}
832
			else if ($checkparent == 2) {
833
				if (strstr($gif['if'], "_vip"))
834
					continue;
835
				if (empty($config['interfaces'][$gif['if']]) || $config['interfaces'][$gif['if']]['ipaddrv6'] != "track6")
836
					continue;
837
			}
838
			/* XXX: Maybe we should report any errors?! */
839
			interface_gif_configure($gif);
840
		}
841
	}
842
}
843

    
844
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
845
function interface_gif_configure(&$gif, $gifkey = "") {
846
	global $config, $g;
847

    
848
	if (!is_array($gif))
849
		return -1;
850

    
851
	$realif = get_real_interface($gif['if']);
852
	$ipaddr = $gif['ipaddr'];
853

    
854
	if (is_ipaddrv4($gif['remote-addr'])) {
855
		if (is_ipaddrv4($ipaddr))
856
			$realifip = $ipaddr;
857
		else
858
			$realifip = get_interface_ip($gif['if']);
859
		$realifgw = get_interface_gateway($gif['if']);
860
	} else if (is_ipaddrv6($gif['remote-addr'])) {
861
		if (is_ipaddrv6($ipaddr))
862
			$realifip = $ipaddr;
863
		else
864
			$realifip = get_interface_ipv6($gif['if']);
865
		$realifgw = get_interface_gateway_v6($gif['if']);
866
	}
867
	/* make sure the parent interface is up */
868
	if($realif)
869
		interfaces_bring_up($realif);
870
	else
871
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
872

    
873
	if ($g['booting'] || !(empty($gif['gifif']))) {
874
		pfSense_interface_destroy($gif['gifif']);
875
		pfSense_interface_create($gif['gifif']);
876
		$gifif = $gif['gifif'];
877
	} else
878
		$gifif = pfSense_interface_create("gif");
879

    
880
	/* Do not change the order here for more see gif(4) NOTES section. */
881
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} " . escapeshellarg($gif['remote-addr']));
882
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
883
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
884
		//mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gif['tunnel-remote-net']));
885
		mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen 128");
886
	} else {
887
		mwexec("/sbin/ifconfig {$gifif} " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
888
	}
889
	if (isset($gif['link0']))
890
		pfSense_interface_flags($gifif, IFF_LINK0);
891
	if (isset($gif['link1']))
892
		pfSense_interface_flags($gifif, IFF_LINK1);
893
	if($gifif)
894
		interfaces_bring_up($gifif);
895
	else
896
		log_error(gettext("could not bring gifif up -- variable not defined"));
897

    
898
	if (!$g['booting']) {
899
		$iflist = get_configured_interface_list();
900
		foreach($iflist as $ifname) {
901
			if($config['interfaces'][$ifname]['if'] == $gifif) {
902
				if(get_interface_gateway($ifname)) {
903
					system_routing_configure($ifname);
904
					break;
905
				}
906
				if(get_interface_gateway_v6($ifname)) {
907
					system_routing_configure($ifname);
908
					break;
909
				}
910
			}
911
		}
912
	}
913

    
914

    
915
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
916
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
917
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
918
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
919

    
920
	if (is_ipaddrv4($realifgw)) {
921
		mwexec("/sbin/route change -host " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
922
	}
923
	if (is_ipaddrv6($realifgw)) {
924
		mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
925
	}
926

    
927
	interfaces_bring_up($gifif);
928

    
929
	return $gifif;
930
}
931

    
932
function interfaces_configure() {
933
	global $config, $g;
934

    
935
	if ($g['platform'] == 'jail')
936
		return;
937

    
938
	/* Set up our loopback interface */
939
	interfaces_loopback_configure();
940

    
941
	/* create the unconfigured wireless clones */
942
	interfaces_create_wireless_clones();
943

    
944
	/* set up LAGG virtual interfaces */
945
	interfaces_lagg_configure();
946

    
947
	/* set up VLAN virtual interfaces */
948
	interfaces_vlan_configure();
949

    
950
	interfaces_qinq_configure();
951

    
952
	$iflist = get_configured_interface_with_descr();
953
	$delayed_list = array();
954
	$bridge_list = array();
955
	$track6_list = array();
956

    
957
	/* This is needed to speedup interfaces on bootup. */
958
	$reload = false;
959
	if (!$g['booting'])
960
		$reload = true;
961

    
962
	foreach($iflist as $if => $ifname) {
963
		$realif = $config['interfaces'][$if]['if'];
964
		if (strstr($realif, "bridge"))
965
			$bridge_list[$if] = $ifname;
966
		else if (strstr($realif, "gre"))
967
			$delayed_list[$if] = $ifname;
968
		else if (strstr($realif, "gif"))
969
			$delayed_list[$if] = $ifname;
970
		else if (strstr($realif, "ovpn")) {
971
			//echo "Delaying OpenVPN interface configuration...done.\n";
972
			continue;
973
		} else if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
974
			$track6_list[$if] = $ifname;
975
		} else {
976
			if ($g['booting'])
977
				printf(gettext("Configuring %s interface..."), $ifname);
978

    
979
			if($g['debug'])
980
				log_error(sprintf(gettext("Configuring %s"), $ifname));
981
			interface_configure($if, $reload);
982
			if ($g['booting'])
983
				echo gettext( "done.") . "\n";
984
		}
985
	}
986

    
987
	/*
988
	 * NOTE: The following function parameter consists of
989
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
990
	 *	2 - Do load gre/gif/bridge with parent/member as vip
991
	 */
992

    
993
	/* set up GRE virtual interfaces */
994
	interfaces_gre_configure(1);
995

    
996
	/* set up GIF virtual interfaces */
997
	interfaces_gif_configure(1);
998

    
999
	/* set up BRIDGe virtual interfaces */
1000
	interfaces_bridge_configure(1);
1001

    
1002
	foreach ($track6_list as $if => $ifname) {
1003
		if ($g['booting'])
1004
			printf(gettext("Configuring %s interface..."), $ifname);
1005
		if ($g['debug'])
1006
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1007

    
1008
		interface_configure($if, $reload);
1009

    
1010
		if ($g['booting'])
1011
			echo gettext("done.") . "\n";
1012
	}
1013

    
1014
	/* bring up vip interfaces */
1015
	interfaces_vips_configure();
1016

    
1017
	/* set up GRE virtual interfaces */
1018
	interfaces_gre_configure(2);
1019

    
1020
	/* set up GIF virtual interfaces */
1021
	interfaces_gif_configure(2);
1022

    
1023
	foreach ($delayed_list as $if => $ifname) {
1024
		if ($g['booting'])
1025
			printf(gettext("Configuring %s interface..."), $ifname);
1026
		if ($g['debug'])
1027
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1028

    
1029
		interface_configure($if, $reload);
1030

    
1031
		if ($g['booting'])
1032
			echo gettext("done.") . "\n";
1033
	}
1034

    
1035
	/* set up BRIDGe virtual interfaces */
1036
	interfaces_bridge_configure(2);
1037

    
1038
	foreach ($bridge_list as $if => $ifname) {
1039
		if ($g['booting'])
1040
			printf(gettext("Configuring %s interface..."), $ifname);
1041
		if($g['debug'])
1042
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1043

    
1044
		interface_configure($if, $reload);
1045

    
1046
		if ($g['booting'])
1047
			echo gettext("done.") . "\n";
1048
	}
1049

    
1050
	/* configure interface groups */
1051
	interfaces_group_setup();
1052

    
1053
	if (!$g['booting']) {
1054
		/* reconfigure static routes (kernel may have deleted them) */
1055
		system_routing_configure();
1056

    
1057
		/* reload IPsec tunnels */
1058
		vpn_ipsec_configure();
1059

    
1060
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1061
		services_dhcpd_configure();
1062

    
1063
		/* restart dnsmasq or unbound */
1064
		if (isset($config['dnsmasq']['enable']))
1065
			services_dnsmasq_configure();
1066
		elseif (isset($config['unbound']['enable']))
1067
			services_unbound_configure();
1068
	}
1069

    
1070
	return 0;
1071
}
1072

    
1073
function interface_reconfigure($interface = "wan", $reloadall = false) {
1074
	interface_bring_down($interface);
1075
	interface_configure($interface, $reloadall);
1076
}
1077

    
1078
function interface_vip_bring_down($vip) {
1079
	global $g;
1080

    
1081
	$vipif = get_real_interface($vip['interface']);
1082
	switch ($vip['mode']) {
1083
	case "proxyarp":
1084
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1085
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1086
		break;
1087
	case "ipalias":
1088
		if (does_interface_exist($vipif)) {
1089
			if (is_ipaddrv6($vip['subnet']))
1090
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " -alias");
1091
			else
1092
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1093
		}
1094
		break;
1095
	case "carp":
1096
		/* XXX: Is enough to delete ip address? */
1097
		if (does_interface_exist($vipif)) {
1098
			if (is_ipaddrv6($vip['subnet']))
1099
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " delete");
1100
			else
1101
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1102
		}
1103
		break;
1104
	}
1105
}
1106

    
1107
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1108
	global $config, $g;
1109

    
1110
	if (!isset($config['interfaces'][$interface]))
1111
		return;
1112

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

    
1116
	/*
1117
	 * NOTE: The $realifv6 is needed when WANv4 is type PPP and v6 is DHCP and the option v6 from v4 is used.
1118
	 * In this case the real $realif of v4 is different from that of v6 for operation.
1119
	 * Keep this in mind while doing changes here!
1120
	 */
1121
	if ($ifacecfg === false) {
1122
		$ifcfg = $config['interfaces'][$interface];
1123
		$ppps = $config['ppps']['ppp'];
1124
		$realif = get_real_interface($interface);
1125
		$realifv6 = get_real_interface($interface, "inet6", true);
1126
	} elseif (!is_array($ifacecfg)) {
1127
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1128
		$ifcfg = $config['interfaces'][$interface];
1129
		$ppps = $config['ppps']['ppp'];
1130
		$realif = get_real_interface($interface);
1131
		$realifv6 = get_real_interface($interface, "inet6", true);
1132
	} else {
1133
		$ifcfg = $ifacecfg['ifcfg'];
1134
		$ppps = $ifacecfg['ppps'];
1135
		if (isset($ifacecfg['ifcfg']['realif'])) {
1136
			$realif = $ifacecfg['ifcfg']['realif'];
1137
			/* XXX: Any better way? */
1138
			$realifv6 = $realif;
1139
		} else {
1140
			$realif = get_real_interface($interface);
1141
			$realifv6 = get_real_interface($interface, "inet6", true);
1142
		}
1143
	}
1144

    
1145
	switch ($ifcfg['ipaddr']) {
1146
	case "ppp":
1147
	case "pppoe":
1148
	case "pptp":
1149
	case "l2tp":
1150
		if (is_array($ppps) && count($ppps)) {
1151
			foreach ($ppps as $pppid => $ppp) {
1152
				if ($realif == $ppp['if']) {
1153
					if (isset($ppp['ondemand']) && !$destroy){
1154
						send_event("interface reconfigure {$interface}");
1155
						break;
1156
					}
1157
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1158
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1159
						sleep(2);
1160
					}
1161
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1162
					break;
1163
				}
1164
			}
1165
		}
1166
		break;
1167
	case "dhcp":
1168
		kill_dhclient_process($realif);
1169
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1170
		if(does_interface_exist("$realif")) {
1171
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1172
			interface_ipalias_cleanup($interface);
1173
			if ($destroy == true)
1174
				pfSense_interface_flags($realif, -IFF_UP);
1175
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1176
		}
1177
		break;
1178
	default:
1179
		if(does_interface_exist("$realif")) {
1180
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1181
			interface_ipalias_cleanup($interface);
1182
			if ($destroy == true)
1183
				pfSense_interface_flags($realif, -IFF_UP);
1184
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1185
		}
1186
		break;
1187
	}
1188

    
1189
	$track6 = array();
1190
	switch ($ifcfg['ipaddrv6']) {
1191
	case "slaac":
1192
	case "dhcp6":
1193
		$pidv6 = find_dhcp6c_process($realif);
1194
		if($pidv6)
1195
			posix_kill($pidv6, SIGTERM);
1196
		sleep(3);
1197
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1198
		if (does_interface_exist($realifv6)) {
1199
			$ip6 = find_interface_ipv6($realifv6);
1200
			if (is_ipaddrv6($ip6) && $ip6 != "::")
1201
				mwexec("/sbin/ifconfig " . escapeshellarg($realifv6) . " inet6 {$ip6} delete", true);
1202
			interface_ipalias_cleanup($interface, "inet6");
1203
			if ($destroy == true)
1204
				pfSense_interface_flags($realif, -IFF_UP);
1205
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1206
		}
1207
		$track6 = link_interface_to_track6($interface);
1208
		break;
1209
	case "6rd":
1210
	case "6to4":
1211
		$realif = "{$interface}_stf";
1212
		if(does_interface_exist("$realif")) {
1213
			$ip6 = get_interface_ipv6($interface);
1214
			if (is_ipaddrv6($ip6))
1215
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1216
			interface_ipalias_cleanup($interface, "inet6");
1217
			if ($destroy == true)
1218
				pfSense_interface_flags($realif, -IFF_UP);
1219
		}
1220
		$track6 = link_interface_to_track6($interface);
1221
		break;
1222
	default:
1223
		if(does_interface_exist("$realif")) {
1224
			$ip6 = get_interface_ipv6($interface);
1225
			if (is_ipaddrv6($ip6))
1226
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1227
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1228
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1229
			interface_ipalias_cleanup($interface, "inet6");
1230
			if ($destroy == true)
1231
				pfSense_interface_flags($realif, -IFF_UP);
1232
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1233
		}
1234
		$track6 = link_interface_to_track6($interface);
1235
		break;
1236
	}
1237

    
1238
	if (!empty($track6) && is_array($track6)) {
1239
		if (!function_exists('services_dhcp_configure'))
1240
			require_once('services.inc');
1241
		/* Bring down radvd and dhcp6 on these interfaces */
1242
		services_dhcpd_configure('inet6', $track6);
1243
	}
1244

    
1245
	$old_router = '';
1246
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1247
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1248

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

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

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

    
1270
	return;
1271
}
1272

    
1273
function interfaces_carp_set_maintenancemode($carp_maintenancemode){
1274
	global $config;
1275
	if (isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == false) {
1276
		unset($config["virtualip_carp_maintenancemode"]);
1277
		write_config("Leave CARP maintenance mode");
1278
		if(is_array($config['virtualip']['vip'])) {
1279
			$viparr = &$config['virtualip']['vip'];
1280
			foreach ($viparr as $vip) {
1281
				switch ($vip['mode']) {
1282
				case "carp":
1283
					interface_vip_bring_down($vip);
1284
					//sleep(1);
1285
					break;
1286
				}
1287
			}
1288
		}
1289
	} else {
1290
		if (!isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == true) {
1291
			$config["virtualip_carp_maintenancemode"] = true;
1292
			write_config("Enter CARP maintenance mode");
1293
		}
1294
	}
1295

    
1296
	$viparr = &$config['virtualip']['vip'];
1297
	foreach ($viparr as $vip) {
1298
		if ($vip['mode'] == "carp") {
1299
			interface_carp_configure($vip);
1300
		}
1301
	}
1302
}
1303

    
1304
function interfaces_ptpid_used($ptpid) {
1305
	global $config;
1306

    
1307
	if (is_array($config['ppps']['ppp']))
1308
		foreach ($config['ppps']['ppp'] as & $settings)
1309
			if ($ptpid == $settings['ptpid'])
1310
				return true;
1311

    
1312
	return false;
1313
}
1314

    
1315
function interfaces_ptpid_next() {
1316

    
1317
	$ptpid = 0;
1318
	while(interfaces_ptpid_used($ptpid))
1319
		$ptpid++;
1320

    
1321
	return $ptpid;
1322
}
1323

    
1324
function getMPDCRONSettings($pppif) {
1325
	global $config;
1326

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

    
1335
	return NULL;
1336
}
1337

    
1338
function handle_pppoe_reset($post_array) {
1339
	global $config, $g;
1340

    
1341
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1342
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1343

    
1344
	if (!is_array($config['cron']['item']))
1345
		$config['cron']['item'] = array();
1346

    
1347
	$itemhash = getMPDCRONSettings($pppif);
1348

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

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

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

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

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

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

    
1455
	if($g['booting']) {
1456
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1457
		echo "starting {$pppif} link...";
1458
		// Do not re-configure the interface if we are booting and it's already been started
1459
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1460
			return 0;
1461
	}
1462

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

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

    
1497
				if(!is_ipaddr($localips[$pid])){
1498
					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!");
1499
					$localips[$pid] = "0.0.0.0";
1500
				}
1501
				if(!is_ipaddr($gateways[$pid])){
1502
					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));
1503
					return 0;
1504
				}
1505
				pfSense_ngctl_attach(".", $port);
1506
				break;
1507
			case "ppp":
1508
				if (!file_exists("{$port}")) {
1509
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1510
					return 0;
1511
				}
1512
				break;
1513
			default:
1514
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1515
				break;
1516
		}
1517
	}
1518

    
1519
	if (is_array($ports) && count($ports) > 1)
1520
		$multilink = "enable";
1521
	else
1522
		$multilink = "disable";
1523

    
1524
	if ($type == "modem"){
1525
		if (is_ipaddr($ppp['localip']))
1526
			$localip = $ppp['localip'];
1527
		else
1528
			$localip = '0.0.0.0';
1529

    
1530
		if (is_ipaddr($ppp['gateway']))
1531
			$gateway = $ppp['gateway'];
1532
		else
1533
			$gateway = "10.64.64.{$pppid}";
1534
		$ranges = "{$localip}/0 {$gateway}/0";
1535

    
1536
		if (empty($ppp['apnum']))
1537
			$ppp['apnum'] = 1;
1538
	} else
1539
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1540

    
1541
	if (isset($ppp['ondemand']))
1542
		$ondemand = "enable";
1543
	else
1544
		$ondemand = "disable";
1545
	if (!isset($ppp['idletimeout']))
1546
		$ppp['idletimeout'] = 0;
1547

    
1548
	if (empty($ppp['username']) && $type == "modem"){
1549
		$ppp['username'] = "user";
1550
		$ppp['password'] = "none";
1551
	}
1552
	if (empty($ppp['password']) && $type == "modem")
1553
		$passwd = "none";
1554
	else
1555
		$passwd = base64_decode($ppp['password']);
1556

    
1557
	$bandwidths = explode(',',$ppp['bandwidth']);
1558
	$defaultmtu = "1492";
1559
	if (!empty($ifcfg['mtu']))
1560
		$defaultmtu = intval($ifcfg['mtu']);
1561
	$mtus = explode(',',$ppp['mtu']);
1562
	$mrus = explode(',',$ppp['mru']);
1563

    
1564
	if (isset($ppp['mrru']))
1565
		$mrrus = explode(',',$ppp['mrru']);
1566

    
1567
	// Construct the mpd.conf file
1568
	$mpdconf = <<<EOD
1569
startup:
1570
	# configure the console
1571
	set console close
1572
	# configure the web server
1573
	set web close
1574

    
1575
default:
1576
{$ppp['type']}client:
1577
	create bundle static {$interface}
1578
	set bundle enable ipv6cp
1579
	set iface name {$pppif}
1580

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

    
1596
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1597
		$setdefaultgw = true;
1598
		$mpdconf .= <<<EOD
1599
	set iface route default
1600

    
1601
EOD;
1602
	}
1603
	$mpdconf .= <<<EOD
1604
	set iface {$ondemand} on-demand
1605
	set iface idle {$ppp['idletimeout']}
1606

    
1607
EOD;
1608

    
1609
	if (isset($ppp['ondemand']))
1610
		$mpdconf .= <<<EOD
1611
	set iface addrs 10.10.1.1 10.10.1.2
1612

    
1613
EOD;
1614

    
1615
	if (isset($ppp['tcpmssfix']))
1616
		$tcpmss = "disable";
1617
	else
1618
		$tcpmss = "enable";
1619
		$mpdconf .= <<<EOD
1620
	set iface {$tcpmss} tcpmssfix
1621

    
1622
EOD;
1623

    
1624
	$mpdconf .= <<<EOD
1625
	set iface up-script /usr/local/sbin/ppp-linkup
1626
	set iface down-script /usr/local/sbin/ppp-linkdown
1627
	set ipcp ranges {$ranges}
1628

    
1629
EOD;
1630
	if (isset($ppp['vjcomp']))
1631
		$mpdconf .= <<<EOD
1632
	set ipcp no vjcomp
1633

    
1634
EOD;
1635

    
1636
	if (isset($config['system']['dnsallowoverride']))
1637
		$mpdconf .= <<<EOD
1638
	set ipcp enable req-pri-dns
1639
	set ipcp enable req-sec-dns
1640

    
1641
EOD;
1642
	if (!isset($ppp['verbose_log']))
1643
		$mpdconf .= <<<EOD
1644
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1645

    
1646
EOD;
1647
	foreach($ports as $pid => $port){
1648
		$port = get_real_interface($port);
1649
		$mpdconf .= <<<EOD
1650

    
1651
	create link static {$interface}_link{$pid} {$type}
1652
	set link action bundle {$interface}
1653
	set link {$multilink} multilink
1654
	set link keep-alive 10 60
1655
	set link max-redial 0
1656

    
1657
EOD;
1658
		if (isset($ppp['shortseq']))
1659
			$mpdconf .= <<<EOD
1660
	set link no shortseq
1661

    
1662
EOD;
1663

    
1664
		if (isset($ppp['acfcomp']))
1665
			$mpdconf .= <<<EOD
1666
	set link no acfcomp
1667

    
1668
EOD;
1669

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

    
1674
EOD;
1675

    
1676
		$mpdconf .= <<<EOD
1677
	set link disable chap pap
1678
	set link accept chap pap eap
1679
	set link disable incoming
1680

    
1681
EOD;
1682

    
1683

    
1684
		if (!empty($bandwidths[$pid]))
1685
			$mpdconf .= <<<EOD
1686
	set link bandwidth {$bandwidths[$pid]}
1687

    
1688
EOD;
1689

    
1690
		if (empty($mtus[$pid]))
1691
			$mtus[$pid] = $defaultmtu;
1692
			$mpdconf .= <<<EOD
1693
	set link mtu {$mtus[$pid]}
1694

    
1695
EOD;
1696

    
1697
		if (!empty($mrus[$pid]))
1698
			$mpdconf .= <<<EOD
1699
	set link mru {$mrus[$pid]}
1700

    
1701
EOD;
1702

    
1703
		if (!empty($mrrus[$pid]))
1704
			$mpdconf .= <<<EOD
1705
	set link mrru {$mrrus[$pid]}
1706

    
1707
EOD;
1708

    
1709
		$mpdconf .= <<<EOD
1710
	set auth authname "{$ppp['username']}"
1711
	set auth password {$passwd}
1712

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

    
1723
EOD;
1724
		}
1725
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1726
			$mpdconf .= <<<EOD
1727
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1728

    
1729
EOD;
1730
		}
1731
		if (isset($ppp['initstr']) && $type == "modem") {
1732
			$initstr = base64_decode($ppp['initstr']);
1733
			$mpdconf .= <<<EOD
1734
	set modem var \$InitString "{$initstr}"
1735

    
1736
EOD;
1737
		}
1738
		if (isset($ppp['simpin']) && $type == "modem") {
1739
			if($ppp['pin-wait'] == "")
1740
				$ppp['pin-wait'] = 0;
1741
			$mpdconf .= <<<EOD
1742
	set modem var \$SimPin "{$ppp['simpin']}"
1743
	set modem var \$PinWait "{$ppp['pin-wait']}"
1744

    
1745
EOD;
1746
		}
1747
		if (isset($ppp['apn']) && $type == "modem") {
1748
			$mpdconf .= <<<EOD
1749
	set modem var \$APN "{$ppp['apn']}"
1750
	set modem var \$APNum "{$ppp['apnum']}"
1751

    
1752
EOD;
1753
		}
1754
		if ($type == "pppoe") {
1755
			// Send a null service name if none is set.
1756
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1757
			$mpdconf .= <<<EOD
1758
	set pppoe service "{$provider}"
1759

    
1760
EOD;
1761
		}
1762
		if ($type == "pppoe")
1763
			$mpdconf .= <<<EOD
1764
	set pppoe iface {$port}
1765

    
1766
EOD;
1767

    
1768
		if ($type == "pptp" || $type == "l2tp") {
1769
			$mpdconf .= <<<EOD
1770
	set {$type} self {$localips[$pid]}
1771
	set {$type} peer {$gateways[$pid]}
1772

    
1773
EOD;
1774
		}
1775

    
1776
		$mpdconf .= "\topen\n";
1777
	} //end foreach($port)
1778

    
1779

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

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

    
1810
	/* clean up old lock files */
1811
	foreach($ports as $port) {
1812
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1813
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1814
	}
1815

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

    
1820
	// Check for PPPoE periodic reset request
1821
	if ($type == "pppoe") {
1822
		if (!empty($ppp['pppoe-reset-type']))
1823
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1824
		else
1825
			interface_setup_pppoe_reset_file($ppp['if']);
1826
	}
1827
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1828
	$i = 0;
1829
	while($i < 10) {
1830
		exec("/sbin/ifconfig " . escapeshellarg($ppp['if']) . " 2>&1", $out, $ret);
1831
		if($ret == 0)
1832
			break;
1833
		sleep(1);
1834
		$i++;
1835
	}
1836

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

    
1855
	return 1;
1856
}
1857

    
1858
function interfaces_sync_setup() {
1859
	global $g, $config;
1860

    
1861
	if (isset($config['system']['developerspew'])) {
1862
		$mt = microtime();
1863
		echo "interfaces_sync_setup() being called $mt\n";
1864
	}
1865

    
1866
	if ($g['booting']) {
1867
		echo gettext("Configuring CARP settings...");
1868
		mute_kernel_msgs();
1869
	}
1870

    
1871
	/* suck in configuration items */
1872
	if ($config['hasync']) {
1873
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1874
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1875
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1876
	} else {
1877
		unset($pfsyncinterface);
1878
		unset($pfsyncenabled);
1879
	}
1880

    
1881
	set_sysctl(array(
1882
		"net.inet.carp.preempt" => "1",
1883
		"net.inet.carp.log" => "1")
1884
	);
1885

    
1886
	if (!empty($pfsyncinterface))
1887
		$carp_sync_int = get_real_interface($pfsyncinterface);
1888
	else
1889
		unset($carp_sync_int);
1890

    
1891
	/* setup pfsync interface */
1892
	if (isset($carp_sync_int) and isset($pfsyncenabled)) {
1893
		if (is_ipaddr($pfsyncpeerip))
1894
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1895
		else
1896
			$syncpeer = "-syncpeer";
1897

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

    
1900
		sleep(1);
1901

    
1902
		/* 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
1903
		 * for existing sessions.
1904
		 */
1905
		log_error("waiting for pfsync...");
1906
		$i = 0;
1907
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1908
			$i++;
1909
			sleep(1);
1910
		}
1911
		log_error("pfsync done in $i seconds.");
1912
		log_error("Configuring CARP settings finalize...");
1913
	} else {
1914
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1915
	}
1916

    
1917
	if($config['virtualip']['vip'])
1918
		set_single_sysctl("net.inet.carp.allow", "1");
1919
	else
1920
		set_single_sysctl("net.inet.carp.allow", "0");
1921

    
1922
	if ($g['booting']) {
1923
		unmute_kernel_msgs();
1924
		echo gettext("done.") . "\n";
1925
	}
1926
}
1927

    
1928
function interface_proxyarp_configure($interface = "") {
1929
	global $config, $g;
1930
	if(isset($config['system']['developerspew'])) {
1931
		$mt = microtime();
1932
		echo "interface_proxyarp_configure() being called $mt\n";
1933
	}
1934

    
1935
	/* kill any running choparp */
1936
	if (empty($interface))
1937
		killbyname("choparp");
1938
	else {
1939
		$vipif = get_real_interface($interface);
1940
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1941
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1942
	}
1943

    
1944
	$paa = array();
1945
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1946

    
1947
		/* group by interface */
1948
		foreach ($config['virtualip']['vip'] as $vipent) {
1949
			if ($vipent['mode'] === "proxyarp") {
1950
				if ($vipent['interface'])
1951
					$proxyif = $vipent['interface'];
1952
				else
1953
					$proxyif = "wan";
1954

    
1955
				if (!empty($interface) && $interface != $proxyif)
1956
					continue;
1957

    
1958
				if (!is_array($paa[$proxyif]))
1959
					$paa[$proxyif] = array();
1960

    
1961
				$paa[$proxyif][] = $vipent;
1962
			}
1963
		}
1964
	}
1965

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

    
1997
function interface_ipalias_cleanup($interface, $inet = "inet4") {
1998
	global $g, $config;
1999

    
2000
	if (is_array($config['virtualip']['vip'])) {
2001
		foreach ($config['virtualip']['vip'] as $vip) {
2002
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
2003
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
2004
					interface_vip_bring_down($vip);
2005
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
2006
					interface_vip_bring_down($vip);
2007
			}
2008
		}
2009
	}
2010
}
2011

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

    
2051
function interface_ipalias_configure(&$vip) {
2052
	global $config;
2053

    
2054
	if ($vip['mode'] != 'ipalias')
2055
		return;
2056

    
2057
	if ($vip['interface'] != 'lo0' && stripos($vip['interface'], '_vip') === false) {
2058
		if (!isset($config['interfaces'][$vip['interface']]))
2059
			return;
2060

    
2061
		if (!isset($config['interfaces'][$vip['interface']]['enable']))
2062
			return;
2063
	}
2064

    
2065
	$af = 'inet';
2066
	if(is_ipaddrv6($vip['subnet']))
2067
		$af = 'inet6';
2068
	$iface = $vip['interface'];
2069
	$vipadd = '';
2070
	if (strpos($vip['interface'], '_vip')) {
2071
		$carpvip = get_configured_carp_interface_list($vip['interface'], $af, 'vip');
2072
		$iface = $carpvip['interface'];
2073
		$vipadd = "vhid {$carpvip['vhid']}";
2074
	}
2075
	$if = get_real_interface($iface);
2076
	mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias {$vipadd}");
2077
	unset($iface, $af, $if, $carpvip, $vipadd);
2078
}
2079

    
2080
function interface_reload_carps($cif) {
2081
	global $config;
2082

    
2083
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2084
	if (empty($carpifs))
2085
		return;
2086

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

    
2109
function interface_carp_configure(&$vip) {
2110
	global $config, $g;
2111
	if(isset($config['system']['developerspew'])) {
2112
		$mt = microtime();
2113
		echo "interface_carp_configure() being called $mt\n";
2114
	}
2115

    
2116
	if ($vip['mode'] != "carp")
2117
		return;
2118

    
2119
	/* NOTE: Maybe its useless nowdays */
2120
	$realif = get_real_interface($vip['interface']);
2121
	if (!does_interface_exist($realif)) {
2122
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2123
		return;
2124
	}
2125

    
2126
	if (is_ipaddrv4($vip['subnet'])) {
2127
		/* Ensure a IP on this interface exists prior to configuring CARP. */
2128
		$ww_subnet_ip = find_interface_ip($realif);
2129
		if (!is_ipaddrv4($ww_subnet_ip)) {
2130
			file_notice("CARP", sprintf(gettext("Interface does not have required IP address in the subnet of virtual IP address %s. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2131
			return;
2132
		}
2133
	} else if (is_ipaddrv6($vip['subnet'])) {
2134
		/* Ensure a IP on this interface exists prior to configuring CARP. */
2135
		$ww_subnet_ip = find_interface_ipv6($realif);
2136
		if (!is_ipaddrv6($ww_subnet_ip)) {
2137
			file_notice("CARP", sprintf(gettext("Interface does not have required IPv6 address in the subnet of virtual IPv6 address %s. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2138
			return;
2139
		}
2140
	}
2141

    
2142
	$vip_password = $vip['password'];
2143
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2144
	if ($vip['password'] != "")
2145
		$password = " pass {$vip_password}";
2146

    
2147
	$advbase = "";
2148
	if (!empty($vip['advbase']))
2149
		$advbase = "advbase " . escapeshellarg($vip['advbase']);
2150

    
2151
	$carp_maintenancemode = isset($config["virtualip_carp_maintenancemode"]);
2152
	if ($carp_maintenancemode)
2153
		$advskew = "advskew 254";
2154
	else
2155
		$advskew = "advskew " . escapeshellarg($vip['advskew']);
2156
	
2157
	mwexec("/sbin/ifconfig {$realif} vhid " . escapeshellarg($vip['vhid']) . " {$advskew} {$advbase} {$password}");
2158

    
2159
	if (is_ipaddrv4($vip['subnet']))
2160
		mwexec("/sbin/ifconfig {$realif} " . escapeshellarg($vip['subnet']) . "/" . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2161
	else if (is_ipaddrv6($vip['subnet']))
2162
		mwexec("/sbin/ifconfig {$realif} inet6 " . escapeshellarg($vip['subnet']) . " prefixlen " . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2163

    
2164
	return $realif;
2165
}
2166

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

    
2208
	if($needs_clone == true) {
2209
		/* remove previous instance if it exists */
2210
		if(does_interface_exist($realif))
2211
			pfSense_interface_destroy($realif);
2212

    
2213
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2214
		// Create the new wlan interface. FreeBSD returns the new interface name.
2215
		// example:  wlan2
2216
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2217
		if($ret <> 0) {
2218
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2219
			return false;
2220
		}
2221
		$newif = trim($out[0]);
2222
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2223
		pfSense_interface_rename($newif, $realif);
2224
		// FIXME: not sure what ngctl is for. Doesn't work.
2225
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2226
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2227
	}
2228
	return true;
2229
}
2230

    
2231
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2232
	global $config, $g;
2233

    
2234
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2235
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2236
				 'regdomain', 'regcountry', 'reglocation');
2237

    
2238
	if(!is_interface_wireless($ifcfg['if']))
2239
		return;
2240

    
2241
	$baseif = interface_get_wireless_base($ifcfg['if']);
2242

    
2243
	// Sync shared settings for assigned clones
2244
	$iflist = get_configured_interface_list(false, true);
2245
	foreach ($iflist as $if) {
2246
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2247
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2248
				foreach ($shared_settings as $setting) {
2249
					if ($sync_changes) {
2250
						if (isset($ifcfg['wireless'][$setting]))
2251
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2252
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2253
							unset($config['interfaces'][$if]['wireless'][$setting]);
2254
					} else {
2255
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2256
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2257
						else if (isset($ifcfg['wireless'][$setting]))
2258
							unset($ifcfg['wireless'][$setting]);
2259
					}
2260
				}
2261
				if (!$sync_changes)
2262
					break;
2263
			}
2264
		}
2265
	}
2266

    
2267
	// Read or write settings at shared area
2268
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2269
		foreach ($shared_settings as $setting) {
2270
			if ($sync_changes) {
2271
				if (isset($ifcfg['wireless'][$setting]))
2272
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2273
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2274
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2275
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2276
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2277
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2278
				else if (isset($ifcfg['wireless'][$setting]))
2279
					unset($ifcfg['wireless'][$setting]);
2280
			}
2281
		}
2282
	}
2283

    
2284
	// Sync the mode on the clone creation page with the configured mode on the interface
2285
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2286
		foreach ($config['wireless']['clone'] as &$clone) {
2287
			if ($clone['cloneif'] == $ifcfg['if']) {
2288
				if ($sync_changes) {
2289
					$clone['mode'] = $ifcfg['wireless']['mode'];
2290
				} else {
2291
					$ifcfg['wireless']['mode'] = $clone['mode'];
2292
				}
2293
				break;
2294
			}
2295
		}
2296
		unset($clone);
2297
	}
2298
}
2299

    
2300
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2301
	global $config, $g;
2302

    
2303
	/*    open up a shell script that will be used to output the commands.
2304
	 *    since wireless is changing a lot, these series of commands are fragile
2305
	 *    and will sometimes need to be verified by a operator by executing the command
2306
	 *    and returning the output of the command to the developers for inspection.  please
2307
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2308
	 */
2309

    
2310
	// Remove script file
2311
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2312

    
2313
	// Clone wireless nic if needed.
2314
	interface_wireless_clone($if, $wl);
2315

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

    
2319
	$fd_set = fopen("{$g['tmp_path']}/{$if}_setup.sh","w");
2320
	fwrite($fd_set, "#!/bin/sh\n");
2321
	fwrite($fd_set, "# {$g['product_name']} wireless configuration script.\n\n");
2322

    
2323
	/* set values for /path/program */
2324
	$hostapd = "/usr/sbin/hostapd";
2325
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2326
	$ifconfig = "/sbin/ifconfig";
2327
	$sysctl = "/sbin/sysctl";
2328
	$killall = "/usr/bin/killall";
2329

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

    
2332
	$wlcmd = array();
2333
	$wl_sysctl = array();
2334
	/* Make sure it's up */
2335
	$wlcmd[] = "up";
2336
	/* Set a/b/g standard */
2337
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2338
	$wlcmd[] = "mode " . escapeshellarg($standard);
2339

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

    
2345
	/* Set ssid */
2346
	if($wlcfg['ssid'])
2347
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2348

    
2349
	/* Set 802.11g protection mode */
2350
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2351

    
2352
	/* set wireless channel value */
2353
	if(isset($wlcfg['channel'])) {
2354
		if($wlcfg['channel'] == "0") {
2355
			$wlcmd[] = "channel any";
2356
		} else {
2357
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2358
		}
2359
	}
2360

    
2361
	/* Set antenna diversity value */
2362
	if(isset($wlcfg['diversity']))
2363
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2364

    
2365
	/* Set txantenna value */
2366
	if(isset($wlcfg['txantenna']))
2367
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2368

    
2369
	/* Set rxantenna value */
2370
	if(isset($wlcfg['rxantenna']))
2371
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2372

    
2373
	/* set Distance value */
2374
	if($wlcfg['distance'])
2375
		$distance = escapeshellarg($wlcfg['distance']);
2376

    
2377
	/* Set wireless hostap mode */
2378
	if ($wlcfg['mode'] == "hostap") {
2379
		$wlcmd[] = "mediaopt hostap";
2380
	} else {
2381
		$wlcmd[] = "-mediaopt hostap";
2382
	}
2383

    
2384
	/* Set wireless adhoc mode */
2385
	if ($wlcfg['mode'] == "adhoc") {
2386
		$wlcmd[] = "mediaopt adhoc";
2387
	} else {
2388
		$wlcmd[] = "-mediaopt adhoc";
2389
	}
2390

    
2391
	/* Not neccesary to set BSS mode as this is default if adhoc and/or hostap is NOT set */
2392

    
2393
	/* handle hide ssid option */
2394
	if(isset($wlcfg['hidessid']['enable'])) {
2395
		$wlcmd[] = "hidessid";
2396
	} else {
2397
		$wlcmd[] = "-hidessid";
2398
	}
2399

    
2400
	/* handle pureg (802.11g) only option */
2401
	if(isset($wlcfg['pureg']['enable'])) {
2402
		$wlcmd[] = "mode 11g pureg";
2403
	} else {
2404
		$wlcmd[] = "-pureg";
2405
	}
2406

    
2407
	/* handle puren (802.11n) only option */
2408
	if(isset($wlcfg['puren']['enable'])) {
2409
		$wlcmd[] = "puren";
2410
	} else {
2411
		$wlcmd[] = "-puren";
2412
	}
2413

    
2414
	/* enable apbridge option */
2415
	if(isset($wlcfg['apbridge']['enable'])) {
2416
		$wlcmd[] = "apbridge";
2417
	} else {
2418
		$wlcmd[] = "-apbridge";
2419
	}
2420

    
2421
	/* handle turbo option */
2422
	if(isset($wlcfg['turbo']['enable'])) {
2423
		$wlcmd[] = "mediaopt turbo";
2424
	} else {
2425
		$wlcmd[] = "-mediaopt turbo";
2426
	}
2427

    
2428
	/* handle txpower setting */
2429
	/* if($wlcfg['txpower'] <> "")
2430
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2431
	*/
2432
	/* handle wme option */
2433
	if(isset($wlcfg['wme']['enable'])) {
2434
		$wlcmd[] = "wme";
2435
	} else {
2436
		$wlcmd[] = "-wme";
2437
	}
2438

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

    
2465
	kill_hostapd($if);
2466
	mwexec(kill_wpasupplicant("{$if}"));
2467

    
2468
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2469
	conf_mount_rw();
2470

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

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

    
2524
EOD;
2525

    
2526
			if (isset($wlcfg['wpa']['rsn_preauth'])) {
2527
				$wpa .= <<<EOD
2528
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2529
rsn_preauth=1
2530
rsn_preauth_interfaces={$if}
2531

    
2532
EOD;
2533
			}
2534
			if (is_array($wlcfg['wpa']['ieee8021x']) && isset($wlcfg['wpa']['ieee8021x']['enable'])) {
2535
				$wpa .= "ieee8021x=1\n";
2536

    
2537
			if (!empty($wlcfg['auth_server_addr']) && !empty($wlcfg['auth_server_shared_secret'])) {
2538
				$auth_server_port = "1812";
2539
				if (!empty($wlcfg['auth_server_port']) && is_numeric($wlcfg['auth_server_port']))
2540
					$auth_server_port = intval($wlcfg['auth_server_port']);
2541
				$wpa .= <<<EOD
2542

    
2543
auth_server_addr={$wlcfg['auth_server_addr']}
2544
auth_server_port={$auth_server_port}
2545
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2546

    
2547
EOD;
2548
				if (!empty($wlcfg['auth_server_addr2']) && !empty($wlcfg['auth_server_shared_secret2'])) {
2549
					$auth_server_port2 = "1812";
2550
					if (!empty($wlcfg['auth_server_port2']) && is_numeric($wlcfg['auth_server_port2']))
2551
						$auth_server_port2 = intval($wlcfg['auth_server_port2']);
2552

    
2553
					$wpa .= <<<EOD
2554
auth_server_addr={$wlcfg['auth_server_addr2']}
2555
auth_server_port={$auth_server_port2}
2556
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2557

    
2558
EOD;
2559
					}
2560
				}
2561
			}
2562

    
2563
			@file_put_contents("{$g['varetc_path']}/hostapd_{$if}.conf", $wpa);
2564
			unset($wpa);
2565
		}
2566
		break;
2567
	}
2568

    
2569
	/*
2570
	 *    all variables are set, lets start up everything
2571
	 */
2572

    
2573
	$baseif = interface_get_wireless_base($if);
2574
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2575
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2576

    
2577
	/* set sysctls for the wireless interface */
2578
	if (!empty($wl_sysctl)) {
2579
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2580
		foreach ($wl_sysctl as $wl_sysctl_line) {
2581
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2582
		}
2583
	}
2584

    
2585
	/* set ack timers according to users preference (if he/she has any) */
2586
	if($distance) {
2587
		fwrite($fd_set, "# Enable ATH distance settings\n");
2588
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2589
	}
2590

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

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

    
2606
			/* add line to script to restore spoofed mac after running hostapd */
2607
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2608
				if ($wl['spoofmac'])
2609
					$if_curmac = $wl['spoofmac'];
2610
				else
2611
					$if_curmac = get_interface_mac($if);
2612
				if (is_macaddr($if_curmac))
2613
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2614
						" link " . escapeshellarg($if_curmac) . "\n");
2615
			}
2616
		}
2617
	}
2618

    
2619
	fclose($fd_set);
2620
	conf_mount_ro();
2621

    
2622
	/* Making sure regulatory settings have actually changed
2623
	 * before applying, because changing them requires bringing
2624
	 * down all wireless networks on the interface. */
2625
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2626
	$ifconfig_str = implode($output);
2627
	unset($output);
2628
	$reg_changing = false;
2629

    
2630
	/* special case for the debug country code */
2631
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2632
		$reg_changing = true;
2633
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2634
		$reg_changing = true;
2635
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2636
		$reg_changing = true;
2637
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2638
		$reg_changing = true;
2639
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2640
		$reg_changing = true;
2641

    
2642
	if ($reg_changing) {
2643
		/* set regulatory domain */
2644
		if($wlcfg['regdomain'])
2645
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2646

    
2647
		/* set country */
2648
		if($wlcfg['regcountry'])
2649
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2650

    
2651
		/* set location */
2652
		if($wlcfg['reglocation'])
2653
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2654

    
2655
		$wlregcmd_args = implode(" ", $wlregcmd);
2656

    
2657
		/* build a complete list of the wireless clones for this interface */
2658
		$clone_list = array();
2659
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2660
			$clone_list[] = interface_get_wireless_clone($baseif);
2661
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2662
			foreach ($config['wireless']['clone'] as $clone) {
2663
				if ($clone['if'] == $baseif)
2664
					$clone_list[] = $clone['cloneif'];
2665
			}
2666
		}
2667

    
2668
		/* find which clones are up and bring them down */
2669
		$clones_up = array();
2670
		foreach ($clone_list as $clone_if) {
2671
			$clone_status = pfSense_get_interface_addresses($clone_if);
2672
			if ($clone_status['status'] == 'up') {
2673
				$clones_up[] = $clone_if;
2674
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2675
			}
2676
		}
2677

    
2678
		/* apply the regulatory settings */
2679
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2680

    
2681
		/* bring the clones back up that were previously up */
2682
		foreach ($clones_up as $clone_if) {
2683
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2684

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

    
2701
	/* The mode must be specified in a separate command before ifconfig
2702
	 * will allow the mode and channel at the same time in the next. */
2703
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " mode " . escapeshellarg($standard));
2704

    
2705
	/* configure wireless */
2706
	$wlcmd_args = implode(" ", $wlcmd);
2707
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $wlcmd_args, false);
2708
	unset($wlcmd_args, $wlcmd);
2709

    
2710

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

    
2715
	return 0;
2716

    
2717
}
2718

    
2719
function kill_hostapd($interface) {
2720
	global $g;
2721

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

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

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

    
2736
	return intval($pid);
2737
}
2738

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

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

    
2754
function find_dhcp6c_process($interface) {
2755
	global $g;
2756

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

    
2762
	return intval($pid);
2763
}
2764

    
2765
function interface_vlan_mtu_configured($realhwif, $mtu) {
2766
	global $config;
2767

    
2768
	if (is_array($config['vlans']) && is_array($config['vlans']['vlan'])) {
2769
		foreach ($config['vlans']['vlan'] as $vlan) {
2770
			if ($vlan['if'] != $realhwif)
2771
				continue;
2772
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2773
			if (!empty($assignedport) && !empty($config['interfaces'][$assignedport]['mtu'])) {
2774
				if (intval($config['interfaces'][$assignedport]['mtu']) > $mtu)
2775
					$mtu = $portmtu;
2776
			}
2777
		}
2778
	}
2779

    
2780
	return $mtu;
2781
}
2782

    
2783
function interface_virtual_create($interface) {
2784
	global $config;
2785

    
2786
	if (strstr($interface, "_vlan")) {
2787
		interfaces_vlan_configure($vlan);
2788
	} else if (substr($interface, 0, 3) == "gre") {
2789
		interfaces_gre_configure(0, $interface);
2790
	} else if (substr($interface, 0, 3) == "gif") {
2791
		interfaces_gif_configure(0, $interface);
2792
	} else if (substr($interface, 0, 5) == "ovpns") {
2793
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-server'])) {
2794
			foreach ($config['openvpn']['openvpn-server'] as $server) {
2795
				if ($interface == "ovpns{$server['vpnid']}") {
2796
					if (!function_exists('openvpn_resync'))
2797
						require_once('openvpn.inc');
2798
					log_error("OpenVPN: Resync server {$server['description']}");
2799
					openvpn_resync('server', $server);
2800
				}
2801
			}
2802
			unset($server);
2803
		}
2804
	} else if (substr($interface, 0, 5) == "ovpnc") {
2805
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-client'])) {
2806
			foreach ($config['openvpn']['openvpn-client'] as $client) {
2807
				if ($interface == "ovpnc{$client['vpnid']}") {
2808
					if (!function_exists('openvpn_resync'))
2809
						require_once('openvpn.inc');
2810
					log_error("OpenVPN: Resync server {$client['description']}");
2811
					openvpn_resync('client', $client);
2812
				}
2813
			}
2814
			unset($client);
2815
		}
2816
	} else if (substr($interface, 0, 4) == "lagg") {
2817
		interfaces_lagg_configure($interface);
2818
	} else if (substr($interface, 0, 6) == "bridge") {
2819
		interfaces_bridge_configure(0, $interface);
2820
	}
2821
}
2822

    
2823
function interface_vlan_adapt_mtu($vlanifs, $mtu) {
2824
	global $config;
2825

    
2826
	if (!is_array($vlanifs))
2827
		return;
2828

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

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

    
2849
	$wancfg = $config['interfaces'][$interface];
2850

    
2851
	if (!isset($wancfg['enable']))
2852
		return;
2853

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

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

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

    
2883
	$interface_to_check = $realif;
2884
	switch ($wancfg['ipaddr']) {
2885
	case 'pppoe':
2886
	case 'l2tp':
2887
	case 'pptp':
2888
	case 'ppp':
2889
		$interface_to_check = $realhwif;
2890
		break;
2891
	}
2892

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

    
2897
	/* Disable Accepting router advertisements unless specifically requested */
2898
	if ($g['debug'])
2899
		log_error("Deny router advertisements for interface {$interface}");
2900
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2901

    
2902
	/* wireless configuration? */
2903
	if (is_array($wancfg['wireless']))
2904
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2905

    
2906
	$mac = get_interface_mac($realhwif);
2907
	/*
2908
	 * Don't try to reapply the spoofed MAC if it's already applied.
2909
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2910
	 * the interface config again, which attempts to spoof the MAC again,
2911
	 * which cycles the link again...
2912
	 */
2913
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2914
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2915
			" link " . escapeshellarg($wancfg['spoofmac']));
2916
	}  else {
2917

    
2918
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2919
			/*   this is not a valid mac address.  generate a
2920
			 *   temporary mac address so the machine can get online.
2921
			 */
2922
			echo gettext("Generating new MAC address.");
2923
			$random_mac = generate_random_mac_address();
2924
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2925
				" link " . escapeshellarg($random_mac));
2926
			$wancfg['spoofmac'] = $random_mac;
2927
			write_config();
2928
			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");
2929
		}
2930
	}
2931

    
2932
	/* media */
2933
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2934
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2935
		if ($wancfg['media'])
2936
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2937
		if ($wancfg['mediaopt'])
2938
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2939
		mwexec($cmd);
2940
	}
2941

    
2942
	/* Apply hw offloading policies as configured */
2943
	enable_hardware_offloading($interface);
2944

    
2945
	/* invaldate interface/ip/sn cache */
2946
	get_interface_arr(true);
2947
	unset($interface_ip_arr_cache[$realif]);
2948
	unset($interface_sn_arr_cache[$realif]);
2949
	unset($interface_ipv6_arr_cache[$realif]);
2950
	unset($interface_snv6_arr_cache[$realif]);
2951

    
2952
	$tunnelif = substr($realif, 0, 3);
2953
	switch ($wancfg['ipaddr']) {
2954
	case 'dhcp':
2955
		interface_dhcp_configure($interface);
2956
		break;
2957
	case 'pppoe':
2958
	case 'l2tp':
2959
	case 'pptp':
2960
	case 'ppp':
2961
		interface_ppps_configure($interface);
2962
		break;
2963
	default:
2964
		/* XXX: Kludge for now related to #3280 */
2965
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
2966
			if (is_ipaddrv4($wancfg['ipaddr']) && $wancfg['subnet'] <> "")
2967
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2968
		}
2969
		break;
2970
	}
2971

    
2972
	switch ($wancfg['ipaddrv6']) {
2973
	case 'slaac':
2974
	case 'dhcp6':
2975
		interface_dhcpv6_configure($interface, $wancfg);
2976
		break;
2977
	case '6rd':
2978
		interface_6rd_configure($interface, $wancfg);
2979
		break;
2980
	case '6to4':
2981
		interface_6to4_configure($interface, $wancfg);
2982
		break;
2983
	case 'track6':
2984
		interface_track6_configure($interface, $wancfg, $linkupevent);
2985
		break;
2986
	default:
2987
		/* XXX: Kludge for now related to #3280 */
2988
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
2989
			if (is_ipaddrv6($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2990
				//pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2991
				// FIXME: Add IPv6 Support to the pfSense module
2992
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$wancfg['ipaddrv6']} prefixlen " . escapeshellarg($wancfg['subnetv6']));
2993
			}
2994
		}
2995
		break;
2996
	}
2997

    
2998
	if (!empty($wancfg['mtu'])) {
2999
		if (stristr($realif, "_vlan")) {
3000
			$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
3001
			if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
3002
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
3003
			else {
3004
				$parentmtu = get_interface_mtu($realhwif);
3005
				$parentmtu = interface_vlan_mtu_configured($realhwif, $parentmtu);
3006
			}
3007

    
3008
			if ($wancfg['mtu'] > $parentmtu) {
3009
				if (get_interface_mtu($realhwif) != $wancfg['mtu'])
3010
					pfSense_interface_mtu($realhwif, $wancfg['mtu']);
3011

    
3012
				/* All vlans need to use the same mtu value as their parent. */
3013
				interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $wancfg['mtu']);
3014
			} else
3015
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3016
		} else if (substr($realif, 0, 4) == 'lagg') {
3017
			/* LAGG interface must be destroyed and re-created to change MTU */
3018
			if ($wancfg['mtu'] != get_interface_mtu($realif)) {
3019
				if (isset($config['laggs']['lagg']) && is_array($config['laggs']['lagg'])) {
3020
					foreach ($config['laggs']['lagg'] as $lagg) {
3021
						if ($lagg['laggif'] == $realif) {
3022
							interface_lagg_configure($lagg);
3023
							break;
3024
						}
3025
					}
3026
				}
3027
			}
3028
		} else {
3029
			if ($wancfg['mtu'] != get_interface_mtu($realif))
3030
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3031

    
3032
			/* This case is needed when the parent of vlans is being configured */
3033
			interface_vlan_adapt_mtu(link_interface_to_vlans($realif), $wancfg['mtu']);
3034
		}
3035
		/* XXX: What about gre/gif/.. ? */
3036
	}
3037

    
3038
	if (does_interface_exist($wancfg['if']))
3039
		interfaces_bring_up($wancfg['if']);
3040

    
3041
	interface_netgraph_needed($interface);
3042

    
3043
	if (!$g['booting']) {
3044
		link_interface_to_vips($interface, "update");
3045

    
3046
		unset($gre);
3047
		$gre = link_interface_to_gre($interface);
3048
		if (!empty($gre))
3049
			array_walk($gre, 'interface_gre_configure');
3050

    
3051
		unset($gif);
3052
		$gif = link_interface_to_gif($interface);
3053
		if (!empty($gif))
3054
			array_walk($gif, 'interface_gif_configure');
3055

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

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

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

    
3071
		if ($reloadall == true) {
3072

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

    
3076
			/* reload ipsec tunnels */
3077
			vpn_ipsec_configure();
3078

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

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

    
3088
			/* XXX: which CPZONE? Needed? */
3089
			/* reload captive portal */
3090
			captiveportal_init_rules();
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 intead 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 autmagically 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 (!$g['booting'] && $linkupevent == false) {
3154
		if (!function_exists('services_dhcpd_configure'))
3155
			require_once("services.inc");
3156

    
3157
		services_dhcpd_configure("inet6");
3158
	}
3159

    
3160
	return 0;
3161
}
3162

    
3163
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3164
	global $config, $g;
3165
	global $interface_ipv6_arr_cache;
3166
	global $interface_snv6_arr_cache;
3167

    
3168
	if (!is_array($lancfg))
3169
		return;
3170

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

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

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

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

    
3193
	/* binary presentation of the prefix for all 128 bits. */
3194
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3195

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

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

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

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

    
3221
	return 0;
3222
}
3223

    
3224
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3225
	global $config, $g;
3226
	global $interface_ipv6_arr_cache;
3227
	global $interface_snv6_arr_cache;
3228

    
3229
	if (!is_array($lancfg))
3230
		return;
3231

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

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

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

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

    
3254
	/* binary presentation of the prefix for all 128 bits. */
3255
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3256

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

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

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

    
3278
	return 0;
3279
}
3280

    
3281
function interface_6rd_configure($interface = "wan", $wancfg) {
3282
	global $config, $g;
3283

    
3284
	/* because this is a tunnel interface we can only function
3285
	 *	with a public IPv4 address on the interface */
3286

    
3287
	if (!is_array($wancfg))
3288
		return;
3289

    
3290
	if (!is_module_loaded('if_stf.ko'))
3291
		mwexec('/sbin/kldload if_stf.ko');
3292

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

    
3301
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3302
		$wancfg['prefix-6rd-v4plen'] = 0;
3303

    
3304
	/* create the long prefix notation for math, save the prefix length */
3305
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3306
	$rd6prefixlen = $rd6prefix[1];
3307
	$brgw = explode('.', $wancfg['gateway-6rd']);
3308
	$rd6brgw = rtrim($rd6prefix[0], ':') . ':' . dechex($brgw[0]) . dechex($brgw[1]) . ':' . dechex($brgw[2]) . dechex($brgw[3]) . '::';
3309
	unset($brgw);
3310
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3311

    
3312
	/* binary presentation of the prefix for all 128 bits. */
3313
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3314

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

    
3322
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3323
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3324

    
3325

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

    
3342
	/* write out a default router file */
3343
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3344
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3345

    
3346
	$ip4gateway = get_interface_gateway($interface);
3347
	if (is_ipaddrv4($ip4gateway))
3348
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3349

    
3350
	/* configure dependent interfaces */
3351
	if (!$g['booting'])
3352
		link_interface_to_track6($interface, "update");
3353

    
3354
	return 0;
3355
}
3356

    
3357
function interface_6to4_configure($interface = "wan", $wancfg){
3358
	global $config, $g;
3359

    
3360
	/* because this is a tunnel interface we can only function
3361
	 *	with a public IPv4 address on the interface */
3362

    
3363
	if (!is_array($wancfg))
3364
		return;
3365

    
3366
	$wanif = get_real_interface($interface);
3367
	$ip4address = find_interface_ip($wanif);
3368
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3369
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3370
		return false;
3371
	}
3372

    
3373
	/* create the long prefix notation for math, save the prefix length */
3374
	$stfprefixlen = 16;
3375
	$stfprefix = Net_IPv6::uncompress("2002::");
3376
	$stfarr = explode(":", $stfprefix);
3377
	$v4prefixlen = "0";
3378

    
3379
	/* we need the hex form of the interface IPv4 address */
3380
	$ip4arr = explode(".", $ip4address);
3381
	$hexwanv4 = "";
3382
	foreach($ip4arr as $octet)
3383
		$hexwanv4 .= sprintf("%02x", $octet);
3384

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

    
3391
	/* binary presentation of the prefix for all 128 bits. */
3392
	$stfprefixbin = "";
3393
	foreach($stfarr as $element) {
3394
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3395
	}
3396
	/* just save the left prefix length bits */
3397
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3398

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

    
3403
	/* for the local subnet too. */
3404
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3405
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);
3406

    
3407
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3408
	$stfbrarr = array();
3409
	$stfbrbinarr = array();
3410
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3411
	foreach($stfbrbinarr as $bin)
3412
		$stfbrarr[] = dechex(bindec($bin));
3413
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3414

    
3415
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3416
	$stflanarr = array();
3417
	$stflanbinarr = array();
3418
	$stflanbinarr = str_split($stflanbin, 16);
3419
	foreach($stflanbinarr as $bin)
3420
		$stflanarr[] = dechex(bindec($bin));
3421
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3422
	$stflanarr[7] = 1;
3423
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3424

    
3425
	/* setup the stf interface */
3426
	if (!is_module_loaded("if_stf"))
3427
		mwexec("/sbin/kldload if_stf.ko");
3428
	$stfiface = "{$interface}_stf";
3429
	if (does_interface_exist($stfiface))
3430
		pfSense_interface_destroy($stfiface);
3431
	$tmpstfiface = pfSense_interface_create("stf");
3432
	pfSense_interface_rename($tmpstfiface, $stfiface);
3433
	pfSense_interface_flags($stfiface, IFF_LINK2);
3434
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3435

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

    
3439
	/* write out a default router file */
3440
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3441
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3442

    
3443
	$ip4gateway = get_interface_gateway($interface);
3444
	if (is_ipaddrv4($ip4gateway))
3445
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3446

    
3447
	if (!$g['booting'])
3448
		link_interface_to_track6($interface, "update");
3449

    
3450
	return 0;
3451
}
3452

    
3453
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3454
	global $config, $g;
3455

    
3456
	if (!is_array($wancfg))
3457
		return;
3458

    
3459
	$wanif = get_real_interface($interface, "inet6");
3460
	$dhcp6cconf = "";
3461
	$dhcp6cconf .= "interface {$wanif} {\n";
3462

    
3463
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3464
	if($wancfg['ipaddrv6'] == "slaac") {
3465
		$dhcp6cconf .= "	information-only;\n";
3466
		$dhcp6cconf .= "	request domain-name-servers;\n";
3467
		$dhcp6cconf .= "	request domain-name;\n";
3468
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3469
		$dhcp6cconf .= "};\n";
3470
	} else {
3471
		/* skip address request if this is set */
3472
		if(!isset($wancfg['dhcp6prefixonly']))
3473
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3474
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3475
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3476

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

    
3481
		$dhcp6cconf .= "};\n";
3482

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

    
3486
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3487
			/* Setup the prefix delegation */
3488
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3489
			$preflen = 64 - $wancfg['dhcp6-ia-pd-len'];
3490
			if (isset($wancfg['dhcp6-ia-pd-send-hint']))
3491
				$dhcp6cconf .= "	prefix ::/{$preflen} infinity;\n";
3492
			$iflist = link_interface_to_track6($interface);
3493
			foreach ($iflist as $friendly => $ifcfg) {
3494
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3495
					if ($g['debug'])
3496
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3497
					$realif = get_real_interface($friendly);
3498
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3499
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3500
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3501
					$dhcp6cconf .= "	};\n";
3502
				}
3503
			}
3504
			unset($preflen, $iflist, $ifcfg);
3505
			$dhcp6cconf .= "};\n";
3506
		}
3507
	}
3508

    
3509
	// DHCP6 Config File Advanced
3510
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3511

    
3512
	// DHCP6 Config File Override
3513
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3514

    
3515
	/* wide-dhcp6c works for now. */
3516
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3517
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3518
		unset($dhcp6cconf);
3519
		return 1;
3520
	}
3521
	unset($dhcp6cconf);
3522

    
3523
	$dhcp6cscript = "#!/bin/sh\n";
3524
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3525
	$dhcp6cscript .= "dmips=\${new_domain_name_servers}\n";
3526
	$dhcp6cscript .= "dmnames=\${new_domain_name}\n";
3527
	$dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
3528
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3529
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3530
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3531
		unset($dhcp6cscript);
3532
		return 1;
3533
	}
3534
	unset($dhcp6cscript);
3535
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3536

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

    
3557
	/* accept router advertisements for this interface */
3558
	set_single_sysctl("net.inet6.ip6.accept_rtadv", "1");
3559
	log_error("Accept router advertisements on interface {$wanif} ");
3560
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3561

    
3562
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3563
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3564
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3565
		sleep(2);
3566
	}
3567
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3568

    
3569
	/* NOTE: will be called from rtsold invoked script
3570
	 * link_interface_to_track6($interface, "update");
3571
	 */
3572

    
3573
	return 0;
3574
}
3575

    
3576
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3577
	global $g;
3578

    
3579
	$send_options = "";
3580
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3581
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_send_options']);
3582
		foreach ($options as $option) {
3583
			$send_options .= "\tsend " . trim($option) . ";\n";
3584
		}
3585
	}
3586

    
3587
	$request_options = "";
3588
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3589
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_request_options']);
3590
		foreach ($options as $option) {
3591
			$request_options .= "\trequest " . trim($option) . ";\n";
3592
		}
3593
	}
3594

    
3595
	$information_only = "";
3596
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3597
		$information_only = "\tinformation-only;\n";
3598

    
3599
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3600
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3601
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3602

    
3603
	$interface_statement  = "interface";
3604
	$interface_statement .= " {$wanif}";
3605
	$interface_statement .= " {\n";
3606
	$interface_statement .= "$send_options";
3607
	$interface_statement .= "$request_options";
3608
	$interface_statement .= "$information_only";
3609
	$interface_statement .= "$script";
3610
	$interface_statement .= "};\n";
3611

    
3612
	$id_assoc_statement_address = "";
3613
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3614
		$id_assoc_statement_address .= "id-assoc";
3615
		$id_assoc_statement_address .= " na";
3616
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3617
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3618
		$id_assoc_statement_address .= " { ";
3619

    
3620
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3621
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3622
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3623
			$id_assoc_statement_address .= "\n\taddress";
3624
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3625
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3626
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3627
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3628
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3629
			$id_assoc_statement_address .= ";\n";
3630
		}
3631

    
3632
		$id_assoc_statement_address  .= "};\n";
3633
	}
3634

    
3635
	$id_assoc_statement_prefix = "";
3636
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3637
		$id_assoc_statement_prefix .= "id-assoc";
3638
		$id_assoc_statement_prefix .= " pd";
3639
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3640
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3641
		$id_assoc_statement_prefix .= " { ";
3642

    
3643
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3644
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3645
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3646
			$id_assoc_statement_prefix .= "\n\tprefix";
3647
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3648
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3649
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3650
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3651
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3652
			$id_assoc_statement_prefix .= ";";
3653
		}
3654

    
3655
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3656
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3657
			$id_assoc_statement_prefix .= " {$wanif}";
3658
			$id_assoc_statement_prefix .= " {\n";
3659
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3660
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3661
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3662
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3663
			$id_assoc_statement_prefix .= "\t};";
3664
		}
3665

    
3666
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3667
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3668
			$id_assoc_statement_prefix .= "\n";
3669
		}
3670

    
3671
		$id_assoc_statement_prefix  .= "};\n";
3672
	}
3673

    
3674
	$authentication_statement = "";
3675
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3676
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3677
		$authentication_statement .= "authentication";
3678
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3679
		$authentication_statement .= " {\n";
3680
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3681
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3682
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3683
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3684
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3685
		$authentication_statement .= "};\n";
3686
	}
3687

    
3688
	$key_info_statement = "";
3689
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3690
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3691
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3692
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3693
		$key_info_statement .= "keyinfo";
3694
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3695
		$key_info_statement .= " {\n";
3696
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3697
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3698
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3699
		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'])) 
3700
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3701
		$key_info_statement .= "};\n";
3702
	}
3703

    
3704
	$dhcp6cconf  = $interface_statement;
3705
	$dhcp6cconf .= $id_assoc_statement_address;
3706
	$dhcp6cconf .= $id_assoc_statement_prefix;
3707
	$dhcp6cconf .= $authentication_statement;
3708
	$dhcp6cconf .= $key_info_statement;
3709

    
3710
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3711

    
3712
	return $dhcp6cconf;
3713
}
3714

    
3715

    
3716
function DHCP6_Config_File_Override($wancfg, $wanif) {
3717

    
3718
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3719
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3720

    
3721
	return $dhcp6cconf;
3722
}
3723

    
3724

    
3725
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3726

    
3727
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3728

    
3729
	return $dhcp6cconf;
3730
}
3731

    
3732

    
3733
function interface_dhcp_configure($interface = "wan") {
3734
	global $config, $g;
3735

    
3736
	$wancfg = $config['interfaces'][$interface];
3737
	$wanif = $wancfg['if'];
3738
	if (empty($wancfg))
3739
		$wancfg = array();
3740

    
3741
	/* generate dhclient_wan.conf */
3742
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3743
	if (!$fd) {
3744
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3745
		return 1;
3746
	}
3747

    
3748
	if ($wancfg['dhcphostname']) {
3749
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3750
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3751
	} else {
3752
		$dhclientconf_hostname = "";
3753
	}
3754

    
3755
	$wanif = get_real_interface($interface);
3756
	if (empty($wanif)) {
3757
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3758
		return 0;
3759
	}
3760
	$dhclientconf = "";
3761

    
3762
	$dhclientconf .= <<<EOD
3763
interface "{$wanif}" {
3764
timeout 60;
3765
retry 15;
3766
select-timeout 0;
3767
initial-interval 1;
3768
	{$dhclientconf_hostname}
3769
	script "/sbin/dhclient-script";
3770
EOD;
3771

    
3772
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3773
	$dhclientconf .= <<<EOD
3774

    
3775
	reject {$wancfg['dhcprejectfrom']};
3776
EOD;
3777
}
3778
	$dhclientconf .= <<<EOD
3779

    
3780
}
3781

    
3782
EOD;
3783

    
3784
	// DHCP Config File Advanced
3785
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3786

    
3787
if(is_ipaddr($wancfg['alias-address'])) {
3788
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3789
	$dhclientconf .= <<<EOD
3790
alias {
3791
	interface  "{$wanif}";
3792
	fixed-address {$wancfg['alias-address']};
3793
	option subnet-mask {$subnetmask};
3794
}
3795

    
3796
EOD;
3797
}
3798

    
3799
	// DHCP Config File Override
3800
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3801

    
3802
	fwrite($fd, $dhclientconf);
3803
	fclose($fd);
3804

    
3805
	/* bring wan interface up before starting dhclient */
3806
	if($wanif)
3807
		interfaces_bring_up($wanif);
3808
	else
3809
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3810

    
3811
	/* Make sure dhclient is not running */
3812
	kill_dhclient_process($wanif);
3813

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

    
3817
	return 0;
3818
}
3819

    
3820
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3821

    
3822
	$hostname = "";
3823
	if ($wancfg['dhcphostname'] != '') {
3824
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3825
	}
3826

    
3827
	/* DHCP Protocol Timings */
3828
	$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");
3829
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3830
		$pt_variable = "{$Protocol_Timing}";
3831
		${$pt_variable} = "";
3832
		if ($wancfg[$Protocol_Timing] != "") {
3833
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3834
		}
3835
	}
3836

    
3837
	$send_options = "";
3838
	if ($wancfg['adv_dhcp_send_options'] != '') {
3839
		$options = split(",", $wancfg['adv_dhcp_send_options']);
3840
		foreach ($options as $option) {
3841
			$send_options .= "\tsend " . trim($option) . ";\n";
3842
		}
3843
	}
3844

    
3845
	$request_options = "";
3846
	if ($wancfg['adv_dhcp_request_options'] != '') {
3847
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3848
	}
3849

    
3850
	$required_options = "";
3851
	if ($wancfg['adv_dhcp_required_options'] != '') {
3852
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3853
	}
3854

    
3855
	$option_modifiers = "";
3856
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3857
		$modifiers = split(",", $wancfg['adv_dhcp_option_modifiers']);
3858
		foreach ($modifiers as $modifier) {
3859
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3860
		}
3861
	}
3862

    
3863
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3864
 	$dhclientconf .= "\n";
3865
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3866
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3867
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3868
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3869
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3870
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3871
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3872
 	$dhclientconf .= "\n";
3873
 	$dhclientconf .= "# DHCP Protocol Options\n";
3874
 	$dhclientconf .= "{$hostname}";
3875
 	$dhclientconf .= "{$send_options}";
3876
 	$dhclientconf .= "{$request_options}";
3877
 	$dhclientconf .= "{$required_options}";
3878
 	$dhclientconf .= "{$option_modifiers}";
3879
 	$dhclientconf .= "\n";
3880
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3881
 	$dhclientconf .= "}\n";
3882

    
3883
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3884

    
3885
	return $dhclientconf;
3886
}
3887

    
3888

    
3889
function DHCP_Config_File_Override($wancfg, $wanif) {
3890

    
3891
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3892
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3893

    
3894
	return $dhclientconf;
3895
}
3896

    
3897

    
3898
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3899

    
3900
	/* Apply Interface Substitutions */
3901
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3902

    
3903
	/* Apply Hostname Substitutions */
3904
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3905

    
3906
	/* Arrays of MAC Address Types, Cases, Delimiters */
3907
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3908
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3909
	$various_mac_cases      = array("U", "L");
3910
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3911

    
3912
	/* Apply MAC Address Substitutions */
3913
	foreach ($various_mac_types as $various_mac_type) {
3914
		foreach ($various_mac_cases as $various_mac_case) {
3915
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3916

    
3917
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3918
				if ($res !== false) {
3919

    
3920
					/* Get MAC Address as ASCII String With Colon (:) Celimiters */
3921
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3922
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3923

    
3924
					if ("$various_mac_type" == "mac_addr_hex") {
3925
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3926
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3927
						$dhcpclientconf_mac_hex = "";
3928
						$delimiter = "";
3929
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3930
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3931
							$delimiter = ":";
3932
						}
3933
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3934
					}
3935

    
3936
					/* MAC Address Delimiter Substitutions */
3937
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3938

    
3939
					/* Apply MAC Address Substitutions */
3940
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
3941
				}
3942
			}
3943
		}
3944
	}
3945

    
3946
	return $dhclientconf;
3947
}
3948

    
3949
function interfaces_group_setup() {
3950
	global $config;
3951

    
3952
	if (!is_array($config['ifgroups']['ifgroupentry']))
3953
		return;
3954

    
3955
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3956
		interface_group_setup($groupar);
3957

    
3958
	return;
3959
}
3960

    
3961
function interface_group_setup(&$groupname /* The parameter is an array */) {
3962
	global $config;
3963

    
3964
	if (!is_array($groupname))
3965
		return;
3966
	$members = explode(" ", $groupname['members']);
3967
	foreach($members as $ifs) {
3968
		$realif = get_real_interface($ifs);
3969
		if ($realif)
3970
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3971
	}
3972

    
3973
	return;
3974
}
3975

    
3976
function is_interface_group($if) {
3977
	global $config;
3978

    
3979
	if (is_array($config['ifgroups']['ifgroupentry']))
3980
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
3981
			if ($groupentry['ifname'] === $if)
3982
				return true;
3983
		}
3984

    
3985
	return false;
3986
}
3987

    
3988
function interface_group_add_member($interface, $groupname) {
3989
	$interface = get_real_interface($interface);
3990
	mwexec("/sbin/ifconfig {$interface} group " . escapeshellarg($groupname), true);
3991
}
3992

    
3993
/* COMPAT Function */
3994
function convert_friendly_interface_to_real_interface_name($interface) {
3995
	return get_real_interface($interface);
3996
}
3997

    
3998
/* COMPAT Function */
3999
function get_real_wan_interface($interface = "wan") {
4000
	return get_real_interface($interface);
4001
}
4002

    
4003
/* COMPAT Function */
4004
function get_current_wan_address($interface = "wan") {
4005
	return get_interface_ip($interface);
4006
}
4007

    
4008
/*
4009
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
4010
 */
4011
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
4012
	global $config;
4013

    
4014
	if (stripos($interface, "_vip")) {
4015
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
4016
			if ($vip['mode'] == "carp")  {
4017
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4018
				return $vip['interface'];
4019
			}
4020
		}
4021
	}
4022

    
4023
	/* XXX: For speed reasons reference directly the interface array */
4024
	$ifdescrs = &$config['interfaces'];
4025
	//$ifdescrs = get_configured_interface_list(false, true);
4026

    
4027
	foreach ($ifdescrs as $if => $ifname) {
4028
		if ($if == $interface || $ifname['if'] == $interface)
4029
			return $if;
4030

    
4031
		if (get_real_interface($if) == $interface)
4032
			return $if;
4033

    
4034
		$int = get_parent_interface($if, true);
4035
		if (is_array($int)) {
4036
			foreach ($int as $iface) {
4037
				if ($iface == $interface)
4038
					return $if;
4039
			}
4040
		}
4041
	}
4042

    
4043
	if ($interface == "enc0")
4044
		return 'IPsec';
4045
}
4046

    
4047
/* attempt to resolve interface to friendly descr */
4048
function convert_friendly_interface_to_friendly_descr($interface) {
4049
	global $config;
4050

    
4051
	switch ($interface) {
4052
	case "l2tp":
4053
		$ifdesc = "L2TP";
4054
		break;
4055
	case "pptp":
4056
		$ifdesc = "PPTP";
4057
		break;
4058
	case "pppoe":
4059
		$ifdesc = "PPPoE";
4060
		break;
4061
	case "openvpn":
4062
		$ifdesc = "OpenVPN";
4063
		break;
4064
	case "enc0":
4065
	case "ipsec":
4066
	case "IPsec":
4067
		$ifdesc = "IPsec";
4068
		break;
4069
	default:
4070
		if (isset($config['interfaces'][$interface])) {
4071
			if (empty($config['interfaces'][$interface]['descr']))
4072
				$ifdesc = strtoupper($interface);
4073
			else
4074
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4075
			break;
4076
		} else if (stristr($interface, "_vip")) {
4077
			if (is_array($config['virtualip']['vip'])) {
4078
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4079
					if ($vip['mode'] == "carp")  {
4080
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4081
							return "{$vip['subnet']} - {$vip['descr']}";
4082
					}
4083
				}
4084
			}
4085
		} else {
4086
			/* if list */
4087
			$ifdescrs = get_configured_interface_with_descr(false, true);
4088
			foreach ($ifdescrs as $if => $ifname) {
4089
				if ($if == $interface || $ifname == $interface)
4090
					return $ifname;
4091
			}
4092
		}
4093
		break;
4094
	}
4095

    
4096
	return $ifdesc;
4097
}
4098

    
4099
function convert_real_interface_to_friendly_descr($interface) {
4100

    
4101
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4102

    
4103
	if (!empty($ifdesc))
4104
		return convert_friendly_interface_to_friendly_descr($ifdesc);
4105

    
4106
	return $interface;
4107
}
4108

    
4109
/*
4110
 *  get_parent_interface($interface):
4111
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4112
 *				or virtual interface (i.e. vlan)
4113
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4114
 *			-- returns $interface passed in if $interface parent is not found
4115
 *			-- returns empty array if an invalid interface is passed
4116
 *	(Only handles ppps and vlans now.)
4117
 */
4118
function get_parent_interface($interface, $avoidrecurse = false) {
4119
	global $config;
4120

    
4121
	$parents = array();
4122
	//Check that we got a valid interface passed
4123
	$realif = get_real_interface($interface);
4124
	if ($realif == NULL)
4125
		return $parents;
4126

    
4127
	// If we got a real interface, find it's friendly assigned name
4128
	if ($interface == $realif && $avoidrecurse == false)
4129
		$interface = convert_real_interface_to_friendly_interface_name($interface);
4130

    
4131
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4132
		$ifcfg = $config['interfaces'][$interface];
4133
		switch ($ifcfg['ipaddr']) {
4134
			case "ppp":
4135
			case "pppoe":
4136
			case "pptp":
4137
			case "l2tp":
4138
				if (empty($parents))
4139
					if (is_array($config['ppps']['ppp']))
4140
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4141
							if ($ifcfg['if'] == $ppp['if']) {
4142
								$ports = explode(',', $ppp['ports']);
4143
								foreach ($ports as $pid => $parent_if)
4144
									$parents[$pid] = get_real_interface($parent_if);
4145
								break;
4146
							}
4147
						}
4148
				break;
4149
			case "dhcp":
4150
			case "static":
4151
			default:
4152
				// Handle _vlans
4153
				if (strpos($realif, '_vlan') !== FALSE) {
4154
					if (is_array($config['vlans']['vlan'])) {
4155
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan) {
4156
							if ($ifcfg['if'] == $vlan['vlanif']) {
4157
								$parents[0] = $vlan['if'];
4158
								break;
4159
							}
4160
						}
4161
					}
4162
				}
4163
				break;
4164
		}
4165
	}
4166

    
4167
	if (empty($parents))
4168
		$parents[0] = $realif;
4169

    
4170
	return $parents;
4171
}
4172

    
4173
function interface_is_wireless_clone($wlif) {
4174
	if(!stristr($wlif, "_wlan")) {
4175
		return false;
4176
	} else {
4177
		return true;
4178
	}
4179
}
4180

    
4181
function interface_get_wireless_base($wlif) {
4182
	if(!stristr($wlif, "_wlan")) {
4183
		return $wlif;
4184
	} else {
4185
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4186
	}
4187
}
4188

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

    
4197
function get_real_interface($interface = "wan", $family = "all", $realv6iface = false, $flush = true) {
4198
	global $config, $g;
4199

    
4200
	$wanif = NULL;
4201

    
4202
	switch ($interface) {
4203
	case "l2tp":
4204
		$wanif = "l2tp";
4205
		break;
4206
	case "pptp":
4207
		$wanif = "pptp";
4208
		break;
4209
	case "pppoe":
4210
		$wanif = "pppoe";
4211
		break;
4212
	case "openvpn":
4213
		$wanif = "openvpn";
4214
		break;
4215
	case "ipsec":
4216
	case "enc0":
4217
		$wanif = "enc0";
4218
		break;
4219
	case "ppp":
4220
		$wanif = "ppp";
4221
		break;
4222
	default:
4223
		// If a real interface was alread passed simply
4224
		// pass the real interface back.  This encourages
4225
		// the usage of this function in more cases so that
4226
		// we can combine logic for more flexibility.
4227
		if(does_interface_exist($interface, $flush)) {
4228
			$wanif = $interface;
4229
			break;
4230
		}
4231

    
4232
		if (empty($config['interfaces'][$interface]))
4233
			break;
4234

    
4235
		$cfg = &$config['interfaces'][$interface];
4236

    
4237
		if ($family == "inet6") {
4238
			switch ($cfg['ipaddrv6']) {
4239
			case "6rd":
4240
			case "6to4":
4241
				$wanif = "{$interface}_stf";
4242
				break;
4243
			case 'pppoe':
4244
			case 'ppp':
4245
			case 'l2tp':
4246
			case 'pptp':
4247
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4248
					$wanif = interface_get_wireless_clone($cfg['if']);
4249
				else
4250
					$wanif = $cfg['if'];
4251
				break;
4252
			default:
4253
				switch ($cfg['ipaddr']) {
4254
				case 'pppoe':
4255
				case 'ppp':
4256
				case 'l2tp':
4257
				case 'pptp':
4258
					if (isset($cfg['dhcp6usev4iface']) && $realv6iface === false)
4259
						$wanif = $cfg['if'];
4260
					else {
4261
						$parents = get_parent_interface($interface);
4262
						if (!empty($parents[0]))
4263
							$wanif = $parents[0];
4264
						else
4265
							$wanif = $cfg['if'];
4266
					}
4267
					break;
4268
				default:
4269
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4270
						$wanif = interface_get_wireless_clone($cfg['if']);
4271
					else
4272
						$wanif = $cfg['if'];
4273
					break;
4274
				}
4275
				break;
4276
			}
4277
		} else {
4278
			// Wireless cloned NIC support (FreeBSD 8+)
4279
			// interface name format: $parentnic_wlanparentnic#
4280
			// example: ath0_wlan0
4281
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4282
				$wanif = interface_get_wireless_clone($cfg['if']);
4283
			else
4284
				$wanif = $cfg['if'];
4285
		}
4286
		break;
4287
	}
4288

    
4289
	return $wanif;
4290
}
4291

    
4292
/* Guess the physical interface by providing a IP address */
4293
function guess_interface_from_ip($ipaddress) {
4294

    
4295
	$family = '';
4296
	if(is_ipaddrv4($ipaddress))
4297
		$family = 'inet';
4298
	if (empty($family) && is_ipaddrv6($ipaddress))
4299
		$family = 'inet6';
4300

    
4301
	if (empty($family))
4302
		return false;
4303

    
4304
	/* create a route table we can search */
4305
	$output = '';
4306
	$_gb = exec("/sbin/route -n get -{$family} " . escapeshellarg($ipaddress) . " | /usr/bin/awk '/interface/ { print \$2; };'", $output);
4307
	$output[0] = trim($output[0], " \n");
4308
	if (!empty($output[0]))
4309
		return $output[0];
4310

    
4311
	return false;
4312
}
4313

    
4314
/*
4315
 * find_ip_interface($ip): return the interface where an ip is defined
4316
 *   (or if $bits is specified, where an IP within the subnet is defined)
4317
 */
4318
function find_ip_interface($ip, $bits = null) {
4319
	if (!is_ipaddr($ip))
4320
		return false;
4321

    
4322
	$isv6ip = is_ipaddrv6($ip);
4323

    
4324
	/* if list */
4325
	$ifdescrs = get_configured_interface_list();
4326

    
4327
	foreach ($ifdescrs as $ifdescr => $ifname) {
4328
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4329
		if (is_null($ifip))
4330
			continue;
4331
		if (is_null($bits)) {
4332
			if ($ip == $ifip) {
4333
				$int = get_real_interface($ifname);
4334
				return $int;
4335
			}
4336
		}
4337
		else {
4338
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4339
				$int = get_real_interface($ifname);
4340
				return $int;
4341
			}
4342
		}
4343
	}
4344

    
4345
	return false;
4346
}
4347

    
4348
/*
4349
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4350
 *   (or if $bits is specified, where an IP within the subnet is found)
4351
 */
4352
function find_virtual_ip_alias($ip, $bits = null) {
4353
	global $config;
4354

    
4355
	if (!is_array($config['virtualip']['vip'])) {
4356
		return false;
4357
	}
4358
	if (!is_ipaddr($ip))
4359
		return false;
4360

    
4361
	$isv6ip = is_ipaddrv6($ip);
4362

    
4363
	foreach ($config['virtualip']['vip'] as $vip) {
4364
		if ($vip['mode'] === "ipalias") {
4365
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4366
				continue;
4367
			if (is_null($bits)) {
4368
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4369
					return $vip;
4370
				}
4371
			}
4372
			else {
4373
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4374
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4375
					return $vip;
4376
				}
4377
			}
4378
		}
4379
	}
4380
	return false;
4381
}
4382

    
4383
/*
4384
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4385
 */
4386
function find_number_of_created_carp_interfaces() {
4387
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4388
}
4389

    
4390
/*
4391
 * find_carp_interface($ip): return the carp interface where an ip is defined
4392
 */
4393
function find_carp_interface($ip) {
4394
	global $config;
4395
	if (is_array($config['virtualip']['vip'])) {
4396
		foreach ($config['virtualip']['vip'] as $vip) {
4397
			if ($vip['mode'] == "carp") {
4398
				if(is_ipaddrv4($ip)) {
4399
					$carp_ip = get_interface_ip($vip['interface']);
4400
				}
4401
				if(is_ipaddrv6($ip)) {
4402
					$carp_ip = get_interface_ipv6($vip['interface']);
4403
				}
4404
				exec("/sbin/ifconfig", $output, $return);
4405
				foreach($output as $line) {
4406
					$elements = preg_split("/[ ]+/i", $line);
4407
					if(strstr($elements[0], "vip"))
4408
						$curif = str_replace(":", "", $elements[0]);
4409
					if(stristr($line, $ip)) {
4410
						$if = $curif;
4411
						continue;
4412
					}
4413
				}
4414

    
4415
				if ($if)
4416
					return $if;
4417
			}
4418
		}
4419
	}
4420
}
4421

    
4422
function link_carp_interface_to_parent($interface) {
4423
	global $config;
4424

    
4425
	if (empty($interface))
4426
		return;
4427

    
4428
	$carp_ip = get_interface_ip($interface);
4429
	$carp_ipv6 = get_interface_ipv6($interface);
4430

    
4431
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4432
		return;
4433

    
4434
	/* if list */
4435
	$ifdescrs = get_configured_interface_list();
4436
	foreach ($ifdescrs as $ifdescr => $ifname) {
4437
		/* check IPv4 */
4438
		if(is_ipaddrv4($carp_ip)) {
4439
			$interfaceip = get_interface_ip($ifname);
4440
			$subnet_bits = get_interface_subnet($ifname);
4441
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4442
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4443
				return $ifname;
4444
		}
4445
		/* Check IPv6 */
4446
		if(is_ipaddrv6($carp_ipv6)) {
4447
			$interfaceipv6 = get_interface_ipv6($ifname);
4448
			$prefixlen = get_interface_subnetv6($ifname);
4449
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4450
				return $ifname;
4451
		}
4452
	}
4453
	return "";
4454
}
4455

    
4456

    
4457
/****f* interfaces/link_ip_to_carp_interface
4458
 * NAME
4459
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4460
 * INPUTS
4461
 *   $ip
4462
 * RESULT
4463
 *   $carp_ints
4464
 ******/
4465
function link_ip_to_carp_interface($ip) {
4466
	global $config;
4467

    
4468
	if (!is_ipaddr($ip))
4469
		return;
4470

    
4471
	$carp_ints = "";
4472
	if (is_array($config['virtualip']['vip'])) {
4473
		$first = 0;
4474
		$carp_int = array();
4475
		foreach ($config['virtualip']['vip'] as $vip) {
4476
			if ($vip['mode'] == "carp") {
4477
				$carp_ip = $vip['subnet'];
4478
				$carp_sn = $vip['subnet_bits'];
4479
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4480
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4481
					$carp_int[] = get_real_interface($vip['interface']);
4482
				}
4483
			}
4484
		}
4485
		if (!empty($carp_int))
4486
			$carp_ints = implode(" ", array_unique($carp_int));
4487
	}
4488

    
4489
	return $carp_ints;
4490
}
4491

    
4492
function link_interface_to_track6($int, $action = "") {
4493
	global $config;
4494

    
4495
	if (empty($int))
4496
		return;
4497

    
4498
	if (is_array($config['interfaces'])) {
4499
		$list = array();
4500
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4501
			if (!isset($ifcfg['enable']))
4502
				continue;
4503
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4504
				if ($action == "update")
4505
					interface_track6_configure($ifname, $ifcfg);
4506
				else if ($action == "")
4507
					$list[$ifname] = $ifcfg;
4508
			}
4509
		}
4510
		return $list;
4511
	}
4512
}
4513

    
4514
function interface_find_child_cfgmtu($realiface) {
4515
	global $config;
4516

    
4517
	$interface = convert_real_interface_to_friendly_interface_name($realiface);
4518
	$vlans = link_interface_to_vlans($realiface);
4519
	$bridge = link_interface_to_bridge($realiface);
4520
	if (!empty($interface)) {
4521
		$gifs = link_interface_to_gif($interface);
4522
		$gres = link_interface_to_gre($interface);
4523
	} else {
4524
		$gifs = array();
4525
		$gres = array();
4526
	}
4527

    
4528
	$mtu = 0;
4529
	foreach ($vlans as $vlan) {
4530
		$ifass = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
4531
		if (empty($ifass))
4532
			continue;
4533
		if (!empty($config['interfaces'][$ifass]['mtu'])) {
4534
			if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4535
				$mtu = intval($config['interfaces'][$ifass]['mtu']);
4536
		}
4537
	}
4538
	foreach ($gifs as $vlan) {
4539
		$ifass = convert_real_interface_to_friendly_interface_name($vlan['gifif']);
4540
		if (empty($ifass))
4541
			continue;
4542
		if (!empty($config['interfaces'][$ifass]['mtu'])) {
4543
			if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4544
				$mtu = intval($config['interfaces'][$ifass]['mtu']);
4545
		}
4546
	}
4547
	foreach ($gres as $vlan) {
4548
		$ifass = convert_real_interface_to_friendly_interface_name($vlan['greif']);
4549
		if (empty($ifass))
4550
			continue;
4551
		if (!empty($config['interfaces'][$ifass]['mtu'])) {
4552
			if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4553
				$mtu = intval($config['interfaces'][$ifass]['mtu']);
4554
		}
4555
	}
4556
	$ifass = convert_real_interface_to_friendly_interface_name($bridge);
4557
	if (!empty($ifass) && !empty($config['interfaces'][$ifass]['mtu'])) {
4558
		if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4559
			$mtu = intval($config['interfaces'][$ifass]['mtu']);
4560
	}
4561
	unset($vlans, $bridge, $gifs, $gres, $ifass, $vlan);
4562

    
4563
	return $mtu;
4564
}
4565

    
4566
function link_interface_to_vlans($int, $action = "") {
4567
	global $config;
4568

    
4569
	if (empty($int))
4570
		return;
4571

    
4572
	if (is_array($config['vlans']['vlan'])) {
4573
		$ifaces = array();
4574
		foreach ($config['vlans']['vlan'] as $vlan) {
4575
			if ($int == $vlan['if']) {
4576
				if ($action == "update") {
4577
					interfaces_bring_up($int);
4578
				} else
4579
					$ifaces[$vlan['tag']] = $vlan;
4580
			}
4581
		}
4582
		if (!empty($ifaces))
4583
			return $ifaces;
4584
	}
4585
}
4586

    
4587
function link_interface_to_vips($int, $action = "") {
4588
	global $config;
4589

    
4590
	if (is_array($config['virtualip']['vip'])) {
4591
		$result = array();
4592
		foreach ($config['virtualip']['vip'] as $vip) {
4593
			if ($int == $vip['interface']) {
4594
				if ($action == "update")
4595
					interfaces_vips_configure($int);
4596
				else
4597
					$result[] = $vip;
4598
			}
4599
		}
4600
		return $result;
4601
	}
4602
}
4603

    
4604
/****f* interfaces/link_interface_to_bridge
4605
 * NAME
4606
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4607
 * INPUTS
4608
 *   $ip
4609
 * RESULT
4610
 *   bridge[0-99]
4611
 ******/
4612
function link_interface_to_bridge($int) {
4613
	global $config;
4614

    
4615
	if (is_array($config['bridges']['bridged'])) {
4616
		foreach ($config['bridges']['bridged'] as $bridge) {
4617
			if (in_array($int, explode(',', $bridge['members'])))
4618
				return "{$bridge['bridgeif']}";
4619
		}
4620
	}
4621
}
4622

    
4623
function link_interface_to_group($int) {
4624
	global $config;
4625

    
4626
	$result = array();
4627

    
4628
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4629
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4630
			if (in_array($int, explode(" ", $group['members'])))
4631
				$result[$group['ifname']] = $int;
4632
		}
4633
	}
4634

    
4635
	return $result;
4636
}
4637

    
4638
function link_interface_to_gre($interface) {
4639
	global $config;
4640

    
4641
	$result = array();
4642

    
4643
	if (is_array($config['gres']['gre'])) {
4644
		foreach ($config['gres']['gre'] as $gre)
4645
			if($gre['if'] == $interface)
4646
				$result[] = $gre;
4647
	}
4648

    
4649
	return $result;
4650
}
4651

    
4652
function link_interface_to_gif($interface) {
4653
	global $config;
4654

    
4655
	$result = array();
4656

    
4657
	if (is_array($config['gifs']['gif'])) {
4658
		foreach ($config['gifs']['gif'] as $gif)
4659
			if($gif['if'] == $interface)
4660
				$result[] = $gif;
4661
	}
4662

    
4663
	return $result;
4664
}
4665

    
4666
/*
4667
 * find_interface_ip($interface): return the interface ip (first found)
4668
 */
4669
function find_interface_ip($interface, $flush = false) {
4670
	global $interface_ip_arr_cache;
4671
	global $interface_sn_arr_cache;
4672

    
4673
	$interface = str_replace("\n", "", $interface);
4674

    
4675
	if (!does_interface_exist($interface))
4676
		return;
4677

    
4678
	/* Setup IP cache */
4679
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4680
		$ifinfo = pfSense_get_interface_addresses($interface);
4681
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4682
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4683
	}
4684

    
4685
	return $interface_ip_arr_cache[$interface];
4686
}
4687

    
4688
/*
4689
 * find_interface_ipv6($interface): return the interface ip (first found)
4690
 */
4691
function find_interface_ipv6($interface, $flush = false) {
4692
	global $interface_ipv6_arr_cache;
4693
	global $interface_snv6_arr_cache;
4694
	global $config;
4695

    
4696
	$interface = trim($interface);
4697
	$interface = get_real_interface($interface);
4698

    
4699
	if (!does_interface_exist($interface))
4700
		return;
4701

    
4702
	/* Setup IP cache */
4703
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4704
		$ifinfo = pfSense_get_interface_addresses($interface);
4705
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4706
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4707
	}
4708

    
4709
	return $interface_ipv6_arr_cache[$interface];
4710
}
4711

    
4712
/*
4713
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4714
 */
4715
function find_interface_ipv6_ll($interface, $flush = false) {
4716
	global $interface_llv6_arr_cache;
4717
	global $config;
4718

    
4719
	$interface = str_replace("\n", "", $interface);
4720

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

    
4724
	/* Setup IP cache */
4725
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4726
		$ifinfo = pfSense_getall_interface_addresses($interface);
4727
		foreach($ifinfo as $line) {
4728
			if (strstr($line, ":")) {
4729
				$parts = explode("/", $line);
4730
				if(is_linklocal($parts[0])) {
4731
					$ifinfo['linklocal'] = $parts[0];
4732
				}
4733
			}
4734
		}
4735
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4736
	}
4737
	return $interface_llv6_arr_cache[$interface];
4738
}
4739

    
4740
function find_interface_subnet($interface, $flush = false) {
4741
	global $interface_sn_arr_cache;
4742
	global $interface_ip_arr_cache;
4743

    
4744
	$interface = str_replace("\n", "", $interface);
4745
	if (does_interface_exist($interface) == false)
4746
		return;
4747

    
4748
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4749
		$ifinfo = pfSense_get_interface_addresses($interface);
4750
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4751
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4752
	}
4753

    
4754
	return $interface_sn_arr_cache[$interface];
4755
}
4756

    
4757
function find_interface_subnetv6($interface, $flush = false) {
4758
	global $interface_snv6_arr_cache;
4759
	global $interface_ipv6_arr_cache;
4760

    
4761
	$interface = str_replace("\n", "", $interface);
4762
	if (does_interface_exist($interface) == false)
4763
		return;
4764

    
4765
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4766
		$ifinfo = pfSense_get_interface_addresses($interface);
4767
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4768
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4769
	}
4770

    
4771
	return $interface_snv6_arr_cache[$interface];
4772
}
4773

    
4774
function ip_in_interface_alias_subnet($interface, $ipalias) {
4775
	global $config;
4776

    
4777
	if (empty($interface) || !is_ipaddr($ipalias))
4778
		return false;
4779
	if (is_array($config['virtualip']['vip'])) {
4780
		foreach ($config['virtualip']['vip'] as $vip) {
4781
			switch ($vip['mode']) {
4782
			case "ipalias":
4783
				if ($vip['interface'] <> $interface)
4784
					break;
4785
				$subnet = is_ipaddrv6($ipalias) ? gen_subnetv6($vip['subnet'], $vip['subnet_bits']) : gen_subnet($vip['subnet'], $vip['subnet_bits']);
4786
				if (ip_in_subnet($ipalias, $subnet . "/" . $vip['subnet_bits']))
4787
					return true;
4788
				break;
4789
			}
4790
		}
4791
	}
4792

    
4793
	return false;
4794
}
4795

    
4796
function get_interface_ip($interface = "wan") {
4797
	$realif = get_failover_interface($interface);
4798
	if (!$realif) {
4799
		if (strstr($interface, "_vip"))
4800
			return get_configured_carp_interface_list($interface);
4801
		else
4802
			return null;
4803
	}
4804

    
4805
	$curip = find_interface_ip($realif);
4806
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4807
		return $curip;
4808
	else
4809
		return null;
4810
}
4811

    
4812
function get_interface_ipv6($interface = "wan", $flush = false) {
4813
	global $config;
4814

    
4815
	$realif = get_failover_interface($interface, "inet6");
4816
	if (!$realif) {
4817
		if (strstr($interface, "_vip"))
4818
			return get_configured_carp_interface_list($interface, "inet6");
4819
		else
4820
			return null;
4821
	}
4822

    
4823
	/*
4824
	 * NOTE: On the case when only the prefix is requested,
4825
	 * the communication on WAN will be done over link-local.
4826
	 */
4827
	if (is_array($config['interfaces'][$interface])) {
4828
		switch ($config['interfaces'][$interface]['ipaddr']) {
4829
		case 'pppoe':
4830
		case 'l2tp':
4831
		case 'pptp':
4832
		case 'ppp':
4833
			if ($config['interfaces'][$interface]['ipaddrv6'] == 'dhcp6')
4834
				$realif = get_real_interface($interface, "inet6", true);
4835
			break;
4836
		}
4837
		if (isset($config['interfaces'][$interface]['dhcp6prefixonly'])) {
4838
			$curip = find_interface_ipv6_ll($realif, $flush);
4839
			if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4840
				return $curip;
4841
		}
4842
	}
4843

    
4844
	$curip = find_interface_ipv6($realif, $flush);
4845
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4846
		return $curip;
4847
	else
4848
		return null;
4849
}
4850

    
4851
function get_interface_linklocal($interface = "wan") {
4852

    
4853
	$realif = get_failover_interface($interface, "inet6");
4854
	if (!$realif) {
4855
		if (strstr($interface, "_vip")) {
4856
			list($interface, $vhid) = explode("_vip", $interface);
4857
			$realif = get_real_interface($interface);
4858
		} else
4859
			return null;
4860
	}
4861

    
4862
	$curip = find_interface_ipv6_ll($realif);
4863
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4864
		return $curip;
4865
	else
4866
		return null;
4867
}
4868

    
4869
function get_interface_subnet($interface = "wan") {
4870
	$realif = get_real_interface($interface);
4871
	if (!$realif) {
4872
		if (strstr($interface, "_vip")) {
4873
			list($interface, $vhid) = explode("_vip", $interface);
4874
			$realif = get_real_interface($interface);
4875
		} else
4876
			return null;
4877
	}
4878

    
4879
	$cursn = find_interface_subnet($realif);
4880
	if (!empty($cursn))
4881
		return $cursn;
4882

    
4883
	return null;
4884
}
4885

    
4886
function get_interface_subnetv6($interface = "wan") {
4887
	global $config;
4888

    
4889
	$realif = get_real_interface($interface, "inet6");
4890
	if (!$realif) {
4891
		if (strstr($interface, "_vip")) {
4892
			list($interface, $vhid) = explode("_vip", $interface);
4893
			$realif = get_real_interface($interface);
4894
		} else
4895
			return null;
4896
	}
4897

    
4898
	$cursn = find_interface_subnetv6($realif);
4899
	if (!empty($cursn))
4900
		return $cursn;
4901

    
4902
	return null;
4903
}
4904

    
4905
/* return outside interfaces with a gateway */
4906
function get_interfaces_with_gateway() {
4907
	global $config;
4908

    
4909
	$ints = array();
4910

    
4911
	/* loop interfaces, check config for outbound */
4912
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4913
		switch ($ifname['ipaddr']) {
4914
			case "dhcp":
4915
			case "ppp";
4916
			case "pppoe":
4917
			case "pptp":
4918
			case "l2tp":
4919
			case "ppp";
4920
				$ints[$ifdescr] = $ifdescr;
4921
			break;
4922
			default:
4923
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4924
				    !empty($ifname['gateway']))
4925
					$ints[$ifdescr] = $ifdescr;
4926
			break;
4927
		}
4928
	}
4929
	return $ints;
4930
}
4931

    
4932
/* return true if interface has a gateway */
4933
function interface_has_gateway($friendly) {
4934
	global $config;
4935

    
4936
	if (!empty($config['interfaces'][$friendly])) {
4937
		$ifname = &$config['interfaces'][$friendly];
4938
		switch ($ifname['ipaddr']) {
4939
			case "dhcp":
4940
			case "pppoe":
4941
			case "pptp":
4942
			case "l2tp":
4943
			case "ppp";
4944
				return true;
4945
			break;
4946
			default:
4947
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4948
					return true;
4949
				$tunnelif = substr($ifname['if'], 0, 3);
4950
				if ($tunnelif == "gif" || $tunnelif == "gre")
4951
					return true;
4952
				if (!empty($ifname['gateway']))
4953
					return true;
4954
			break;
4955
		}
4956
	}
4957

    
4958
	return false;
4959
}
4960

    
4961
/* return true if interface has a gateway */
4962
function interface_has_gatewayv6($friendly) {
4963
	global $config;
4964

    
4965
	if (!empty($config['interfaces'][$friendly])) {
4966
		$ifname = &$config['interfaces'][$friendly];
4967
		switch ($ifname['ipaddrv6']) {
4968
			case "slaac":
4969
			case "dhcp6":
4970
			case "6to4":
4971
			case "6rd":
4972
				return true;
4973
				break;
4974
			default:
4975
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4976
					return true;
4977
				$tunnelif = substr($ifname['if'], 0, 3);
4978
				if ($tunnelif == "gif" || $tunnelif == "gre")
4979
					return true;
4980
				if (!empty($ifname['gatewayv6']))
4981
					return true;
4982
				break;
4983
		}
4984
	}
4985

    
4986
	return false;
4987
}
4988

    
4989
/****f* interfaces/is_altq_capable
4990
 * NAME
4991
 *   is_altq_capable - Test if interface is capable of using ALTQ
4992
 * INPUTS
4993
 *   $int            - string containing interface name
4994
 * RESULT
4995
 *   boolean         - true or false
4996
 ******/
4997

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

    
5011
	$int_family = remove_ifindex($int);
5012

    
5013
	if (in_array($int_family, $capable))
5014
		return true;
5015
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
5016
		return true;
5017
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
5018
		return true;
5019
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
5020
		return true;
5021
	else
5022
		return false;
5023
}
5024

    
5025
/****f* interfaces/is_interface_wireless
5026
 * NAME
5027
 *   is_interface_wireless - Returns if an interface is wireless
5028
 * RESULT
5029
 *   $tmp       - Returns if an interface is wireless
5030
 ******/
5031
function is_interface_wireless($interface) {
5032
	global $config, $g;
5033

    
5034
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
5035
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
5036
		if (preg_match($g['wireless_regex'], $interface)) {
5037
			if (isset($config['interfaces'][$friendly]))
5038
				$config['interfaces'][$friendly]['wireless'] = array();
5039
			return true;
5040
		}
5041
		return false;
5042
	} else
5043
		return true;
5044
}
5045

    
5046
function get_wireless_modes($interface) {
5047
	/* return wireless modes and channels */
5048
	$wireless_modes = array();
5049

    
5050
	$cloned_interface = get_real_interface($interface);
5051

    
5052
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5053
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
5054
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5055
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
5056

    
5057
		$interface_channels = "";
5058
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5059
		$interface_channel_count = count($interface_channels);
5060

    
5061
		$c = 0;
5062
		while ($c < $interface_channel_count) {
5063
			$channel_line = explode(",", $interface_channels["$c"]);
5064
			$wireless_mode = trim($channel_line[0]);
5065
			$wireless_channel = trim($channel_line[1]);
5066
			if(trim($wireless_mode) != "") {
5067
				/* if we only have 11g also set 11b channels */
5068
				if($wireless_mode == "11g") {
5069
					if(!isset($wireless_modes["11b"]))
5070
						$wireless_modes["11b"] = array();
5071
				} else if($wireless_mode == "11g ht") {
5072
					if(!isset($wireless_modes["11b"]))
5073
						$wireless_modes["11b"] = array();
5074
					if(!isset($wireless_modes["11g"]))
5075
						$wireless_modes["11g"] = array();
5076
					$wireless_mode = "11ng";
5077
				} else if($wireless_mode == "11a ht") {
5078
					if(!isset($wireless_modes["11a"]))
5079
						$wireless_modes["11a"] = array();
5080
					$wireless_mode = "11na";
5081
				}
5082
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
5083
			}
5084
			$c++;
5085
		}
5086
	}
5087
	return($wireless_modes);
5088
}
5089

    
5090
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5091
function get_wireless_channel_info($interface) {
5092
	$wireless_channels = array();
5093

    
5094
	$cloned_interface = get_real_interface($interface);
5095

    
5096
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5097
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5098
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5099
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5100

    
5101
		$interface_channels = "";
5102
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5103

    
5104
		foreach ($interface_channels as $channel_line) {
5105
			$channel_line = explode(",", $channel_line);
5106
			if(!isset($wireless_channels[$channel_line[0]]))
5107
				$wireless_channels[$channel_line[0]] = $channel_line;
5108
		}
5109
	}
5110
	return($wireless_channels);
5111
}
5112

    
5113
/****f* interfaces/get_interface_mtu
5114
 * NAME
5115
 *   get_interface_mtu - Return the mtu of an interface
5116
 * RESULT
5117
 *   $tmp       - Returns the mtu of an interface
5118
 ******/
5119
function get_interface_mtu($interface) {
5120
	$mtu = pfSense_get_interface_addresses($interface);
5121
	return $mtu['mtu'];
5122
}
5123

    
5124
function get_interface_mac($interface) {
5125

    
5126
	$macinfo = pfSense_get_interface_addresses($interface);
5127
	return $macinfo["macaddr"];
5128
}
5129

    
5130
/****f* pfsense-utils/generate_random_mac_address
5131
 * NAME
5132
 *   generate_random_mac - generates a random mac address
5133
 * INPUTS
5134
 *   none
5135
 * RESULT
5136
 *   $mac - a random mac address
5137
 ******/
5138
function generate_random_mac_address() {
5139
	$mac = "02";
5140
	for($x=0; $x<5; $x++)
5141
		$mac .= ":" . dechex(rand(16, 255));
5142
	return $mac;
5143
}
5144

    
5145
/****f* interfaces/is_jumbo_capable
5146
 * NAME
5147
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5148
 * INPUTS
5149
 *   $int             - string containing interface name
5150
 * RESULT
5151
 *   boolean          - true or false
5152
 ******/
5153
function is_jumbo_capable($iface) {
5154
	$iface = trim($iface);
5155
	$capable = pfSense_get_interface_addresses($iface);
5156

    
5157
	if (isset($capable['caps']['vlanmtu']))
5158
		return true;
5159

    
5160
	return false;
5161
}
5162

    
5163
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5164
	global $g;
5165

    
5166
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5167

    
5168
	if(!empty($iface) && !empty($pppif)){
5169
		$cron_cmd = <<<EOD
5170
#!/bin/sh
5171
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5172
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5173

    
5174
EOD;
5175

    
5176
		@file_put_contents($cron_file, $cron_cmd);
5177
		chmod($cron_file, 0755);
5178
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5179
	} else
5180
		unlink_if_exists($cron_file);
5181
}
5182

    
5183
function get_interface_default_mtu($type = "ethernet") {
5184
	switch ($type) {
5185
	case "gre":
5186
		return 1476;
5187
		break;
5188
	case "gif":
5189
		return 1280;
5190
		break;
5191
	case "tun":
5192
	case "vlan":
5193
	case "tap":
5194
	case "ethernet":
5195
	default:
5196
		return 1500;
5197
		break;
5198
	}
5199

    
5200
	/* Never reached */
5201
	return 1500;
5202
}
5203

    
5204
function get_vip_descr($ipaddress) {
5205
	global $config;
5206

    
5207
	foreach ($config['virtualip']['vip'] as $vip) {
5208
		if ($vip['subnet'] == $ipaddress) {
5209
			return ($vip['descr']);
5210
		}
5211
	}
5212
	return "";
5213
}
5214

    
5215
function interfaces_staticarp_configure($if) {
5216
	global $config, $g;
5217
	if(isset($config['system']['developerspew'])) {
5218
		$mt = microtime();
5219
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5220
	}
5221

    
5222
	$ifcfg = $config['interfaces'][$if];
5223

    
5224
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5225
		return 0;
5226

    
5227
	/* Enable staticarp, if enabled */
5228
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5229
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5230
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5231
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5232

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

    
5236
			}
5237

    
5238
		}
5239
	} else {
5240
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5241
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5242
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5243
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5244
				if (isset($arpent['arp_table_static_entry'])) {
5245
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5246
				}
5247
			}
5248
		}
5249
	}
5250

    
5251
	return 0;
5252
}
5253

    
5254
function get_failover_interface($interface, $family = "all") {
5255
	global $config;
5256

    
5257
	/* shortcut to get_real_interface if we find it in the config */
5258
	if (is_array($config['interfaces'][$interface])) {
5259
		return get_real_interface($interface, $family);
5260
	}
5261

    
5262
	/* compare against gateway groups */
5263
	$a_groups = return_gateway_groups_array();
5264
	if (is_array($a_groups[$interface])) {
5265
		/* we found a gateway group, fetch the interface or vip */
5266
		if ($a_groups[$interface][0]['vip'] <> "")
5267
			return $a_groups[$interface][0]['vip'];
5268
		else
5269
			return $a_groups[$interface][0]['int'];
5270
	}
5271
	/* fall through to get_real_interface */
5272
	/* XXX: Really needed? */
5273
	return get_real_interface($interface, $family);
5274
}
5275

    
5276
function remove_ifindex($ifname) {
5277
	return preg_replace("/[0-9]+$/", "", $ifname);
5278
}
5279

    
5280
?>
(26-26/68)