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
	$vipif = get_real_interface($vip['interface']);
1058
	switch ($vip['mode']) {
1059
	case "proxyarp":
1060
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1061
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1062
		break;
1063
	case "ipalias":
1064
		if (does_interface_exist($vipif)) {
1065
			if (is_ipaddrv6($vip['subnet']))
1066
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " -alias");
1067
			else
1068
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1069
		}
1070
		break;
1071
	case "carp":
1072
		/* XXX: Is enough to delete ip address? */
1073
		if (does_interface_exist($vipif)) {
1074
			if (is_ipaddrv6($vip['subnet']))
1075
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " delete");
1076
			else
1077
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1078
		}
1079
		break;
1080
	}
1081
}
1082

    
1083
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1084
	global $config, $g;
1085

    
1086
	if (!isset($config['interfaces'][$interface]))
1087
		return;
1088

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

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

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

    
1165
	$track6 = array();
1166
	switch ($ifcfg['ipaddrv6']) {
1167
	case "slaac":
1168
	case "dhcp6":
1169
		$pidv6 = find_dhcp6c_process($realif);
1170
		if($pidv6)
1171
			posix_kill($pidv6, SIGTERM);
1172
		sleep(3);
1173
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1174
		if (does_interface_exist($realifv6)) {
1175
			$ip6 = find_interface_ipv6($realifv6);
1176
			if (is_ipaddrv6($ip6) && $ip6 != "::")
1177
				mwexec("/sbin/ifconfig " . escapeshellarg($realifv6) . " inet6 {$ip6} delete", true);
1178
			interface_ipalias_cleanup($interface, "inet6");
1179
			if ($destroy == true)
1180
				pfSense_interface_flags($realif, -IFF_UP);
1181
			//mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1182
		}
1183
		$track6 = link_interface_to_track6($interface);
1184
		break;
1185
	case "6rd":
1186
	case "6to4":
1187
		$realif = "{$interface}_stf";
1188
		if(does_interface_exist("$realif")) {
1189
			$ip6 = get_interface_ipv6($interface);
1190
			if (is_ipaddrv6($ip6))
1191
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1192
			interface_ipalias_cleanup($interface, "inet6");
1193
			if ($destroy == true)
1194
				pfSense_interface_flags($realif, -IFF_UP);
1195
		}
1196
		$track6 = link_interface_to_track6($interface);
1197
		break;
1198
	default:
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
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1204
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1205
			interface_ipalias_cleanup($interface, "inet6");
1206
			if ($destroy == true)
1207
				pfSense_interface_flags($realif, -IFF_UP);
1208
			//mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1209
		}
1210
		$track6 = link_interface_to_track6($interface);
1211
		break;
1212
	}
1213

    
1214
	if (!empty($track6) && is_array($track6)) {
1215
		if (!function_exists('services_dhcp_configure'))
1216
			require_once('services.inc');
1217
		/* Bring down radvd and dhcp6 on these interfaces */
1218
		services_dhcpd_configure('inet6', $track6);
1219
	}
1220

    
1221
	$old_router = '';
1222
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1223
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1224

    
1225
	/* remove interface up file if it exists */
1226
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1227
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1228
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1229
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1230
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1231
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1232
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1233

    
1234
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1235
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1236
	if (is_array($ifcfg['wireless'])) {
1237
		kill_hostapd($realif);
1238
		mwexec(kill_wpasupplicant($realif));
1239
	}
1240

    
1241
	if ($destroy == true) {
1242
		if (preg_match("/^[a-z0-9]+^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1243
			pfSense_interface_destroy($realif);
1244
	}
1245

    
1246
	return;
1247
}
1248

    
1249
function interfaces_carp_set_maintenancemode($carp_maintenancemode){
1250
	global $config;
1251
	if (isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == false) {
1252
		unset($config["virtualip_carp_maintenancemode"]);
1253
		write_config("Leave CARP maintenance mode");
1254
		if(is_array($config['virtualip']['vip'])) {
1255
			$viparr = &$config['virtualip']['vip'];
1256
			foreach ($viparr as $vip) {
1257
				switch ($vip['mode']) {
1258
				case "carp":
1259
					interface_vip_bring_down($vip);
1260
					//sleep(1);
1261
					break;
1262
				}
1263
			}
1264
		}
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

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

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

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

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

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

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

    
1307
	return false;
1308
}
1309

    
1310
function interfaces_ptpid_next() {
1311

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

    
1316
	return $ptpid;
1317
}
1318

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

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

    
1330
	return NULL;
1331
}
1332

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

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

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

    
1342
	$itemhash = getMPDCRONSettings($pppif);
1343

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1604
EOD;
1605

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

    
1610
EOD;
1611

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

    
1619
EOD;
1620

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

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

    
1631
EOD;
1632

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

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

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

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

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

    
1659
EOD;
1660

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

    
1665
EOD;
1666

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

    
1671
EOD;
1672

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

    
1678
EOD;
1679

    
1680

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

    
1685
EOD;
1686

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

    
1692
EOD;
1693

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

    
1698
EOD;
1699

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

    
1704
EOD;
1705

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

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

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

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

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

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

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

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

    
1763
EOD;
1764

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

    
1770
EOD;
1771
		}
1772

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

    
1776

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1896
		sleep(1);
1897

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2122
	if (is_ipaddrv4($vip['subnet'])) {
2123
		/* Ensure a IP on this interface exists prior to configuring CARP. */
2124
		$ww_subnet_ip = find_interface_ip($realif);
2125
		if (!is_ipaddrv4($ww_subnet_ip)) {
2126
			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", "");
2127
			return;
2128
		}
2129
	} else if (is_ipaddrv6($vip['subnet'])) {
2130
		/* Ensure a IP on this interface exists prior to configuring CARP. */
2131
		$ww_subnet_ip = find_interface_ipv6($realif);
2132
		if (!is_ipaddrv6($ww_subnet_ip)) {
2133
			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", "");
2134
			return;
2135
		}
2136
	}
2137

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

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

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

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

    
2160
	return $realif;
2161
}
2162

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2520
EOD;
2521

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

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

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

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

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

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

    
2554
EOD;
2555
					}
2556
				}
2557
			}
2558

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2706

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

    
2711
	return 0;
2712

    
2713
}
2714

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

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

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

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

    
2732
	return intval($pid);
2733
}
2734

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

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

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

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

    
2758
	return intval($pid);
2759
}
2760

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

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

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

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

    
2816
	return $mtu;
2817
}
2818

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3033
	interface_netgraph_needed($interface);
3034

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

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

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

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

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

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

    
3063
		if ($reloadall == true) {
3064

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

    
3068
			/* reload ipsec tunnels */
3069
			vpn_ipsec_configure();
3070

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

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

    
3080
			/* XXX: which CPZONE? Needed? */
3081
			/* reload captive portal */
3082
			captiveportal_init_rules();
3083
		}
3084
	}
3085

    
3086
	interfaces_staticarp_configure($interface);
3087
	return 0;
3088
}
3089

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

    
3093
	if (!is_array($wancfg))
3094
		return;
3095

    
3096
	if (!isset($wancfg['enable']))
3097
		return;
3098

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

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

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

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

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

    
3149
		if (isset($config['unbound']['enable']))
3150
			services_unbound_configure();
3151

    
3152
		services_dhcpd_configure("inet6");
3153
	}
3154

    
3155
	return 0;
3156
}
3157

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

    
3163
	if (!is_array($lancfg))
3164
		return;
3165

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

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

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

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

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

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

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

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

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

    
3216
	return 0;
3217
}
3218

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

    
3224
	if (!is_array($lancfg))
3225
		return;
3226

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

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

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

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

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

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

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

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

    
3273
	return 0;
3274
}
3275

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

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

    
3282
	if (!is_array($wancfg))
3283
		return;
3284

    
3285
	if (!is_module_loaded('if_stf.ko'))
3286
		mwexec('/sbin/kldload if_stf.ko');
3287

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

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

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

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

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

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

    
3320

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

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

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

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

    
3349
	return 0;
3350
}
3351

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

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

    
3358
	if (!is_array($wancfg))
3359
		return;
3360

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3442
	if (!platform_booting())
3443
		link_interface_to_track6($interface, "update");
3444

    
3445
	return 0;
3446
}
3447

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

    
3451
	if (!is_array($wancfg))
3452
		return;
3453

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

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

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

    
3476
		$dhcp6cconf .= "};\n";
3477

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

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

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

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

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

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

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

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

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

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

    
3568
	return 0;
3569
}
3570

    
3571
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3572
	global $g;
3573

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

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

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

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

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

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

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

    
3627
		$id_assoc_statement_address  .= "};\n";
3628
	}
3629

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

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

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

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

    
3666
		$id_assoc_statement_prefix  .= "};\n";
3667
	}
3668

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

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

    
3699
	$dhcp6cconf  = $interface_statement;
3700
	$dhcp6cconf .= $id_assoc_statement_address;
3701
	$dhcp6cconf .= $id_assoc_statement_prefix;
3702
	$dhcp6cconf .= $authentication_statement;
3703
	$dhcp6cconf .= $key_info_statement;
3704

    
3705
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3706

    
3707
	return $dhcp6cconf;
3708
}
3709

    
3710

    
3711
function DHCP6_Config_File_Override($wancfg, $wanif) {
3712

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

    
3716
	return $dhcp6cconf;
3717
}
3718

    
3719

    
3720
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3721

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

    
3724
	return $dhcp6cconf;
3725
}
3726

    
3727

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

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

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

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

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

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

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

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

    
3775
}
3776

    
3777
EOD;
3778

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

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

    
3791
EOD;
3792
}
3793

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

    
3797
	fwrite($fd, $dhclientconf);
3798
	fclose($fd);
3799

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

    
3806
	/* Make sure dhclient is not running */
3807
	kill_dhclient_process($wanif);
3808

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

    
3812
	return 0;
3813
}
3814

    
3815
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3816

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

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

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

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

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

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

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

    
3878
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3879

    
3880
	return $dhclientconf;
3881
}
3882

    
3883

    
3884
function DHCP_Config_File_Override($wancfg, $wanif) {
3885

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

    
3889
	return $dhclientconf;
3890
}
3891

    
3892

    
3893
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3894

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

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

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

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

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

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

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

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

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

    
3941
	return $dhclientconf;
3942
}
3943

    
3944
function interfaces_group_setup() {
3945
	global $config;
3946

    
3947
	if (!is_array($config['ifgroups']['ifgroupentry']))
3948
		return;
3949

    
3950
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3951
		interface_group_setup($groupar);
3952

    
3953
	return;
3954
}
3955

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

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

    
3968
	return;
3969
}
3970

    
3971
function is_interface_group($if) {
3972
	global $config;
3973

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

    
3980
	return false;
3981
}
3982

    
3983
function interface_group_add_member($interface, $groupname) {
3984
	$interface = get_real_interface($interface);
3985
	mwexec("/sbin/ifconfig {$interface} group " . escapeshellarg($groupname), true);
3986
}
3987

    
3988
/* COMPAT Function */
3989
function convert_friendly_interface_to_real_interface_name($interface) {
3990
	return get_real_interface($interface);
3991
}
3992

    
3993
/* COMPAT Function */
3994
function get_real_wan_interface($interface = "wan") {
3995
	return get_real_interface($interface);
3996
}
3997

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

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

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

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

    
4022
	foreach ($ifdescrs as $if => $ifname) {
4023
		if ($if == $interface || $ifname['if'] == $interface)
4024
			return $if;
4025

    
4026
		if (get_real_interface($if) == $interface)
4027
			return $if;
4028

    
4029
		if ($checkparent == false)
4030
			continue;
4031

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

    
4041
	if ($interface == "enc0")
4042
		return 'IPsec';
4043
}
4044

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

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

    
4094
	return $ifdesc;
4095
}
4096

    
4097
function convert_real_interface_to_friendly_descr($interface) {
4098

    
4099
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4100

    
4101
	if (!empty($ifdesc))
4102
		return convert_friendly_interface_to_friendly_descr($ifdesc);
4103

    
4104
	return $interface;
4105
}
4106

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

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

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

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

    
4165
	if (empty($parents))
4166
		$parents[0] = $realif;
4167

    
4168
	return $parents;
4169
}
4170

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

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

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

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

    
4198
	$wanif = NULL;
4199

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

    
4230
		if (empty($config['interfaces'][$interface]))
4231
			break;
4232

    
4233
		$cfg = &$config['interfaces'][$interface];
4234

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

    
4287
	return $wanif;
4288
}
4289

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

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

    
4299
	if (empty($family))
4300
		return false;
4301

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

    
4309
	return false;
4310
}
4311

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

    
4320
	$isv6ip = is_ipaddrv6($ip);
4321

    
4322
	/* if list */
4323
	$ifdescrs = get_configured_interface_list();
4324

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

    
4343
	return false;
4344
}
4345

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

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

    
4359
	$isv6ip = is_ipaddrv6($ip);
4360

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

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

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

    
4413
				if ($if)
4414
					return $if;
4415
			}
4416
		}
4417
	}
4418
}
4419

    
4420
function link_carp_interface_to_parent($interface) {
4421
	global $config;
4422

    
4423
	if (empty($interface))
4424
		return;
4425

    
4426
	$carp_ip = get_interface_ip($interface);
4427
	$carp_ipv6 = get_interface_ipv6($interface);
4428

    
4429
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4430
		return;
4431

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

    
4454

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

    
4466
	if (!is_ipaddr($ip))
4467
		return;
4468

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

    
4487
	return $carp_ints;
4488
}
4489

    
4490
function link_interface_to_track6($int, $action = "") {
4491
	global $config;
4492

    
4493
	if (empty($int))
4494
		return;
4495

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

    
4512
function interface_find_child_cfgmtu($realiface) {
4513
	global $config;
4514

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

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

    
4567
	return $mtu;
4568
}
4569

    
4570
function link_interface_to_vlans($int, $action = "") {
4571
	global $config;
4572

    
4573
	if (empty($int))
4574
		return;
4575

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

    
4591
function link_interface_to_vips($int, $action = "") {
4592
	global $config;
4593

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

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

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

    
4627
function link_interface_to_group($int) {
4628
	global $config;
4629

    
4630
	$result = array();
4631

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

    
4639
	return $result;
4640
}
4641

    
4642
function link_interface_to_gre($interface) {
4643
	global $config;
4644

    
4645
	$result = array();
4646

    
4647
	if (is_array($config['gres']['gre'])) {
4648
		foreach ($config['gres']['gre'] as $gre)
4649
			if($gre['if'] == $interface)
4650
				$result[] = $gre;
4651
	}
4652

    
4653
	return $result;
4654
}
4655

    
4656
function link_interface_to_gif($interface) {
4657
	global $config;
4658

    
4659
	$result = array();
4660

    
4661
	if (is_array($config['gifs']['gif'])) {
4662
		foreach ($config['gifs']['gif'] as $gif)
4663
			if($gif['if'] == $interface)
4664
				$result[] = $gif;
4665
	}
4666

    
4667
	return $result;
4668
}
4669

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

    
4677
	$interface = str_replace("\n", "", $interface);
4678

    
4679
	if (!does_interface_exist($interface))
4680
		return;
4681

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

    
4689
	return $interface_ip_arr_cache[$interface];
4690
}
4691

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

    
4700
	$interface = trim($interface);
4701
	$interface = get_real_interface($interface);
4702

    
4703
	if (!does_interface_exist($interface))
4704
		return;
4705

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

    
4713
	return $interface_ipv6_arr_cache[$interface];
4714
}
4715

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

    
4723
	$interface = str_replace("\n", "", $interface);
4724

    
4725
	if (!does_interface_exist($interface))
4726
		return;
4727

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

    
4744
function find_interface_subnet($interface, $flush = false) {
4745
	global $interface_sn_arr_cache;
4746
	global $interface_ip_arr_cache;
4747

    
4748
	$interface = str_replace("\n", "", $interface);
4749
	if (does_interface_exist($interface) == false)
4750
		return;
4751

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

    
4758
	return $interface_sn_arr_cache[$interface];
4759
}
4760

    
4761
function find_interface_subnetv6($interface, $flush = false) {
4762
	global $interface_snv6_arr_cache;
4763
	global $interface_ipv6_arr_cache;
4764

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

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

    
4775
	return $interface_snv6_arr_cache[$interface];
4776
}
4777

    
4778
function ip_in_interface_alias_subnet($interface, $ipalias) {
4779
	global $config;
4780

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

    
4797
	return false;
4798
}
4799

    
4800
function get_interface_ip($interface = "wan") {
4801
	// if we get passed an IP for some reason, return the IP. 
4802
	if (is_ipaddr($interface))
4803
		return $interface;
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
	// if we get passed an IP for some reason, return the IP. 
4824
	if (is_ipaddr($interface))
4825
		return $interface;
4826

    
4827
	$realif = get_failover_interface($interface, "inet6");
4828
	if (!$realif) {
4829
		if (strstr($interface, "_vip"))
4830
			return get_configured_carp_interface_list($interface, "inet6");
4831
		else
4832
			return null;
4833
	}
4834

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

    
4856
	$curip = find_interface_ipv6($realif, $flush);
4857
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4858
		return $curip;
4859
	else
4860
		return null;
4861
}
4862

    
4863
function get_interface_linklocal($interface = "wan") {
4864

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

    
4874
	$curip = find_interface_ipv6_ll($realif);
4875
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4876
		return $curip;
4877
	else
4878
		return null;
4879
}
4880

    
4881
function get_interface_subnet($interface = "wan") {
4882
	$realif = get_real_interface($interface);
4883
	if (!$realif) {
4884
		if (strstr($interface, "_vip")) {
4885
			list($interface, $vhid) = explode("_vip", $interface);
4886
			$realif = get_real_interface($interface);
4887
		} else
4888
			return null;
4889
	}
4890

    
4891
	$cursn = find_interface_subnet($realif);
4892
	if (!empty($cursn))
4893
		return $cursn;
4894

    
4895
	return null;
4896
}
4897

    
4898
function get_interface_subnetv6($interface = "wan") {
4899
	global $config;
4900

    
4901
	$realif = get_real_interface($interface, "inet6");
4902
	if (!$realif) {
4903
		if (strstr($interface, "_vip")) {
4904
			list($interface, $vhid) = explode("_vip", $interface);
4905
			$realif = get_real_interface($interface);
4906
		} else
4907
			return null;
4908
	}
4909

    
4910
	$cursn = find_interface_subnetv6($realif);
4911
	if (!empty($cursn))
4912
		return $cursn;
4913

    
4914
	return null;
4915
}
4916

    
4917
/* return outside interfaces with a gateway */
4918
function get_interfaces_with_gateway() {
4919
	global $config;
4920

    
4921
	$ints = array();
4922

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

    
4944
/* return true if interface has a gateway */
4945
function interface_has_gateway($friendly) {
4946
	global $config;
4947

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

    
4970
	return false;
4971
}
4972

    
4973
/* return true if interface has a gateway */
4974
function interface_has_gatewayv6($friendly) {
4975
	global $config;
4976

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

    
4998
	return false;
4999
}
5000

    
5001
/****f* interfaces/is_altq_capable
5002
 * NAME
5003
 *   is_altq_capable - Test if interface is capable of using ALTQ
5004
 * INPUTS
5005
 *   $int            - string containing interface name
5006
 * RESULT
5007
 *   boolean         - true or false
5008
 ******/
5009

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

    
5023
	$int_family = remove_ifindex($int);
5024

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

    
5037
/****f* interfaces/is_interface_wireless
5038
 * NAME
5039
 *   is_interface_wireless - Returns if an interface is wireless
5040
 * RESULT
5041
 *   $tmp       - Returns if an interface is wireless
5042
 ******/
5043
function is_interface_wireless($interface) {
5044
	global $config, $g;
5045

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

    
5058
function get_wireless_modes($interface) {
5059
	/* return wireless modes and channels */
5060
	$wireless_modes = array();
5061

    
5062
	$cloned_interface = get_real_interface($interface);
5063

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

    
5069
		$interface_channels = "";
5070
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5071
		$interface_channel_count = count($interface_channels);
5072

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

    
5102
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5103
function get_wireless_channel_info($interface) {
5104
	$wireless_channels = array();
5105

    
5106
	$cloned_interface = get_real_interface($interface);
5107

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

    
5113
		$interface_channels = "";
5114
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5115

    
5116
		foreach ($interface_channels as $channel_line) {
5117
			$channel_line = explode(",", $channel_line);
5118
			if(!isset($wireless_channels[$channel_line[0]]))
5119
				$wireless_channels[$channel_line[0]] = $channel_line;
5120
		}
5121
	}
5122
	return($wireless_channels);
5123
}
5124

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

    
5136
function get_interface_mac($interface) {
5137

    
5138
	$macinfo = pfSense_get_interface_addresses($interface);
5139
	return $macinfo["macaddr"];
5140
}
5141

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

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

    
5169
	if (isset($capable['caps']['vlanmtu']))
5170
		return true;
5171

    
5172
	return false;
5173
}
5174

    
5175
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5176
	global $g;
5177

    
5178
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5179

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

    
5186
EOD;
5187

    
5188
		@file_put_contents($cron_file, $cron_cmd);
5189
		chmod($cron_file, 0755);
5190
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5191
	} else
5192
		unlink_if_exists($cron_file);
5193
}
5194

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

    
5212
	/* Never reached */
5213
	return 1500;
5214
}
5215

    
5216
function get_vip_descr($ipaddress) {
5217
	global $config;
5218

    
5219
	foreach ($config['virtualip']['vip'] as $vip) {
5220
		if ($vip['subnet'] == $ipaddress) {
5221
			return ($vip['descr']);
5222
		}
5223
	}
5224
	return "";
5225
}
5226

    
5227
function interfaces_staticarp_configure($if) {
5228
	global $config, $g;
5229
	if(isset($config['system']['developerspew'])) {
5230
		$mt = microtime();
5231
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5232
	}
5233

    
5234
	$ifcfg = $config['interfaces'][$if];
5235

    
5236
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5237
		return 0;
5238

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

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

    
5248
			}
5249

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

    
5263
	return 0;
5264
}
5265

    
5266
function get_failover_interface($interface, $family = "all") {
5267
	global $config;
5268

    
5269
	/* shortcut to get_real_interface if we find it in the config */
5270
	if (is_array($config['interfaces'][$interface])) {
5271
		return get_real_interface($interface, $family);
5272
	}
5273

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

    
5288
function remove_ifindex($ifname) {
5289
	return preg_replace("/[0-9]+$/", "", $ifname);
5290
}
5291

    
5292
?>
(26-26/68)