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

    
2139
	$vip_password = $vip['password'];
2140
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2141
	if ($vip['password'] != "")
2142
		$password = " pass {$vip_password}";
2143

    
2144
	$advbase = "";
2145
	if (!empty($vip['advbase']))
2146
		$advbase = "advbase " . escapeshellarg($vip['advbase']);
2147

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

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

    
2161
	return $realif;
2162
}
2163

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

    
2205
	if($needs_clone == true) {
2206
		/* remove previous instance if it exists */
2207
		if(does_interface_exist($realif))
2208
			pfSense_interface_destroy($realif);
2209

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

    
2228
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2229
	global $config, $g;
2230

    
2231
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2232
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2233
				 'regdomain', 'regcountry', 'reglocation');
2234

    
2235
	if(!is_interface_wireless($ifcfg['if']))
2236
		return;
2237

    
2238
	$baseif = interface_get_wireless_base($ifcfg['if']);
2239

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

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

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

    
2297
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2298
	global $config, $g;
2299

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

    
2307
	// Remove script file
2308
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2309

    
2310
	// Clone wireless nic if needed.
2311
	interface_wireless_clone($if, $wl);
2312

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

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

    
2320
	/* set values for /path/program */
2321
	$hostapd = "/usr/sbin/hostapd";
2322
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2323
	$ifconfig = "/sbin/ifconfig";
2324
	$sysctl = "/sbin/sysctl";
2325
	$killall = "/usr/bin/killall";
2326

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

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

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

    
2342
	/* Set ssid */
2343
	if($wlcfg['ssid'])
2344
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2345

    
2346
	/* Set 802.11g protection mode */
2347
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2348

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

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

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

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

    
2370
	/* set Distance value */
2371
	if($wlcfg['distance'])
2372
		$distance = escapeshellarg($wlcfg['distance']);
2373

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

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

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

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

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

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

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

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

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

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

    
2462
	kill_hostapd($if);
2463
	mwexec(kill_wpasupplicant("{$if}"));
2464

    
2465
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2466
	conf_mount_rw();
2467

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

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

    
2521
EOD;
2522

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

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

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

    
2540
auth_server_addr={$wlcfg['auth_server_addr']}
2541
auth_server_port={$auth_server_port}
2542
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2543

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

    
2550
					$wpa .= <<<EOD
2551
auth_server_addr={$wlcfg['auth_server_addr2']}
2552
auth_server_port={$auth_server_port2}
2553
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2554

    
2555
EOD;
2556
					}
2557
				}
2558
			}
2559

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

    
2566
	/*
2567
	 *    all variables are set, lets start up everything
2568
	 */
2569

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

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

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

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

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

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

    
2616
	fclose($fd_set);
2617
	conf_mount_ro();
2618

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

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

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

    
2644
		/* set country */
2645
		if($wlcfg['regcountry'])
2646
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2647

    
2648
		/* set location */
2649
		if($wlcfg['reglocation'])
2650
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2651

    
2652
		$wlregcmd_args = implode(" ", $wlregcmd);
2653

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

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

    
2675
		/* apply the regulatory settings */
2676
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2677

    
2678
		/* bring the clones back up that were previously up */
2679
		foreach ($clones_up as $clone_if) {
2680
			interfaces_bring_up($clone_if);
2681

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

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

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

    
2707

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

    
2712
	return 0;
2713

    
2714
}
2715

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

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

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

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

    
2733
	return intval($pid);
2734
}
2735

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

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

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

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

    
2759
	return intval($pid);
2760
}
2761

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

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

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

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

    
2817
	return $mtu;
2818
}
2819

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2909
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2910
			/*   this is not a valid mac address.  generate a
2911
			 *   temporary mac address so the machine can get online.
2912
			 */
2913
			echo gettext("Generating new MAC address.");
2914
			$random_mac = generate_random_mac_address();
2915
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2916
				" link " . escapeshellarg($random_mac));
2917
			$wancfg['spoofmac'] = $random_mac;
2918
			write_config();
2919
			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");
2920
		}
2921
	}
2922

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

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

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

    
2943
	$tunnelif = substr($realif, 0, 3);
2944
	switch ($wancfg['ipaddr']) {
2945
	case 'dhcp':
2946
		interface_dhcp_configure($interface);
2947
		break;
2948
	case 'pppoe':
2949
	case 'l2tp':
2950
	case 'pptp':
2951
	case 'ppp':
2952
		interface_ppps_configure($interface);
2953
		break;
2954
	default:
2955
		/* XXX: Kludge for now related to #3280 */
2956
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
2957
			if (is_ipaddrv4($wancfg['ipaddr']) && $wancfg['subnet'] <> "")
2958
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2959
		}
2960
		break;
2961
	}
2962

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

    
2989
	if (!empty($wancfg['mtu'])) {
2990
		if (stristr($realif, "_vlan")) {
2991
			$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2992
			if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu'])) {
2993
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
2994
				if ($wancfg['mtu'] > $parentmtu)
2995
					log_error("There is a conflict on MTU between parent {$realhwif} and VLAN({$realif})");
2996
			} else
2997
				$parentmtu = 0;
2998

    
2999
			$parentmtu = interface_vlan_mtu_configured($realhwif, $parentmtu);
3000

    
3001
			if (get_interface_mtu($realhwif) != $parentmtu)
3002
				pfSense_interface_mtu($realhwif, $parentmtu);
3003

    
3004
			/* All vlans need to use the same mtu value as their parent. */
3005
			interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $parentmtu);
3006
		} else if (substr($realif, 0, 4) == 'lagg') {
3007
			/* LAGG interface must be destroyed and re-created to change MTU */
3008
			if ($wancfg['mtu'] != get_interface_mtu($realif)) {
3009
				if (isset($config['laggs']['lagg']) && is_array($config['laggs']['lagg'])) {
3010
					foreach ($config['laggs']['lagg'] as $lagg) {
3011
						if ($lagg['laggif'] == $realif) {
3012
							interface_lagg_configure($lagg);
3013
							break;
3014
						}
3015
					}
3016
				}
3017
			}
3018
		} else {
3019
			if ($wancfg['mtu'] != get_interface_mtu($realif))
3020
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3021

    
3022
			/* This case is needed when the parent of vlans is being configured */
3023
			$vlans = link_interface_to_vlans($realif);
3024
			if (is_array($vlans))
3025
				interface_vlan_adapt_mtu($vlans, $wancfg['mtu']);
3026
			unset($vlans);
3027
		}
3028
		/* XXX: What about gre/gif/.. ? */
3029
	}
3030

    
3031
	if (does_interface_exist($wancfg['if']))
3032
		interfaces_bring_up($wancfg['if']);
3033

    
3034
	interface_netgraph_needed($interface);
3035

    
3036
	if (!platform_booting()) {
3037
		link_interface_to_vips($interface, "update");
3038

    
3039
		unset($gre);
3040
		$gre = link_interface_to_gre($interface);
3041
		if (!empty($gre))
3042
			array_walk($gre, 'interface_gre_configure');
3043

    
3044
		unset($gif);
3045
		$gif = link_interface_to_gif($interface);
3046
		if (!empty($gif))
3047
			array_walk($gif, 'interface_gif_configure');
3048

    
3049
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3050
			unset($bridgetmp);
3051
			$bridgetmp = link_interface_to_bridge($interface);
3052
			if (!empty($bridgetmp))
3053
				interface_bridge_add_member($bridgetmp, $realif);
3054
		}
3055

    
3056
		$grouptmp = link_interface_to_group($interface);
3057
		if (!empty($grouptmp))
3058
			array_walk($grouptmp, 'interface_group_add_member');
3059

    
3060
		if ($interface == "lan")
3061
			/* make new hosts file */
3062
			system_hosts_generate();
3063

    
3064
		if ($reloadall == true) {
3065

    
3066
			/* reconfigure static routes (kernel may have deleted them) */
3067
			system_routing_configure($interface);
3068

    
3069
			/* reload ipsec tunnels */
3070
			send_event("service reload ipsecdns");
3071

    
3072
			/* restart dnsmasq or unbound */
3073
			if (isset($config['dnsmasq']['enable']))
3074
				services_dnsmasq_configure();
3075
			elseif (isset($config['unbound']['enable']))
3076
				services_unbound_configure();
3077

    
3078
			/* update dyndns */
3079
			send_event("service reload dyndns {$interface}");
3080

    
3081
			/* reload captive portal */
3082
			if (!function_exists('captiveportal_init_rules_byinterface'))
3083
				require_once('captiveportal.inc');
3084
			captiveportal_init_rules_byinterface($interface);
3085
		}
3086
	}
3087

    
3088
	interfaces_staticarp_configure($interface);
3089
	return 0;
3090
}
3091

    
3092
function interface_track6_configure($interface = "lan", $wancfg, $linkupevent = false) {
3093
	global $config, $g;
3094

    
3095
	if (!is_array($wancfg))
3096
		return;
3097

    
3098
	if (!isset($wancfg['enable']))
3099
		return;
3100

    
3101
	/* If the interface is not configured via another, exit */
3102
	if (empty($wancfg['track6-interface']))
3103
		return;
3104

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

    
3114
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3115
	if (!isset($trackcfg['enable'])) {
3116
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3117
		return;
3118
	}
3119

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

    
3147
	if ($linkupevent == false) {
3148
		if (!function_exists('services_dhcpd_configure'))
3149
			require_once("services.inc");
3150

    
3151
		if (isset($config['unbound']['enable']))
3152
			services_unbound_configure();
3153

    
3154
		services_dhcpd_configure("inet6");
3155
	}
3156

    
3157
	return 0;
3158
}
3159

    
3160
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3161
	global $config, $g;
3162
	global $interface_ipv6_arr_cache;
3163
	global $interface_snv6_arr_cache;
3164

    
3165
	if (!is_array($lancfg))
3166
		return;
3167

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

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

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

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

    
3190
	/* binary presentation of the prefix for all 128 bits. */
3191
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3192

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

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

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

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

    
3218
	return 0;
3219
}
3220

    
3221
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3222
	global $config, $g;
3223
	global $interface_ipv6_arr_cache;
3224
	global $interface_snv6_arr_cache;
3225

    
3226
	if (!is_array($lancfg))
3227
		return;
3228

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

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

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

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

    
3251
	/* binary presentation of the prefix for all 128 bits. */
3252
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3253

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

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

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

    
3275
	return 0;
3276
}
3277

    
3278
function interface_6rd_configure($interface = "wan", $wancfg) {
3279
	global $config, $g;
3280

    
3281
	/* because this is a tunnel interface we can only function
3282
	 *	with a public IPv4 address on the interface */
3283

    
3284
	if (!is_array($wancfg))
3285
		return;
3286

    
3287
	if (!is_module_loaded('if_stf.ko'))
3288
		mwexec('/sbin/kldload if_stf.ko');
3289

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

    
3298
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3299
		$wancfg['prefix-6rd-v4plen'] = 0;
3300

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

    
3309
	/* binary presentation of the prefix for all 128 bits. */
3310
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3311

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

    
3319
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3320
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3321

    
3322

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

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

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

    
3347
	/* configure dependent interfaces */
3348
	if (!platform_booting())
3349
		link_interface_to_track6($interface, "update");
3350

    
3351
	return 0;
3352
}
3353

    
3354
function interface_6to4_configure($interface = "wan", $wancfg){
3355
	global $config, $g;
3356

    
3357
	/* because this is a tunnel interface we can only function
3358
	 *	with a public IPv4 address on the interface */
3359

    
3360
	if (!is_array($wancfg))
3361
		return;
3362

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

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

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

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

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

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

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

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

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

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

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

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

    
3440
	$ip4gateway = get_interface_gateway($interface);
3441
	if (is_ipaddrv4($ip4gateway))
3442
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3443

    
3444
	if (!platform_booting())
3445
		link_interface_to_track6($interface, "update");
3446

    
3447
	return 0;
3448
}
3449

    
3450
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3451
	global $config, $g;
3452

    
3453
	if (!is_array($wancfg))
3454
		return;
3455

    
3456
	$wanif = get_real_interface($interface, "inet6");
3457
	$dhcp6cconf = "";
3458
	$dhcp6cconf .= "interface {$wanif} {\n";
3459

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

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

    
3478
		$dhcp6cconf .= "};\n";
3479

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

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

    
3506
	// DHCP6 Config File Advanced
3507
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3508

    
3509
	// DHCP6 Config File Override
3510
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3511

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

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

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

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

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

    
3566
	/* NOTE: will be called from rtsold invoked script
3567
	 * link_interface_to_track6($interface, "update");
3568
	 */
3569

    
3570
	return 0;
3571
}
3572

    
3573
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3574
	global $g;
3575

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

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

    
3592
	$information_only = "";
3593
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3594
		$information_only = "\tinformation-only;\n";
3595

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

    
3600
	$interface_statement  = "interface";
3601
	$interface_statement .= " {$wanif}";
3602
	$interface_statement .= " {\n";
3603
	$interface_statement .= "$send_options";
3604
	$interface_statement .= "$request_options";
3605
	$interface_statement .= "$information_only";
3606
	$interface_statement .= "$script";
3607
	$interface_statement .= "};\n";
3608

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

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

    
3629
		$id_assoc_statement_address  .= "};\n";
3630
	}
3631

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

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

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

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

    
3668
		$id_assoc_statement_prefix  .= "};\n";
3669
	}
3670

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

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

    
3701
	$dhcp6cconf  = $interface_statement;
3702
	$dhcp6cconf .= $id_assoc_statement_address;
3703
	$dhcp6cconf .= $id_assoc_statement_prefix;
3704
	$dhcp6cconf .= $authentication_statement;
3705
	$dhcp6cconf .= $key_info_statement;
3706

    
3707
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3708

    
3709
	return $dhcp6cconf;
3710
}
3711

    
3712

    
3713
function DHCP6_Config_File_Override($wancfg, $wanif) {
3714

    
3715
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3716
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3717

    
3718
	return $dhcp6cconf;
3719
}
3720

    
3721

    
3722
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3723

    
3724
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3725

    
3726
	return $dhcp6cconf;
3727
}
3728

    
3729

    
3730
function interface_dhcp_configure($interface = "wan") {
3731
	global $config, $g;
3732

    
3733
	$wancfg = $config['interfaces'][$interface];
3734
	$wanif = $wancfg['if'];
3735
	if (empty($wancfg))
3736
		$wancfg = array();
3737

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

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

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

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

    
3769
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3770
	$dhclientconf .= <<<EOD
3771

    
3772
	reject {$wancfg['dhcprejectfrom']};
3773
EOD;
3774
}
3775
	$dhclientconf .= <<<EOD
3776

    
3777
}
3778

    
3779
EOD;
3780

    
3781
	// DHCP Config File Advanced
3782
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3783

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

    
3793
EOD;
3794
}
3795

    
3796
	// DHCP Config File Override
3797
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3798

    
3799
	fwrite($fd, $dhclientconf);
3800
	fclose($fd);
3801

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

    
3808
	/* Make sure dhclient is not running */
3809
	kill_dhclient_process($wanif);
3810

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

    
3814
	return 0;
3815
}
3816

    
3817
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3818

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

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

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

    
3842
	$request_options = "";
3843
	if ($wancfg['adv_dhcp_request_options'] != '') {
3844
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3845
	}
3846

    
3847
	$required_options = "";
3848
	if ($wancfg['adv_dhcp_required_options'] != '') {
3849
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3850
	}
3851

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

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

    
3880
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3881

    
3882
	return $dhclientconf;
3883
}
3884

    
3885

    
3886
function DHCP_Config_File_Override($wancfg, $wanif) {
3887

    
3888
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3889
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3890

    
3891
	return $dhclientconf;
3892
}
3893

    
3894

    
3895
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3896

    
3897
	/* Apply Interface Substitutions */
3898
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3899

    
3900
	/* Apply Hostname Substitutions */
3901
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3902

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

    
3909
	/* Apply MAC Address Substitutions */
3910
	foreach ($various_mac_types as $various_mac_type) {
3911
		foreach ($various_mac_cases as $various_mac_case) {
3912
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3913

    
3914
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3915
				if ($res !== false) {
3916

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

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

    
3933
					/* MAC Address Delimiter Substitutions */
3934
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3935

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

    
3943
	return $dhclientconf;
3944
}
3945

    
3946
function interfaces_group_setup() {
3947
	global $config;
3948

    
3949
	if (!is_array($config['ifgroups']['ifgroupentry']))
3950
		return;
3951

    
3952
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3953
		interface_group_setup($groupar);
3954

    
3955
	return;
3956
}
3957

    
3958
function interface_group_setup(&$groupname /* The parameter is an array */) {
3959
	global $config;
3960

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

    
3970
	return;
3971
}
3972

    
3973
function is_interface_group($if) {
3974
	global $config;
3975

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

    
3982
	return false;
3983
}
3984

    
3985
function interface_group_add_member($interface, $groupname) {
3986
	$interface = get_real_interface($interface);
3987
	if (does_interface_exist($interface))
3988
		mwexec("/sbin/ifconfig {$interface} group " . escapeshellarg($groupname), true);
3989
}
3990

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

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

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

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

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

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

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

    
4029
		if (get_real_interface($if) == $interface)
4030
			return $if;
4031

    
4032
		if ($checkparent == false)
4033
			continue;
4034

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

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

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

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

    
4097
	return $ifdesc;
4098
}
4099

    
4100
function convert_real_interface_to_friendly_descr($interface) {
4101

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

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

    
4107
	return $interface;
4108
}
4109

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

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

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

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

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

    
4171
	return $parents;
4172
}
4173

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

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

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

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

    
4201
	$wanif = NULL;
4202

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

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

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

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

    
4290
	return $wanif;
4291
}
4292

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

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

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

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

    
4312
	return false;
4313
}
4314

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

    
4323
	$isv6ip = is_ipaddrv6($ip);
4324

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

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

    
4346
	return false;
4347
}
4348

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

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

    
4362
	$isv6ip = is_ipaddrv6($ip);
4363

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

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

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

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

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

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

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

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

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

    
4457

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

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

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

    
4490
	return $carp_ints;
4491
}
4492

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

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

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

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

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

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

    
4570
	return $mtu;
4571
}
4572

    
4573
function link_interface_to_vlans($int, $action = "") {
4574
	global $config;
4575

    
4576
	if (empty($int))
4577
		return;
4578

    
4579
	if (is_array($config['vlans']['vlan'])) {
4580
		$ifaces = array();
4581
		foreach ($config['vlans']['vlan'] as $vlan) {
4582
			if ($int == $vlan['if']) {
4583
				if ($action == "update") {
4584
					interfaces_bring_up($int);
4585
				} else
4586
					$ifaces[$vlan['tag']] = $vlan;
4587
			}
4588
		}
4589
		if (!empty($ifaces))
4590
			return $ifaces;
4591
	}
4592
}
4593

    
4594
function link_interface_to_vips($int, $action = "") {
4595
	global $config;
4596

    
4597
	if (is_array($config['virtualip']['vip'])) {
4598
		$result = array();
4599
		foreach ($config['virtualip']['vip'] as $vip) {
4600
			if ($int == $vip['interface']) {
4601
				if ($action == "update")
4602
					interfaces_vips_configure($int);
4603
				else
4604
					$result[] = $vip;
4605
			}
4606
		}
4607
		return $result;
4608
	}
4609
}
4610

    
4611
/****f* interfaces/link_interface_to_bridge
4612
 * NAME
4613
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4614
 * INPUTS
4615
 *   $ip
4616
 * RESULT
4617
 *   bridge[0-99]
4618
 ******/
4619
function link_interface_to_bridge($int) {
4620
	global $config;
4621

    
4622
	if (is_array($config['bridges']['bridged'])) {
4623
		foreach ($config['bridges']['bridged'] as $bridge) {
4624
			if (in_array($int, explode(',', $bridge['members'])))
4625
				return "{$bridge['bridgeif']}";
4626
		}
4627
	}
4628
}
4629

    
4630
function link_interface_to_group($int) {
4631
	global $config;
4632

    
4633
	$result = array();
4634

    
4635
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4636
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4637
			if (in_array($int, explode(" ", $group['members'])))
4638
				$result[$group['ifname']] = $int;
4639
		}
4640
	}
4641

    
4642
	return $result;
4643
}
4644

    
4645
function link_interface_to_gre($interface) {
4646
	global $config;
4647

    
4648
	$result = array();
4649

    
4650
	if (is_array($config['gres']['gre'])) {
4651
		foreach ($config['gres']['gre'] as $gre)
4652
			if($gre['if'] == $interface)
4653
				$result[] = $gre;
4654
	}
4655

    
4656
	return $result;
4657
}
4658

    
4659
function link_interface_to_gif($interface) {
4660
	global $config;
4661

    
4662
	$result = array();
4663

    
4664
	if (is_array($config['gifs']['gif'])) {
4665
		foreach ($config['gifs']['gif'] as $gif)
4666
			if($gif['if'] == $interface)
4667
				$result[] = $gif;
4668
	}
4669

    
4670
	return $result;
4671
}
4672

    
4673
/*
4674
 * find_interface_ip($interface): return the interface ip (first found)
4675
 */
4676
function find_interface_ip($interface, $flush = false) {
4677
	global $interface_ip_arr_cache;
4678
	global $interface_sn_arr_cache;
4679

    
4680
	$interface = str_replace("\n", "", $interface);
4681

    
4682
	if (!does_interface_exist($interface))
4683
		return;
4684

    
4685
	/* Setup IP cache */
4686
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4687
		$ifinfo = pfSense_get_interface_addresses($interface);
4688
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4689
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4690
	}
4691

    
4692
	return $interface_ip_arr_cache[$interface];
4693
}
4694

    
4695
/*
4696
 * find_interface_ipv6($interface): return the interface ip (first found)
4697
 */
4698
function find_interface_ipv6($interface, $flush = false) {
4699
	global $interface_ipv6_arr_cache;
4700
	global $interface_snv6_arr_cache;
4701
	global $config;
4702

    
4703
	$interface = trim($interface);
4704
	$interface = get_real_interface($interface);
4705

    
4706
	if (!does_interface_exist($interface))
4707
		return;
4708

    
4709
	/* Setup IP cache */
4710
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4711
		$ifinfo = pfSense_get_interface_addresses($interface);
4712
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4713
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4714
	}
4715

    
4716
	return $interface_ipv6_arr_cache[$interface];
4717
}
4718

    
4719
/*
4720
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4721
 */
4722
function find_interface_ipv6_ll($interface, $flush = false) {
4723
	global $interface_llv6_arr_cache;
4724
	global $config;
4725

    
4726
	$interface = str_replace("\n", "", $interface);
4727

    
4728
	if (!does_interface_exist($interface))
4729
		return;
4730

    
4731
	/* Setup IP cache */
4732
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4733
		$ifinfo = pfSense_getall_interface_addresses($interface);
4734
		foreach($ifinfo as $line) {
4735
			if (strstr($line, ":")) {
4736
				$parts = explode("/", $line);
4737
				if(is_linklocal($parts[0])) {
4738
					$ifinfo['linklocal'] = $parts[0];
4739
				}
4740
			}
4741
		}
4742
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4743
	}
4744
	return $interface_llv6_arr_cache[$interface];
4745
}
4746

    
4747
function find_interface_subnet($interface, $flush = false) {
4748
	global $interface_sn_arr_cache;
4749
	global $interface_ip_arr_cache;
4750

    
4751
	$interface = str_replace("\n", "", $interface);
4752
	if (does_interface_exist($interface) == false)
4753
		return;
4754

    
4755
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4756
		$ifinfo = pfSense_get_interface_addresses($interface);
4757
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4758
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4759
	}
4760

    
4761
	return $interface_sn_arr_cache[$interface];
4762
}
4763

    
4764
function find_interface_subnetv6($interface, $flush = false) {
4765
	global $interface_snv6_arr_cache;
4766
	global $interface_ipv6_arr_cache;
4767

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

    
4772
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4773
		$ifinfo = pfSense_get_interface_addresses($interface);
4774
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4775
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4776
	}
4777

    
4778
	return $interface_snv6_arr_cache[$interface];
4779
}
4780

    
4781
function ip_in_interface_alias_subnet($interface, $ipalias) {
4782
	global $config;
4783

    
4784
	if (empty($interface) || !is_ipaddr($ipalias))
4785
		return false;
4786
	if (is_array($config['virtualip']['vip'])) {
4787
		foreach ($config['virtualip']['vip'] as $vip) {
4788
			switch ($vip['mode']) {
4789
			case "ipalias":
4790
				if ($vip['interface'] <> $interface)
4791
					break;
4792
				$subnet = is_ipaddrv6($ipalias) ? gen_subnetv6($vip['subnet'], $vip['subnet_bits']) : gen_subnet($vip['subnet'], $vip['subnet_bits']);
4793
				if (ip_in_subnet($ipalias, $subnet . "/" . $vip['subnet_bits']))
4794
					return true;
4795
				break;
4796
			}
4797
		}
4798
	}
4799

    
4800
	return false;
4801
}
4802

    
4803
function get_interface_ip($interface = "wan") {
4804
	
4805
	$realif = get_failover_interface($interface);
4806
	if (!$realif) {
4807
		if (strstr($interface, "_vip"))
4808
			return get_configured_carp_interface_list($interface);
4809
		else
4810
			return null;
4811
	}
4812

    
4813
	$curip = find_interface_ip($realif);
4814
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4815
		return $curip;
4816
	else
4817
		return null;
4818
}
4819

    
4820
function get_interface_ipv6($interface = "wan", $flush = false) {
4821
	global $config;
4822

    
4823
	$realif = get_failover_interface($interface, "inet6");
4824
	if (!$realif) {
4825
		if (strstr($interface, "_vip"))
4826
			return get_configured_carp_interface_list($interface, "inet6");
4827
		else
4828
			return null;
4829
	}
4830

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

    
4852
	$curip = find_interface_ipv6($realif, $flush);
4853
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4854
		return $curip;
4855
	else
4856
		return null;
4857
}
4858

    
4859
function get_interface_linklocal($interface = "wan") {
4860

    
4861
	$realif = get_failover_interface($interface, "inet6");
4862
	if (!$realif) {
4863
		if (strstr($interface, "_vip")) {
4864
			list($interface, $vhid) = explode("_vip", $interface);
4865
			$realif = get_real_interface($interface);
4866
		} else
4867
			return null;
4868
	}
4869

    
4870
	$curip = find_interface_ipv6_ll($realif);
4871
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4872
		return $curip;
4873
	else
4874
		return null;
4875
}
4876

    
4877
function get_interface_subnet($interface = "wan") {
4878
	$realif = get_real_interface($interface);
4879
	if (!$realif) {
4880
		if (strstr($interface, "_vip")) {
4881
			list($interface, $vhid) = explode("_vip", $interface);
4882
			$realif = get_real_interface($interface);
4883
		} else
4884
			return null;
4885
	}
4886

    
4887
	$cursn = find_interface_subnet($realif);
4888
	if (!empty($cursn))
4889
		return $cursn;
4890

    
4891
	return null;
4892
}
4893

    
4894
function get_interface_subnetv6($interface = "wan") {
4895
	global $config;
4896

    
4897
	$realif = get_real_interface($interface, "inet6");
4898
	if (!$realif) {
4899
		if (strstr($interface, "_vip")) {
4900
			list($interface, $vhid) = explode("_vip", $interface);
4901
			$realif = get_real_interface($interface);
4902
		} else
4903
			return null;
4904
	}
4905

    
4906
	$cursn = find_interface_subnetv6($realif);
4907
	if (!empty($cursn))
4908
		return $cursn;
4909

    
4910
	return null;
4911
}
4912

    
4913
/* return outside interfaces with a gateway */
4914
function get_interfaces_with_gateway() {
4915
	global $config;
4916

    
4917
	$ints = array();
4918

    
4919
	/* loop interfaces, check config for outbound */
4920
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4921
		switch ($ifname['ipaddr']) {
4922
			case "dhcp":
4923
			case "ppp";
4924
			case "pppoe":
4925
			case "pptp":
4926
			case "l2tp":
4927
			case "ppp";
4928
				$ints[$ifdescr] = $ifdescr;
4929
			break;
4930
			default:
4931
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4932
				    !empty($ifname['gateway']))
4933
					$ints[$ifdescr] = $ifdescr;
4934
			break;
4935
		}
4936
	}
4937
	return $ints;
4938
}
4939

    
4940
/* return true if interface has a gateway */
4941
function interface_has_gateway($friendly) {
4942
	global $config;
4943

    
4944
	if (!empty($config['interfaces'][$friendly])) {
4945
		$ifname = &$config['interfaces'][$friendly];
4946
		switch ($ifname['ipaddr']) {
4947
			case "dhcp":
4948
			case "pppoe":
4949
			case "pptp":
4950
			case "l2tp":
4951
			case "ppp";
4952
				return true;
4953
			break;
4954
			default:
4955
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4956
					return true;
4957
				$tunnelif = substr($ifname['if'], 0, 3);
4958
				if ($tunnelif == "gif" || $tunnelif == "gre")
4959
					return true;
4960
				if (!empty($ifname['gateway']))
4961
					return true;
4962
			break;
4963
		}
4964
	}
4965

    
4966
	return false;
4967
}
4968

    
4969
/* return true if interface has a gateway */
4970
function interface_has_gatewayv6($friendly) {
4971
	global $config;
4972

    
4973
	if (!empty($config['interfaces'][$friendly])) {
4974
		$ifname = &$config['interfaces'][$friendly];
4975
		switch ($ifname['ipaddrv6']) {
4976
			case "slaac":
4977
			case "dhcp6":
4978
			case "6to4":
4979
			case "6rd":
4980
				return true;
4981
				break;
4982
			default:
4983
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4984
					return true;
4985
				$tunnelif = substr($ifname['if'], 0, 3);
4986
				if ($tunnelif == "gif" || $tunnelif == "gre")
4987
					return true;
4988
				if (!empty($ifname['gatewayv6']))
4989
					return true;
4990
				break;
4991
		}
4992
	}
4993

    
4994
	return false;
4995
}
4996

    
4997
/****f* interfaces/is_altq_capable
4998
 * NAME
4999
 *   is_altq_capable - Test if interface is capable of using ALTQ
5000
 * INPUTS
5001
 *   $int            - string containing interface name
5002
 * RESULT
5003
 *   boolean         - true or false
5004
 ******/
5005

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

    
5019
	$int_family = remove_ifindex($int);
5020

    
5021
	if (in_array($int_family, $capable))
5022
		return true;
5023
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
5024
		return true;
5025
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
5026
		return true;
5027
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
5028
		return true;
5029
	else
5030
		return false;
5031
}
5032

    
5033
/****f* interfaces/is_interface_wireless
5034
 * NAME
5035
 *   is_interface_wireless - Returns if an interface is wireless
5036
 * RESULT
5037
 *   $tmp       - Returns if an interface is wireless
5038
 ******/
5039
function is_interface_wireless($interface) {
5040
	global $config, $g;
5041

    
5042
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
5043
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
5044
		if (preg_match($g['wireless_regex'], $interface)) {
5045
			if (isset($config['interfaces'][$friendly]))
5046
				$config['interfaces'][$friendly]['wireless'] = array();
5047
			return true;
5048
		}
5049
		return false;
5050
	} else
5051
		return true;
5052
}
5053

    
5054
function get_wireless_modes($interface) {
5055
	/* return wireless modes and channels */
5056
	$wireless_modes = array();
5057

    
5058
	$cloned_interface = get_real_interface($interface);
5059

    
5060
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5061
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
5062
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5063
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
5064

    
5065
		$interface_channels = "";
5066
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5067
		$interface_channel_count = count($interface_channels);
5068

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

    
5098
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5099
function get_wireless_channel_info($interface) {
5100
	$wireless_channels = array();
5101

    
5102
	$cloned_interface = get_real_interface($interface);
5103

    
5104
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5105
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5106
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5107
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5108

    
5109
		$interface_channels = "";
5110
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5111

    
5112
		foreach ($interface_channels as $channel_line) {
5113
			$channel_line = explode(",", $channel_line);
5114
			if(!isset($wireless_channels[$channel_line[0]]))
5115
				$wireless_channels[$channel_line[0]] = $channel_line;
5116
		}
5117
	}
5118
	return($wireless_channels);
5119
}
5120

    
5121
/****f* interfaces/get_interface_mtu
5122
 * NAME
5123
 *   get_interface_mtu - Return the mtu of an interface
5124
 * RESULT
5125
 *   $tmp       - Returns the mtu of an interface
5126
 ******/
5127
function get_interface_mtu($interface) {
5128
	$mtu = pfSense_interface_getmtu($interface);
5129
	return $mtu['mtu'];
5130
}
5131

    
5132
function get_interface_mac($interface) {
5133

    
5134
	$macinfo = pfSense_get_interface_addresses($interface);
5135
	return $macinfo["macaddr"];
5136
}
5137

    
5138
/****f* pfsense-utils/generate_random_mac_address
5139
 * NAME
5140
 *   generate_random_mac - generates a random mac address
5141
 * INPUTS
5142
 *   none
5143
 * RESULT
5144
 *   $mac - a random mac address
5145
 ******/
5146
function generate_random_mac_address() {
5147
	$mac = "02";
5148
	for($x=0; $x<5; $x++)
5149
		$mac .= ":" . dechex(rand(16, 255));
5150
	return $mac;
5151
}
5152

    
5153
/****f* interfaces/is_jumbo_capable
5154
 * NAME
5155
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5156
 * INPUTS
5157
 *   $int             - string containing interface name
5158
 * RESULT
5159
 *   boolean          - true or false
5160
 ******/
5161
function is_jumbo_capable($iface) {
5162
	$iface = trim($iface);
5163
	$capable = pfSense_get_interface_addresses($iface);
5164

    
5165
	if (isset($capable['caps']['vlanmtu']))
5166
		return true;
5167

    
5168
	return false;
5169
}
5170

    
5171
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5172
	global $g;
5173

    
5174
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5175

    
5176
	if(!empty($iface) && !empty($pppif)){
5177
		$cron_cmd = <<<EOD
5178
#!/bin/sh
5179
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5180
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5181

    
5182
EOD;
5183

    
5184
		@file_put_contents($cron_file, $cron_cmd);
5185
		chmod($cron_file, 0755);
5186
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5187
	} else
5188
		unlink_if_exists($cron_file);
5189
}
5190

    
5191
function get_interface_default_mtu($type = "ethernet") {
5192
	switch ($type) {
5193
	case "gre":
5194
		return 1476;
5195
		break;
5196
	case "gif":
5197
		return 1280;
5198
		break;
5199
	case "tun":
5200
	case "vlan":
5201
	case "tap":
5202
	case "ethernet":
5203
	default:
5204
		return 1500;
5205
		break;
5206
	}
5207

    
5208
	/* Never reached */
5209
	return 1500;
5210
}
5211

    
5212
function get_vip_descr($ipaddress) {
5213
	global $config;
5214

    
5215
	foreach ($config['virtualip']['vip'] as $vip) {
5216
		if ($vip['subnet'] == $ipaddress) {
5217
			return ($vip['descr']);
5218
		}
5219
	}
5220
	return "";
5221
}
5222

    
5223
function interfaces_staticarp_configure($if) {
5224
	global $config, $g;
5225
	if(isset($config['system']['developerspew'])) {
5226
		$mt = microtime();
5227
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5228
	}
5229

    
5230
	$ifcfg = $config['interfaces'][$if];
5231

    
5232
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5233
		return 0;
5234

    
5235
	/* Enable staticarp, if enabled */
5236
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5237
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5238
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5239
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5240

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

    
5244
			}
5245

    
5246
		}
5247
	} else {
5248
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5249
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5250
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5251
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5252
				if (isset($arpent['arp_table_static_entry'])) {
5253
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5254
				}
5255
			}
5256
		}
5257
	}
5258

    
5259
	return 0;
5260
}
5261

    
5262
function get_failover_interface($interface, $family = "all") {
5263
	global $config;
5264

    
5265
	/* shortcut to get_real_interface if we find it in the config */
5266
	if (is_array($config['interfaces'][$interface])) {
5267
		return get_real_interface($interface, $family);
5268
	}
5269

    
5270
	/* compare against gateway groups */
5271
	$a_groups = return_gateway_groups_array();
5272
	if (is_array($a_groups[$interface])) {
5273
		/* we found a gateway group, fetch the interface or vip */
5274
		if ($a_groups[$interface][0]['vip'] <> "")
5275
			return $a_groups[$interface][0]['vip'];
5276
		else
5277
			return $a_groups[$interface][0]['int'];
5278
	}
5279
	/* fall through to get_real_interface */
5280
	/* XXX: Really needed? */
5281
	return get_real_interface($interface, $family);
5282
}
5283

    
5284
function remove_ifindex($ifname) {
5285
	return preg_replace("/[0-9]+$/", "", $ifname);
5286
}
5287

    
5288
?>
(26-26/68)