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
		$found = interface_isppp_type($interface);
144

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

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

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

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

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

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

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

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

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

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

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

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

    
244
	interfaces_bring_up($vlanif);
245

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

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

    
252
	return $vlanif;
253
}
254

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

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

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

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

    
275
	$vlanif = interface_vlan_configure($vlan);
276

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

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

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

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

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

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

    
328
	return $vlanif;
329
}
330

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

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

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

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

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

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

    
371
	return $vlanif;
372
}
373

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

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

    
380
	$iflist = get_configured_interface_list();
381

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

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

    
401
}
402

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

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

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

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

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

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

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

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

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

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

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

    
494
	$checklist = get_configured_interface_list();
495

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
706
	interfaces_bring_up($laggif);
707

    
708
	return $laggif;
709
}
710

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

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

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

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

    
743
	if (!is_array($gre))
744
		return -1;
745

    
746
	$realif = get_real_interface($gre['if']);
747
	$realifip = get_interface_ip($gre['if']);
748

    
749
	/* make sure the parent interface is up */
750
	interfaces_bring_up($realif);
751

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

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

    
775
	if($greif)
776
		interfaces_bring_up($greif);
777
	else
778
		log_error(gettext("Could not bring greif up -- variable not defined."));
779

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

    
787
	interfaces_bring_up($greif);
788

    
789
	return $greif;
790
}
791

    
792
function interfaces_gif_configure($checkparent = 0, $realif = "") {
793
	global $config;
794

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

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

    
820
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
821
function interface_gif_configure(&$gif, $gifkey = "") {
822
	global $config, $g;
823

    
824
	if (!is_array($gif))
825
		return -1;
826

    
827
	$realif = get_real_interface($gif['if']);
828
	$ipaddr = $gif['ipaddr'];
829

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

    
849
	if (platform_booting() || !(empty($gif['gifif']))) {
850
		pfSense_interface_destroy($gif['gifif']);
851
		pfSense_interface_create($gif['gifif']);
852
		$gifif = $gif['gifif'];
853
	} else
854
		$gifif = pfSense_interface_create("gif");
855

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

    
874
	if (!platform_booting()) {
875
		$iflist = get_configured_interface_list();
876
		foreach($iflist as $ifname) {
877
			if($config['interfaces'][$ifname]['if'] == $gifif) {
878
				if(get_interface_gateway($ifname)) {
879
					system_routing_configure($ifname);
880
					break;
881
				}
882
				if(get_interface_gateway_v6($ifname)) {
883
					system_routing_configure($ifname);
884
					break;
885
				}
886
			}
887
		}
888
	}
889

    
890

    
891
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
892
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
893
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
894
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
895

    
896
	if (is_ipaddrv4($realifgw)) {
897
		mwexec("/sbin/route change -host " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
898
	}
899
	if (is_ipaddrv6($realifgw)) {
900
		mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
901
	}
902

    
903
	interfaces_bring_up($gifif);
904

    
905
	return $gifif;
906
}
907

    
908
function interfaces_configure() {
909
	global $config, $g;
910

    
911
	if ($g['platform'] == 'jail')
912
		return;
913

    
914
	/* Set up our loopback interface */
915
	interfaces_loopback_configure();
916

    
917
	/* create the unconfigured wireless clones */
918
	interfaces_create_wireless_clones();
919

    
920
	/* set up LAGG virtual interfaces */
921
	interfaces_lagg_configure();
922

    
923
	/* set up VLAN virtual interfaces */
924
	interfaces_vlan_configure();
925

    
926
	interfaces_qinq_configure();
927

    
928
	$iflist = get_configured_interface_with_descr();
929
	$delayed_list = array();
930
	$bridge_list = array();
931
	$track6_list = array();
932

    
933
	/* This is needed to speedup interfaces on bootup. */
934
	$reload = false;
935
	if (!platform_booting())
936
		$reload = true;
937

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

    
955
			if($g['debug'])
956
				log_error(sprintf(gettext("Configuring %s"), $ifname));
957
			interface_configure($if, $reload);
958
			if (platform_booting())
959
				echo gettext( "done.") . "\n";
960
		}
961
	}
962

    
963
	/*
964
	 * NOTE: The following function parameter consists of
965
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
966
	 *	2 - Do load gre/gif/bridge with parent/member as vip
967
	 */
968

    
969
	/* set up GRE virtual interfaces */
970
	interfaces_gre_configure(1);
971

    
972
	/* set up GIF virtual interfaces */
973
	interfaces_gif_configure(1);
974

    
975
	/* set up BRIDGe virtual interfaces */
976
	interfaces_bridge_configure(1);
977

    
978
	foreach ($track6_list as $if => $ifname) {
979
		if (platform_booting())
980
			printf(gettext("Configuring %s interface..."), $ifname);
981
		if ($g['debug'])
982
			log_error(sprintf(gettext("Configuring %s"), $ifname));
983

    
984
		interface_configure($if, $reload);
985

    
986
		if (platform_booting())
987
			echo gettext("done.") . "\n";
988
	}
989

    
990
	/* bring up vip interfaces */
991
	interfaces_vips_configure();
992

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

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

    
999
	foreach ($delayed_list as $if => $ifname) {
1000
		if (platform_booting())
1001
			printf(gettext("Configuring %s interface..."), $ifname);
1002
		if ($g['debug'])
1003
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1004

    
1005
		interface_configure($if, $reload);
1006

    
1007
		if (platform_booting())
1008
			echo gettext("done.") . "\n";
1009
	}
1010

    
1011
	/* set up BRIDGe virtual interfaces */
1012
	interfaces_bridge_configure(2);
1013

    
1014
	foreach ($bridge_list as $if => $ifname) {
1015
		if (platform_booting())
1016
			printf(gettext("Configuring %s interface..."), $ifname);
1017
		if($g['debug'])
1018
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1019

    
1020
		interface_configure($if, $reload);
1021

    
1022
		if (platform_booting())
1023
			echo gettext("done.") . "\n";
1024
	}
1025

    
1026
	/* configure interface groups */
1027
	interfaces_group_setup();
1028

    
1029
	if (!platform_booting()) {
1030
		/* reconfigure static routes (kernel may have deleted them) */
1031
		system_routing_configure();
1032

    
1033
		/* reload IPsec tunnels */
1034
		vpn_ipsec_configure();
1035

    
1036
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1037
		services_dhcpd_configure();
1038

    
1039
		/* restart dnsmasq or unbound */
1040
		if (isset($config['dnsmasq']['enable']))
1041
			services_dnsmasq_configure();
1042
		elseif (isset($config['unbound']['enable']))
1043
			services_unbound_configure();
1044
	}
1045

    
1046
	return 0;
1047
}
1048

    
1049
function interface_reconfigure($interface = "wan", $reloadall = false) {
1050
	interface_bring_down($interface);
1051
	interface_configure($interface, $reloadall);
1052
}
1053

    
1054
function interface_vip_bring_down($vip) {
1055
	global $g;
1056

    
1057
	if (strpos($vip['interface'], '_vip')) {
1058
		if (is_ipaddrv6($vip['subnet']))
1059
			$family = 'inet6';
1060
		else
1061
			$family = 'inet';
1062

    
1063
		$carpvip = get_configured_carp_interface_list($vip['interface'], $family, 'vip');
1064
		$iface = $carpvip['interface'];
1065
	} else
1066
		$iface = $vip['interface'];
1067

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

    
1094
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1095
	global $config, $g;
1096

    
1097
	if (!isset($config['interfaces'][$interface]))
1098
		return;
1099

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

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

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

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

    
1225
	if (!empty($track6) && is_array($track6)) {
1226
		if (!function_exists('services_dhcp_configure'))
1227
			require_once('services.inc');
1228
		/* Bring down radvd and dhcp6 on these interfaces */
1229
		services_dhcpd_configure('inet6', $track6);
1230
	}
1231

    
1232
	$old_router = '';
1233
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1234
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1235

    
1236
	/* remove interface up file if it exists */
1237
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1238
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1239
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1240
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1241
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1242
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1243
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1244

    
1245
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1246
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1247
	if (is_array($ifcfg['wireless'])) {
1248
		kill_hostapd($realif);
1249
		mwexec(kill_wpasupplicant($realif));
1250
	}
1251

    
1252
	if ($destroy == true) {
1253
		if (preg_match("/^[a-z0-9]+^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1254
			pfSense_interface_destroy($realif);
1255
	}
1256

    
1257
	return;
1258
}
1259

    
1260
function interfaces_carp_set_maintenancemode($carp_maintenancemode){
1261
	global $config;
1262
	if (isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == false) {
1263
		unset($config["virtualip_carp_maintenancemode"]);
1264
		write_config("Leave CARP maintenance mode");
1265
	} else
1266
	if (!isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == true) {
1267
		$config["virtualip_carp_maintenancemode"] = true;
1268
		write_config("Enter CARP maintenance mode");
1269
	}
1270

    
1271
	$viparr = &$config['virtualip']['vip'];
1272
	foreach ($viparr as $vip) {
1273
		if ($vip['mode'] == "carp") {
1274
			interface_carp_configure($vip);
1275
		}
1276
	}
1277
}
1278

    
1279
function interface_isppp_type($interface) {
1280
	global $config;
1281

    
1282
	if (!is_array($config['interfaces'][$interface]))
1283
		return false;
1284

    
1285
	switch ($config['interfaces'][$interface]['ipaddr']) {
1286
	case 'pptp':
1287
	case 'l2tp':
1288
	case 'pppoe':
1289
	case 'ppp':
1290
		return true;
1291
		break;
1292
	default:
1293
		return false;
1294
		break;
1295
	}
1296
}
1297

    
1298
function interfaces_ptpid_used($ptpid) {
1299
	global $config;
1300

    
1301
	if (is_array($config['ppps']['ppp']))
1302
		foreach ($config['ppps']['ppp'] as & $settings)
1303
			if ($ptpid == $settings['ptpid'])
1304
				return true;
1305

    
1306
	return false;
1307
}
1308

    
1309
function interfaces_ptpid_next() {
1310

    
1311
	$ptpid = 0;
1312
	while(interfaces_ptpid_used($ptpid))
1313
		$ptpid++;
1314

    
1315
	return $ptpid;
1316
}
1317

    
1318
function getMPDCRONSettings($pppif) {
1319
	global $config;
1320

    
1321
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1322
	if (is_array($config['cron']['item'])) {
1323
		foreach ($config['cron']['item'] as $i => $item) {
1324
			if (stripos($item['command'], $cron_cmd_file) !== false)
1325
				return array("ID" => $i, "ITEM" => $item);
1326
		}
1327
	}
1328

    
1329
	return NULL;
1330
}
1331

    
1332
function handle_pppoe_reset($post_array) {
1333
	global $config, $g;
1334

    
1335
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1336
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1337

    
1338
	if (!is_array($config['cron']['item']))
1339
		$config['cron']['item'] = array();
1340

    
1341
	$itemhash = getMPDCRONSettings($pppif);
1342

    
1343
	// reset cron items if necessary and return
1344
	if (empty($post_array['pppoe-reset-type'])) {
1345
		if (isset($itemhash))
1346
			unset($config['cron']['item'][$itemhash['ID']]);
1347
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1348
		return;
1349
	}
1350

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

    
1410
/*
1411
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1412
 * It writes the mpd config file to /var/etc every time the link is opened.
1413
 */
1414
function interface_ppps_configure($interface) {
1415
	global $config, $g;
1416

    
1417
	/* Return for unassigned interfaces. This is a minimum requirement. */
1418
	if (empty($config['interfaces'][$interface]))
1419
		return 0;
1420
	$ifcfg = $config['interfaces'][$interface];
1421
	if (!isset($ifcfg['enable']))
1422
		return 0;
1423

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

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

    
1449
	/* XXX: This does not make sense and may create trouble
1450
	 * comment it for now to be removed later on.
1451
	if (platform_booting()) {
1452
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1453
		echo "starting {$pppif} link...";
1454
		if(isvalidpid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1455
			return 0;
1456
	}
1457
	*/
1458

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

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

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

    
1515
	if (is_array($ports) && count($ports) > 1)
1516
		$multilink = "enable";
1517
	else
1518
		$multilink = "disable";
1519

    
1520
	if ($type == "modem"){
1521
		if (is_ipaddr($ppp['localip']))
1522
			$localip = $ppp['localip'];
1523
		else
1524
			$localip = '0.0.0.0';
1525

    
1526
		if (is_ipaddr($ppp['gateway']))
1527
			$gateway = $ppp['gateway'];
1528
		else
1529
			$gateway = "10.64.64.{$pppid}";
1530
		$ranges = "{$localip}/0 {$gateway}/0";
1531

    
1532
		if (empty($ppp['apnum']))
1533
			$ppp['apnum'] = 1;
1534
	} else
1535
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1536

    
1537
	if (isset($ppp['ondemand']))
1538
		$ondemand = "enable";
1539
	else
1540
		$ondemand = "disable";
1541
	if (!isset($ppp['idletimeout']))
1542
		$ppp['idletimeout'] = 0;
1543

    
1544
	if (empty($ppp['username']) && $type == "modem"){
1545
		$ppp['username'] = "user";
1546
		$ppp['password'] = "none";
1547
	}
1548
	if (empty($ppp['password']) && $type == "modem")
1549
		$passwd = "none";
1550
	else
1551
		$passwd = base64_decode($ppp['password']);
1552

    
1553
	$bandwidths = explode(',',$ppp['bandwidth']);
1554
	$defaultmtu = "1492";
1555
	if (!empty($ifcfg['mtu']))
1556
		$defaultmtu = intval($ifcfg['mtu']);
1557
	$mtus = explode(',',$ppp['mtu']);
1558
	$mrus = explode(',',$ppp['mru']);
1559

    
1560
	if (isset($ppp['mrru']))
1561
		$mrrus = explode(',',$ppp['mrru']);
1562

    
1563
	// Construct the mpd.conf file
1564
	$mpdconf = <<<EOD
1565
startup:
1566
	# configure the console
1567
	set console close
1568
	# configure the web server
1569
	set web close
1570

    
1571
default:
1572
{$ppp['type']}client:
1573
	create bundle static {$interface}
1574
	set bundle enable ipv6cp
1575
	set iface name {$pppif}
1576

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

    
1592
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1593
		$setdefaultgw = true;
1594
		$mpdconf .= <<<EOD
1595
	set iface route default
1596

    
1597
EOD;
1598
	}
1599
	$mpdconf .= <<<EOD
1600
	set iface {$ondemand} on-demand
1601
	set iface idle {$ppp['idletimeout']}
1602

    
1603
EOD;
1604

    
1605
	if (isset($ppp['ondemand']))
1606
		$mpdconf .= <<<EOD
1607
	set iface addrs 10.10.1.1 10.10.1.2
1608

    
1609
EOD;
1610

    
1611
	if (isset($ppp['tcpmssfix']))
1612
		$tcpmss = "disable";
1613
	else
1614
		$tcpmss = "enable";
1615
		$mpdconf .= <<<EOD
1616
	set iface {$tcpmss} tcpmssfix
1617

    
1618
EOD;
1619

    
1620
	$mpdconf .= <<<EOD
1621
	set iface up-script /usr/local/sbin/ppp-linkup
1622
	set iface down-script /usr/local/sbin/ppp-linkdown
1623
	set ipcp ranges {$ranges}
1624

    
1625
EOD;
1626
	if (isset($ppp['vjcomp']))
1627
		$mpdconf .= <<<EOD
1628
	set ipcp no vjcomp
1629

    
1630
EOD;
1631

    
1632
	if (isset($config['system']['dnsallowoverride']))
1633
		$mpdconf .= <<<EOD
1634
	set ipcp enable req-pri-dns
1635
	set ipcp enable req-sec-dns
1636

    
1637
EOD;
1638
	if (!isset($ppp['verbose_log']))
1639
		$mpdconf .= <<<EOD
1640
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1641

    
1642
EOD;
1643
	foreach($ports as $pid => $port){
1644
		$port = get_real_interface($port);
1645
		$mpdconf .= <<<EOD
1646

    
1647
	create link static {$interface}_link{$pid} {$type}
1648
	set link action bundle {$interface}
1649
	set link {$multilink} multilink
1650
	set link keep-alive 10 60
1651
	set link max-redial 0
1652

    
1653
EOD;
1654
		if (isset($ppp['shortseq']))
1655
			$mpdconf .= <<<EOD
1656
	set link no shortseq
1657

    
1658
EOD;
1659

    
1660
		if (isset($ppp['acfcomp']))
1661
			$mpdconf .= <<<EOD
1662
	set link no acfcomp
1663

    
1664
EOD;
1665

    
1666
		if (isset($ppp['protocomp']))
1667
			$mpdconf .= <<<EOD
1668
	set link no protocomp
1669

    
1670
EOD;
1671

    
1672
		$mpdconf .= <<<EOD
1673
	set link disable chap pap
1674
	set link accept chap pap eap
1675
	set link disable incoming
1676

    
1677
EOD;
1678

    
1679

    
1680
		if (!empty($bandwidths[$pid]))
1681
			$mpdconf .= <<<EOD
1682
	set link bandwidth {$bandwidths[$pid]}
1683

    
1684
EOD;
1685

    
1686
		if (empty($mtus[$pid]))
1687
			$mtus[$pid] = $defaultmtu;
1688
			$mpdconf .= <<<EOD
1689
	set link mtu {$mtus[$pid]}
1690

    
1691
EOD;
1692

    
1693
		if (!empty($mrus[$pid]))
1694
			$mpdconf .= <<<EOD
1695
	set link mru {$mrus[$pid]}
1696

    
1697
EOD;
1698

    
1699
		if (!empty($mrrus[$pid]))
1700
			$mpdconf .= <<<EOD
1701
	set link mrru {$mrrus[$pid]}
1702

    
1703
EOD;
1704

    
1705
		$mpdconf .= <<<EOD
1706
	set auth authname "{$ppp['username']}"
1707
	set auth password {$passwd}
1708

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

    
1719
EOD;
1720
		}
1721
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1722
			$mpdconf .= <<<EOD
1723
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1724

    
1725
EOD;
1726
		}
1727
		if (isset($ppp['initstr']) && $type == "modem") {
1728
			$initstr = base64_decode($ppp['initstr']);
1729
			$mpdconf .= <<<EOD
1730
	set modem var \$InitString "{$initstr}"
1731

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

    
1741
EOD;
1742
		}
1743
		if (isset($ppp['apn']) && $type == "modem") {
1744
			$mpdconf .= <<<EOD
1745
	set modem var \$APN "{$ppp['apn']}"
1746
	set modem var \$APNum "{$ppp['apnum']}"
1747

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

    
1756
EOD;
1757
		}
1758
		if ($type == "pppoe")
1759
			$mpdconf .= <<<EOD
1760
	set pppoe iface {$port}
1761

    
1762
EOD;
1763

    
1764
		if ($type == "pptp" || $type == "l2tp") {
1765
			$mpdconf .= <<<EOD
1766
	set {$type} self {$localips[$pid]}
1767
	set {$type} peer {$gateways[$pid]}
1768

    
1769
EOD;
1770
		}
1771

    
1772
		$mpdconf .= "\topen\n";
1773
	} //end foreach($port)
1774

    
1775

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

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

    
1806
	/* clean up old lock files */
1807
	foreach($ports as $port) {
1808
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1809
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1810
	}
1811

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

    
1816
	// Check for PPPoE periodic reset request
1817
	if ($type == "pppoe") {
1818
		if (!empty($ppp['pppoe-reset-type']))
1819
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1820
		else
1821
			interface_setup_pppoe_reset_file($ppp['if']);
1822
	}
1823
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1824
	$i = 0;
1825
	while($i < 3) {
1826
		sleep(10);
1827
		if (does_interface_exist($ppp['if'], true))
1828
			break;
1829
		$i++;
1830
	}
1831

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

    
1852
	return 1;
1853
}
1854

    
1855
function interfaces_sync_setup() {
1856
	global $g, $config;
1857

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

    
1863
	if (platform_booting()) {
1864
		echo gettext("Configuring CARP settings...");
1865
		mute_kernel_msgs();
1866
	}
1867

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

    
1878
	set_sysctl(array(
1879
		"net.inet.carp.preempt" => "1",
1880
		"net.inet.carp.log" => "1")
1881
	);
1882

    
1883
	if (!empty($pfsyncinterface))
1884
		$carp_sync_int = get_real_interface($pfsyncinterface);
1885
	else
1886
		unset($carp_sync_int);
1887

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

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

    
1897
		sleep(1);
1898

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

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

    
1919
	if (platform_booting()) {
1920
		unmute_kernel_msgs();
1921
		echo gettext("done.") . "\n";
1922
	}
1923
}
1924

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

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

    
1941
	$paa = array();
1942
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1943

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

    
1952
				if (!empty($interface) && $interface != $proxyif)
1953
					continue;
1954

    
1955
				if (!is_array($paa[$proxyif]))
1956
					$paa[$proxyif] = array();
1957

    
1958
				$paa[$proxyif][] = $vipent;
1959
			}
1960
		}
1961
	}
1962

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

    
1994
function interface_ipalias_cleanup($interface, $inet = "inet4") {
1995
	global $g, $config;
1996

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

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

    
2048
function interface_ipalias_configure(&$vip) {
2049
	global $config;
2050

    
2051
	if ($vip['mode'] != 'ipalias')
2052
		return;
2053

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

    
2058
		if (!isset($config['interfaces'][$vip['interface']]['enable']))
2059
			return;
2060
	}
2061

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

    
2077
function interface_reload_carps($cif) {
2078
	global $config;
2079

    
2080
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2081
	if (empty($carpifs))
2082
		return;
2083

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

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

    
2113
	if ($vip['mode'] != "carp")
2114
		return;
2115

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

    
2123
	$vip_password = $vip['password'];
2124
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2125
	if ($vip['password'] != "")
2126
		$password = " pass {$vip_password}";
2127

    
2128
	$advbase = "";
2129
	if (!empty($vip['advbase']))
2130
		$advbase = "advbase " . escapeshellarg($vip['advbase']);
2131

    
2132
	$carp_maintenancemode = isset($config["virtualip_carp_maintenancemode"]);
2133
	if ($carp_maintenancemode)
2134
		$advskew = "advskew 254";
2135
	else
2136
		$advskew = "advskew " . escapeshellarg($vip['advskew']);
2137
	
2138
	mwexec("/sbin/ifconfig {$realif} vhid " . escapeshellarg($vip['vhid']) . " {$advskew} {$advbase} {$password}");
2139

    
2140
	if (is_ipaddrv4($vip['subnet']))
2141
		mwexec("/sbin/ifconfig {$realif} " . escapeshellarg($vip['subnet']) . "/" . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2142
	else if (is_ipaddrv6($vip['subnet']))
2143
		mwexec("/sbin/ifconfig {$realif} inet6 " . escapeshellarg($vip['subnet']) . " prefixlen " . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2144

    
2145
	return $realif;
2146
}
2147

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

    
2189
	if($needs_clone == true) {
2190
		/* remove previous instance if it exists */
2191
		if(does_interface_exist($realif))
2192
			pfSense_interface_destroy($realif);
2193

    
2194
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2195
		// Create the new wlan interface. FreeBSD returns the new interface name.
2196
		// example:  wlan2
2197
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2198
		if($ret <> 0) {
2199
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2200
			return false;
2201
		}
2202
		$newif = trim($out[0]);
2203
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2204
		pfSense_interface_rename($newif, $realif);
2205
		// FIXME: not sure what ngctl is for. Doesn't work.
2206
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2207
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2208
	}
2209
	return true;
2210
}
2211

    
2212
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2213
	global $config, $g;
2214

    
2215
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2216
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2217
				 'regdomain', 'regcountry', 'reglocation');
2218

    
2219
	if(!is_interface_wireless($ifcfg['if']))
2220
		return;
2221

    
2222
	$baseif = interface_get_wireless_base($ifcfg['if']);
2223

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

    
2248
	// Read or write settings at shared area
2249
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2250
		foreach ($shared_settings as $setting) {
2251
			if ($sync_changes) {
2252
				if (isset($ifcfg['wireless'][$setting]))
2253
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2254
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2255
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2256
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2257
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2258
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2259
				else if (isset($ifcfg['wireless'][$setting]))
2260
					unset($ifcfg['wireless'][$setting]);
2261
			}
2262
		}
2263
	}
2264

    
2265
	// Sync the mode on the clone creation page with the configured mode on the interface
2266
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2267
		foreach ($config['wireless']['clone'] as &$clone) {
2268
			if ($clone['cloneif'] == $ifcfg['if']) {
2269
				if ($sync_changes) {
2270
					$clone['mode'] = $ifcfg['wireless']['mode'];
2271
				} else {
2272
					$ifcfg['wireless']['mode'] = $clone['mode'];
2273
				}
2274
				break;
2275
			}
2276
		}
2277
		unset($clone);
2278
	}
2279
}
2280

    
2281
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2282
	global $config, $g;
2283

    
2284
	/*    open up a shell script that will be used to output the commands.
2285
	 *    since wireless is changing a lot, these series of commands are fragile
2286
	 *    and will sometimes need to be verified by a operator by executing the command
2287
	 *    and returning the output of the command to the developers for inspection.  please
2288
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2289
	 */
2290

    
2291
	// Remove script file
2292
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2293

    
2294
	// Clone wireless nic if needed.
2295
	interface_wireless_clone($if, $wl);
2296

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

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

    
2304
	/* set values for /path/program */
2305
	$hostapd = "/usr/sbin/hostapd";
2306
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2307
	$ifconfig = "/sbin/ifconfig";
2308
	$sysctl = "/sbin/sysctl";
2309
	$killall = "/usr/bin/killall";
2310

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

    
2313
	$wlcmd = array();
2314
	$wl_sysctl = array();
2315
	/* Make sure it's up */
2316
	$wlcmd[] = "up";
2317
	/* Set a/b/g standard */
2318
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2319
	$wlcmd[] = "mode " . escapeshellarg($standard);
2320

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

    
2326
	/* Set ssid */
2327
	if($wlcfg['ssid'])
2328
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2329

    
2330
	/* Set 802.11g protection mode */
2331
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2332

    
2333
	/* set wireless channel value */
2334
	if(isset($wlcfg['channel'])) {
2335
		if($wlcfg['channel'] == "0") {
2336
			$wlcmd[] = "channel any";
2337
		} else {
2338
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2339
		}
2340
	}
2341

    
2342
	/* Set antenna diversity value */
2343
	if(isset($wlcfg['diversity']))
2344
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2345

    
2346
	/* Set txantenna value */
2347
	if(isset($wlcfg['txantenna']))
2348
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2349

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

    
2354
	/* set Distance value */
2355
	if($wlcfg['distance'])
2356
		$distance = escapeshellarg($wlcfg['distance']);
2357

    
2358
	/* Set wireless hostap mode */
2359
	if ($wlcfg['mode'] == "hostap") {
2360
		$wlcmd[] = "mediaopt hostap";
2361
	} else {
2362
		$wlcmd[] = "-mediaopt hostap";
2363
	}
2364

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

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

    
2374
	/* handle hide ssid option */
2375
	if(isset($wlcfg['hidessid']['enable'])) {
2376
		$wlcmd[] = "hidessid";
2377
	} else {
2378
		$wlcmd[] = "-hidessid";
2379
	}
2380

    
2381
	/* handle pureg (802.11g) only option */
2382
	if(isset($wlcfg['pureg']['enable'])) {
2383
		$wlcmd[] = "mode 11g pureg";
2384
	} else {
2385
		$wlcmd[] = "-pureg";
2386
	}
2387

    
2388
	/* handle puren (802.11n) only option */
2389
	if(isset($wlcfg['puren']['enable'])) {
2390
		$wlcmd[] = "puren";
2391
	} else {
2392
		$wlcmd[] = "-puren";
2393
	}
2394

    
2395
	/* enable apbridge option */
2396
	if(isset($wlcfg['apbridge']['enable'])) {
2397
		$wlcmd[] = "apbridge";
2398
	} else {
2399
		$wlcmd[] = "-apbridge";
2400
	}
2401

    
2402
	/* handle turbo option */
2403
	if(isset($wlcfg['turbo']['enable'])) {
2404
		$wlcmd[] = "mediaopt turbo";
2405
	} else {
2406
		$wlcmd[] = "-mediaopt turbo";
2407
	}
2408

    
2409
	/* handle txpower setting */
2410
	/* if($wlcfg['txpower'] <> "")
2411
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2412
	*/
2413
	/* handle wme option */
2414
	if(isset($wlcfg['wme']['enable'])) {
2415
		$wlcmd[] = "wme";
2416
	} else {
2417
		$wlcmd[] = "-wme";
2418
	}
2419

    
2420
	/* set up wep if enabled */
2421
	$wepset = "";
2422
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2423
		switch($wlcfg['wpa']['auth_algs']) {
2424
			case "1":
2425
				$wepset .= "authmode open wepmode on ";
2426
				break;
2427
			case "2":
2428
				$wepset .= "authmode shared wepmode on ";
2429
				break;
2430
			case "3":
2431
				$wepset .= "authmode mixed wepmode on ";
2432
		}
2433
		$i = 1;
2434
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2435
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2436
			if (isset($wepkey['txkey'])) {
2437
				$wlcmd[] = "weptxkey {$i} ";
2438
			}
2439
			$i++;
2440
		}
2441
		$wlcmd[] = $wepset;
2442
	} else {
2443
		$wlcmd[] = "authmode open wepmode off ";
2444
	}
2445

    
2446
	kill_hostapd($if);
2447
	mwexec(kill_wpasupplicant("{$if}"));
2448

    
2449
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2450
	conf_mount_rw();
2451

    
2452
	switch ($wlcfg['mode']) {
2453
	case 'bss':
2454
		if (isset($wlcfg['wpa']['enable'])) {
2455
			$wpa .= <<<EOD
2456
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2457
ctrl_interface_group=0
2458
ap_scan=1
2459
#fast_reauth=1
2460
network={
2461
ssid="{$wlcfg['ssid']}"
2462
scan_ssid=1
2463
priority=5
2464
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2465
psk="{$wlcfg['wpa']['passphrase']}"
2466
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2467
group={$wlcfg['wpa']['wpa_pairwise']}
2468
}
2469
EOD;
2470

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

    
2505
EOD;
2506

    
2507
			if (isset($wlcfg['wpa']['rsn_preauth'])) {
2508
				$wpa .= <<<EOD
2509
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2510
rsn_preauth=1
2511
rsn_preauth_interfaces={$if}
2512

    
2513
EOD;
2514
			}
2515
			if (is_array($wlcfg['wpa']['ieee8021x']) && isset($wlcfg['wpa']['ieee8021x']['enable'])) {
2516
				$wpa .= "ieee8021x=1\n";
2517

    
2518
			if (!empty($wlcfg['auth_server_addr']) && !empty($wlcfg['auth_server_shared_secret'])) {
2519
				$auth_server_port = "1812";
2520
				if (!empty($wlcfg['auth_server_port']) && is_numeric($wlcfg['auth_server_port']))
2521
					$auth_server_port = intval($wlcfg['auth_server_port']);
2522
				$wpa .= <<<EOD
2523

    
2524
auth_server_addr={$wlcfg['auth_server_addr']}
2525
auth_server_port={$auth_server_port}
2526
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2527

    
2528
EOD;
2529
				if (!empty($wlcfg['auth_server_addr2']) && !empty($wlcfg['auth_server_shared_secret2'])) {
2530
					$auth_server_port2 = "1812";
2531
					if (!empty($wlcfg['auth_server_port2']) && is_numeric($wlcfg['auth_server_port2']))
2532
						$auth_server_port2 = intval($wlcfg['auth_server_port2']);
2533

    
2534
					$wpa .= <<<EOD
2535
auth_server_addr={$wlcfg['auth_server_addr2']}
2536
auth_server_port={$auth_server_port2}
2537
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2538

    
2539
EOD;
2540
					}
2541
				}
2542
			}
2543

    
2544
			@file_put_contents("{$g['varetc_path']}/hostapd_{$if}.conf", $wpa);
2545
			unset($wpa);
2546
		}
2547
		break;
2548
	}
2549

    
2550
	/*
2551
	 *    all variables are set, lets start up everything
2552
	 */
2553

    
2554
	$baseif = interface_get_wireless_base($if);
2555
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2556
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2557

    
2558
	/* set sysctls for the wireless interface */
2559
	if (!empty($wl_sysctl)) {
2560
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2561
		foreach ($wl_sysctl as $wl_sysctl_line) {
2562
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2563
		}
2564
	}
2565

    
2566
	/* set ack timers according to users preference (if he/she has any) */
2567
	if($distance) {
2568
		fwrite($fd_set, "# Enable ATH distance settings\n");
2569
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2570
	}
2571

    
2572
	if (isset($wlcfg['wpa']['enable'])) {
2573
		if ($wlcfg['mode'] == "bss") {
2574
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2575
		}
2576
		if ($wlcfg['mode'] == "hostap") {
2577
			/* add line to script to restore old mac to make hostapd happy */
2578
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2579
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2580
				if (is_macaddr($if_oldmac))
2581
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2582
						" link " . escapeshellarg($if_oldmac) . "\n");
2583
			}
2584

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

    
2587
			/* add line to script to restore spoofed mac after running hostapd */
2588
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2589
				if ($wl['spoofmac'])
2590
					$if_curmac = $wl['spoofmac'];
2591
				else
2592
					$if_curmac = get_interface_mac($if);
2593
				if (is_macaddr($if_curmac))
2594
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2595
						" link " . escapeshellarg($if_curmac) . "\n");
2596
			}
2597
		}
2598
	}
2599

    
2600
	fclose($fd_set);
2601
	conf_mount_ro();
2602

    
2603
	/* Making sure regulatory settings have actually changed
2604
	 * before applying, because changing them requires bringing
2605
	 * down all wireless networks on the interface. */
2606
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2607
	$ifconfig_str = implode($output);
2608
	unset($output);
2609
	$reg_changing = false;
2610

    
2611
	/* special case for the debug country code */
2612
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2613
		$reg_changing = true;
2614
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2615
		$reg_changing = true;
2616
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2617
		$reg_changing = true;
2618
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2619
		$reg_changing = true;
2620
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2621
		$reg_changing = true;
2622

    
2623
	if ($reg_changing) {
2624
		/* set regulatory domain */
2625
		if($wlcfg['regdomain'])
2626
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2627

    
2628
		/* set country */
2629
		if($wlcfg['regcountry'])
2630
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2631

    
2632
		/* set location */
2633
		if($wlcfg['reglocation'])
2634
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2635

    
2636
		$wlregcmd_args = implode(" ", $wlregcmd);
2637

    
2638
		/* build a complete list of the wireless clones for this interface */
2639
		$clone_list = array();
2640
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2641
			$clone_list[] = interface_get_wireless_clone($baseif);
2642
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2643
			foreach ($config['wireless']['clone'] as $clone) {
2644
				if ($clone['if'] == $baseif)
2645
					$clone_list[] = $clone['cloneif'];
2646
			}
2647
		}
2648

    
2649
		/* find which clones are up and bring them down */
2650
		$clones_up = array();
2651
		foreach ($clone_list as $clone_if) {
2652
			$clone_status = pfSense_get_interface_addresses($clone_if);
2653
			if ($clone_status['status'] == 'up') {
2654
				$clones_up[] = $clone_if;
2655
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2656
			}
2657
		}
2658

    
2659
		/* apply the regulatory settings */
2660
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2661

    
2662
		/* bring the clones back up that were previously up */
2663
		foreach ($clones_up as $clone_if) {
2664
			interfaces_bring_up($clone_if);
2665

    
2666
			/*
2667
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2668
			 * is in infrastructure mode, and WPA is enabled.
2669
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2670
			 */
2671
			if ($clone_if != $if) {
2672
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2673
				if ( !empty($friendly_if)
2674
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2675
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2676
					mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($clone_if) . "_setup.sh");
2677
				}
2678
			}
2679
		}
2680
	}
2681

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

    
2686
	/* configure wireless */
2687
	$wlcmd_args = implode(" ", $wlcmd);
2688
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $wlcmd_args, false);
2689
	unset($wlcmd_args, $wlcmd);
2690

    
2691

    
2692
	sleep(1);
2693
	/* execute hostapd and wpa_supplicant if required in shell */
2694
	mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($if) . "_setup.sh");
2695

    
2696
	return 0;
2697

    
2698
}
2699

    
2700
function kill_hostapd($interface) {
2701
	global $g;
2702

    
2703
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2704
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2705
}
2706

    
2707
function kill_wpasupplicant($interface) {
2708
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2709
}
2710

    
2711
function find_dhclient_process($interface) {
2712
	if ($interface)
2713
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2714
	else
2715
		$pid = 0;
2716

    
2717
	return intval($pid);
2718
}
2719

    
2720
function kill_dhclient_process($interface) {
2721
	if (empty($interface) || !does_interface_exist($interface))
2722
		return;
2723

    
2724
	$i = 0;
2725
	while ((($pid = find_dhclient_process($interface)) != 0) && ($i < 3)) {
2726
		/* 3rd time make it die for sure */
2727
		$sig = ($i == 2 ? SIGKILL : SIGTERM);
2728
		posix_kill($pid, $sig);
2729
		sleep(1);
2730
		$i++;
2731
	}
2732
	unset($i);
2733
}
2734

    
2735
function find_dhcp6c_process($interface) {
2736
	global $g;
2737

    
2738
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2739
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2740
	else
2741
		return(false);
2742

    
2743
	return intval($pid);
2744
}
2745

    
2746
function interface_virtual_create($interface) {
2747
	global $config;
2748

    
2749
	if (strstr($interface, "_vlan")) {
2750
		interfaces_vlan_configure($vlan);
2751
	} else if (substr($interface, 0, 3) == "gre") {
2752
		interfaces_gre_configure(0, $interface);
2753
	} else if (substr($interface, 0, 3) == "gif") {
2754
		interfaces_gif_configure(0, $interface);
2755
	} else if (substr($interface, 0, 5) == "ovpns") {
2756
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-server'])) {
2757
			foreach ($config['openvpn']['openvpn-server'] as $server) {
2758
				if ($interface == "ovpns{$server['vpnid']}") {
2759
					if (!function_exists('openvpn_resync'))
2760
						require_once('openvpn.inc');
2761
					log_error("OpenVPN: Resync server {$server['description']}");
2762
					openvpn_resync('server', $server);
2763
				}
2764
			}
2765
			unset($server);
2766
		}
2767
	} else if (substr($interface, 0, 5) == "ovpnc") {
2768
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-client'])) {
2769
			foreach ($config['openvpn']['openvpn-client'] as $client) {
2770
				if ($interface == "ovpnc{$client['vpnid']}") {
2771
					if (!function_exists('openvpn_resync'))
2772
						require_once('openvpn.inc');
2773
					log_error("OpenVPN: Resync server {$client['description']}");
2774
					openvpn_resync('client', $client);
2775
				}
2776
			}
2777
			unset($client);
2778
		}
2779
	} else if (substr($interface, 0, 4) == "lagg") {
2780
		interfaces_lagg_configure($interface);
2781
	} else if (substr($interface, 0, 6) == "bridge") {
2782
		interfaces_bridge_configure(0, $interface);
2783
	}
2784
}
2785

    
2786
function interface_vlan_mtu_configured($realhwif, $mtu) {
2787
	global $config;
2788

    
2789
	if (is_array($config['vlans']) && is_array($config['vlans']['vlan'])) {
2790
		foreach ($config['vlans']['vlan'] as $vlan) {
2791
			if ($vlan['if'] != $realhwif)
2792
				continue;
2793
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2794
			if (!empty($assignedport) && !empty($config['interfaces'][$assignedport]['mtu'])) {
2795
				if (intval($config['interfaces'][$assignedport]['mtu']) > $mtu)
2796
					$mtu = $config['interfaces'][$assignedport]['mtu'];
2797
			}
2798
		}
2799
	}
2800

    
2801
	return $mtu;
2802
}
2803

    
2804
function interface_vlan_adapt_mtu($vlanifs, $mtu) {
2805
	global $config;
2806

    
2807
	if (!is_array($vlanifs))
2808
		return;
2809

    
2810
	/* All vlans need to use the same mtu value as their parent. */
2811
	foreach ($vlanifs as $vlan) {
2812
		$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2813
		if (!empty($assignedport)) {
2814
			if (!empty($config['interfaces'][$assignedport]['mtu'])) {
2815
				pfSense_interface_mtu($vlan['vlanif'], $config['interfaces'][$assignedport]['mtu']);
2816
			} else {
2817
				if (get_interface_mtu($vlan['vlanif']) != $mtu)
2818
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
2819
			}
2820
		} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
2821
			pfSense_interface_mtu($vlan['vlanif'], $mtu);
2822
	}
2823
}
2824

    
2825
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2826
	global $config, $g;
2827
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2828
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2829

    
2830
	$wancfg = $config['interfaces'][$interface];
2831

    
2832
	if (!isset($wancfg['enable']))
2833
		return;
2834

    
2835
	$realif = get_real_interface($interface);
2836
	$realhwif_array = get_parent_interface($interface);
2837
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2838
	$realhwif = $realhwif_array[0];
2839

    
2840
	if (!platform_booting() && !(substr($realif, 0, 4) == "ovpn")) {
2841
		/* remove all IPv4 and IPv6 addresses */
2842
		$tmpifaces = pfSense_getall_interface_addresses($realif);
2843
		if (is_array($tmpifaces)) {
2844
			foreach ($tmpifaces as $tmpiface) {
2845
				if (is_ipaddrv6($tmpiface) || is_subnetv6($tmpiface)) {
2846
					if (!is_linklocal($tmpiface))
2847
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$tmpiface} delete");
2848
				} else {
2849
					if (is_subnetv4($tmpiface)) {
2850
						$tmpip = explode('/', $tmpiface);
2851
						$tmpip = $tmpip[0];
2852
					} else
2853
						$tmpip = $tmpiface;
2854
					pfSense_interface_deladdress($realif, $tmpip);
2855
				}
2856
			}
2857
		}
2858

    
2859
		/* only bring down the interface when both v4 and v6 are set to NONE */
2860
		if (empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6']))
2861
			interface_bring_down($interface);
2862
	}
2863

    
2864
	$interface_to_check = $realif;
2865
	if (interface_isppp_type($interface))
2866
		$interface_to_check = $realhwif;
2867

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

    
2872
	/* Disable Accepting router advertisements unless specifically requested */
2873
	if ($g['debug'])
2874
		log_error("Deny router advertisements for interface {$interface}");
2875
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv", true);
2876

    
2877
	/* wireless configuration? */
2878
	if (is_array($wancfg['wireless']))
2879
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2880

    
2881
	$mac = get_interface_mac($realhwif);
2882
	/*
2883
	 * Don't try to reapply the spoofed MAC if it's already applied.
2884
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2885
	 * the interface config again, which attempts to spoof the MAC again,
2886
	 * which cycles the link again...
2887
	 */
2888
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2889
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2890
			" link " . escapeshellarg($wancfg['spoofmac']));
2891
	}  else {
2892

    
2893
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2894
			/*   this is not a valid mac address.  generate a
2895
			 *   temporary mac address so the machine can get online.
2896
			 */
2897
			echo gettext("Generating new MAC address.");
2898
			$random_mac = generate_random_mac_address();
2899
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2900
				" link " . escapeshellarg($random_mac));
2901
			$wancfg['spoofmac'] = $random_mac;
2902
			write_config();
2903
			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");
2904
		}
2905
	}
2906

    
2907
	/* media */
2908
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2909
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2910
		if ($wancfg['media'])
2911
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2912
		if ($wancfg['mediaopt'])
2913
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2914
		mwexec($cmd);
2915
	}
2916

    
2917
	/* Apply hw offloading policies as configured */
2918
	enable_hardware_offloading($interface);
2919

    
2920
	/* invalidate interface/ip/sn cache */
2921
	get_interface_arr(true);
2922
	unset($interface_ip_arr_cache[$realif]);
2923
	unset($interface_sn_arr_cache[$realif]);
2924
	unset($interface_ipv6_arr_cache[$realif]);
2925
	unset($interface_snv6_arr_cache[$realif]);
2926

    
2927
	$tunnelif = substr($realif, 0, 3);
2928
	switch ($wancfg['ipaddr']) {
2929
	case 'dhcp':
2930
		interface_dhcp_configure($interface);
2931
		break;
2932
	case 'pppoe':
2933
	case 'l2tp':
2934
	case 'pptp':
2935
	case 'ppp':
2936
		interface_ppps_configure($interface);
2937
		break;
2938
	default:
2939
		/* XXX: Kludge for now related to #3280 */
2940
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
2941
			if (is_ipaddrv4($wancfg['ipaddr']) && $wancfg['subnet'] <> "")
2942
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2943
		}
2944
		break;
2945
	}
2946

    
2947
	switch ($wancfg['ipaddrv6']) {
2948
	case 'slaac':
2949
	case 'dhcp6':
2950
		interface_dhcpv6_configure($interface, $wancfg);
2951
		break;
2952
	case '6rd':
2953
		interface_6rd_configure($interface, $wancfg);
2954
		break;
2955
	case '6to4':
2956
		interface_6to4_configure($interface, $wancfg);
2957
		break;
2958
	case 'track6':
2959
		interface_track6_configure($interface, $wancfg, $linkupevent);
2960
		break;
2961
	default:
2962
		/* XXX: Kludge for now related to #3280 */
2963
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
2964
			if (is_ipaddrv6($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2965
				//pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2966
				// FIXME: Add IPv6 Support to the pfSense module
2967
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$wancfg['ipaddrv6']} prefixlen " . escapeshellarg($wancfg['subnetv6']));
2968
			}
2969
		}
2970
		break;
2971
	}
2972

    
2973
	if (!empty($wancfg['mtu'])) {
2974
		if (stristr($realif, "_vlan")) {
2975
			$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2976
			if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu'])) {
2977
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
2978
				if ($wancfg['mtu'] > $parentmtu)
2979
					log_error("There is a conflict on MTU between parent {$realhwif} and VLAN({$realif})");
2980
			} else
2981
				$parentmtu = 0;
2982

    
2983
			$parentmtu = interface_vlan_mtu_configured($realhwif, $parentmtu);
2984

    
2985
			if (get_interface_mtu($realhwif) != $parentmtu)
2986
				pfSense_interface_mtu($realhwif, $parentmtu);
2987

    
2988
			/* All vlans need to use the same mtu value as their parent. */
2989
			interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $parentmtu);
2990
		} else if (substr($realif, 0, 4) == 'lagg') {
2991
			/* LAGG interface must be destroyed and re-created to change MTU */
2992
			if ($wancfg['mtu'] != get_interface_mtu($realif)) {
2993
				if (isset($config['laggs']['lagg']) && is_array($config['laggs']['lagg'])) {
2994
					foreach ($config['laggs']['lagg'] as $lagg) {
2995
						if ($lagg['laggif'] == $realif) {
2996
							interface_lagg_configure($lagg);
2997
							break;
2998
						}
2999
					}
3000
				}
3001
			}
3002
		} else {
3003
			if ($wancfg['mtu'] != get_interface_mtu($realif))
3004
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3005

    
3006
			/* This case is needed when the parent of vlans is being configured */
3007
			$vlans = link_interface_to_vlans($realif);
3008
			if (is_array($vlans))
3009
				interface_vlan_adapt_mtu($vlans, $wancfg['mtu']);
3010
			unset($vlans);
3011
		}
3012
		/* XXX: What about gre/gif/.. ? */
3013
	}
3014

    
3015
	if (does_interface_exist($wancfg['if']))
3016
		interfaces_bring_up($wancfg['if']);
3017

    
3018
	interface_netgraph_needed($interface);
3019

    
3020
	if (!platform_booting()) {
3021
		link_interface_to_vips($interface, "update");
3022

    
3023
		if ($tunnelif != 'gre') {
3024
			unset($gre);
3025
			$gre = link_interface_to_gre($interface);
3026
			if (!empty($gre))
3027
				array_walk($gre, 'interface_gre_configure');
3028
		}
3029

    
3030
		if ($tunnelif != 'gif') {
3031
			unset($gif);
3032
			$gif = link_interface_to_gif($interface);
3033
			if (!empty($gif))
3034
				array_walk($gif, 'interface_gif_configure');
3035
		}
3036

    
3037
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3038
			unset($bridgetmp);
3039
			$bridgetmp = link_interface_to_bridge($interface);
3040
			if (!empty($bridgetmp))
3041
				interface_bridge_add_member($bridgetmp, $realif);
3042
		}
3043

    
3044
		$grouptmp = link_interface_to_group($interface);
3045
		if (!empty($grouptmp))
3046
			array_walk($grouptmp, 'interface_group_add_member');
3047

    
3048
		if ($interface == "lan")
3049
			/* make new hosts file */
3050
			system_hosts_generate();
3051

    
3052
		if ($reloadall == true) {
3053

    
3054
			/* reconfigure static routes (kernel may have deleted them) */
3055
			system_routing_configure($interface);
3056

    
3057
			/* reload ipsec tunnels */
3058
			send_event("service reload ipsecdns");
3059

    
3060
			/* restart dnsmasq or unbound */
3061
			if (isset($config['dnsmasq']['enable']))
3062
				services_dnsmasq_configure();
3063
			elseif (isset($config['unbound']['enable']))
3064
				services_unbound_configure();
3065

    
3066
			/* update dyndns */
3067
			send_event("service reload dyndns {$interface}");
3068

    
3069
			/* reload captive portal */
3070
			if (!function_exists('captiveportal_init_rules_byinterface'))
3071
				require_once('captiveportal.inc');
3072
			captiveportal_init_rules_byinterface($interface);
3073
		}
3074
	}
3075

    
3076
	interfaces_staticarp_configure($interface);
3077
	return 0;
3078
}
3079

    
3080
function interface_track6_configure($interface = "lan", $wancfg, $linkupevent = false) {
3081
	global $config, $g;
3082

    
3083
	if (!is_array($wancfg))
3084
		return;
3085

    
3086
	if (!isset($wancfg['enable']))
3087
		return;
3088

    
3089
	/* If the interface is not configured via another, exit */
3090
	if (empty($wancfg['track6-interface']))
3091
		return;
3092

    
3093
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3094
	$realif = get_real_interface($interface);
3095
	$linklocal = find_interface_ipv6_ll($realif);
3096
	if (!empty($linklocal))
3097
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3098
	/* XXX: This might break for good on a carp installation using link-local as network ips */
3099
	/* XXX: Probably should remove? */
3100
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3101

    
3102
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3103
	if (!isset($trackcfg['enable'])) {
3104
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3105
		return;
3106
	}
3107

    
3108
	switch($trackcfg['ipaddrv6']) {
3109
	case "6to4":
3110
		if ($g['debug'])
3111
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3112
		interface_track6_6to4_configure($interface, $wancfg);
3113
		break;
3114
	case "6rd":
3115
		if ($g['debug'])
3116
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3117
		interface_track6_6rd_configure($interface, $wancfg);
3118
		break;
3119
	case "dhcp6":
3120
		if ($linkupevent == true) {
3121
			/* 
3122
			 * NOTE: Usually come here from rc.linkup calling so just call directly intead of generating event
3123
			 * 	Instead of disrupting all other v4 configuration just restart DHCPv6 client for now
3124
			 *
3125
			 * XXX: Probably DHCPv6 client should handle this autmagically itself?
3126
			 */
3127
			$parentrealif = get_real_interface($wancfg['track6-interface']);
3128
			$pidv6 = find_dhcp6c_process($parentrealif);
3129
			if($pidv6)
3130
				posix_kill($pidv6, SIGHUP);
3131
		}
3132
		break;
3133
	}
3134

    
3135
	if ($linkupevent == false) {
3136
		if (!function_exists('services_dhcpd_configure'))
3137
			require_once("services.inc");
3138

    
3139
		if (isset($config['unbound']['enable']))
3140
			services_unbound_configure();
3141

    
3142
		services_dhcpd_configure("inet6");
3143
	}
3144

    
3145
	return 0;
3146
}
3147

    
3148
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3149
	global $config, $g;
3150
	global $interface_ipv6_arr_cache;
3151
	global $interface_snv6_arr_cache;
3152

    
3153
	if (!is_array($lancfg))
3154
		return;
3155

    
3156
	/* If the interface is not configured via another, exit */
3157
	if (empty($lancfg['track6-interface']))
3158
		return;
3159

    
3160
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3161
	if (empty($wancfg)) {
3162
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3163
		return;
3164
	}
3165

    
3166
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3167
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3168
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not valid, not configuring 6RD tunnel");
3169
		return;
3170
	}
3171
	$hexwanv4 = return_hex_ipv4($ip4address);
3172

    
3173
	/* create the long prefix notation for math, save the prefix length */
3174
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3175
	$rd6prefixlen = $rd6prefix[1];
3176
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3177

    
3178
	/* binary presentation of the prefix for all 128 bits. */
3179
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3180

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

    
3186
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3187
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3188
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3189
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3190
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3191
	/* fill the rest out with zeros */
3192
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);
3193

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

    
3197
	$lanif = get_real_interface($interface);
3198
	$oip = find_interface_ipv6($lanif);
3199
	if (is_ipaddrv6($oip))
3200
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3201
	unset($interface_ipv6_arr_cache[$lanif]);
3202
	unset($interface_snv6_arr_cache[$lanif]);
3203
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3204
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3205

    
3206
	return 0;
3207
}
3208

    
3209
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3210
	global $config, $g;
3211
	global $interface_ipv6_arr_cache;
3212
	global $interface_snv6_arr_cache;
3213

    
3214
	if (!is_array($lancfg))
3215
		return;
3216

    
3217
	/* If the interface is not configured via another, exit */
3218
	if (empty($lancfg['track6-interface']))
3219
		return;
3220

    
3221
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3222
	if (empty($wancfg)) {
3223
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3224
		return;
3225
	}
3226

    
3227
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3228
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3229
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3230
		return;
3231
	}
3232
	$hexwanv4 = return_hex_ipv4($ip4address);
3233

    
3234
	/* create the long prefix notation for math, save the prefix length */
3235
	$sixto4prefix = "2002::";
3236
	$sixto4prefixlen = 16;
3237
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3238

    
3239
	/* binary presentation of the prefix for all 128 bits. */
3240
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3241

    
3242
	/* just save the left prefix length bits */
3243
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3244
	/* add the v4 address */
3245
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3246
	/* add the custom prefix id */
3247
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3248
	/* fill the rest out with zeros */
3249
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);
3250

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

    
3254
	$lanif = get_real_interface($interface);
3255
	$oip = find_interface_ipv6($lanif);
3256
	if (is_ipaddrv6($oip))
3257
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3258
	unset($interface_ipv6_arr_cache[$lanif]);
3259
	unset($interface_snv6_arr_cache[$lanif]);
3260
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3261
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3262

    
3263
	return 0;
3264
}
3265

    
3266
function interface_6rd_configure($interface = "wan", $wancfg) {
3267
	global $config, $g;
3268

    
3269
	/* because this is a tunnel interface we can only function
3270
	 *	with a public IPv4 address on the interface */
3271

    
3272
	if (!is_array($wancfg))
3273
		return;
3274

    
3275
	if (!is_module_loaded('if_stf.ko'))
3276
		mwexec('/sbin/kldload if_stf.ko');
3277

    
3278
	$wanif = get_real_interface($interface);
3279
	$ip4address = find_interface_ip($wanif);
3280
	if (!is_ipaddrv4($ip4address)) {
3281
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3282
		return false;
3283
	}
3284
	$hexwanv4 = return_hex_ipv4($ip4address);
3285

    
3286
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3287
		$wancfg['prefix-6rd-v4plen'] = 0;
3288

    
3289
	/* create the long prefix notation for math, save the prefix length */
3290
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3291
	$rd6prefixlen = $rd6prefix[1];
3292
	$brgw = explode('.', $wancfg['gateway-6rd']);
3293
	$rd6brgw = rtrim($rd6prefix[0], ':') . ':' . dechex($brgw[0]) . dechex($brgw[1]) . ':' . dechex($brgw[2]) . dechex($brgw[3]) . '::';
3294
	unset($brgw);
3295
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3296

    
3297
	/* binary presentation of the prefix for all 128 bits. */
3298
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3299

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

    
3307
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3308
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3309

    
3310

    
3311
	/* XXX: need to extend to support variable prefix size for v4 */
3312
	if (!is_module_loaded("if_stf"))
3313
		mwexec("/sbin/kldload if_stf.ko");
3314
	$stfiface = "{$interface}_stf";
3315
	if (does_interface_exist($stfiface))
3316
		pfSense_interface_destroy($stfiface);
3317
	$tmpstfiface = pfSense_interface_create("stf");
3318
	pfSense_interface_rename($tmpstfiface, $stfiface);
3319
	pfSense_interface_flags($stfiface, IFF_LINK2);
3320
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3321
	mwexec("/sbin/ifconfig {$stfiface} stfv4br " . escapeshellarg($wancfg['gateway-6rd']));
3322
	if ($wancfg['prefix-6rd-v4plen'] >= 0 && $wancfg['prefix-6rd-v4plen'] <= 32)
3323
		mwexec("/sbin/ifconfig {$stfiface} stfv4net {$ip4address}/" . escapeshellarg($wancfg['prefix-6rd-v4plen']));
3324
	if ($g['debug'])
3325
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3326

    
3327
	/* write out a default router file */
3328
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3329
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3330

    
3331
	$ip4gateway = get_interface_gateway($interface);
3332
	if (is_ipaddrv4($ip4gateway))
3333
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3334

    
3335
	/* configure dependent interfaces */
3336
	if (!platform_booting())
3337
		link_interface_to_track6($interface, "update");
3338

    
3339
	return 0;
3340
}
3341

    
3342
function interface_6to4_configure($interface = "wan", $wancfg){
3343
	global $config, $g;
3344

    
3345
	/* because this is a tunnel interface we can only function
3346
	 *	with a public IPv4 address on the interface */
3347

    
3348
	if (!is_array($wancfg))
3349
		return;
3350

    
3351
	$wanif = get_real_interface($interface);
3352
	$ip4address = find_interface_ip($wanif);
3353
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3354
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3355
		return false;
3356
	}
3357

    
3358
	/* create the long prefix notation for math, save the prefix length */
3359
	$stfprefixlen = 16;
3360
	$stfprefix = Net_IPv6::uncompress("2002::");
3361
	$stfarr = explode(":", $stfprefix);
3362
	$v4prefixlen = "0";
3363

    
3364
	/* we need the hex form of the interface IPv4 address */
3365
	$ip4arr = explode(".", $ip4address);
3366
	$hexwanv4 = "";
3367
	foreach($ip4arr as $octet)
3368
		$hexwanv4 .= sprintf("%02x", $octet);
3369

    
3370
	/* we need the hex form of the broker IPv4 address */
3371
	$ip4arr = explode(".", "192.88.99.1");
3372
	$hexbrv4 = "";
3373
	foreach($ip4arr as $octet)
3374
		$hexbrv4 .= sprintf("%02x", $octet);
3375

    
3376
	/* binary presentation of the prefix for all 128 bits. */
3377
	$stfprefixbin = "";
3378
	foreach($stfarr as $element) {
3379
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3380
	}
3381
	/* just save the left prefix length bits */
3382
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3383

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

    
3388
	/* for the local subnet too. */
3389
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3390
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);
3391

    
3392
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3393
	$stfbrarr = array();
3394
	$stfbrbinarr = array();
3395
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3396
	foreach($stfbrbinarr as $bin)
3397
		$stfbrarr[] = dechex(bindec($bin));
3398
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3399

    
3400
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3401
	$stflanarr = array();
3402
	$stflanbinarr = array();
3403
	$stflanbinarr = str_split($stflanbin, 16);
3404
	foreach($stflanbinarr as $bin)
3405
		$stflanarr[] = dechex(bindec($bin));
3406
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3407
	$stflanarr[7] = 1;
3408
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3409

    
3410
	/* setup the stf interface */
3411
	if (!is_module_loaded("if_stf"))
3412
		mwexec("/sbin/kldload if_stf.ko");
3413
	$stfiface = "{$interface}_stf";
3414
	if (does_interface_exist($stfiface))
3415
		pfSense_interface_destroy($stfiface);
3416
	$tmpstfiface = pfSense_interface_create("stf");
3417
	pfSense_interface_rename($tmpstfiface, $stfiface);
3418
	pfSense_interface_flags($stfiface, IFF_LINK2);
3419
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3420

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

    
3424
	/* write out a default router file */
3425
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3426
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3427

    
3428
	$ip4gateway = get_interface_gateway($interface);
3429
	if (is_ipaddrv4($ip4gateway))
3430
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3431

    
3432
	if (!platform_booting())
3433
		link_interface_to_track6($interface, "update");
3434

    
3435
	return 0;
3436
}
3437

    
3438
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3439
	global $config, $g;
3440

    
3441
	if (!is_array($wancfg))
3442
		return;
3443

    
3444
	$wanif = get_real_interface($interface, "inet6");
3445
	$dhcp6cconf = "";
3446
	$dhcp6cconf .= "interface {$wanif} {\n";
3447

    
3448
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3449
	if($wancfg['ipaddrv6'] == "slaac") {
3450
		$dhcp6cconf .= "	information-only;\n";
3451
		$dhcp6cconf .= "	request domain-name-servers;\n";
3452
		$dhcp6cconf .= "	request domain-name;\n";
3453
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3454
		$dhcp6cconf .= "};\n";
3455
	} else {
3456
		/* skip address request if this is set */
3457
		if(!isset($wancfg['dhcp6prefixonly']))
3458
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3459
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3460
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3461

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

    
3466
		$dhcp6cconf .= "};\n";
3467

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

    
3471
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3472
			/* Setup the prefix delegation */
3473
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3474
			$preflen = 64 - $wancfg['dhcp6-ia-pd-len'];
3475
			if (isset($wancfg['dhcp6-ia-pd-send-hint']))
3476
				$dhcp6cconf .= "	prefix ::/{$preflen} infinity;\n";
3477
			$iflist = link_interface_to_track6($interface);
3478
			foreach ($iflist as $friendly => $ifcfg) {
3479
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3480
					if ($g['debug'])
3481
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3482
					$realif = get_real_interface($friendly);
3483
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3484
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3485
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3486
					$dhcp6cconf .= "	};\n";
3487
				}
3488
			}
3489
			unset($preflen, $iflist, $ifcfg);
3490
			$dhcp6cconf .= "};\n";
3491
		}
3492
	}
3493

    
3494
	// DHCP6 Config File Advanced
3495
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3496

    
3497
	// DHCP6 Config File Override
3498
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3499

    
3500
	/* wide-dhcp6c works for now. */
3501
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3502
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3503
		unset($dhcp6cconf);
3504
		return 1;
3505
	}
3506
	unset($dhcp6cconf);
3507

    
3508
	$dhcp6cscript = "#!/bin/sh\n";
3509
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3510
	$dhcp6cscript .= "dmips=\${new_domain_name_servers}\n";
3511
	$dhcp6cscript .= "dmnames=\${new_domain_name}\n";
3512
	$dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
3513
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3514
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3515
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3516
		unset($dhcp6cscript);
3517
		return 1;
3518
	}
3519
	unset($dhcp6cscript);
3520
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3521

    
3522
	$rtsoldscript = "#!/bin/sh\n";
3523
	$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
3524
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
3525
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_defaultgwv6\n";
3526
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Recieved RA specifying route \$2 for interface {$interface}({$wanif})\"\n";
3527
	$rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
3528
	$rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
3529
	$rtsoldscript .= "\t/bin/sleep 1\n";
3530
	$rtsoldscript .= "fi\n";
3531
	$rtsoldscript .= "/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
3532
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Starting dhcp6 client for interface {$interface}({$wanif})\"\n";
3533
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3534
	if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) {
3535
		printf("Error: cannot open rtsold_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3536
		unset($rtsoldscript);
3537
		return 1;
3538
	}
3539
	unset($rtsoldscript);
3540
	@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
3541

    
3542
	/* accept router advertisements for this interface */
3543
	set_single_sysctl("net.inet6.ip6.accept_rtadv", "1");
3544
	log_error("Accept router advertisements on interface {$wanif} ");
3545
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3546

    
3547
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3548
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3549
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3550
		sleep(2);
3551
	}
3552
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3553

    
3554
	/* NOTE: will be called from rtsold invoked script
3555
	 * link_interface_to_track6($interface, "update");
3556
	 */
3557

    
3558
	return 0;
3559
}
3560

    
3561
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3562
	global $g;
3563

    
3564
	$send_options = "";
3565
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3566
		$options = explode(',', $wancfg['adv_dhcp6_interface_statement_send_options']);
3567
		foreach ($options as $option) {
3568
			$send_options .= "\tsend " . trim($option) . ";\n";
3569
		}
3570
	}
3571

    
3572
	$request_options = "";
3573
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3574
		$options = explode(',', $wancfg['adv_dhcp6_interface_statement_request_options']);
3575
		foreach ($options as $option) {
3576
			$request_options .= "\trequest " . trim($option) . ";\n";
3577
		}
3578
	}
3579

    
3580
	$information_only = "";
3581
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3582
		$information_only = "\tinformation-only;\n";
3583

    
3584
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3585
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3586
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3587

    
3588
	$interface_statement  = "interface";
3589
	$interface_statement .= " {$wanif}";
3590
	$interface_statement .= " {\n";
3591
	$interface_statement .= "$send_options";
3592
	$interface_statement .= "$request_options";
3593
	$interface_statement .= "$information_only";
3594
	$interface_statement .= "$script";
3595
	$interface_statement .= "};\n";
3596

    
3597
	$id_assoc_statement_address = "";
3598
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3599
		$id_assoc_statement_address .= "id-assoc";
3600
		$id_assoc_statement_address .= " na";
3601
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3602
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3603
		$id_assoc_statement_address .= " { ";
3604

    
3605
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3606
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3607
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3608
			$id_assoc_statement_address .= "\n\taddress";
3609
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3610
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3611
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3612
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3613
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3614
			$id_assoc_statement_address .= ";\n";
3615
		}
3616

    
3617
		$id_assoc_statement_address  .= "};\n";
3618
	}
3619

    
3620
	$id_assoc_statement_prefix = "";
3621
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3622
		$id_assoc_statement_prefix .= "id-assoc";
3623
		$id_assoc_statement_prefix .= " pd";
3624
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3625
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3626
		$id_assoc_statement_prefix .= " { ";
3627

    
3628
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3629
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3630
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3631
			$id_assoc_statement_prefix .= "\n\tprefix";
3632
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3633
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3634
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3635
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3636
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3637
			$id_assoc_statement_prefix .= ";";
3638
		}
3639

    
3640
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3641
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3642
			$id_assoc_statement_prefix .= " {$wanif}";
3643
			$id_assoc_statement_prefix .= " {\n";
3644
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3645
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3646
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3647
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3648
			$id_assoc_statement_prefix .= "\t};";
3649
		}
3650

    
3651
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3652
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3653
			$id_assoc_statement_prefix .= "\n";
3654
		}
3655

    
3656
		$id_assoc_statement_prefix  .= "};\n";
3657
	}
3658

    
3659
	$authentication_statement = "";
3660
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3661
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3662
		$authentication_statement .= "authentication";
3663
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3664
		$authentication_statement .= " {\n";
3665
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3666
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3667
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3668
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3669
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3670
		$authentication_statement .= "};\n";
3671
	}
3672

    
3673
	$key_info_statement = "";
3674
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3675
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3676
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3677
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3678
		$key_info_statement .= "keyinfo";
3679
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3680
		$key_info_statement .= " {\n";
3681
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3682
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3683
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3684
		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'])) 
3685
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3686
		$key_info_statement .= "};\n";
3687
	}
3688

    
3689
	$dhcp6cconf  = $interface_statement;
3690
	$dhcp6cconf .= $id_assoc_statement_address;
3691
	$dhcp6cconf .= $id_assoc_statement_prefix;
3692
	$dhcp6cconf .= $authentication_statement;
3693
	$dhcp6cconf .= $key_info_statement;
3694

    
3695
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3696

    
3697
	return $dhcp6cconf;
3698
}
3699

    
3700

    
3701
function DHCP6_Config_File_Override($wancfg, $wanif) {
3702

    
3703
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3704
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3705

    
3706
	return $dhcp6cconf;
3707
}
3708

    
3709

    
3710
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3711

    
3712
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3713

    
3714
	return $dhcp6cconf;
3715
}
3716

    
3717

    
3718
function interface_dhcp_configure($interface = "wan") {
3719
	global $config, $g;
3720

    
3721
	$wancfg = $config['interfaces'][$interface];
3722
	$wanif = $wancfg['if'];
3723
	if (empty($wancfg))
3724
		$wancfg = array();
3725

    
3726
	/* generate dhclient_wan.conf */
3727
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3728
	if (!$fd) {
3729
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3730
		return 1;
3731
	}
3732

    
3733
	if ($wancfg['dhcphostname']) {
3734
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3735
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3736
	} else {
3737
		$dhclientconf_hostname = "";
3738
	}
3739

    
3740
	$wanif = get_real_interface($interface);
3741
	if (empty($wanif)) {
3742
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3743
		return 0;
3744
	}
3745
	$dhclientconf = "";
3746

    
3747
	$dhclientconf .= <<<EOD
3748
interface "{$wanif}" {
3749
timeout 60;
3750
retry 15;
3751
select-timeout 0;
3752
initial-interval 1;
3753
	{$dhclientconf_hostname}
3754
	script "/sbin/dhclient-script";
3755
EOD;
3756

    
3757
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3758
	$dhclientconf .= <<<EOD
3759

    
3760
	reject {$wancfg['dhcprejectfrom']};
3761
EOD;
3762
}
3763
	$dhclientconf .= <<<EOD
3764

    
3765
}
3766

    
3767
EOD;
3768

    
3769
	// DHCP Config File Advanced
3770
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3771

    
3772
if(is_ipaddr($wancfg['alias-address'])) {
3773
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3774
	$dhclientconf .= <<<EOD
3775
alias {
3776
	interface  "{$wanif}";
3777
	fixed-address {$wancfg['alias-address']};
3778
	option subnet-mask {$subnetmask};
3779
}
3780

    
3781
EOD;
3782
}
3783

    
3784
	// DHCP Config File Override
3785
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3786

    
3787
	fwrite($fd, $dhclientconf);
3788
	fclose($fd);
3789

    
3790
	/* bring wan interface up before starting dhclient */
3791
	if($wanif)
3792
		interfaces_bring_up($wanif);
3793
	else
3794
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3795

    
3796
	/* Make sure dhclient is not running */
3797
	kill_dhclient_process($wanif);
3798

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

    
3802
	return 0;
3803
}
3804

    
3805
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3806

    
3807
	$hostname = "";
3808
	if ($wancfg['dhcphostname'] != '') {
3809
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3810
	}
3811

    
3812
	/* DHCP Protocol Timings */
3813
	$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");
3814
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3815
		$pt_variable = "{$Protocol_Timing}";
3816
		${$pt_variable} = "";
3817
		if ($wancfg[$Protocol_Timing] != "") {
3818
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3819
		}
3820
	}
3821

    
3822
	$send_options = "";
3823
	if ($wancfg['adv_dhcp_send_options'] != '') {
3824
		$options = explode(',', $wancfg['adv_dhcp_send_options']);
3825
		foreach ($options as $option) {
3826
			$send_options .= "\tsend " . trim($option) . ";\n";
3827
		}
3828
	}
3829

    
3830
	$request_options = "";
3831
	if ($wancfg['adv_dhcp_request_options'] != '') {
3832
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3833
	}
3834

    
3835
	$required_options = "";
3836
	if ($wancfg['adv_dhcp_required_options'] != '') {
3837
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3838
	}
3839

    
3840
	$option_modifiers = "";
3841
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3842
		$modifiers = explode(',', $wancfg['adv_dhcp_option_modifiers']);
3843
		foreach ($modifiers as $modifier) {
3844
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3845
		}
3846
	}
3847

    
3848
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3849
 	$dhclientconf .= "\n";
3850
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3851
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3852
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3853
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3854
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3855
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3856
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3857
 	$dhclientconf .= "\n";
3858
 	$dhclientconf .= "# DHCP Protocol Options\n";
3859
 	$dhclientconf .= "{$hostname}";
3860
 	$dhclientconf .= "{$send_options}";
3861
 	$dhclientconf .= "{$request_options}";
3862
 	$dhclientconf .= "{$required_options}";
3863
 	$dhclientconf .= "{$option_modifiers}";
3864
 	$dhclientconf .= "\n";
3865
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3866
 	$dhclientconf .= "}\n";
3867

    
3868
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3869

    
3870
	return $dhclientconf;
3871
}
3872

    
3873

    
3874
function DHCP_Config_File_Override($wancfg, $wanif) {
3875

    
3876
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3877
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3878

    
3879
	return $dhclientconf;
3880
}
3881

    
3882

    
3883
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3884

    
3885
	/* Apply Interface Substitutions */
3886
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3887

    
3888
	/* Apply Hostname Substitutions */
3889
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3890

    
3891
	/* Arrays of MAC Address Types, Cases, Delimiters */
3892
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3893
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3894
	$various_mac_cases      = array("U", "L");
3895
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3896

    
3897
	/* Apply MAC Address Substitutions */
3898
	foreach ($various_mac_types as $various_mac_type) {
3899
		foreach ($various_mac_cases as $various_mac_case) {
3900
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3901

    
3902
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3903
				if ($res !== false) {
3904

    
3905
					/* Get MAC Address as ASCII String With Colon (:) Celimiters */
3906
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3907
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3908

    
3909
					if ("$various_mac_type" == "mac_addr_hex") {
3910
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3911
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3912
						$dhcpclientconf_mac_hex = "";
3913
						$delimiter = "";
3914
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3915
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3916
							$delimiter = ":";
3917
						}
3918
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3919
					}
3920

    
3921
					/* MAC Address Delimiter Substitutions */
3922
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3923

    
3924
					/* Apply MAC Address Substitutions */
3925
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
3926
				}
3927
			}
3928
		}
3929
	}
3930

    
3931
	return $dhclientconf;
3932
}
3933

    
3934
function interfaces_group_setup() {
3935
	global $config;
3936

    
3937
	if (!is_array($config['ifgroups']['ifgroupentry']))
3938
		return;
3939

    
3940
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3941
		interface_group_setup($groupar);
3942

    
3943
	return;
3944
}
3945

    
3946
function interface_group_setup(&$groupname /* The parameter is an array */) {
3947
	global $config;
3948

    
3949
	if (!is_array($groupname))
3950
		return;
3951
	$members = explode(" ", $groupname['members']);
3952
	foreach($members as $ifs) {
3953
		$realif = get_real_interface($ifs);
3954
		if ($realif && does_interface_exist($realif))
3955
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3956
	}
3957

    
3958
	return;
3959
}
3960

    
3961
function is_interface_group($if) {
3962
	global $config;
3963

    
3964
	if (is_array($config['ifgroups']['ifgroupentry']))
3965
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
3966
			if ($groupentry['ifname'] === $if)
3967
				return true;
3968
		}
3969

    
3970
	return false;
3971
}
3972

    
3973
function interface_group_add_member($interface, $groupname) {
3974
	$interface = get_real_interface($interface);
3975
	if (does_interface_exist($interface))
3976
		mwexec("/sbin/ifconfig {$interface} group " . escapeshellarg($groupname), true);
3977
}
3978

    
3979
/* COMPAT Function */
3980
function convert_friendly_interface_to_real_interface_name($interface) {
3981
	return get_real_interface($interface);
3982
}
3983

    
3984
/* COMPAT Function */
3985
function get_real_wan_interface($interface = "wan") {
3986
	return get_real_interface($interface);
3987
}
3988

    
3989
/* COMPAT Function */
3990
function get_current_wan_address($interface = "wan") {
3991
	return get_interface_ip($interface);
3992
}
3993

    
3994
/*
3995
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3996
 */
3997
function convert_real_interface_to_friendly_interface_name($interface = "wan", $checkparent = false) {
3998
	global $config;
3999

    
4000
	if (stripos($interface, "_vip")) {
4001
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
4002
			if ($vip['mode'] == "carp")  {
4003
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4004
				return $vip['interface'];
4005
			}
4006
		}
4007
	}
4008

    
4009
	/* XXX: For speed reasons reference directly the interface array */
4010
	$ifdescrs = &$config['interfaces'];
4011
	//$ifdescrs = get_configured_interface_list(false, true);
4012

    
4013
	foreach ($ifdescrs as $if => $ifname) {
4014
		if ($if == $interface || $ifname['if'] == $interface)
4015
			return $if;
4016

    
4017
		if (get_real_interface($if) == $interface)
4018
			return $if;
4019

    
4020
		if ($checkparent == false)
4021
			continue;
4022

    
4023
		$int = get_parent_interface($if, true);
4024
		if (is_array($int)) {
4025
			foreach ($int as $iface) {
4026
				if ($iface == $interface)
4027
					return $if;
4028
			}
4029
		}
4030
	}
4031

    
4032
	if ($interface == "enc0")
4033
		return 'IPsec';
4034
}
4035

    
4036
/* attempt to resolve interface to friendly descr */
4037
function convert_friendly_interface_to_friendly_descr($interface) {
4038
	global $config;
4039

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

    
4085
	return $ifdesc;
4086
}
4087

    
4088
function convert_real_interface_to_friendly_descr($interface) {
4089

    
4090
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4091

    
4092
	if (!empty($ifdesc))
4093
		return convert_friendly_interface_to_friendly_descr($ifdesc);
4094

    
4095
	return $interface;
4096
}
4097

    
4098
/*
4099
 *  get_parent_interface($interface):
4100
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4101
 *				or virtual interface (i.e. vlan)
4102
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4103
 *			-- returns $interface passed in if $interface parent is not found
4104
 *			-- returns empty array if an invalid interface is passed
4105
 *	(Only handles ppps and vlans now.)
4106
 */
4107
function get_parent_interface($interface, $avoidrecurse = false) {
4108
	global $config;
4109

    
4110
	$parents = array();
4111
	//Check that we got a valid interface passed
4112
	$realif = get_real_interface($interface);
4113
	if ($realif == NULL)
4114
		return $parents;
4115

    
4116
	// If we got a real interface, find it's friendly assigned name
4117
	if ($interface == $realif && $avoidrecurse == false)
4118
		$interface = convert_real_interface_to_friendly_interface_name($interface);
4119

    
4120
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4121
		$ifcfg = $config['interfaces'][$interface];
4122
		switch ($ifcfg['ipaddr']) {
4123
			case "ppp":
4124
			case "pppoe":
4125
			case "pptp":
4126
			case "l2tp":
4127
				if (empty($parents))
4128
					if (is_array($config['ppps']['ppp']))
4129
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4130
							if ($ifcfg['if'] == $ppp['if']) {
4131
								$ports = explode(',', $ppp['ports']);
4132
								foreach ($ports as $pid => $parent_if)
4133
									$parents[$pid] = get_real_interface($parent_if);
4134
								break;
4135
							}
4136
						}
4137
				break;
4138
			case "dhcp":
4139
			case "static":
4140
			default:
4141
				// Handle _vlans
4142
				if (strpos($realif, '_vlan') !== FALSE) {
4143
					if (is_array($config['vlans']['vlan'])) {
4144
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan) {
4145
							if ($ifcfg['if'] == $vlan['vlanif']) {
4146
								$parents[0] = $vlan['if'];
4147
								break;
4148
							}
4149
						}
4150
					}
4151
				}
4152
				break;
4153
		}
4154
	}
4155

    
4156
	if (empty($parents))
4157
		$parents[0] = $realif;
4158

    
4159
	return $parents;
4160
}
4161

    
4162
function interface_is_wireless_clone($wlif) {
4163
	if(!stristr($wlif, "_wlan")) {
4164
		return false;
4165
	} else {
4166
		return true;
4167
	}
4168
}
4169

    
4170
function interface_get_wireless_base($wlif) {
4171
	if(!stristr($wlif, "_wlan")) {
4172
		return $wlif;
4173
	} else {
4174
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4175
	}
4176
}
4177

    
4178
function interface_get_wireless_clone($wlif) {
4179
	if(!stristr($wlif, "_wlan")) {
4180
		return $wlif . "_wlan0";
4181
	} else {
4182
		return $wlif;
4183
	}
4184
}
4185

    
4186
function get_real_interface($interface = "wan", $family = "all", $realv6iface = false, $flush = true) {
4187
	global $config, $g;
4188

    
4189
	$wanif = NULL;
4190

    
4191
	switch ($interface) {
4192
	case "l2tp":
4193
		$wanif = "l2tp";
4194
		break;
4195
	case "pptp":
4196
		$wanif = "pptp";
4197
		break;
4198
	case "pppoe":
4199
		$wanif = "pppoe";
4200
		break;
4201
	case "openvpn":
4202
		$wanif = "openvpn";
4203
		break;
4204
	case "ipsec":
4205
	case "enc0":
4206
		$wanif = "enc0";
4207
		break;
4208
	case "ppp":
4209
		$wanif = "ppp";
4210
		break;
4211
	default:
4212
		// If a real interface was alread passed simply
4213
		// pass the real interface back.  This encourages
4214
		// the usage of this function in more cases so that
4215
		// we can combine logic for more flexibility.
4216
		if(does_interface_exist($interface, $flush)) {
4217
			$wanif = $interface;
4218
			break;
4219
		}
4220

    
4221
		if (empty($config['interfaces'][$interface]))
4222
			break;
4223

    
4224
		$cfg = &$config['interfaces'][$interface];
4225

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

    
4278
	return $wanif;
4279
}
4280

    
4281
/* Guess the physical interface by providing a IP address */
4282
function guess_interface_from_ip($ipaddress) {
4283

    
4284
	$family = '';
4285
	if(is_ipaddrv4($ipaddress))
4286
		$family = 'inet';
4287
	if (empty($family) && is_ipaddrv6($ipaddress))
4288
		$family = 'inet6';
4289

    
4290
	if (empty($family))
4291
		return false;
4292

    
4293
	/* create a route table we can search */
4294
	$output = '';
4295
	$_gb = exec("/sbin/route -n get -{$family} " . escapeshellarg($ipaddress) . " | /usr/bin/awk '/interface/ { print \$2; };'", $output);
4296
	$output[0] = trim($output[0], " \n");
4297
	if (!empty($output[0]))
4298
		return $output[0];
4299

    
4300
	return false;
4301
}
4302

    
4303
/*
4304
 * find_ip_interface($ip): return the interface where an ip is defined
4305
 *   (or if $bits is specified, where an IP within the subnet is defined)
4306
 */
4307
function find_ip_interface($ip, $bits = null) {
4308
	if (!is_ipaddr($ip))
4309
		return false;
4310

    
4311
	$isv6ip = is_ipaddrv6($ip);
4312

    
4313
	/* if list */
4314
	$ifdescrs = get_configured_interface_list();
4315

    
4316
	foreach ($ifdescrs as $ifdescr => $ifname) {
4317
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4318
		if (is_null($ifip))
4319
			continue;
4320
		if (is_null($bits)) {
4321
			if ($ip == $ifip) {
4322
				$int = get_real_interface($ifname);
4323
				return $int;
4324
			}
4325
		}
4326
		else {
4327
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4328
				$int = get_real_interface($ifname);
4329
				return $int;
4330
			}
4331
		}
4332
	}
4333

    
4334
	return false;
4335
}
4336

    
4337
/*
4338
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4339
 *   (or if $bits is specified, where an IP within the subnet is found)
4340
 */
4341
function find_virtual_ip_alias($ip, $bits = null) {
4342
	global $config;
4343

    
4344
	if (!is_array($config['virtualip']['vip'])) {
4345
		return false;
4346
	}
4347
	if (!is_ipaddr($ip))
4348
		return false;
4349

    
4350
	$isv6ip = is_ipaddrv6($ip);
4351

    
4352
	foreach ($config['virtualip']['vip'] as $vip) {
4353
		if ($vip['mode'] === "ipalias") {
4354
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4355
				continue;
4356
			if (is_null($bits)) {
4357
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4358
					return $vip;
4359
				}
4360
			}
4361
			else {
4362
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4363
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4364
					return $vip;
4365
				}
4366
			}
4367
		}
4368
	}
4369
	return false;
4370
}
4371

    
4372
/*
4373
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4374
 */
4375
function find_number_of_created_carp_interfaces() {
4376
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4377
}
4378

    
4379
/*
4380
 * find_carp_interface($ip): return the carp interface where an ip is defined
4381
 */
4382
function find_carp_interface($ip) {
4383
	global $config;
4384
	if (is_array($config['virtualip']['vip'])) {
4385
		foreach ($config['virtualip']['vip'] as $vip) {
4386
			if ($vip['mode'] == "carp") {
4387
				if(is_ipaddrv4($ip)) {
4388
					$carp_ip = get_interface_ip($vip['interface']);
4389
				}
4390
				if(is_ipaddrv6($ip)) {
4391
					$carp_ip = get_interface_ipv6($vip['interface']);
4392
				}
4393
				exec("/sbin/ifconfig", $output, $return);
4394
				foreach($output as $line) {
4395
					$elements = preg_split("/[ ]+/i", $line);
4396
					if(strstr($elements[0], "vip"))
4397
						$curif = str_replace(":", "", $elements[0]);
4398
					if(stristr($line, $ip)) {
4399
						$if = $curif;
4400
						continue;
4401
					}
4402
				}
4403

    
4404
				if ($if)
4405
					return $if;
4406
			}
4407
		}
4408
	}
4409
}
4410

    
4411
function link_carp_interface_to_parent($interface) {
4412
	global $config;
4413

    
4414
	if (empty($interface))
4415
		return;
4416

    
4417
	$carp_ip = get_interface_ip($interface);
4418
	$carp_ipv6 = get_interface_ipv6($interface);
4419

    
4420
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4421
		return;
4422

    
4423
	/* if list */
4424
	$ifdescrs = get_configured_interface_list();
4425
	foreach ($ifdescrs as $ifdescr => $ifname) {
4426
		/* check IPv4 */
4427
		if(is_ipaddrv4($carp_ip)) {
4428
			$interfaceip = get_interface_ip($ifname);
4429
			$subnet_bits = get_interface_subnet($ifname);
4430
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4431
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4432
				return $ifname;
4433
		}
4434
		/* Check IPv6 */
4435
		if(is_ipaddrv6($carp_ipv6)) {
4436
			$interfaceipv6 = get_interface_ipv6($ifname);
4437
			$prefixlen = get_interface_subnetv6($ifname);
4438
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4439
				return $ifname;
4440
		}
4441
	}
4442
	return "";
4443
}
4444

    
4445

    
4446
/****f* interfaces/link_ip_to_carp_interface
4447
 * NAME
4448
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4449
 * INPUTS
4450
 *   $ip
4451
 * RESULT
4452
 *   $carp_ints
4453
 ******/
4454
function link_ip_to_carp_interface($ip) {
4455
	global $config;
4456

    
4457
	if (!is_ipaddr($ip))
4458
		return;
4459

    
4460
	$carp_ints = "";
4461
	if (is_array($config['virtualip']['vip'])) {
4462
		$first = 0;
4463
		$carp_int = array();
4464
		foreach ($config['virtualip']['vip'] as $vip) {
4465
			if ($vip['mode'] == "carp") {
4466
				$carp_ip = $vip['subnet'];
4467
				$carp_sn = $vip['subnet_bits'];
4468
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4469
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4470
					$carp_int[] = get_real_interface($vip['interface']);
4471
				}
4472
			}
4473
		}
4474
		if (!empty($carp_int))
4475
			$carp_ints = implode(" ", array_unique($carp_int));
4476
	}
4477

    
4478
	return $carp_ints;
4479
}
4480

    
4481
function link_interface_to_track6($int, $action = "") {
4482
	global $config;
4483

    
4484
	if (empty($int))
4485
		return;
4486

    
4487
	if (is_array($config['interfaces'])) {
4488
		$list = array();
4489
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4490
			if (!isset($ifcfg['enable']))
4491
				continue;
4492
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4493
				if ($action == "update")
4494
					interface_track6_configure($ifname, $ifcfg);
4495
				else if ($action == "")
4496
					$list[$ifname] = $ifcfg;
4497
			}
4498
		}
4499
		return $list;
4500
	}
4501
}
4502

    
4503
function interface_find_child_cfgmtu($realiface) {
4504
	global $config;
4505

    
4506
	$interface = convert_real_interface_to_friendly_interface_name($realiface);
4507
	$vlans = link_interface_to_vlans($realiface);
4508
	$bridge = link_interface_to_bridge($realiface);
4509
	if (!empty($interface)) {
4510
		$gifs = link_interface_to_gif($interface);
4511
		$gres = link_interface_to_gre($interface);
4512
	} else {
4513
		$gifs = array();
4514
		$gres = array();
4515
	}
4516

    
4517
	$mtu = 0;
4518
	if (is_array($vlans)) {
4519
		foreach ($vlans as $vlan) {
4520
			$ifass = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
4521
			if (empty($ifass))
4522
				continue;
4523
			if (!empty($config['interfaces'][$ifass]['mtu'])) {
4524
				if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4525
					$mtu = intval($config['interfaces'][$ifass]['mtu']);
4526
			}
4527
		}
4528
	}
4529
	if (is_array($gifs)) {
4530
		foreach ($gifs as $vlan) {
4531
			$ifass = convert_real_interface_to_friendly_interface_name($vlan['gifif']);
4532
			if (empty($ifass))
4533
				continue;
4534
			if (!empty($config['interfaces'][$ifass]['mtu'])) {
4535
				if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4536
					$mtu = intval($config['interfaces'][$ifass]['mtu']);
4537
			}
4538
		}
4539
	}
4540
	if (is_array($gres)) {
4541
		foreach ($gres as $vlan) {
4542
			$ifass = convert_real_interface_to_friendly_interface_name($vlan['greif']);
4543
			if (empty($ifass))
4544
				continue;
4545
			if (!empty($config['interfaces'][$ifass]['mtu'])) {
4546
				if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4547
					$mtu = intval($config['interfaces'][$ifass]['mtu']);
4548
			}
4549
		}
4550
	}
4551
	$ifass = convert_real_interface_to_friendly_interface_name($bridge);
4552
	if (!empty($ifass) && !empty($config['interfaces'][$ifass]['mtu'])) {
4553
		if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4554
			$mtu = intval($config['interfaces'][$ifass]['mtu']);
4555
	}
4556
	unset($vlans, $bridge, $gifs, $gres, $ifass, $vlan);
4557

    
4558
	return $mtu;
4559
}
4560

    
4561
function link_interface_to_vlans($int, $action = "") {
4562
	global $config;
4563

    
4564
	if (empty($int))
4565
		return;
4566

    
4567
	if (is_array($config['vlans']['vlan'])) {
4568
		$ifaces = array();
4569
		foreach ($config['vlans']['vlan'] as $vlan) {
4570
			if ($int == $vlan['if']) {
4571
				if ($action == "update") {
4572
					interfaces_bring_up($int);
4573
				} else
4574
					$ifaces[$vlan['tag']] = $vlan;
4575
			}
4576
		}
4577
		if (!empty($ifaces))
4578
			return $ifaces;
4579
	}
4580
}
4581

    
4582
function link_interface_to_vips($int, $action = "") {
4583
	global $config;
4584

    
4585
	if (is_array($config['virtualip']['vip'])) {
4586
		$result = array();
4587
		foreach ($config['virtualip']['vip'] as $vip) {
4588
			if ($int == $vip['interface']) {
4589
				if ($action == "update")
4590
					interfaces_vips_configure($int);
4591
				else
4592
					$result[] = $vip;
4593
			}
4594
		}
4595
		return $result;
4596
	}
4597
}
4598

    
4599
/****f* interfaces/link_interface_to_bridge
4600
 * NAME
4601
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4602
 * INPUTS
4603
 *   $ip
4604
 * RESULT
4605
 *   bridge[0-99]
4606
 ******/
4607
function link_interface_to_bridge($int) {
4608
	global $config;
4609

    
4610
	if (is_array($config['bridges']['bridged'])) {
4611
		foreach ($config['bridges']['bridged'] as $bridge) {
4612
			if (in_array($int, explode(',', $bridge['members'])))
4613
				return "{$bridge['bridgeif']}";
4614
		}
4615
	}
4616
}
4617

    
4618
function link_interface_to_group($int) {
4619
	global $config;
4620

    
4621
	$result = array();
4622

    
4623
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4624
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4625
			if (in_array($int, explode(" ", $group['members'])))
4626
				$result[$group['ifname']] = $int;
4627
		}
4628
	}
4629

    
4630
	return $result;
4631
}
4632

    
4633
function link_interface_to_gre($interface) {
4634
	global $config;
4635

    
4636
	$result = array();
4637

    
4638
	if (is_array($config['gres']['gre'])) {
4639
		foreach ($config['gres']['gre'] as $gre)
4640
			if($gre['if'] == $interface)
4641
				$result[] = $gre;
4642
	}
4643

    
4644
	return $result;
4645
}
4646

    
4647
function link_interface_to_gif($interface) {
4648
	global $config;
4649

    
4650
	$result = array();
4651

    
4652
	if (is_array($config['gifs']['gif'])) {
4653
		foreach ($config['gifs']['gif'] as $gif)
4654
			if($gif['if'] == $interface)
4655
				$result[] = $gif;
4656
	}
4657

    
4658
	return $result;
4659
}
4660

    
4661
/*
4662
 * find_interface_ip($interface): return the interface ip (first found)
4663
 */
4664
function find_interface_ip($interface, $flush = false) {
4665
	global $interface_ip_arr_cache;
4666
	global $interface_sn_arr_cache;
4667

    
4668
	$interface = str_replace("\n", "", $interface);
4669

    
4670
	if (!does_interface_exist($interface))
4671
		return;
4672

    
4673
	/* Setup IP cache */
4674
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4675
		$ifinfo = pfSense_get_interface_addresses($interface);
4676
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4677
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4678
	}
4679

    
4680
	return $interface_ip_arr_cache[$interface];
4681
}
4682

    
4683
/*
4684
 * find_interface_ipv6($interface): return the interface ip (first found)
4685
 */
4686
function find_interface_ipv6($interface, $flush = false) {
4687
	global $interface_ipv6_arr_cache;
4688
	global $interface_snv6_arr_cache;
4689
	global $config;
4690

    
4691
	$interface = trim($interface);
4692
	$interface = get_real_interface($interface);
4693

    
4694
	if (!does_interface_exist($interface))
4695
		return;
4696

    
4697
	/* Setup IP cache */
4698
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4699
		$ifinfo = pfSense_get_interface_addresses($interface);
4700
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4701
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4702
	}
4703

    
4704
	return $interface_ipv6_arr_cache[$interface];
4705
}
4706

    
4707
/*
4708
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4709
 */
4710
function find_interface_ipv6_ll($interface, $flush = false) {
4711
	global $interface_llv6_arr_cache;
4712
	global $config;
4713

    
4714
	$interface = str_replace("\n", "", $interface);
4715

    
4716
	if (!does_interface_exist($interface))
4717
		return;
4718

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

    
4735
function find_interface_subnet($interface, $flush = false) {
4736
	global $interface_sn_arr_cache;
4737
	global $interface_ip_arr_cache;
4738

    
4739
	$interface = str_replace("\n", "", $interface);
4740
	if (does_interface_exist($interface) == false)
4741
		return;
4742

    
4743
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4744
		$ifinfo = pfSense_get_interface_addresses($interface);
4745
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4746
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4747
	}
4748

    
4749
	return $interface_sn_arr_cache[$interface];
4750
}
4751

    
4752
function find_interface_subnetv6($interface, $flush = false) {
4753
	global $interface_snv6_arr_cache;
4754
	global $interface_ipv6_arr_cache;
4755

    
4756
	$interface = str_replace("\n", "", $interface);
4757
	if (does_interface_exist($interface) == false)
4758
		return;
4759

    
4760
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4761
		$ifinfo = pfSense_get_interface_addresses($interface);
4762
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4763
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4764
	}
4765

    
4766
	return $interface_snv6_arr_cache[$interface];
4767
}
4768

    
4769
function ip_in_interface_alias_subnet($interface, $ipalias) {
4770
	global $config;
4771

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

    
4788
	return false;
4789
}
4790

    
4791
function get_interface_ip($interface = "wan") {
4792
	
4793
	$realif = get_failover_interface($interface);
4794
	if (!$realif) {
4795
		if (strstr($interface, "_vip"))
4796
			return get_configured_carp_interface_list($interface);
4797
		else
4798
			return null;
4799
	}
4800

    
4801
	$curip = find_interface_ip($realif);
4802
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4803
		return $curip;
4804
	else
4805
		return null;
4806
}
4807

    
4808
function get_interface_ipv6($interface = "wan", $flush = false) {
4809
	global $config;
4810

    
4811
	$realif = get_failover_interface($interface, "inet6");
4812
	if (!$realif) {
4813
		if (strstr($interface, "_vip"))
4814
			return get_configured_carp_interface_list($interface, "inet6");
4815
		else
4816
			return null;
4817
	}
4818

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

    
4840
	$curip = find_interface_ipv6($realif, $flush);
4841
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4842
		return $curip;
4843
	else
4844
		return null;
4845
}
4846

    
4847
function get_interface_linklocal($interface = "wan") {
4848

    
4849
	$realif = get_failover_interface($interface, "inet6");
4850
	if (!$realif) {
4851
		if (strstr($interface, "_vip")) {
4852
			list($interface, $vhid) = explode("_vip", $interface);
4853
			$realif = get_real_interface($interface);
4854
		} else
4855
			return null;
4856
	}
4857

    
4858
	$curip = find_interface_ipv6_ll($realif);
4859
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4860
		return $curip;
4861
	else
4862
		return null;
4863
}
4864

    
4865
function get_interface_subnet($interface = "wan") {
4866
	$realif = get_real_interface($interface);
4867
	if (!$realif) {
4868
		if (strstr($interface, "_vip")) {
4869
			list($interface, $vhid) = explode("_vip", $interface);
4870
			$realif = get_real_interface($interface);
4871
		} else
4872
			return null;
4873
	}
4874

    
4875
	$cursn = find_interface_subnet($realif);
4876
	if (!empty($cursn))
4877
		return $cursn;
4878

    
4879
	return null;
4880
}
4881

    
4882
function get_interface_subnetv6($interface = "wan") {
4883
	global $config;
4884

    
4885
	$realif = get_real_interface($interface, "inet6");
4886
	if (!$realif) {
4887
		if (strstr($interface, "_vip")) {
4888
			list($interface, $vhid) = explode("_vip", $interface);
4889
			$realif = get_real_interface($interface);
4890
		} else
4891
			return null;
4892
	}
4893

    
4894
	$cursn = find_interface_subnetv6($realif);
4895
	if (!empty($cursn))
4896
		return $cursn;
4897

    
4898
	return null;
4899
}
4900

    
4901
/* return outside interfaces with a gateway */
4902
function get_interfaces_with_gateway() {
4903
	global $config;
4904

    
4905
	$ints = array();
4906

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

    
4928
/* return true if interface has a gateway */
4929
function interface_has_gateway($friendly) {
4930
	global $config;
4931

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

    
4954
	return false;
4955
}
4956

    
4957
/* return true if interface has a gateway */
4958
function interface_has_gatewayv6($friendly) {
4959
	global $config;
4960

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

    
4982
	return false;
4983
}
4984

    
4985
/****f* interfaces/is_altq_capable
4986
 * NAME
4987
 *   is_altq_capable - Test if interface is capable of using ALTQ
4988
 * INPUTS
4989
 *   $int            - string containing interface name
4990
 * RESULT
4991
 *   boolean         - true or false
4992
 ******/
4993

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

    
5007
	$int_family = remove_ifindex($int);
5008

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

    
5021
/****f* interfaces/is_interface_wireless
5022
 * NAME
5023
 *   is_interface_wireless - Returns if an interface is wireless
5024
 * RESULT
5025
 *   $tmp       - Returns if an interface is wireless
5026
 ******/
5027
function is_interface_wireless($interface) {
5028
	global $config, $g;
5029

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

    
5042
function get_wireless_modes($interface) {
5043
	/* return wireless modes and channels */
5044
	$wireless_modes = array();
5045

    
5046
	$cloned_interface = get_real_interface($interface);
5047

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

    
5053
		$interface_channels = "";
5054
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5055
		$interface_channel_count = count($interface_channels);
5056

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

    
5086
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5087
function get_wireless_channel_info($interface) {
5088
	$wireless_channels = array();
5089

    
5090
	$cloned_interface = get_real_interface($interface);
5091

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

    
5097
		$interface_channels = "";
5098
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5099

    
5100
		foreach ($interface_channels as $channel_line) {
5101
			$channel_line = explode(",", $channel_line);
5102
			if(!isset($wireless_channels[$channel_line[0]]))
5103
				$wireless_channels[$channel_line[0]] = $channel_line;
5104
		}
5105
	}
5106
	return($wireless_channels);
5107
}
5108

    
5109
/****f* interfaces/get_interface_mtu
5110
 * NAME
5111
 *   get_interface_mtu - Return the mtu of an interface
5112
 * RESULT
5113
 *   $tmp       - Returns the mtu of an interface
5114
 ******/
5115
function get_interface_mtu($interface) {
5116
	$mtu = pfSense_interface_getmtu($interface);
5117
	return $mtu['mtu'];
5118
}
5119

    
5120
function get_interface_mac($interface) {
5121

    
5122
	$macinfo = pfSense_get_interface_addresses($interface);
5123
	return $macinfo["macaddr"];
5124
}
5125

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

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

    
5153
	if (isset($capable['caps']['vlanmtu']))
5154
		return true;
5155

    
5156
	// hack for some lagg modes missing vlanmtu, but work fine w/VLANs
5157
	if (substr($iface, 0, 4) == "lagg")
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)