Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
68
	return $interface_arr_cache;
69
}
70

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

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

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

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

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

    
98

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

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

    
120
	return false;
121
}
122

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

    
126
	$found = false;
127
	if (!empty($config['pptpd']) &&
128
		$config['pptpd']['mode'] == "server")
129
		$found = true;
130
	if ($found == false && !empty($config['l2tp']) &&
131
		$config['l2tp']['mode'] == "server")
132
		$found = true;
133
	if ($found == false && is_array($config['pppoes']['pppoe'])) {
134
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
135
			if ($pppoe['mode'] != "server")
136
				continue;
137
			if ($pppoe['interface'] == $interface)
138
				$found = true;
139
				break;
140
		}
141
	}
142
	if ($found == false) {
143
		if (!empty($config['interfaces'][$interface])) {
144
			switch ($config['interfaces'][$interface]['ipaddr']) {
145
			case "ppp":
146
			case "pppoe":
147
			case "l2tp":
148
			case "pptp":
149
				$found = true;
150
				break;
151
			default:
152
				$found = false;
153
				break;
154
			}
155
		}
156
	}
157
	if ($found == false) {
158
		$realif = get_real_interface($interface);
159
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
160
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
161

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

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

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

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

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

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

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

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

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

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

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

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

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

    
266
	interfaces_bring_up($vlanif);
267

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

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

    
274
	return $vlanif;
275
}
276

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

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

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

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

    
297
	$vlanif = interface_vlan_configure($vlan);
298

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

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

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

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

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

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

    
350
	return $vlanif;
351
}
352

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

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

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

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

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

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

    
393
	return $vlanif;
394
}
395

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

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

    
402
	$iflist = get_configured_interface_list();
403

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

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

    
423
}
424

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

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

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

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

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

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

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

    
476
	/* Calculate smaller mtu and enforce it */
477
	$smallermtu = 0;
478
	$commonrx = true;
479
	$commontx = true;
480
	$foundgif = false;
481
	foreach ($members as $member) {
482
		$realif = get_real_interface($member);
483
		$opts = pfSense_get_interface_addresses($realif);
484
		$mtu = $opts['mtu'];
485
		if (substr($realif, 0, 3) == "gif") {
486
			$foundgif = true;
487
			if ($checkmember == 1)
488
				return;
489
			if ($mtu <= 1500)
490
				continue;
491
		}
492
		if (!isset($opts['caps']['txcsum']))
493
			$commontx = false;
494
		if (!isset($opts['caps']['rxcsum']))
495
			$commonrx = false;
496
		if (!isset($opts['caps']['tso4']))
497
			$commontso4 = false;
498
		if (!isset($opts['caps']['tso6']))
499
			$commontso6 = false;
500
		if (!isset($opts['caps']['lro']))
501
			$commonlro = false;
502
		if ($smallermtu == 0 && !empty($mtu))
503
			$smallermtu = $mtu;
504
		else if (!empty($mtu) && $mtu < $smallermtu)
505
			$smallermtu = $mtu;
506
	}
507
	if ($foundgif == false && $checkmember == 2)
508
		return;
509

    
510
	/* Just in case anything is not working well */
511
	if ($smallermtu == 0)
512
		$smallermtu = 1500;
513

    
514
	$flags_on = 0;
515
	$flags_off = 0;
516
	if (isset($config['system']['disablechecksumoffloading']) || ($commonrx === false))
517
		$flags_off |= IFCAP_RXCSUM;
518
	else
519
		$flags_on |= IFCAP_RXCSUM;
520
	if (isset($config['system']['disablechecksumoffloading']) || ($commontx === false))
521
		$flags_off |= IFCAP_TXCSUM;
522
	else
523
		$flags_on |= IFCAP_TXCSUM;
524
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso4 === false))
525
		$flags_off |= IFCAP_TSO4;
526
	else
527
		$flags_on |= IFCAP_TSO4;
528
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso6 === false))
529
		$flags_off |= IFCAP_TSO6;
530
	else
531
		$flags_on |= IFCAP_TSO6;
532
	if (isset($config['system']['disablelargereceiveoffloading']) || ($commonlro === false))
533
		$flags_off |= IFCAP_LRO;
534
	else
535
		$flags_on |= IFCAP_LRO;
536

    
537
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
538
		pfSense_interface_destroy($bridge['bridgeif']);
539
		pfSense_interface_create($bridge['bridgeif']);
540
		$bridgeif = escapeshellarg($bridge['bridgeif']);
541
	} else {
542
		$bridgeif = pfSense_interface_create("bridge");
543
		$bridge['bridgeif'] = $bridgeif;
544
	}
545

    
546
	$checklist = get_configured_interface_list();
547

    
548
	/* Add interfaces to bridge */
549
	foreach ($members as $member) {
550
		if (empty($checklist[$member]))
551
			continue;
552
		$realif = get_real_interface($member);
553
		if (!$realif) {
554
			log_error(gettext("realif not defined in interfaces bridge - up"));
555
			continue;
556
		}
557
		/* make sure the parent interface is up */
558
		pfSense_interface_mtu($realif, $smallermtu);
559
		pfSense_interface_capabilities($realif, -$flags_off);
560
		pfSense_interface_capabilities($realif, $flags_on);
561
		interfaces_bring_up($realif);
562
		pfSense_bridge_add_member($bridge['bridgeif'], $realif);
563
	}
564

    
565
	if (isset($bridge['enablestp'])) {
566
		/* Choose spanning tree proto */
567
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
568

    
569
		if (!empty($bridge['stp'])) {
570
			$stpifs = explode(',', $bridge['stp']);
571
			foreach ($stpifs as $stpif) {
572
				$realif = get_real_interface($stpif);
573
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
574
			}
575
		}
576
		if (!empty($bridge['maxage']))
577
			mwexec("/sbin/ifconfig {$bridgeif} maxage " . escapeshellarg($bridge['maxage']));
578
		if (!empty($bridge['fwdelay']))
579
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay " . escapeshellarg($bridge['fwdelay']));
580
		if (!empty($bridge['hellotime']))
581
			mwexec("/sbin/ifconfig {$bridgeif} hellotime " . escapeshellarg($bridge['hellotime']));
582
		if (!empty($bridge['priority']))
583
			mwexec("/sbin/ifconfig {$bridgeif} priority " . escapeshellarg($bridge['priority']));
584
		if (!empty($bridge['holdcnt']))
585
			mwexec("/sbin/ifconfig {$bridgeif} holdcnt " . escapeshellarg($bridge['holdcnt']));
586
		if (!empty($bridge['ifpriority'])) {
587
			$pconfig = explode(",", $bridge['ifpriority']);
588
			$ifpriority = array();
589
			foreach ($pconfig as $cfg) {
590
				$embcfg = explode_assoc(":", $cfg);
591
				foreach ($embcfg as $key => $value)
592
					$ifpriority[$key] = $value;
593
			}
594
			foreach ($ifpriority as $key => $value) {
595
				$realif = get_real_interface($key);
596
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} " . escapeshellarg($value));
597
			}
598
		}
599
		if (!empty($bridge['ifpathcost'])) {
600
			$pconfig = explode(",", $bridge['ifpathcost']);
601
			$ifpathcost = array();
602
			foreach ($pconfig as $cfg) {
603
				$embcfg = explode_assoc(":", $cfg);
604
				foreach ($embcfg as $key => $value)
605
					$ifpathcost[$key] = $value;
606
			}
607
			foreach ($ifpathcost as $key => $value) {
608
				$realif = get_real_interface($key);
609
				mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} " . escapeshellarg($value));
610
			}
611
		}
612
	}
613

    
614
	if ($bridge['maxaddr'] <> "")
615
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr " . escapeshellarg($bridge['maxaddr']));
616
	if ($bridge['timeout'] <> "")
617
		mwexec("/sbin/ifconfig {$bridgeif} timeout " . escapeshellarg($bridge['timeout']));
618
	if ($bridge['span'] <> "") {
619
		$realif = get_real_interface($bridge['span']);
620
		mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
621
	}
622
	if (!empty($bridge['edge'])) {
623
		$edgeifs = explode(',', $bridge['edge']);
624
		foreach ($edgeifs as $edgeif) {
625
			$realif = get_real_interface($edgeif);
626
			mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
627
		}
628
	}
629
	if (!empty($bridge['autoedge'])) {
630
		$edgeifs = explode(',', $bridge['autoedge']);
631
		foreach ($edgeifs as $edgeif) {
632
			$realif = get_real_interface($edgeif);
633
			mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
634
		}
635
	}
636
	if (!empty($bridge['ptp'])) {
637
		$ptpifs = explode(',', $bridge['ptp']);
638
		foreach ($ptpifs as $ptpif) {
639
			$realif = get_real_interface($ptpif);
640
			mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
641
		}
642
	}
643
	if (!empty($bridge['autoptp'])) {
644
		$ptpifs = explode(',', $bridge['autoptp']);
645
		foreach ($ptpifs as $ptpif) {
646
			$realif = get_real_interface($ptpif);
647
			mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
648
		}
649
	}
650
	if (!empty($bridge['static'])) {
651
		$stickyifs = explode(',', $bridge['static']);
652
		foreach ($stickyifs as $stickyif) {
653
			$realif = get_real_interface($stickyif);
654
			mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
655
		}
656
	}
657
	if (!empty($bridge['private'])) {
658
		$privateifs = explode(',', $bridge['private']);
659
		foreach ($privateifs as $privateif) {
660
			$realif = get_real_interface($privateif);
661
			mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
662
		}
663
	}
664

    
665
	if ($bridge['bridgeif'])
666
		interfaces_bring_up($bridge['bridgeif']);
667
	else
668
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
669
}
670

    
671
function interface_bridge_add_member($bridgeif, $interface) {
672

    
673
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
674
		return;
675

    
676
	$mtu = get_interface_mtu($bridgeif);
677
	$mtum = get_interface_mtu($interface);
678

    
679
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
680
		pfSense_interface_mtu($interface, $mtu);
681

    
682
	$options = pfSense_get_interface_addresses($bridgeif);
683
	$flags_on = 0;
684
	$flags_off = 0;
685
	if (isset($options['encaps']['txcsum']))
686
		$flags_on |= IFCAP_TXCSUM;
687
	else
688
		$flags_off |= IFCAP_TXCSUM;
689
	if (isset($options['encaps']['rxcsum']))
690
		$flags_on |= IFCAP_RXCSUM;
691
	else
692
		$flags_off |= IFCAP_RXCSUM;
693
	if (isset($options['encaps']['tso4']))
694
		$flags_on |= IFCAP_TSO4;
695
	else
696
		$flags_off |= IFCAP_TSO4;
697
	if (isset($options['encaps']['tso6']))
698
		$flags_on |= IFCAP_TSO6;
699
	else
700
		$flags_off |= IFCAP_TSO6;
701
	if (isset($options['encaps']['lro']))
702
		$flags_on |= IFCAP_LRO;
703
	else
704
		$flags_off |= IFCAP_LRO;
705

    
706
	pfSense_interface_capabilities($interface, -$flags_off);
707
	pfSense_interface_capabilities($interface, $flags_on);
708

    
709
	interfaces_bring_up($interface);
710
	pfSense_bridge_add_member($bridgeif, $interface);
711
}
712

    
713
function interfaces_lagg_configure($realif = "") {
714
	global $config, $g;
715
	if($g['booting'])
716
		echo gettext("Configuring LAGG interfaces...");
717
	$i = 0;
718
	if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
719
		foreach ($config['laggs']['lagg'] as $lagg) {
720
			if(empty($lagg['laggif']))
721
				$lagg['laggif'] = "lagg{$i}";
722
			if (!empty($realif) && $realif != $lagg['laggif'])
723
				continue;
724
			/* XXX: Maybe we should report any errors?! */
725
			interface_lagg_configure($lagg);
726
			$i++;
727
		}
728
	}
729
	if($g['booting'])
730
		echo gettext("done.") . "\n";
731
}
732

    
733
function interface_lagg_configure(&$lagg) {
734
	global $config, $g;
735

    
736
	if (!is_array($lagg))
737
		return -1;
738

    
739
	$members = explode(',', $lagg['members']);
740
	if (!count($members))
741
		return -1;
742

    
743
	if ($g['booting'] || !(empty($lagg['laggif']))) {
744
		pfSense_interface_destroy($lagg['laggif']);
745
		pfSense_interface_create($lagg['laggif']);
746
		$laggif = $lagg['laggif'];
747
	} else
748
		$laggif = pfSense_interface_create("lagg");
749

    
750
	/* Calculate smaller mtu and enforce it */
751
	$smallermtu = 0;
752
	foreach ($members as $member) {
753
		$opts = pfSense_get_interface_addresses($member);
754
		$mtu = $opts['mtu'];
755
		if (!isset($opts['caps']['txcsum']))
756
			$commontx = false;
757
		if (!isset($opts['caps']['rxcsum']))
758
			$commonrx = false;
759
		if (!isset($opts['caps']['tso4']))
760
			$commontso4 = false;
761
		if (!isset($opts['caps']['tso6']))
762
			$commontso6 = false;
763
		if (!isset($opts['caps']['lro']))
764
			$commonlro = false;
765
		if ($smallermtu == 0 && !empty($mtu))
766
			$smallermtu = $mtu;
767
		else if (!empty($mtu) && $mtu < $smallermtu)
768
			$smallermtu = $mtu;
769
	}
770

    
771
	/* Just in case anything is not working well */
772
	if ($smallermtu == 0)
773
		$smallermtu = 1500;
774

    
775
	$flags_on = 0;
776
	$flags_off = 0;
777
	if (isset($config['system']['disablechecksumoffloading']) || ($commonrx === false))
778
		$flags_off |= IFCAP_RXCSUM;
779
	else
780
		$flags_on |= IFCAP_RXCSUM;
781
	if (isset($config['system']['disablechecksumoffloading']) || ($commontx === false))
782
		$flags_off |= IFCAP_TXCSUM;
783
	else
784
		$flags_on |= IFCAP_TXCSUM;
785
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso4 === false))
786
		$flags_off |= IFCAP_TSO4;
787
	else
788
		$flags_on |= IFCAP_TSO4;
789
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso6 === false))
790
		$flags_off |= IFCAP_TSO6;
791
	else
792
		$flags_on |= IFCAP_TSO6;
793
	if (isset($config['system']['disablelargereceiveoffloading']) || ($commonlro === false))
794
		$flags_off |= IFCAP_LRO;
795
	else
796
		$flags_on |= IFCAP_LRO;
797

    
798
	$checklist = get_interface_list();
799

    
800
	foreach ($members as $member) {
801
		if (!array_key_exists($member, $checklist))
802
			continue;
803
		/* make sure the parent interface is up */
804
		pfSense_interface_mtu($member, $smallermtu);
805
		pfSense_interface_capabilities($member, -$flags_off);
806
		pfSense_interface_capabilities($member, $flags_on);
807
		interfaces_bring_up($member);
808
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
809
	}
810

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

    
813
	interfaces_bring_up($laggif);
814

    
815
	return $laggif;
816
}
817

    
818
function interfaces_gre_configure($checkparent = 0, $realif = "") {
819
	global $config;
820

    
821
	if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
822
		foreach ($config['gres']['gre'] as $i => $gre) {
823
			if (empty($gre['greif']))
824
				$gre['greif'] = "gre{$i}";
825
			if (!empty($realif) && $realif != $gre['greif'])
826
				continue;
827

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

    
846
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
847
function interface_gre_configure(&$gre, $grekey = "") {
848
	global $config, $g;
849

    
850
	if (!is_array($gre))
851
		return -1;
852

    
853
	$realif = get_real_interface($gre['if']);
854
	$realifip = get_interface_ip($gre['if']);
855

    
856
	/* make sure the parent interface is up */
857
	interfaces_bring_up($realif);
858

    
859
	if ($g['booting'] || !(empty($gre['greif']))) {
860
		pfSense_interface_destroy($gre['greif']);
861
		pfSense_interface_create($gre['greif']);
862
		$greif = $gre['greif'];
863
	} else
864
		$greif = pfSense_interface_create("gre");
865

    
866
	/* Do not change the order here for more see gre(4) NOTES section. */
867
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} " . escapeshellarg($gre['remote-addr']));
868
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
869
		mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gre['tunnel-remote-net']));
870
	} else {
871
		mwexec("/sbin/ifconfig {$greif} " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
872
	}
873
	if (isset($gre['link0']))
874
		pfSense_interface_flags($greif, IFF_LINK0);
875
	if (isset($gre['link1']))
876
		pfSense_interface_flags($greif, IFF_LINK1);
877
	if (isset($gre['link2']))
878
		pfSense_interface_flags($greif, IFF_LINK2);
879

    
880
	if($greif)
881
		interfaces_bring_up($greif);
882
	else
883
		log_error(gettext("Could not bring greif up -- variable not defined."));
884

    
885
	if (isset($gre['link1']) && $gre['link1'])
886
		mwexec("/sbin/route add " . escapeshellarg($gre['tunnel-remote-addr']) . "/" . escapeshellarg($gre['tunnel-remote-net']) . " " . escapeshellarg($gre['tunnel-local-addr']));
887
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
888
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
889
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
890
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
891

    
892
	return $greif;
893
}
894

    
895
function interfaces_gif_configure($checkparent = 0, $realif = "") {
896
	global $config;
897

    
898
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
899
		foreach ($config['gifs']['gif'] as $i => $gif) {
900
			if (empty($gif['gifif']))
901
				$gre['gifif'] = "gif{$i}";
902
			if (!empty($realif) && $realif != $gif['gifif'])
903
				continue;
904

    
905
			if ($checkparent == 1) {
906
				if (strstr($gif['if'], "_vip"))
907
					continue;
908
				if (!empty($config['interfaces'][$gif['if']]) && $config['interfaces'][$gif['if']]['ipaddrv6'] == "track6")
909
					continue;
910
			}
911
			else if ($checkparent == 2) {
912
				if (strstr($gif['if'], "_vip"))
913
					continue;
914
				if (empty($config['interfaces'][$gif['if']]) || $config['interfaces'][$gif['if']]['ipaddrv6'] != "track6")
915
					continue;
916
			}
917
			/* XXX: Maybe we should report any errors?! */
918
			interface_gif_configure($gif);
919
		}
920
	}
921
}
922

    
923
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
924
function interface_gif_configure(&$gif, $gifkey = "") {
925
	global $config, $g;
926

    
927
	if (!is_array($gif))
928
		return -1;
929

    
930
	$realif = get_real_interface($gif['if']);
931
	$ipaddr = $gif['ipaddr'];
932

    
933
	if (is_ipaddrv4($gif['remote-addr'])) {
934
		if (is_ipaddrv4($ipaddr))
935
			$realifip = $ipaddr;
936
		else
937
			$realifip = get_interface_ip($gif['if']);
938
		$realifgw = get_interface_gateway($gif['if']);
939
	} else if (is_ipaddrv6($gif['remote-addr'])) {
940
		if (is_ipaddrv6($ipaddr))
941
			$realifip = $ipaddr;
942
		else
943
			$realifip = get_interface_ipv6($gif['if']);
944
		$realifgw = get_interface_gatewayv6($gif['if']);
945
	}
946
	/* make sure the parent interface is up */
947
	if($realif)
948
		interfaces_bring_up($realif);
949
	else
950
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
951

    
952
	if ($g['booting'] || !(empty($gif['gifif']))) {
953
		pfSense_interface_destroy($gif['gifif']);
954
		pfSense_interface_create($gif['gifif']);
955
		$gifif = $gif['gifif'];
956
	} else
957
		$gifif = pfSense_interface_create("gif");
958

    
959
	/* Do not change the order here for more see gif(4) NOTES section. */
960
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} " . escapeshellarg($gif['remote-addr']));
961
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
962
		mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gif['tunnel-remote-net']));
963
	} else {
964
		mwexec("/sbin/ifconfig {$gifif} " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
965
	}
966
	if (isset($gif['link0']))
967
		pfSense_interface_flags($gifif, IFF_LINK0);
968
	if (isset($gif['link1']))
969
		pfSense_interface_flags($gifif, IFF_LINK1);
970
	if($gifif)
971
		interfaces_bring_up($gifif);
972
	else
973
		log_error(gettext("could not bring gifif up -- variable not defined"));
974

    
975
	$iflist = get_configured_interface_list();
976
	foreach($iflist as $ifname) {
977
		if($config['interfaces'][$ifname]['if'] == $gifif) {
978
			if(get_interface_gateway($ifname)) {
979
				system_routing_configure($ifname);
980
				break;
981
			}
982
			if(get_interface_gateway_v6($ifname)) {
983
				system_routing_configure($ifname);
984
				break;
985
			}
986
		}
987
	}
988

    
989

    
990
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
991
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
992
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
993
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
994

    
995
	if (is_ipaddrv4($realifgw)) {
996
		mwexec("/sbin/route change -host " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
997
	}
998
	if (is_ipaddrv6($realifgw)) {
999
		mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
1000
	}
1001

    
1002
	return $gifif;
1003
}
1004

    
1005
function interfaces_configure() {
1006
	global $config, $g;
1007

    
1008
	if ($g['platform'] == 'jail')
1009
		return;
1010

    
1011
	/* Set up our loopback interface */
1012
	interfaces_loopback_configure();
1013

    
1014
	/* create the unconfigured wireless clones */
1015
	interfaces_create_wireless_clones();
1016

    
1017
	/* set up LAGG virtual interfaces */
1018
	interfaces_lagg_configure();
1019

    
1020
	/* set up VLAN virtual interfaces */
1021
	interfaces_vlan_configure();
1022

    
1023
	interfaces_qinq_configure();
1024

    
1025
	$iflist = get_configured_interface_with_descr();
1026
	$delayed_list = array();
1027
	$bridge_list = array();
1028
	$track6_list = array();
1029

    
1030
	/* This is needed to speedup interfaces on bootup. */
1031
	$reload = false;
1032
	if (!$g['booting'])
1033
		$reload = true;
1034

    
1035
	foreach($iflist as $if => $ifname) {
1036
		$realif = $config['interfaces'][$if]['if'];
1037
		if (strstr($realif, "bridge"))
1038
			$bridge_list[$if] = $ifname;
1039
		else if (strstr($realif, "gre"))
1040
			$delayed_list[$if] = $ifname;
1041
		else if (strstr($realif, "gif"))
1042
			$delayed_list[$if] = $ifname;
1043
		else if (strstr($realif, "ovpn")) {
1044
			//echo "Delaying OpenVPN interface configuration...done.\n";
1045
			continue;
1046
		} else if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
1047
			$track6_list[$if] = $ifname;
1048
		} else {
1049
			if ($g['booting'])
1050
				printf(gettext("Configuring %s interface..."), $ifname);
1051

    
1052
			if($g['debug'])
1053
				log_error(sprintf(gettext("Configuring %s"), $ifname));
1054
			interface_configure($if, $reload);
1055
			if ($g['booting'])
1056
				echo gettext( "done.") . "\n";
1057
		}
1058
	}
1059

    
1060
	/*
1061
	 * NOTE: The following function parameter consists of
1062
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
1063
	 *	2 - Do load gre/gif/bridge with parent/member as vip
1064
	 */
1065

    
1066
	/* set up GRE virtual interfaces */
1067
	interfaces_gre_configure(1);
1068

    
1069
	/* set up GIF virtual interfaces */
1070
	interfaces_gif_configure(1);
1071

    
1072
	/* set up BRIDGe virtual interfaces */
1073
	interfaces_bridge_configure(1);
1074

    
1075
	foreach ($track6_list as $if => $ifname) {
1076
		if ($g['booting'])
1077
			printf(gettext("Configuring %s interface..."), $ifname);
1078
		if ($g['debug'])
1079
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1080

    
1081
		interface_configure($if, $reload);
1082

    
1083
		if ($g['booting'])
1084
			echo gettext("done.") . "\n";
1085
	}
1086

    
1087
	/* bring up vip interfaces */
1088
	interfaces_vips_configure();
1089

    
1090
	/* set up GRE virtual interfaces */
1091
	interfaces_gre_configure(2);
1092

    
1093
	/* set up GIF virtual interfaces */
1094
	interfaces_gif_configure(2);
1095

    
1096
	foreach ($delayed_list as $if => $ifname) {
1097
		if ($g['booting'])
1098
			printf(gettext("Configuring %s interface..."), $ifname);
1099
		if ($g['debug'])
1100
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1101

    
1102
		interface_configure($if, $reload);
1103

    
1104
		if ($g['booting'])
1105
			echo gettext("done.") . "\n";
1106
	}
1107

    
1108
	/* set up BRIDGe virtual interfaces */
1109
	interfaces_bridge_configure(2);
1110

    
1111
	foreach ($bridge_list as $if => $ifname) {
1112
		if ($g['booting'])
1113
			printf(gettext("Configuring %s interface..."), $ifname);
1114
		if($g['debug'])
1115
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1116

    
1117
		interface_configure($if, $reload);
1118

    
1119
		if ($g['booting'])
1120
			echo gettext("done.") . "\n";
1121
	}
1122

    
1123
	/* configure interface groups */
1124
	interfaces_group_setup();
1125

    
1126
	if (!$g['booting']) {
1127
		/* reconfigure static routes (kernel may have deleted them) */
1128
		system_routing_configure();
1129

    
1130
		/* reload IPsec tunnels */
1131
		vpn_ipsec_configure();
1132

    
1133
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1134
		services_dhcpd_configure();
1135

    
1136
		/* restart dnsmasq */
1137
		services_dnsmasq_configure();
1138
	}
1139

    
1140
	return 0;
1141
}
1142

    
1143
function interface_reconfigure($interface = "wan", $reloadall = false) {
1144
	interface_bring_down($interface);
1145
	interface_configure($interface, $reloadall);
1146
}
1147

    
1148
function interface_vip_bring_down($vip) {
1149
	global $g;
1150

    
1151
	$vipif = get_real_interface($vip['interface']);
1152
	switch ($vip['mode']) {
1153
	case "proxyarp":
1154
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1155
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1156
		break;
1157
	case "ipalias":
1158
		if (does_interface_exist($vipif)) {
1159
			if (is_ipaddrv6($vip['subnet']))
1160
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " -alias");
1161
			else
1162
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1163
		}
1164
		break;
1165
	case "carp":
1166
		/* XXX: Is enough to delete ip address? */
1167
		if (does_interface_exist($vipif))
1168
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1169
		break;
1170
	}
1171
}
1172

    
1173
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1174
	global $config, $g;
1175

    
1176
	if (!isset($config['interfaces'][$interface]))
1177
		return;
1178

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

    
1182
	/*
1183
	 * NOTE: The $realifv6 is needed when WANv4 is type PPP and v6 is DHCP and the option v6 from v4 is used.
1184
	 * In this case the real $realif of v4 is different from that of v6 for operation.
1185
	 * Keep this in mind while doing changes here!
1186
	 */
1187
	if ($ifacecfg === false) {
1188
		$ifcfg = $config['interfaces'][$interface];
1189
		$ppps = $config['ppps']['ppp'];
1190
		$realif = get_real_interface($interface);
1191
		$realifv6 = get_real_interface($interface, "inet6", true);
1192
	} elseif (!is_array($ifacecfg)) {
1193
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1194
		$ifcfg = $config['interfaces'][$interface];
1195
		$ppps = $config['ppps']['ppp'];
1196
		$realif = get_real_interface($interface);
1197
		$realifv6 = get_real_interface($interface, "inet6", true);
1198
	} else {
1199
		$ifcfg = $ifacecfg['ifcfg'];
1200
		$ppps = $ifacecfg['ppps'];
1201
		if (isset($ifacecfg['ifcfg']['realif'])) {
1202
			$realif = $ifacecfg['ifcfg']['realif'];
1203
			/* XXX: Any better way? */
1204
			$realifv6 = $realif;
1205
		} else {
1206
			$realif = get_real_interface($interface);
1207
			$realifv6 = get_real_interface($interface, "inet6", true);
1208
		}
1209
	}
1210

    
1211
	switch ($ifcfg['ipaddr']) {
1212
	case "ppp":
1213
	case "pppoe":
1214
	case "pptp":
1215
	case "l2tp":
1216
		if (is_array($ppps) && count($ppps)) {
1217
			foreach ($ppps as $pppid => $ppp) {
1218
				if ($realif == $ppp['if']) {
1219
					if (isset($ppp['ondemand']) && !$destroy){
1220
						send_event("interface reconfigure {$interface}");
1221
						break;
1222
					}
1223
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1224
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1225
						sleep(2);
1226
					}
1227
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1228
					break;
1229
				}
1230
			}
1231
		}
1232
		break;
1233
	case "dhcp":
1234
		$pid = find_dhclient_process($realif);
1235
		if($pid)
1236
			posix_kill($pid, SIGTERM);
1237
		sleep(1);
1238
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1239
		if(does_interface_exist("$realif")) {
1240
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1241
			if ($destroy == true)
1242
				pfSense_interface_flags($realif, -IFF_UP);
1243
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1244
		}
1245
		break;
1246
	default:
1247
		if(does_interface_exist("$realif")) {
1248
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1249
			if ($destroy == true)
1250
				pfSense_interface_flags($realif, -IFF_UP);
1251
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1252
		}
1253
		break;
1254
	}
1255

    
1256
	switch ($ifcfg['ipaddrv6']) {
1257
	case "slaac":
1258
	case "dhcp6":
1259
		$pidv6 = find_dhcp6c_process($realif);
1260
		if($pidv6)
1261
			posix_kill($pidv6, SIGTERM);
1262
		sleep(3);
1263
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1264
		if (does_interface_exist($realifv6)) {
1265
			$ip6 = find_interface_ipv6($realifv6);
1266
			if (is_ipaddrv6($ip6) && $ip6 != "::")
1267
				mwexec("/sbin/ifconfig " . escapeshellarg($realifv6) . " inet6 {$ip6} delete", true);
1268
			if ($destroy == true)
1269
				pfSense_interface_flags($realif, -IFF_UP);
1270
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1271
		}
1272
		break;
1273
	case "6rd":
1274
	case "6to4":
1275
		$realif = "{$interface}_stf";
1276
		if(does_interface_exist("$realif")) {
1277
			$ip6 = get_interface_ipv6($interface);
1278
			if (is_ipaddrv6($ip6))
1279
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1280
			if ($destroy == true)
1281
				pfSense_interface_flags($realif, -IFF_UP);
1282
		}
1283
		break;
1284
	default:
1285
		if(does_interface_exist("$realif")) {
1286
			$ip6 = get_interface_ipv6($interface);
1287
			if (is_ipaddrv6($ip6))
1288
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1289
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1290
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1291
			if ($destroy == true)
1292
				pfSense_interface_flags($realif, -IFF_UP);
1293
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1294
		}
1295
		break;
1296
	}
1297

    
1298
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1299
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1300
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1301
	if (!empty($old_router)) {
1302
		log_error("Clearing states to old gateway {$old_router}.");
1303
		mwexec("/sbin/pfctl -i " . escapeshellarg($realif) . " -Fs -G {$old_router}");
1304
	}
1305

    
1306
	/* remove interface up file if it exists */
1307
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1308
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1309
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1310
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1311
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1312
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1313
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1314

    
1315
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1316
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1317
	if (is_array($ifcfg['wireless'])) {
1318
		kill_hostapd($realif);
1319
		mwexec(kill_wpasupplicant($realif));
1320
	}
1321

    
1322
	if ($destroy == true) {
1323
		if (preg_match("/^[a-z0-9]+^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1324
			pfSense_interface_destroy($realif);
1325
	}
1326

    
1327
	return;
1328
}
1329

    
1330
function interfaces_ptpid_used($ptpid) {
1331
	global $config;
1332

    
1333
	if (is_array($config['ppps']['ppp']))
1334
		foreach ($config['ppps']['ppp'] as & $settings)
1335
			if ($ptpid == $settings['ptpid'])
1336
				return true;
1337

    
1338
	return false;
1339
}
1340

    
1341
function interfaces_ptpid_next() {
1342

    
1343
	$ptpid = 0;
1344
	while(interfaces_ptpid_used($ptpid))
1345
		$ptpid++;
1346

    
1347
	return $ptpid;
1348
}
1349

    
1350
function getMPDCRONSettings($pppif) {
1351
	global $config;
1352

    
1353
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1354
	if (is_array($config['cron']['item'])) {
1355
		foreach ($config['cron']['item'] as $i => $item) {
1356
			if (stripos($item['command'], $cron_cmd_file) !== false)
1357
				return array("ID" => $i, "ITEM" => $item);
1358
		}
1359
	}
1360

    
1361
	return NULL;
1362
}
1363

    
1364
function handle_pppoe_reset($post_array) {
1365
	global $config, $g;
1366

    
1367
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1368
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1369

    
1370
	if (!is_array($config['cron']['item']))
1371
		$config['cron']['item'] = array();
1372

    
1373
	$itemhash = getMPDCRONSettings($pppif);
1374

    
1375
	// reset cron items if necessary and return
1376
	if (empty($post_array['pppoe-reset-type'])) {
1377
		if (isset($itemhash))
1378
			unset($config['cron']['item'][$itemhash['ID']]);
1379
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1380
		return;
1381
	}
1382

    
1383
	if (empty($itemhash))
1384
		$itemhash = array();
1385
	$item = array();
1386
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1387
		$item['minute'] = $post_array['pppoe_resetminute'];
1388
		$item['hour'] = $post_array['pppoe_resethour'];
1389
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1390
			$date = explode("/", $post_array['pppoe_resetdate']);
1391
			$item['mday'] = $date[1];
1392
			$item['month'] = $date[0];
1393
		} else {
1394
			$item['mday'] = "*";
1395
			$item['month'] = "*";
1396
		}
1397
		$item['wday'] = "*";
1398
		$item['who'] = "root";
1399
		$item['command'] = $cron_cmd_file;
1400
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1401
		switch ($post_array['pppoe_pr_preset_val']) {
1402
		case "monthly":
1403
			$item['minute'] = "0";
1404
			$item['hour'] = "0";
1405
			$item['mday'] = "1";
1406
			$item['month'] = "*";
1407
			$item['wday'] = "*";
1408
			break;
1409
		case "weekly":
1410
			$item['minute'] = "0";
1411
			$item['hour'] = "0";
1412
			$item['mday'] = "*";
1413
			$item['month'] = "*";
1414
			$item['wday'] = "0";
1415
			break;
1416
		case "daily":
1417
			$item['minute'] = "0";
1418
			$item['hour'] = "0";
1419
			$item['mday'] = "*";
1420
			$item['month'] = "*";
1421
			$item['wday'] = "*";
1422
			break;
1423
		case "hourly":
1424
			$item['minute'] = "0";
1425
			$item['hour'] = "*";
1426
			$item['mday'] = "*";
1427
			$item['month'] = "*";
1428
			$item['wday'] = "*";
1429
			break;
1430
		} // end switch
1431
		$item['who'] = "root";
1432
		$item['command'] = $cron_cmd_file;
1433
	}
1434
	if (empty($item))
1435
		return;
1436
	if (isset($itemhash['ID']))
1437
		$config['cron']['item'][$itemhash['ID']] = $item;
1438
	else
1439
		$config['cron']['item'][] = $item;
1440
}
1441

    
1442
/*
1443
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1444
 * It writes the mpd config file to /var/etc every time the link is opened.
1445
 */
1446
function interface_ppps_configure($interface) {
1447
	global $config, $g;
1448

    
1449
	/* Return for unassigned interfaces. This is a minimum requirement. */
1450
	if (empty($config['interfaces'][$interface]))
1451
		return 0;
1452
	$ifcfg = $config['interfaces'][$interface];
1453
	if (!isset($ifcfg['enable']))
1454
		return 0;
1455

    
1456
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1457
	if(!is_dir("/var/spool/lock")) {
1458
		mkdir("/var/spool/lock", 0777, true);
1459
	}
1460
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1461
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1462
		@symlink("/usr/local/sbin/mpd.script", "{$g['varetc_path']}/.");
1463

    
1464
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1465
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1466
			if ($ifcfg['if'] == $ppp['if'])
1467
				break;
1468
		}
1469
	}
1470
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1471
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1472
		return 0;
1473
	}
1474
	$pppif = $ifcfg['if'];
1475
	if ($ppp['type'] == "ppp")
1476
		$type = "modem";
1477
	else
1478
		$type = $ppp['type'];
1479
	$upper_type = strtoupper($ppp['type']);
1480

    
1481
	if($g['booting']) {
1482
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1483
		echo "starting {$pppif} link...";
1484
		// Do not re-configure the interface if we are booting and it's already been started
1485
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1486
			return 0;
1487
	}
1488

    
1489
	$ports = explode(',',$ppp['ports']);
1490
	if ($type != "modem") {
1491
		foreach ($ports as $pid => $port) {
1492
			$ports[$pid] = get_real_interface($port);
1493
			if (empty($ports[$pid]))
1494
				return 0;
1495
		}
1496
	}
1497
	$localips = explode(',',$ppp['localip']);
1498
	$gateways = explode(',',$ppp['gateway']);
1499
	$subnets = explode(',',$ppp['subnet']);
1500

    
1501
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1502
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1503
	 */
1504
	foreach($ports as $pid => $port){
1505
		switch ($ppp['type']) {
1506
			case "pppoe":
1507
				/* Bring the parent interface up */
1508
				interfaces_bring_up($port);
1509
				pfSense_ngctl_attach(".", $port);
1510
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1511
				mwexec("ngctl msg {$port}: setautosrc 1");
1512
				break;
1513
			case "pptp":
1514
			case "l2tp":
1515
				/* configure interface */
1516
				if(is_ipaddr($localips[$pid])){
1517
					// Manually configure interface IP/subnet
1518
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1519
					interfaces_bring_up($port);
1520
				} else if (empty($localips[$pid]))
1521
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1522

    
1523
				if(!is_ipaddr($localips[$pid])){
1524
					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!");
1525
					$localips[$pid] = "0.0.0.0";
1526
				}
1527
				if(!is_ipaddr($gateways[$pid])){
1528
					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));
1529
					return 0;
1530
				}
1531
				pfSense_ngctl_attach(".", $port);
1532
				break;
1533
			case "ppp":
1534
				if (!file_exists("{$port}")) {
1535
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1536
					return 0;
1537
				}
1538
				break;
1539
			default:
1540
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1541
				break;
1542
		}
1543
	}
1544

    
1545
	if (is_array($ports) && count($ports) > 1)
1546
		$multilink = "enable";
1547
	else
1548
		$multilink = "disable";
1549

    
1550
	if ($type == "modem"){
1551
		if (is_ipaddr($ppp['localip']))
1552
			$localip = $ppp['localip'];
1553
		else
1554
			$localip = '0.0.0.0';
1555

    
1556
		if (is_ipaddr($ppp['gateway']))
1557
			$gateway = $ppp['gateway'];
1558
		else
1559
			$gateway = "10.64.64.{$pppid}";
1560
		$ranges = "{$localip}/0 {$gateway}/0";
1561

    
1562
		if (empty($ppp['apnum']))
1563
			$ppp['apnum'] = 1;
1564
	} else
1565
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1566

    
1567
	if (isset($ppp['ondemand']))
1568
		$ondemand = "enable";
1569
	else
1570
		$ondemand = "disable";
1571
	if (!isset($ppp['idletimeout']))
1572
		$ppp['idletimeout'] = 0;
1573

    
1574
	if (empty($ppp['username']) && $type == "modem"){
1575
		$ppp['username'] = "user";
1576
		$ppp['password'] = "none";
1577
	}
1578
	if (empty($ppp['password']) && $type == "modem")
1579
		$passwd = "none";
1580
	else
1581
		$passwd = base64_decode($ppp['password']);
1582

    
1583
	$bandwidths = explode(',',$ppp['bandwidth']);
1584
	$defaultmtu = "1492";
1585
	if (!empty($ifcfg['mtu']))
1586
		$defaultmtu = intval($ifcfg['mtu']);
1587
	$mtus = explode(',',$ppp['mtu']);
1588
	$mrus = explode(',',$ppp['mru']);
1589

    
1590
	if (isset($ppp['mrru']))
1591
		$mrrus = explode(',',$ppp['mrru']);
1592

    
1593
	// Construct the mpd.conf file
1594
	$mpdconf = <<<EOD
1595
startup:
1596
	# configure the console
1597
	set console close
1598
	# configure the web server
1599
	set web close
1600

    
1601
default:
1602
{$ppp['type']}client:
1603
	create bundle static {$interface}
1604
	set bundle enable ipv6cp
1605
	set iface name {$pppif}
1606

    
1607
EOD;
1608
	$setdefaultgw = false;
1609
	$founddefaultgw = false;
1610
	if (is_array($config['gateways']['gateway_item'])) {
1611
		foreach($config['gateways']['gateway_item'] as $gateway) {
1612
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1613
				$setdefaultgw = true;
1614
				break;
1615
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1616
				$founddefaultgw = true;
1617
				break;
1618
			}
1619
		}
1620
	}
1621

    
1622
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1623
		$setdefaultgw = true;
1624
		$mpdconf .= <<<EOD
1625
	set iface route default
1626

    
1627
EOD;
1628
	}
1629
	$mpdconf .= <<<EOD
1630
	set iface {$ondemand} on-demand
1631
	set iface idle {$ppp['idletimeout']}
1632

    
1633
EOD;
1634

    
1635
	if (isset($ppp['ondemand']))
1636
		$mpdconf .= <<<EOD
1637
	set iface addrs 10.10.1.1 10.10.1.2
1638

    
1639
EOD;
1640

    
1641
	if (isset($ppp['tcpmssfix']))
1642
		$tcpmss = "disable";
1643
	else
1644
		$tcpmss = "enable";
1645
		$mpdconf .= <<<EOD
1646
	set iface {$tcpmss} tcpmssfix
1647

    
1648
EOD;
1649

    
1650
	$mpdconf .= <<<EOD
1651
	set iface up-script /usr/local/sbin/ppp-linkup
1652
	set iface down-script /usr/local/sbin/ppp-linkdown
1653
	set ipcp ranges {$ranges}
1654

    
1655
EOD;
1656
	if (isset($ppp['vjcomp']))
1657
		$mpdconf .= <<<EOD
1658
	set ipcp no vjcomp
1659

    
1660
EOD;
1661

    
1662
	if (isset($config['system']['dnsallowoverride']))
1663
		$mpdconf .= <<<EOD
1664
	set ipcp enable req-pri-dns
1665
	set ipcp enable req-sec-dns
1666

    
1667
EOD;
1668
	if (!isset($ppp['verbose_log']))
1669
		$mpdconf .= <<<EOD
1670
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1671

    
1672
EOD;
1673
	foreach($ports as $pid => $port){
1674
		$port = get_real_interface($port);
1675
		$mpdconf .= <<<EOD
1676

    
1677
	create link static {$interface}_link{$pid} {$type}
1678
	set link action bundle {$interface}
1679
	set link {$multilink} multilink
1680
	set link keep-alive 10 60
1681
	set link max-redial 0
1682

    
1683
EOD;
1684
		if (isset($ppp['shortseq']))
1685
			$mpdconf .= <<<EOD
1686
	set link no shortseq
1687

    
1688
EOD;
1689

    
1690
		if (isset($ppp['acfcomp']))
1691
			$mpdconf .= <<<EOD
1692
	set link no acfcomp
1693

    
1694
EOD;
1695

    
1696
		if (isset($ppp['protocomp']))
1697
			$mpdconf .= <<<EOD
1698
	set link no protocomp
1699

    
1700
EOD;
1701

    
1702
		$mpdconf .= <<<EOD
1703
	set link disable chap pap
1704
	set link accept chap pap eap
1705
	set link disable incoming
1706

    
1707
EOD;
1708

    
1709

    
1710
		if (!empty($bandwidths[$pid]))
1711
			$mpdconf .= <<<EOD
1712
	set link bandwidth {$bandwidths[$pid]}
1713

    
1714
EOD;
1715

    
1716
		if (empty($mtus[$pid]))
1717
			$mtus[$pid] = $defaultmtu;
1718
			$mpdconf .= <<<EOD
1719
	set link mtu {$mtus[$pid]}
1720

    
1721
EOD;
1722

    
1723
		if (!empty($mrus[$pid]))
1724
			$mpdconf .= <<<EOD
1725
	set link mru {$mrus[$pid]}
1726

    
1727
EOD;
1728

    
1729
		if (!empty($mrrus[$pid]))
1730
			$mpdconf .= <<<EOD
1731
	set link mrru {$mrrus[$pid]}
1732

    
1733
EOD;
1734

    
1735
		$mpdconf .= <<<EOD
1736
	set auth authname "{$ppp['username']}"
1737
	set auth password {$passwd}
1738

    
1739
EOD;
1740
		if ($type == "modem") {
1741
			$mpdconf .= <<<EOD
1742
	set modem device {$ppp['ports']}
1743
	set modem script DialPeer
1744
	set modem idle-script Ringback
1745
	set modem watch -cd
1746
	set modem var \$DialPrefix "DT"
1747
	set modem var \$Telephone "{$ppp['phone']}"
1748

    
1749
EOD;
1750
		}
1751
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1752
			$mpdconf .= <<<EOD
1753
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1754

    
1755
EOD;
1756
		}
1757
		if (isset($ppp['initstr']) && $type == "modem") {
1758
			$initstr = base64_decode($ppp['initstr']);
1759
			$mpdconf .= <<<EOD
1760
	set modem var \$InitString "{$initstr}"
1761

    
1762
EOD;
1763
		}
1764
		if (isset($ppp['simpin']) && $type == "modem") {
1765
			if($ppp['pin-wait'] == "")
1766
				$ppp['pin-wait'] = 0;
1767
			$mpdconf .= <<<EOD
1768
	set modem var \$SimPin "{$ppp['simpin']}"
1769
	set modem var \$PinWait "{$ppp['pin-wait']}"
1770

    
1771
EOD;
1772
		}
1773
		if (isset($ppp['apn']) && $type == "modem") {
1774
			$mpdconf .= <<<EOD
1775
	set modem var \$APN "{$ppp['apn']}"
1776
	set modem var \$APNum "{$ppp['apnum']}"
1777

    
1778
EOD;
1779
		}
1780
		if ($type == "pppoe") {
1781
			// Send a null service name if none is set.
1782
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1783
			$mpdconf .= <<<EOD
1784
	set pppoe service "{$provider}"
1785

    
1786
EOD;
1787
		}
1788
		if ($type == "pppoe")
1789
			$mpdconf .= <<<EOD
1790
	set pppoe iface {$port}
1791

    
1792
EOD;
1793

    
1794
		if ($type == "pptp" || $type == "l2tp") {
1795
			$mpdconf .= <<<EOD
1796
	set {$type} self {$localips[$pid]}
1797
	set {$type} peer {$gateways[$pid]}
1798

    
1799
EOD;
1800
		}
1801

    
1802
		$mpdconf .= "\topen\n";
1803
	} //end foreach($port)
1804

    
1805

    
1806
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1807
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1808
		@symlink("{$g['conf_path']}/mpd_{$interface}.conf", "{$g['varetc_path']}/.");
1809
	else {
1810
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1811
		if (!$fd) {
1812
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1813
			return 0;
1814
		}
1815
		// Write out mpd_ppp.conf
1816
		fwrite($fd, $mpdconf);
1817
		fclose($fd);
1818
		unset($mpdconf);
1819
	}
1820

    
1821
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1822
	if (isset($ppp['uptime'])) {
1823
		if (!file_exists("/conf/{$pppif}.log")) {
1824
			conf_mount_rw();
1825
			file_put_contents("/conf/{$pppif}.log", '');
1826
			conf_mount_ro();
1827
		}
1828
	} else {
1829
		if (file_exists("/conf/{$pppif}.log")) {
1830
			conf_mount_rw();
1831
			@unlink("/conf/{$pppif}.log");
1832
			conf_mount_ro();
1833
		}
1834
	}
1835

    
1836
	/* clean up old lock files */
1837
	foreach($ports as $port) {
1838
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1839
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1840
	}
1841

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

    
1846
	// Check for PPPoE periodic reset request
1847
	if ($type == "pppoe") {
1848
		if (!empty($ppp['pppoe-reset-type']))
1849
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1850
		else
1851
			interface_setup_pppoe_reset_file($ppp['if']);
1852
	}
1853
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1854
	$i = 0;
1855
	while($i < 10) {
1856
		exec("/sbin/ifconfig " . escapeshellarg($ppp['if']) . " 2>&1", $out, $ret);
1857
		if($ret == 0)
1858
			break;
1859
		sleep(1);
1860
		$i++;
1861
	}
1862

    
1863
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1864
	/* We should be able to launch the right version for each modem */
1865
	/* We can also guess the mondev from the manufacturer */
1866
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1867
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1868
	foreach($ports as $port) {
1869
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1870
			$mondev  = substr(basename($port), 0, -1);
1871
			$devlist = glob("/dev/{$mondev}?");
1872
			$mondev = basename(end($devlist));
1873
		}
1874
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1875
			$mondev  = substr(basename($port), 0, -1) . "1";
1876
		}
1877
		log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1878
		mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1879
	}
1880

    
1881
	return 1;
1882
}
1883

    
1884
function interfaces_carp_setup() {
1885
	global $g, $config;
1886

    
1887
	if (isset($config['system']['developerspew'])) {
1888
		$mt = microtime();
1889
		echo "interfaces_carp_setup() being called $mt\n";
1890
	}
1891

    
1892
	if ($g['booting']) {
1893
		echo gettext("Configuring CARP settings...");
1894
		mute_kernel_msgs();
1895
	}
1896

    
1897
	/* suck in configuration items */
1898
	if ($config['hasync']) {
1899
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1900
		$balancing = $config['hasync']['balancing'];
1901
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1902
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1903
	} else {
1904
		unset($pfsyncinterface);
1905
		unset($balancing);
1906
		unset($pfsyncenabled);
1907
	}
1908

    
1909
	if ($balancing) {
1910
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1911
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1912
	} else
1913
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1914

    
1915
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1916
	if (!empty($pfsyncinterface))
1917
		$carp_sync_int = get_real_interface($pfsyncinterface);
1918
	else
1919
		unset($carp_sync_int);
1920

    
1921
	/* setup pfsync interface */
1922
	if ($carp_sync_int and $pfsyncenabled) {
1923
		if (is_ipaddr($pfsyncpeerip))
1924
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1925
		else
1926
			$syncpeer = "-syncpeer";
1927

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

    
1930
		sleep(1);
1931

    
1932
		/* 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
1933
		 * for existing sessions.
1934
		 */
1935
		log_error("waiting for pfsync...");
1936
		$i = 0;
1937
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1938
			$i++;
1939
			sleep(1);
1940
		}
1941
		log_error("pfsync done in $i seconds.");
1942
		log_error("Configuring CARP settings finalize...");
1943
	} else {
1944
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1945
	}
1946

    
1947
	if($config['virtualip']['vip'])
1948
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1949
	else
1950
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1951

    
1952
	if ($g['booting']) {
1953
		unmute_kernel_msgs();
1954
		echo gettext("done.") . "\n";
1955
	}
1956
}
1957

    
1958
function interface_proxyarp_configure($interface = "") {
1959
	global $config, $g;
1960
	if(isset($config['system']['developerspew'])) {
1961
		$mt = microtime();
1962
		echo "interface_proxyarp_configure() being called $mt\n";
1963
	}
1964

    
1965
	/* kill any running choparp */
1966
	if (empty($interface))
1967
		killbyname("choparp");
1968
	else {
1969
		$vipif = get_real_interface($interface);
1970
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1971
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1972
	}
1973

    
1974
	$paa = array();
1975
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1976

    
1977
		/* group by interface */
1978
		foreach ($config['virtualip']['vip'] as $vipent) {
1979
			if ($vipent['mode'] === "proxyarp") {
1980
				if ($vipent['interface'])
1981
					$proxyif = $vipent['interface'];
1982
				else
1983
					$proxyif = "wan";
1984

    
1985
				if (!empty($interface) && $interface != $proxyif)
1986
					continue;
1987

    
1988
				if (!is_array($paa[$proxyif]))
1989
					$paa[$proxyif] = array();
1990

    
1991
				$paa[$proxyif][] = $vipent;
1992
			}
1993
		}
1994
	}
1995

    
1996
	if (!empty($interface)) {
1997
		if (is_array($paa[$interface])) {
1998
			$paaifip = get_interface_ip($interface);
1999
			if (!is_ipaddr($paaifip))
2000
				return;
2001
			$args = get_real_interface($interface) . " auto";
2002
			foreach ($paa[$interface] as $paent) {
2003
				if (isset($paent['subnet']))
2004
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
2005
				else if (isset($paent['range']))
2006
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
2007
			}
2008
			mwexec_bg("/usr/local/sbin/choparp " . $args);
2009
		}
2010
	} else if (count($paa) > 0) {
2011
		foreach ($paa as $paif => $paents)  {
2012
			$paaifip = get_interface_ip($paif);
2013
			if (!is_ipaddr($paaifip))
2014
				continue;
2015
			$args = get_real_interface($paif) . " auto";
2016
			foreach ($paents as $paent) {
2017
				if (isset($paent['subnet']))
2018
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
2019
				else if (isset($paent['range']))
2020
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
2021
			}
2022
			mwexec_bg("/usr/local/sbin/choparp " . $args);
2023
		}
2024
	}
2025
}
2026

    
2027
function interface_ipalias_cleanup($interface, $inet = "inet4") {
2028
	global $g, $config;
2029

    
2030
	if (is_array($config['virtualip']['vip'])) {
2031
		foreach ($config['virtualip']['vip'] as $vip) {
2032
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
2033
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
2034
					interface_vip_bring_down($vip);
2035
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
2036
					interface_vip_bring_down($vip);
2037
			}
2038
		}
2039
	}
2040
}
2041

    
2042
function interfaces_vips_configure($interface = "") {
2043
	global $g, $config;
2044
	if(isset($config['system']['developerspew'])) {
2045
		$mt = microtime();
2046
		echo "interfaces_vips_configure() being called $mt\n";
2047
	}
2048
	$paa = array();
2049
	if(is_array($config['virtualip']['vip'])) {
2050
		$carp_setuped = false;
2051
		$anyproxyarp = false;
2052
		foreach ($config['virtualip']['vip'] as $vip) {
2053
			switch ($vip['mode']) {
2054
			case "proxyarp":
2055
				/* nothing it is handled on interface_proxyarp_configure() */
2056
				if ($interface <> "" && $vip['interface'] <> $interface)
2057
					continue;
2058
				$anyproxyarp = true;
2059
				break;
2060
			case "ipalias":
2061
				if ($interface <> "" && $vip['interface'] <> $interface)
2062
					continue;
2063
				interface_ipalias_configure($vip);
2064
				break;
2065
			case "carp":
2066
				if ($interface <> "" && $vip['interface'] <> $interface)
2067
					continue;
2068
				if ($carp_setuped == false)
2069
					$carp_setuped = true;
2070
				interface_carp_configure($vip);
2071
				break;
2072
			}
2073
		}
2074
		if ($carp_setuped == true)
2075
			interfaces_carp_setup();
2076
		if ($anyproxyarp == true)
2077
			interface_proxyarp_configure();
2078
	}
2079
}
2080

    
2081
function interface_ipalias_configure(&$vip) {
2082
	if ($vip['mode'] == "ipalias") {
2083
		$if = get_real_interface($vip['interface']);
2084
		$af = "inet";
2085
		if(is_ipaddrv6($vip['subnet']))
2086
			$af = "inet6";
2087
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
2088
	}
2089
}
2090

    
2091
function interface_reload_carps($cif) {
2092
	global $config;
2093

    
2094
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2095
	if (empty($carpifs))
2096
		return;
2097

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

    
2120
function interface_carp_configure(&$vip) {
2121
	global $config, $g;
2122
	if(isset($config['system']['developerspew'])) {
2123
		$mt = microtime();
2124
		echo "interface_carp_configure() being called $mt\n";
2125
	}
2126

    
2127
	if ($vip['mode'] != "carp")
2128
		return;
2129

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

    
2137
	if (is_ipaddrv4($vip['subnet'])) {
2138
		/* Ensure CARP IP really exists prior to loading up. */
2139
		$ww_subnet_ip = find_interface_ip($realif);
2140
		$ww_subnet_bits = find_interface_subnet($realif);
2141
		if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
2142
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IP address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
2143
			return;
2144
		}
2145
	} else if (is_ipaddrv6($vip['subnet'])) {
2146
		/* Ensure CARP IP really exists prior to loading up. */
2147
		$ww_subnet_ip = find_interface_ipv6($realif);
2148
		$ww_subnet_bits = find_interface_subnetv6($realif);
2149
		if (!ip_in_subnet($vip['subnet'], gen_subnetv6($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
2150
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IPv6 address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
2151
			return;
2152
		}
2153
	}
2154

    
2155
	$vip_password = $vip['password'];
2156
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2157
	if ($vip['password'] != "")
2158
		$password = " pass {$vip_password}";
2159

    
2160
	$advbase = "";
2161
	if (!empty($vip['advbase']))
2162
		$advbase = "advbase " . escapeshellarg($vip['advbase']);
2163

    
2164
	if (is_ipaddrv4($vip['subnet']))
2165
		mwexec("/sbin/ifconfig {$realif} " . escapeshellarg($vip['subnet']) . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
2166
	else if (is_ipaddrv6($vip['subnet']))
2167
		mwexec("/sbin/ifconfig {$realif} inet6 " . escapeshellarg($vip['subnet']) . " prefixlen " . escapeshellarg($vip['subnet_bits']));
2168

    
2169
	mwexec("/sbin/ifconfig {$realif} vhid " . escapeshellarg($vip['vhid']) . " advskew " . escapeshellarg($vip['advskew']) . " {$advbase} {$password}");
2170

    
2171
	return $realif;
2172
}
2173

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

    
2215
	if($needs_clone == true) {
2216
		/* remove previous instance if it exists */
2217
		if(does_interface_exist($realif))
2218
			pfSense_interface_destroy($realif);
2219

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

    
2238
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2239
	global $config, $g;
2240

    
2241
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2242
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2243
				 'regdomain', 'regcountry', 'reglocation');
2244

    
2245
	if(!is_interface_wireless($ifcfg['if']))
2246
		return;
2247

    
2248
	$baseif = interface_get_wireless_base($ifcfg['if']);
2249

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

    
2274
	// Read or write settings at shared area
2275
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2276
		foreach ($shared_settings as $setting) {
2277
			if ($sync_changes) {
2278
				if (isset($ifcfg['wireless'][$setting]))
2279
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2280
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2281
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2282
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2283
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2284
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2285
				else if (isset($ifcfg['wireless'][$setting]))
2286
					unset($ifcfg['wireless'][$setting]);
2287
			}
2288
		}
2289
	}
2290

    
2291
	// Sync the mode on the clone creation page with the configured mode on the interface
2292
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2293
		foreach ($config['wireless']['clone'] as &$clone) {
2294
			if ($clone['cloneif'] == $ifcfg['if']) {
2295
				if ($sync_changes) {
2296
					$clone['mode'] = $ifcfg['wireless']['mode'];
2297
				} else {
2298
					$ifcfg['wireless']['mode'] = $clone['mode'];
2299
				}
2300
				break;
2301
			}
2302
		}
2303
		unset($clone);
2304
	}
2305
}
2306

    
2307
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2308
	global $config, $g;
2309

    
2310
	/*    open up a shell script that will be used to output the commands.
2311
	 *    since wireless is changing a lot, these series of commands are fragile
2312
	 *    and will sometimes need to be verified by a operator by executing the command
2313
	 *    and returning the output of the command to the developers for inspection.  please
2314
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2315
	 */
2316

    
2317
	// Remove script file
2318
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2319

    
2320
	// Clone wireless nic if needed.
2321
	interface_wireless_clone($if, $wl);
2322

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

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

    
2330
	/* set values for /path/program */
2331
	$hostapd = "/usr/sbin/hostapd";
2332
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2333
	$ifconfig = "/sbin/ifconfig";
2334
	$sysctl = "/sbin/sysctl";
2335
	$killall = "/usr/bin/killall";
2336

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

    
2339
	$wlcmd = array();
2340
	$wl_sysctl = array();
2341
	/* Make sure it's up */
2342
	$wlcmd[] = "up";
2343
	/* Set a/b/g standard */
2344
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2345
	$wlcmd[] = "mode " . escapeshellarg($standard);
2346

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

    
2352
	/* Set ssid */
2353
	if($wlcfg['ssid'])
2354
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2355

    
2356
	/* Set 802.11g protection mode */
2357
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2358

    
2359
	/* set wireless channel value */
2360
	if(isset($wlcfg['channel'])) {
2361
		if($wlcfg['channel'] == "0") {
2362
			$wlcmd[] = "channel any";
2363
		} else {
2364
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2365
		}
2366
	}
2367

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

    
2372
	/* Set txantenna value */
2373
	if(isset($wlcfg['txantenna']))
2374
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2375

    
2376
	/* Set rxantenna value */
2377
	if(isset($wlcfg['rxantenna']))
2378
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2379

    
2380
	/* set Distance value */
2381
	if($wlcfg['distance'])
2382
		$distance = escapeshellarg($wlcfg['distance']);
2383

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

    
2391
	/* Set wireless adhoc mode */
2392
	if ($wlcfg['mode'] == "adhoc") {
2393
		$wlcmd[] = "mediaopt adhoc";
2394
	} else {
2395
		$wlcmd[] = "-mediaopt adhoc";
2396
	}
2397

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

    
2400
	/* handle hide ssid option */
2401
	if(isset($wlcfg['hidessid']['enable'])) {
2402
		$wlcmd[] = "hidessid";
2403
	} else {
2404
		$wlcmd[] = "-hidessid";
2405
	}
2406

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

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

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

    
2428
	/* handle turbo option */
2429
	if(isset($wlcfg['turbo']['enable'])) {
2430
		$wlcmd[] = "mediaopt turbo";
2431
	} else {
2432
		$wlcmd[] = "-mediaopt turbo";
2433
	}
2434

    
2435
	/* handle txpower setting */
2436
	/* if($wlcfg['txpower'] <> "")
2437
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2438
	*/
2439
	/* handle wme option */
2440
	if(isset($wlcfg['wme']['enable'])) {
2441
		$wlcmd[] = "wme";
2442
	} else {
2443
		$wlcmd[] = "-wme";
2444
	}
2445

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

    
2472
	kill_hostapd($if);
2473
	mwexec(kill_wpasupplicant("{$if}"));
2474

    
2475
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2476
	conf_mount_rw();
2477

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

    
2497
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2498
				fwrite($fd, "{$wpa}");
2499
				fclose($fd);
2500
			}
2501
			break;
2502
		case 'hostap':
2503
			if($wlcfg['wpa']['passphrase'])
2504
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2505
			else
2506
				$wpa_passphrase = "";
2507
			if (isset($wlcfg['wpa']['enable'])) {
2508
				$wpa .= <<<EOD
2509
interface={$if}
2510
driver=bsd
2511
logger_syslog=-1
2512
logger_syslog_level=0
2513
logger_stdout=-1
2514
logger_stdout_level=0
2515
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2516
ctrl_interface={$g['varrun_path']}/hostapd
2517
ctrl_interface_group=wheel
2518
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2519
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2520
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2521
ssid={$wlcfg['ssid']}
2522
debug={$wlcfg['wpa']['debug_mode']}
2523
auth_algs={$wlcfg['wpa']['auth_algs']}
2524
wpa={$wlcfg['wpa']['wpa_mode']}
2525
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2526
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2527
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2528
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2529
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2530
{$wpa_passphrase}
2531

    
2532
EOD;
2533

    
2534
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2535
	$wpa .= <<<EOD
2536
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2537
rsn_preauth=1
2538
rsn_preauth_interfaces={$if}
2539

    
2540
EOD;
2541

    
2542
}
2543
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2544
					$auth_server_port = "1812";
2545
					if($wlcfg['auth_server_port'])
2546
						$auth_server_port = $wlcfg['auth_server_port'];
2547
					$auth_server_port2 = "1812";
2548
					if($wlcfg['auth_server_port2'])
2549
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2550
					$wpa .= <<<EOD
2551

    
2552
ieee8021x=1
2553
auth_server_addr={$wlcfg['auth_server_addr']}
2554
auth_server_port={$auth_server_port}
2555
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2556
auth_server_addr={$wlcfg['auth_server_addr2']}
2557
auth_server_port={$auth_server_port2}
2558
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2559

    
2560
EOD;
2561
				} else if (isset($wlcfg['wpa']['ieee8021x'])) {
2562
					$wpa .= "ieee8021x=1\n";
2563
				}
2564

    
2565
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2566
				fwrite($fd, "{$wpa}");
2567
				fclose($fd);
2568

    
2569
			}
2570
			break;
2571
	}
2572

    
2573
	/*
2574
	 *    all variables are set, lets start up everything
2575
	 */
2576

    
2577
	$baseif = interface_get_wireless_base($if);
2578
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2579
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2580

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

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

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

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

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

    
2623
	fclose($fd_set);
2624
	conf_mount_ro();
2625

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

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

    
2646
	if ($reg_changing) {
2647
		/* set regulatory domain */
2648
		if($wlcfg['regdomain'])
2649
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2650

    
2651
		/* set country */
2652
		if($wlcfg['regcountry'])
2653
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2654

    
2655
		/* set location */
2656
		if($wlcfg['reglocation'])
2657
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2658

    
2659
		$wlregcmd_args = implode(" ", $wlregcmd);
2660

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

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

    
2682
		/* apply the regulatory settings */
2683
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2684

    
2685
		/* bring the clones back up that were previously up */
2686
		foreach ($clones_up as $clone_if) {
2687
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2688

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

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

    
2709
	/* configure wireless */
2710
	$wlcmd_args = implode(" ", $wlcmd);
2711
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $wlcmd_args, false);
2712

    
2713

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

    
2718
	return 0;
2719

    
2720
}
2721

    
2722
function kill_hostapd($interface) {
2723
	global $g;
2724

    
2725
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2726
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2727
}
2728

    
2729
function kill_wpasupplicant($interface) {
2730
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2731
}
2732

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

    
2739
	return intval($pid);
2740
}
2741

    
2742
function find_dhcp6c_process($interface) {
2743
	global $g;
2744

    
2745
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2746
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2747
	else
2748
		return(false);
2749

    
2750
	return intval($pid);
2751
}
2752

    
2753
function interface_vlan_mtu_configured($realhwif, $mtu) {
2754
	global $config;
2755

    
2756
	if (is_array($config['vlans']) && is_array($config['vlans']['vlan'])) {
2757
		foreach ($config['vlans']['vlan'] as $vlan) {
2758
			if ($vlan['if'] != $realhwif)
2759
				continue;
2760
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2761
			if (!empty($assignedport) && !empty($config['interfaces'][$assignedport]['mtu'])) {
2762
				if (intval($config['interfaces'][$assignedport]['mtu']) > $mtu)
2763
					$mtu = $portmtu;
2764
			}
2765
		}
2766
	}
2767

    
2768
	return $mtu;
2769
}
2770

    
2771
function interface_virtual_create($interface) {
2772
	global $config;
2773

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

    
2811
function interface_vlan_adapt_mtu($vlanifs, $mtu) {
2812
	global $config;
2813

    
2814
	if (!is_array($vlanifs))
2815
		return;
2816

    
2817
	/* All vlans need to use the same mtu value as their parent. */
2818
	foreach ($vlanifs as $vlan) {
2819
		$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2820
		if (!empty($assignedport)) {
2821
			if (!empty($config['interfaces'][$assignedport]['mtu'])) {
2822
				/*
2823
				* XXX: This is really never going to happen just keep the code for safety and readbility.
2824
				* It never happens since interface_vlan_mtu_configured finds the biggest mtu on vlans.
2825
				* Also if it has a lower mtu configured just respect user choice.
2826
				*/
2827
				if (intval($config['interfaces'][$assignedport]['mtu']) > $mtu)
2828
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
2829
			} else {
2830
				if (get_interface_mtu($vlan['vlanif']) != $mtu)
2831
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
2832
			}
2833
		} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
2834
			pfSense_interface_mtu($vlan['vlanif'], $mtu);
2835
	}
2836
}
2837

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

    
2843
	$wancfg = $config['interfaces'][$interface];
2844

    
2845
	if (!isset($wancfg['enable']))
2846
		return;
2847

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

    
2853
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2854
		/* remove all IPv4 and IPv6 addresses */
2855
		$tmpifaces = pfSense_getall_interface_addresses($realif);
2856
		if (is_array($tmpifaces)) {
2857
			foreach ($tmpifaces as $tmpiface) {
2858
				if (strstr($tmpiface, ":"))
2859
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$tmpiface} delete");
2860
				else
2861
					pfSense_interface_deladdress($realif, $tmpiface);
2862
			}
2863
		}
2864

    
2865
		/* only bring down the interface when both v4 and v6 are set to NONE */
2866
		if (empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6']))
2867
			interface_bring_down($interface);
2868
	}
2869

    
2870
	$interface_to_check = $realif;
2871
	switch ($wancfg['ipaddr']) {
2872
	case 'pppoe':
2873
	case 'l2tp':
2874
	case 'pptp':
2875
	case 'ppp':
2876
		$interface_to_check = $realhwif;
2877
		break;
2878
	}
2879

    
2880
	/* Need to check that the interface exists or not in the case where its coming back from disabled state see #3270 */
2881
	if (!does_interface_exist($interface_to_check))
2882
		interface_virtual_create($interface_to_check);
2883

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

    
2889
	/* wireless configuration? */
2890
	if (is_array($wancfg['wireless']))
2891
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2892

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

    
2904
		/*
2905
		 * All vlans need to spoof their parent mac address, too.  see
2906
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2907
		 */
2908
		if (is_array($config['vlans']['vlan'])) {
2909
			foreach ($config['vlans']['vlan'] as $vlan) {
2910
				if ($vlan['if'] == $realhwif)
2911
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2912
					" link " . escapeshellarg($wancfg['spoofmac']));
2913
			}
2914
		}
2915
	}  else {
2916

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

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

    
2942
	/* skip vlans for checksumming and polling */
2943
	if (!stristr($realif, "_vlan") && is_array($options)) {
2944
		$flags_on = 0;
2945
		$flags_off = 0;
2946
		if(isset($config['system']['disablechecksumoffloading'])) {
2947
			if (isset($options['encaps']['txcsum']))
2948
				$flags_off |= IFCAP_TXCSUM;
2949
			if (isset($options['encaps']['rxcsum']))
2950
				$flags_off |= IFCAP_RXCSUM;
2951
		} else {
2952
			if (isset($options['caps']['txcsum']))
2953
				$flags_on |= IFCAP_TXCSUM;
2954
			if (isset($options['caps']['rxcsum']))
2955
				$flags_on |= IFCAP_RXCSUM;
2956
		}
2957

    
2958
		if(isset($config['system']['disablesegmentationoffloading']))
2959
			$flags_off |= IFCAP_TSO;
2960
		else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6']))
2961
			$flags_on |= IFCAP_TSO;
2962

    
2963
		if(isset($config['system']['disablelargereceiveoffloading']))
2964
			$flags_off |= IFCAP_LRO;
2965
		else if (isset($options['caps']['lro']))
2966
			$flags_on |= IFCAP_LRO;
2967

    
2968
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2969
		if (!isset($config['system']['polling']))
2970
			$flags_off |= IFCAP_POLLING;
2971
		else if (isset($options['caps']['polling']))
2972
			$flags_on |= IFCAP_POLLING;
2973

    
2974
		pfSense_interface_capabilities($realhwif, -$flags_off);
2975
		pfSense_interface_capabilities($realhwif, $flags_on);
2976
	}
2977

    
2978
	/* invalidate interface/ip/sn cache */
2979
	get_interface_arr(true);
2980
	unset($interface_ip_arr_cache[$realif]);
2981
	unset($interface_sn_arr_cache[$realif]);
2982
	unset($interface_ipv6_arr_cache[$realif]);
2983
	unset($interface_snv6_arr_cache[$realif]);
2984

    
2985
	switch ($wancfg['ipaddr']) {
2986
		case 'dhcp':
2987
			interface_dhcp_configure($interface);
2988
			break;
2989
		case 'pppoe':
2990
		case 'l2tp':
2991
		case 'pptp':
2992
		case 'ppp':
2993
			interface_ppps_configure($interface);
2994
			break;
2995
		default:
2996
			if (is_ipaddrv4($wancfg['ipaddr']) && $wancfg['subnet'] <> "")
2997
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2998
			break;
2999
	}
3000

    
3001
	switch ($wancfg['ipaddrv6']) {
3002
		case 'slaac':
3003
		case 'dhcp6':
3004
			interface_dhcpv6_configure($interface, $wancfg);
3005
			break;
3006
		case '6rd':
3007
			interface_6rd_configure($interface, $wancfg);
3008
			break;
3009
		case '6to4':
3010
			interface_6to4_configure($interface, $wancfg);
3011
			break;
3012
		case 'track6':
3013
			interface_track6_configure($interface, $wancfg);
3014
			break;
3015
		default:
3016
			if (is_ipaddrv6($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
3017
				//pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
3018
				// FIXME: Add IPv6 Support to the pfSense module
3019
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$wancfg['ipaddrv6']} prefixlen " . escapeshellarg($wancfg['subnetv6']));
3020
			}
3021
			break;
3022
	}
3023

    
3024
	if (!empty($wancfg['mtu'])) {
3025
		if (stristr($realif, "_vlan")) {
3026
			$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
3027
			if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
3028
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
3029
			else
3030
				$parentmtu = interface_vlan_mtu_configured($realhwif, $wancfg['mtu']);
3031

    
3032
			if ($wancfg['mtu'] > $parentmtu) {
3033
				if (get_interface_mtu($realhwif) != $wancfg['mtu'])
3034
					pfSense_interface_mtu($realhwif, $wancfg['mtu']);
3035

    
3036
				/* All vlans need to use the same mtu value as their parent. */
3037
				interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $wancfg['mtu']);
3038
			} else
3039
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3040
		} else {
3041
			if ($wancfg['mtu'] != get_interface_mtu($realif))
3042
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3043

    
3044
			/* This case is needed when the parent of vlans is being configured */
3045
			interface_vlan_adapt_mtu(link_interface_to_vlans($realif), $wancfg['mtu']);
3046
		}
3047
		/* XXX: What about gre/gif/lagg/.. ? */
3048
	}
3049

    
3050
	if (does_interface_exist($wancfg['if']))
3051
		interfaces_bring_up($wancfg['if']);
3052

    
3053
	interface_netgraph_needed($interface);
3054

    
3055
	if (!$g['booting']) {
3056
		link_interface_to_vips($interface, "update");
3057

    
3058
		unset($gre);
3059
		$gre = link_interface_to_gre($interface);
3060
		if (!empty($gre))
3061
			array_walk($gre, 'interface_gre_configure');
3062

    
3063
		unset($gif);
3064
		$gif = link_interface_to_gif($interface);
3065
		if (!empty($gif))
3066
			array_walk($gif, 'interface_gif_configure');
3067

    
3068
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3069
			unset($bridgetmp);
3070
			$bridgetmp = link_interface_to_bridge($interface);
3071
			if (!empty($bridgetmp))
3072
				interface_bridge_add_member($bridgetmp, $realif);
3073
		}
3074

    
3075
		$grouptmp = link_interface_to_group($interface);
3076
		if (!empty($grouptmp))
3077
			array_walk($grouptmp, 'interface_group_add_member');
3078

    
3079
		if ($interface == "lan")
3080
			/* make new hosts file */
3081
			system_hosts_generate();
3082

    
3083
		if ($reloadall == true) {
3084

    
3085
			/* reconfigure static routes (kernel may have deleted them) */
3086
			system_routing_configure($interface);
3087

    
3088
			/* reload ipsec tunnels */
3089
			vpn_ipsec_configure();
3090

    
3091
			/* restart dnsmasq */
3092
			services_dnsmasq_configure();
3093

    
3094
			/* update dyndns */
3095
			send_event("service reload dyndns {$interface}");
3096

    
3097
			/* XXX: which CPZONE? Needed? */
3098
			/* reload captive portal */
3099
			captiveportal_init_rules();
3100
		}
3101
	}
3102

    
3103
	interfaces_staticarp_configure($interface);
3104
	return 0;
3105
}
3106

    
3107
function interface_track6_configure($interface = "lan", $wancfg) {
3108
	global $config, $g;
3109

    
3110
	if (!is_array($wancfg))
3111
		return;
3112

    
3113
	if (!isset($wancfg['enable']))
3114
		return;
3115

    
3116
	/* If the interface is not configured via another, exit */
3117
	if (empty($wancfg['track6-interface']))
3118
		return;
3119

    
3120
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3121
	$realif = get_real_interface($interface);
3122
	$linklocal = find_interface_ipv6_ll($realif);
3123
	if (!empty($linklocal))
3124
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3125
	/* XXX: This might break for good on a carp installation using link-local as network ips */
3126
	/* XXX: Probably should remove? */
3127
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3128

    
3129
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3130
	if (!isset($trackcfg['enable'])) {
3131
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3132
		return;
3133
	}
3134

    
3135
	switch($trackcfg['ipaddrv6']) {
3136
	case "6to4":
3137
		if ($g['debug'])
3138
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3139
		interface_track6_6to4_configure($interface, $wancfg);
3140
		break;
3141
	case "6rd":
3142
		if ($g['debug'])
3143
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3144
		interface_track6_6rd_configure($interface, $wancfg);
3145
		break;
3146
	}
3147

    
3148
	if (!$g['booting']) {
3149
		if (!function_exists('services_dhcpd_configure'))
3150
			require_once("services.inc");
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 public, 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
	$wanif = get_real_interface($interface);
3286
	$ip4address = find_interface_ip($wanif);
3287
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3288
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3289
		return false;
3290
	}
3291
	$hexwanv4 = return_hex_ipv4($ip4address);
3292

    
3293
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3294
		$wancfg['prefix-6rd-v4plen'] = 0;
3295

    
3296
	/* create the long prefix notation for math, save the prefix length */
3297
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3298
	$rd6prefixlen = $rd6prefix[1];
3299
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3300

    
3301
	/* binary presentation of the prefix for all 128 bits. */
3302
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3303

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

    
3311
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3312
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3313

    
3314
	$rd6brgw = "{$rd6prefix}{$wancfg['gateway-6rd']}";
3315

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

    
3332
	/* write out a default router file */
3333
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3334
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3335

    
3336
	$ip4gateway = get_interface_gateway($interface);
3337
	if (is_ipaddrv4($ip4gateway))
3338
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3339

    
3340
	/* configure dependent interfaces */
3341
	if (!$g['booting'])
3342
		link_interface_to_track6($interface, "update");
3343

    
3344
	return 0;
3345
}
3346

    
3347
function interface_6to4_configure($interface = "wan", $wancfg){
3348
	global $config, $g;
3349

    
3350
	/* because this is a tunnel interface we can only function
3351
	 *	with a public IPv4 address on the interface */
3352

    
3353
	if (!is_array($wancfg))
3354
		return;
3355

    
3356
	$wanif = get_real_interface($interface);
3357
	$ip4address = find_interface_ip($wanif);
3358
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3359
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3360
		return false;
3361
	}
3362

    
3363
	/* create the long prefix notation for math, save the prefix length */
3364
	$stfprefixlen = 16;
3365
	$stfprefix = Net_IPv6::uncompress("2002::");
3366
	$stfarr = explode(":", $stfprefix);
3367
	$v4prefixlen = "0";
3368

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

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

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

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

    
3393
	/* for the local subnet too. */
3394
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3395
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3396

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

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

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

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

    
3429
	/* write out a default router file */
3430
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3431
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3432

    
3433
	$ip4gateway = get_interface_gateway($interface);
3434
	if (is_ipaddrv4($ip4gateway))
3435
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3436

    
3437
	if (!$g['booting'])
3438
		link_interface_to_track6($interface, "update");
3439

    
3440
	return 0;
3441
}
3442

    
3443
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3444
	global $config, $g;
3445

    
3446
	if (!is_array($wancfg))
3447
		return;
3448

    
3449
	$wanif = get_real_interface($interface, "inet6");
3450
	$dhcp6cconf = "";
3451
	$dhcp6cconf .= "interface {$wanif} {\n";
3452

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

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

    
3471
		$dhcp6cconf .= "};\n";
3472

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

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

    
3499
	// DHCP6 Config File Advanced
3500
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3501

    
3502
	// DHCP6 Config File Override
3503
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3504

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

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

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

    
3546
	/* accept router advertisements for this interface */
3547
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3548
	log_error("Accept router advertisements on interface {$wanif} ");
3549
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3550

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

    
3558
	/* NOTE: will be called from rtsold invoked script
3559
	 * link_interface_to_track6($interface, "update");
3560
	 */
3561

    
3562
	return 0;
3563
}
3564

    
3565
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3566
	global $g;
3567

    
3568
	$send_options = "";
3569
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3570
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_send_options']);
3571
		foreach ($options as $option) {
3572
			$send_options .= "\tsend " . trim($option) . ";\n";
3573
		}
3574
	}
3575

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

    
3584
	$information_only = "";
3585
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3586
		$information_only = "\tinformation-only;\n";
3587

    
3588
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3589
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3590
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3591

    
3592
	$interface_statement  = "interface";
3593
	$interface_statement .= " {$wanif}";
3594
	$interface_statement .= " {\n";
3595
	$interface_statement .= "$send_options";
3596
	$interface_statement .= "$request_options";
3597
	$interface_statement .= "$information_only";
3598
	$interface_statement .= "$script";
3599
	$interface_statement .= "};\n";
3600

    
3601
	$id_assoc_statement_address = "";
3602
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3603
		$id_assoc_statement_address .= "id-assoc";
3604
		$id_assoc_statement_address .= " na";
3605
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3606
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3607
		$id_assoc_statement_address .= " { ";
3608

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

    
3621
		$id_assoc_statement_address  .= "};\n";
3622
	}
3623

    
3624
	$id_assoc_statement_prefix = "";
3625
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3626
		$id_assoc_statement_prefix .= "id-assoc";
3627
		$id_assoc_statement_prefix .= " pd";
3628
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3629
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3630
		$id_assoc_statement_prefix .= " { ";
3631

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

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

    
3655
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3656
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3657
			$id_assoc_statement_prefix .= "\n";
3658
		}
3659

    
3660
		$id_assoc_statement_prefix  .= "};\n";
3661
	}
3662

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

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

    
3693
	$dhcp6cconf  = $interface_statement;
3694
	$dhcp6cconf .= $id_assoc_statement_address;
3695
	$dhcp6cconf .= $id_assoc_statement_prefix;
3696
	$dhcp6cconf .= $authentication_statement;
3697
	$dhcp6cconf .= $key_info_statement;
3698

    
3699
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3700

    
3701
	return $dhcp6cconf;
3702
}
3703

    
3704

    
3705
function DHCP6_Config_File_Override($wancfg, $wanif) {
3706

    
3707
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3708
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3709

    
3710
	return $dhcp6cconf;
3711
}
3712

    
3713

    
3714
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3715

    
3716
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3717

    
3718
	return $dhcp6cconf;
3719
}
3720

    
3721

    
3722
function interface_dhcp_configure($interface = "wan") {
3723
	global $config, $g;
3724

    
3725
	$wancfg = $config['interfaces'][$interface];
3726
	$wanif = $wancfg['if'];
3727
	if (empty($wancfg))
3728
		$wancfg = array();
3729

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

    
3737
	if ($wancfg['dhcphostname']) {
3738
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3739
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3740
	} else {
3741
		$dhclientconf_hostname = "";
3742
	}
3743

    
3744
	$wanif = get_real_interface($interface);
3745
	if (empty($wanif)) {
3746
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3747
		return 0;
3748
	}
3749
	$dhclientconf = "";
3750

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

    
3761
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3762
	$dhclientconf .= <<<EOD
3763

    
3764
	reject {$wancfg['dhcprejectfrom']};
3765
EOD;
3766
}
3767
	$dhclientconf .= <<<EOD
3768

    
3769
}
3770

    
3771
EOD;
3772

    
3773
	// DHCP Config File Advanced
3774
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3775

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

    
3785
EOD;
3786
}
3787

    
3788
	// DHCP Config File Override
3789
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3790

    
3791
	fwrite($fd, $dhclientconf);
3792
	fclose($fd);
3793

    
3794
	/* bring wan interface up before starting dhclient */
3795
	if($wanif)
3796
		interfaces_bring_up($wanif);
3797
	else
3798
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3799

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

    
3803
	return 0;
3804
}
3805

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

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

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

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

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

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

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

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

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

    
3871
	return $dhclientconf;
3872
}
3873

    
3874

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

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

    
3880
	return $dhclientconf;
3881
}
3882

    
3883

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

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

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

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

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

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

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

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

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

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

    
3932
	return $dhclientconf;
3933
}
3934

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

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

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

    
3944
	return;
3945
}
3946

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

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

    
3959
	return;
3960
}
3961

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

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

    
3971
	return false;
3972
}
3973

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

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

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

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

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

    
4000
	/* XXX: For speed reasons reference directly the interface array */
4001
	$ifdescrs = &$config['interfaces'];
4002
	//$ifdescrs = get_configured_interface_list(false, true);
4003

    
4004
	foreach ($ifdescrs as $if => $ifname) {
4005
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
4006
			return $if;
4007

    
4008
		if (get_real_interface($if) == $interface)
4009
			return $if;
4010

    
4011
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
4012
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
4013
		/*
4014
		$int = get_parent_interface($if);
4015
		if ($int[0] == $interface)
4016
			return $ifname;
4017
		*/
4018
	}
4019

    
4020
	return NULL;
4021
}
4022

    
4023
/* attempt to resolve interface to friendly descr */
4024
function convert_friendly_interface_to_friendly_descr($interface) {
4025
	global $config;
4026

    
4027
	switch ($interface) {
4028
	case "l2tp":
4029
		$ifdesc = "L2TP";
4030
		break;
4031
	case "pptp":
4032
		$ifdesc = "PPTP";
4033
		break;
4034
	case "pppoe":
4035
		$ifdesc = "PPPoE";
4036
		break;
4037
	case "openvpn":
4038
		$ifdesc = "OpenVPN";
4039
		break;
4040
	case "enc0":
4041
	case "ipsec":
4042
		$ifdesc = "IPsec";
4043
		break;
4044
	default:
4045
		if (isset($config['interfaces'][$interface])) {
4046
			if (empty($config['interfaces'][$interface]['descr']))
4047
				$ifdesc = strtoupper($interface);
4048
			else
4049
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4050
			break;
4051
		} else if (stristr($interface, "_vip")) {
4052
			if (is_array($config['virtualip']['vip'])) {
4053
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4054
					if ($vip['mode'] == "carp")  {
4055
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4056
							return "{$vip['subnet']} - {$vip['descr']}";
4057
					}
4058
				}
4059
			}
4060
		} else {
4061
			/* if list */
4062
			$ifdescrs = get_configured_interface_with_descr(false, true);
4063
			foreach ($ifdescrs as $if => $ifname) {
4064
				if ($if == $interface || $ifname == $interface)
4065
					return $ifname;
4066
			}
4067
		}
4068
		break;
4069
	}
4070

    
4071
	return $ifdesc;
4072
}
4073

    
4074
function convert_real_interface_to_friendly_descr($interface) {
4075
	global $config;
4076

    
4077
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4078

    
4079
	if ($ifdesc) {
4080
		$iflist = get_configured_interface_with_descr(false, true);
4081
		return $iflist[$ifdesc];
4082
	}
4083

    
4084
	return $interface;
4085
}
4086

    
4087
/*
4088
 *  get_parent_interface($interface):
4089
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4090
 *				or virtual interface (i.e. vlan)
4091
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4092
 *			-- returns $interface passed in if $interface parent is not found
4093
 *			-- returns empty array if an invalid interface is passed
4094
 *	(Only handles ppps and vlans now.)
4095
 */
4096
function get_parent_interface($interface) {
4097
	global $config;
4098

    
4099
	$parents = array();
4100
	//Check that we got a valid interface passed
4101
	$realif = get_real_interface($interface);
4102
	if ($realif == NULL)
4103
		return $parents;
4104

    
4105
	// If we got a real interface, find it's friendly assigned name
4106
	if ($interface == $realif)
4107
		$interface = convert_real_interface_to_friendly_interface_name($interface);
4108

    
4109
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4110
		$ifcfg = $config['interfaces'][$interface];
4111
		switch ($ifcfg['ipaddr']) {
4112
			case "ppp":
4113
			case "pppoe":
4114
			case "pptp":
4115
			case "l2tp":
4116
				if (empty($parents))
4117
					if (is_array($config['ppps']['ppp']))
4118
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4119
							if ($ifcfg['if'] == $ppp['if']) {
4120
								$ports = explode(',', $ppp['ports']);
4121
								foreach ($ports as $pid => $parent_if)
4122
									$parents[$pid] = get_real_interface($parent_if);
4123
								break;
4124
							}
4125
						}
4126
				break;
4127
			case "dhcp":
4128
			case "static":
4129
			default:
4130
				// Handle _vlans
4131
				if (stristr($realif,"_vlan"))
4132
					if (is_array($config['vlans']['vlan']))
4133
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
4134
							if ($ifcfg['if'] == $vlan['vlanif']){
4135
								$parents[0] = $vlan['if'];
4136
								break;
4137
							}
4138
				break;
4139
		}
4140
	}
4141

    
4142
	if (empty($parents))
4143
		$parents[0] = $realif;
4144

    
4145
	return $parents;
4146
}
4147

    
4148
function interface_is_wireless_clone($wlif) {
4149
	if(!stristr($wlif, "_wlan")) {
4150
		return false;
4151
	} else {
4152
		return true;
4153
	}
4154
}
4155

    
4156
function interface_get_wireless_base($wlif) {
4157
	if(!stristr($wlif, "_wlan")) {
4158
		return $wlif;
4159
	} else {
4160
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4161
	}
4162
}
4163

    
4164
function interface_get_wireless_clone($wlif) {
4165
	if(!stristr($wlif, "_wlan")) {
4166
		return $wlif . "_wlan0";
4167
	} else {
4168
		return $wlif;
4169
	}
4170
}
4171

    
4172
function get_real_interface($interface = "wan", $family = "all", $realv6iface = false, $flush = true) {
4173
	global $config, $g;
4174

    
4175
	$wanif = NULL;
4176

    
4177
	switch ($interface) {
4178
	case "l2tp":
4179
		$wanif = "l2tp";
4180
		break;
4181
	case "pptp":
4182
		$wanif = "pptp";
4183
		break;
4184
	case "pppoe":
4185
		$wanif = "pppoe";
4186
		break;
4187
	case "openvpn":
4188
		$wanif = "openvpn";
4189
		break;
4190
	case "ipsec":
4191
	case "enc0":
4192
		$wanif = "enc0";
4193
		break;
4194
	case "ppp":
4195
		$wanif = "ppp";
4196
		break;
4197
	default:
4198
		// If a real interface was alread passed simply
4199
		// pass the real interface back.  This encourages
4200
		// the usage of this function in more cases so that
4201
		// we can combine logic for more flexibility.
4202
		if(does_interface_exist($interface, $flush)) {
4203
			$wanif = $interface;
4204
			break;
4205
		}
4206

    
4207
		if (empty($config['interfaces'][$interface]))
4208
			break;
4209

    
4210
		$cfg = &$config['interfaces'][$interface];
4211

    
4212
		if ($family == "inet6") {
4213
			switch ($cfg['ipaddrv6']) {
4214
			case "6rd":
4215
			case "6to4":
4216
				$wanif = "{$interface}_stf";
4217
				break;
4218
			case 'pppoe':
4219
			case 'ppp':
4220
			case 'l2tp':
4221
			case 'pptp':
4222
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4223
					$wanif = interface_get_wireless_clone($cfg['if']);
4224
				else
4225
					$wanif = $cfg['if'];
4226
				break;
4227
			default:
4228
				switch ($cfg['ipaddr']) {
4229
				case 'pppoe':
4230
				case 'ppp':
4231
				case 'l2tp':
4232
				case 'pptp':
4233
					if (isset($cfg['dhcp6usev4iface']) && $realv6iface === false)
4234
						$wanif = $cfg['if'];
4235
					else {
4236
						$parents = get_parent_interface($interface);
4237
						if (!empty($parents[0]))
4238
							$wanif = $parents[0];
4239
						else
4240
							$wanif = $cfg['if'];
4241
					}
4242
					break;
4243
				default:
4244
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4245
						$wanif = interface_get_wireless_clone($cfg['if']);
4246
					else
4247
						$wanif = $cfg['if'];
4248
					break;
4249
				}
4250
				break;
4251
			}
4252
		} else {
4253
			// Wireless cloned NIC support (FreeBSD 8+)
4254
			// interface name format: $parentnic_wlanparentnic#
4255
			// example: ath0_wlan0
4256
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4257
				$wanif = interface_get_wireless_clone($cfg['if']);
4258
			else
4259
				$wanif = $cfg['if'];
4260
		}
4261
		break;
4262
	}
4263

    
4264
	return $wanif;
4265
}
4266

    
4267
/* Guess the physical interface by providing a IP address */
4268
function guess_interface_from_ip($ipaddress) {
4269
	if(! is_ipaddr($ipaddress)) {
4270
		return false;
4271
	}
4272
	if(is_ipaddrv4($ipaddress)) {
4273
		/* create a route table we can search */
4274
		exec("netstat -rnWf inet", $output, $ret);
4275
		foreach($output as $line) {
4276
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
4277
				$fields = preg_split("/[ ]+/", $line);
4278
				if(ip_in_subnet($ipaddress, $fields[0])) {
4279
					return $fields[6];
4280
				}
4281
			}
4282
		}
4283
	}
4284
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
4285
	if(is_ipaddrv6($ipaddress)) {
4286
		/* create a route table we can search */
4287
		exec("netstat -rnWf inet6", $output, $ret);
4288
		foreach($output as $line) {
4289
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
4290
				$fields = preg_split("/[ ]+/", $line);
4291
				if(ip_in_subnet($ipaddress, $fields[0])) {
4292
					return $fields[6];
4293
				}
4294
			}
4295
		}
4296
	}
4297
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
4298
	if(empty($ret)) {
4299
		return false;
4300
	}
4301
	return $ret;
4302
}
4303

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

    
4312
	$isv6ip = is_ipaddrv6($ip);
4313

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

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

    
4335
	return false;
4336
}
4337

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

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

    
4351
	$isv6ip = is_ipaddrv6($ip);
4352

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

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

    
4380
function get_all_carp_interfaces() {
4381
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
4382
	$ints = explode(" ", $ints);
4383
	return $ints;
4384
}
4385

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

    
4411
				if ($if)
4412
					return $if;
4413
			}
4414
		}
4415
	}
4416
}
4417

    
4418
function link_carp_interface_to_parent($interface) {
4419
	global $config;
4420

    
4421
	if (empty($interface))
4422
		return;
4423

    
4424
	$carp_ip = get_interface_ip($interface);
4425
	$carp_ipv6 = get_interface_ipv6($interface);
4426

    
4427
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4428
		return;
4429

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

    
4452

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

    
4464
	if (!is_ipaddr($ip))
4465
		return;
4466

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

    
4485
	return $carp_ints;
4486
}
4487

    
4488
function link_interface_to_track6($int, $action = "") {
4489
	global $config;
4490

    
4491
	if (empty($int))
4492
		return;
4493

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

    
4510
function link_interface_to_vlans($int, $action = "") {
4511
	global $config;
4512

    
4513
	if (empty($int))
4514
		return;
4515

    
4516
	if (is_array($config['vlans']['vlan'])) {
4517
		$ifaces = array();
4518
		foreach ($config['vlans']['vlan'] as $vlan) {
4519
			if ($int == $vlan['if']) {
4520
				if ($action == "update") {
4521
					interfaces_bring_up($int);
4522
				} else if ($action == "")
4523
					$ifaces[$vlan['tag']] = $vlan;
4524
			}
4525
		}
4526
		if (!empty($ifaces))
4527
			return $ifaces;
4528
	}
4529
}
4530

    
4531
function link_interface_to_vips($int, $action = "") {
4532
	global $config;
4533

    
4534
	if (is_array($config['virtualip']['vip'])) {
4535
		$result = array();
4536
		foreach ($config['virtualip']['vip'] as $vip) {
4537
			if ($int == $vip['interface']) {
4538
				if ($action == "update")
4539
					interfaces_vips_configure($int);
4540
				else
4541
					$result[] = $vip;
4542
			}
4543
		}
4544
		return $result;
4545
	}
4546
}
4547

    
4548
/****f* interfaces/link_interface_to_bridge
4549
 * NAME
4550
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4551
 * INPUTS
4552
 *   $ip
4553
 * RESULT
4554
 *   bridge[0-99]
4555
 ******/
4556
function link_interface_to_bridge($int) {
4557
	global $config;
4558

    
4559
	if (is_array($config['bridges']['bridged'])) {
4560
		foreach ($config['bridges']['bridged'] as $bridge) {
4561
			if (in_array($int, explode(',', $bridge['members'])))
4562
				return "{$bridge['bridgeif']}";
4563
		}
4564
	}
4565
}
4566

    
4567
function link_interface_to_group($int) {
4568
	global $config;
4569

    
4570
	$result = array();
4571

    
4572
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4573
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4574
			if (in_array($int, explode(" ", $group['members'])))
4575
				$result[$group['ifname']] = $int;
4576
		}
4577
	}
4578

    
4579
	return $result;
4580
}
4581

    
4582
function link_interface_to_gre($interface) {
4583
	global $config;
4584

    
4585
	$result = array();
4586

    
4587
	if (is_array($config['gres']['gre'])) {
4588
		foreach ($config['gres']['gre'] as $gre)
4589
			if($gre['if'] == $interface)
4590
				$result[] = $gre;
4591
	}
4592

    
4593
	return $result;
4594
}
4595

    
4596
function link_interface_to_gif($interface) {
4597
	global $config;
4598

    
4599
	$result = array();
4600

    
4601
	if (is_array($config['gifs']['gif'])) {
4602
		foreach ($config['gifs']['gif'] as $gif)
4603
			if($gif['if'] == $interface)
4604
				$result[] = $gif;
4605
	}
4606

    
4607
	return $result;
4608
}
4609

    
4610
/*
4611
 * find_interface_ip($interface): return the interface ip (first found)
4612
 */
4613
function find_interface_ip($interface, $flush = false) {
4614
	global $interface_ip_arr_cache;
4615
	global $interface_sn_arr_cache;
4616

    
4617
	$interface = str_replace("\n", "", $interface);
4618

    
4619
	if (!does_interface_exist($interface))
4620
		return;
4621

    
4622
	/* Setup IP cache */
4623
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4624
		$ifinfo = pfSense_get_interface_addresses($interface);
4625
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4626
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4627
	}
4628

    
4629
	return $interface_ip_arr_cache[$interface];
4630
}
4631

    
4632
/*
4633
 * find_interface_ipv6($interface): return the interface ip (first found)
4634
 */
4635
function find_interface_ipv6($interface, $flush = false) {
4636
	global $interface_ipv6_arr_cache;
4637
	global $interface_snv6_arr_cache;
4638
	global $config;
4639

    
4640
	$interface = trim($interface);
4641
	$interface = get_real_interface($interface);
4642

    
4643
	if (!does_interface_exist($interface))
4644
		return;
4645

    
4646
	/* Setup IP cache */
4647
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4648
		$ifinfo = pfSense_get_interface_addresses($interface);
4649
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4650
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4651
	}
4652

    
4653
	return $interface_ipv6_arr_cache[$interface];
4654
}
4655

    
4656
/*
4657
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4658
 */
4659
function find_interface_ipv6_ll($interface, $flush = false) {
4660
	global $interface_llv6_arr_cache;
4661
	global $config;
4662

    
4663
	$interface = str_replace("\n", "", $interface);
4664

    
4665
	if (!does_interface_exist($interface))
4666
		return;
4667

    
4668
	/* Setup IP cache */
4669
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4670
		$ifinfo = pfSense_getall_interface_addresses($interface);
4671
		foreach($ifinfo as $line) {
4672
			if (strstr($line, ":")) {
4673
				$parts = explode("/", $line);
4674
				if(is_linklocal($parts[0])) {
4675
					$ifinfo['linklocal'] = $parts[0];
4676
				}
4677
			}
4678
		}
4679
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4680
	}
4681
	return $interface_llv6_arr_cache[$interface];
4682
}
4683

    
4684
function find_interface_subnet($interface, $flush = false) {
4685
	global $interface_sn_arr_cache;
4686
	global $interface_ip_arr_cache;
4687

    
4688
	$interface = str_replace("\n", "", $interface);
4689
	if (does_interface_exist($interface) == false)
4690
		return;
4691

    
4692
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4693
		$ifinfo = pfSense_get_interface_addresses($interface);
4694
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4695
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4696
	}
4697

    
4698
	return $interface_sn_arr_cache[$interface];
4699
}
4700

    
4701
function find_interface_subnetv6($interface, $flush = false) {
4702
	global $interface_snv6_arr_cache;
4703
	global $interface_ipv6_arr_cache;
4704

    
4705
	$interface = str_replace("\n", "", $interface);
4706
	if (does_interface_exist($interface) == false)
4707
		return;
4708

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

    
4715
	return $interface_snv6_arr_cache[$interface];
4716
}
4717

    
4718
function ip_in_interface_alias_subnet($interface, $ipalias) {
4719
	global $config;
4720

    
4721
	if (empty($interface) || !is_ipaddr($ipalias))
4722
		return false;
4723
	if (is_array($config['virtualip']['vip'])) {
4724
		foreach ($config['virtualip']['vip'] as $vip) {
4725
			switch ($vip['mode']) {
4726
			case "ipalias":
4727
				if ($vip['interface'] <> $interface)
4728
					break;
4729
				$subnet = is_ipaddrv6($ipalias) ? gen_subnetv6($vip['subnet'], $vip['subnet_bits']) : gen_subnet($vip['subnet'], $vip['subnet_bits']);
4730
				if (ip_in_subnet($ipalias, $subnet . "/" . $vip['subnet_bits']))
4731
					return true;
4732
				break;
4733
			}
4734
		}
4735
	}
4736

    
4737
	return false;
4738
}
4739

    
4740
function get_interface_ip($interface = "wan") {
4741
	$realif = get_failover_interface($interface);
4742
	if (!$realif) {
4743
		if (strstr($interface, "_vip"))
4744
			return get_configured_carp_interface_list($interface);
4745
		else
4746
			return null;
4747
	}
4748

    
4749
	$curip = find_interface_ip($realif);
4750
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4751
		return $curip;
4752
	else
4753
		return null;
4754
}
4755

    
4756
function get_interface_ipv6($interface = "wan", $flush = false) {
4757
	global $config;
4758

    
4759
	$realif = get_failover_interface($interface, "inet6");
4760
	if (!$realif) {
4761
		if (strstr($interface, "_vip"))
4762
			return get_configured_carp_interface_list($interface, "inet6");
4763
		else
4764
			return null;
4765
	}
4766

    
4767
	/*
4768
	 * NOTE: On the case when only the prefix is requested,
4769
	 * the communication on WAN will be done over link-local.
4770
	 */
4771
	if (is_array($config['interfaces'][$interface])) {
4772
		switch ($config['interfaces'][$interface]['ipaddr']) {
4773
		case 'pppoe':
4774
		case 'l2tp':
4775
		case 'pptp':
4776
		case 'ppp':
4777
			if ($config['interfaces'][$interface]['ipaddrv6'] == 'dhcp6')
4778
				$realif = get_real_interface($interface, "inet6", true);
4779
			break;
4780
		}
4781
		if (isset($config['interfaces'][$interface]['dhcp6prefixonly'])) {
4782
			$curip = find_interface_ipv6_ll($realif, $flush);
4783
			if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4784
				return $curip;
4785
		}
4786
	}
4787

    
4788
	$curip = find_interface_ipv6($realif, $flush);
4789
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4790
		return $curip;
4791
	else
4792
		return null;
4793
}
4794

    
4795
function get_interface_linklocal($interface = "wan") {
4796

    
4797
	$realif = get_failover_interface($interface, "inet6");
4798
	if (!$realif) {
4799
		if (strstr($interface, "_vip")) {
4800
			list($interface, $vhid) = explode("_vip", $interface);
4801
			$realif = get_real_interface($interface);
4802
		} else
4803
			return null;
4804
	}
4805

    
4806
	$curip = find_interface_ipv6_ll($realif);
4807
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4808
		return $curip;
4809
	else
4810
		return null;
4811
}
4812

    
4813
function get_interface_subnet($interface = "wan") {
4814
	$realif = get_real_interface($interface);
4815
	if (!$realif) {
4816
		if (strstr($interface, "_vip")) {
4817
			list($interface, $vhid) = explode("_vip", $interface);
4818
			$realif = get_real_interface($interface);
4819
		} else
4820
			return null;
4821
	}
4822

    
4823
	$cursn = find_interface_subnet($realif);
4824
	if (!empty($cursn))
4825
		return $cursn;
4826

    
4827
	return null;
4828
}
4829

    
4830
function get_interface_subnetv6($interface = "wan") {
4831
	global $config;
4832

    
4833
	$realif = get_real_interface($interface, "inet6");
4834
	if (!$realif) {
4835
		if (strstr($interface, "_vip")) {
4836
			list($interface, $vhid) = explode("_vip", $interface);
4837
			$realif = get_real_interface($interface);
4838
		} else
4839
			return null;
4840
	}
4841

    
4842
	$cursn = find_interface_subnetv6($realif);
4843
	if (!empty($cursn))
4844
		return $cursn;
4845

    
4846
	return null;
4847
}
4848

    
4849
/* return outside interfaces with a gateway */
4850
function get_interfaces_with_gateway() {
4851
	global $config;
4852

    
4853
	$ints = array();
4854

    
4855
	/* loop interfaces, check config for outbound */
4856
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4857
		switch ($ifname['ipaddr']) {
4858
			case "dhcp":
4859
			case "ppp";
4860
			case "pppoe":
4861
			case "pptp":
4862
			case "l2tp":
4863
			case "ppp";
4864
				$ints[$ifdescr] = $ifdescr;
4865
			break;
4866
			default:
4867
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4868
				    !empty($ifname['gateway']))
4869
					$ints[$ifdescr] = $ifdescr;
4870
			break;
4871
		}
4872
	}
4873
	return $ints;
4874
}
4875

    
4876
/* return true if interface has a gateway */
4877
function interface_has_gateway($friendly) {
4878
	global $config;
4879

    
4880
	if (!empty($config['interfaces'][$friendly])) {
4881
		$ifname = &$config['interfaces'][$friendly];
4882
		switch ($ifname['ipaddr']) {
4883
			case "dhcp":
4884
			case "pppoe":
4885
			case "pptp":
4886
			case "l2tp":
4887
			case "ppp";
4888
				return true;
4889
			break;
4890
			default:
4891
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4892
					return true;
4893
				if (!empty($ifname['gateway']))
4894
					return true;
4895
			break;
4896
		}
4897
	}
4898

    
4899
	return false;
4900
}
4901

    
4902
/* return true if interface has a gateway */
4903
function interface_has_gatewayv6($friendly) {
4904
	global $config;
4905

    
4906
	if (!empty($config['interfaces'][$friendly])) {
4907
		$ifname = &$config['interfaces'][$friendly];
4908
		switch ($ifname['ipaddrv6']) {
4909
			case "slaac":
4910
			case "dhcp6":
4911
			case "6to4":
4912
			case "6rd":
4913
				return true;
4914
				break;
4915
			default:
4916
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4917
					return true;
4918
				if (!empty($ifname['gatewayv6']))
4919
					return true;
4920
				break;
4921
		}
4922
	}
4923

    
4924
	return false;
4925
}
4926

    
4927
/****f* interfaces/is_altq_capable
4928
 * NAME
4929
 *   is_altq_capable - Test if interface is capable of using ALTQ
4930
 * INPUTS
4931
 *   $int            - string containing interface name
4932
 * RESULT
4933
 *   boolean         - true or false
4934
 ******/
4935

    
4936
function is_altq_capable($int) {
4937
	/* Per:
4938
	 * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
4939
	 * Only the following drivers have ALTQ support
4940
	 */
4941
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
4942
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
4943
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
4944
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
4945
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
4946
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
4947
			"l2tp", "ppp", "vtnet");
4948

    
4949
	$int_family = remove_ifindex($int);
4950

    
4951
	if (in_array($int_family, $capable))
4952
		return true;
4953
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4954
		return true;
4955
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
4956
		return true;
4957
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4958
		return true;
4959
	else
4960
		return false;
4961
}
4962

    
4963
/****f* interfaces/is_interface_wireless
4964
 * NAME
4965
 *   is_interface_wireless - Returns if an interface is wireless
4966
 * RESULT
4967
 *   $tmp       - Returns if an interface is wireless
4968
 ******/
4969
function is_interface_wireless($interface) {
4970
	global $config, $g;
4971

    
4972
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4973
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4974
		if (preg_match($g['wireless_regex'], $interface)) {
4975
			if (isset($config['interfaces'][$friendly]))
4976
				$config['interfaces'][$friendly]['wireless'] = array();
4977
			return true;
4978
		}
4979
		return false;
4980
	} else
4981
		return true;
4982
}
4983

    
4984
function get_wireless_modes($interface) {
4985
	/* return wireless modes and channels */
4986
	$wireless_modes = array();
4987

    
4988
	$cloned_interface = get_real_interface($interface);
4989

    
4990
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4991
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4992
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4993
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4994

    
4995
		$interface_channels = "";
4996
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4997
		$interface_channel_count = count($interface_channels);
4998

    
4999
		$c = 0;
5000
		while ($c < $interface_channel_count) {
5001
			$channel_line = explode(",", $interface_channels["$c"]);
5002
			$wireless_mode = trim($channel_line[0]);
5003
			$wireless_channel = trim($channel_line[1]);
5004
			if(trim($wireless_mode) != "") {
5005
				/* if we only have 11g also set 11b channels */
5006
				if($wireless_mode == "11g") {
5007
					if(!isset($wireless_modes["11b"]))
5008
						$wireless_modes["11b"] = array();
5009
				} else if($wireless_mode == "11g ht") {
5010
					if(!isset($wireless_modes["11b"]))
5011
						$wireless_modes["11b"] = array();
5012
					if(!isset($wireless_modes["11g"]))
5013
						$wireless_modes["11g"] = array();
5014
					$wireless_mode = "11ng";
5015
				} else if($wireless_mode == "11a ht") {
5016
					if(!isset($wireless_modes["11a"]))
5017
						$wireless_modes["11a"] = array();
5018
					$wireless_mode = "11na";
5019
				}
5020
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
5021
			}
5022
			$c++;
5023
		}
5024
	}
5025
	return($wireless_modes);
5026
}
5027

    
5028
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5029
function get_wireless_channel_info($interface) {
5030
	$wireless_channels = array();
5031

    
5032
	$cloned_interface = get_real_interface($interface);
5033

    
5034
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5035
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5036
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5037
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5038

    
5039
		$interface_channels = "";
5040
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5041

    
5042
		foreach ($interface_channels as $channel_line) {
5043
			$channel_line = explode(",", $channel_line);
5044
			if(!isset($wireless_channels[$channel_line[0]]))
5045
				$wireless_channels[$channel_line[0]] = $channel_line;
5046
		}
5047
	}
5048
	return($wireless_channels);
5049
}
5050

    
5051
/****f* interfaces/get_interface_mtu
5052
 * NAME
5053
 *   get_interface_mtu - Return the mtu of an interface
5054
 * RESULT
5055
 *   $tmp       - Returns the mtu of an interface
5056
 ******/
5057
function get_interface_mtu($interface) {
5058
	$mtu = pfSense_get_interface_addresses($interface);
5059
	return $mtu['mtu'];
5060
}
5061

    
5062
function get_interface_mac($interface) {
5063

    
5064
	$macinfo = pfSense_get_interface_addresses($interface);
5065
	return $macinfo["macaddr"];
5066
}
5067

    
5068
/****f* pfsense-utils/generate_random_mac_address
5069
 * NAME
5070
 *   generate_random_mac - generates a random mac address
5071
 * INPUTS
5072
 *   none
5073
 * RESULT
5074
 *   $mac - a random mac address
5075
 ******/
5076
function generate_random_mac_address() {
5077
	$mac = "02";
5078
	for($x=0; $x<5; $x++)
5079
		$mac .= ":" . dechex(rand(16, 255));
5080
	return $mac;
5081
}
5082

    
5083
/****f* interfaces/is_jumbo_capable
5084
 * NAME
5085
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5086
 * INPUTS
5087
 *   $int             - string containing interface name
5088
 * RESULT
5089
 *   boolean          - true or false
5090
 ******/
5091
function is_jumbo_capable($iface) {
5092
	$iface = trim($iface);
5093
	$capable = pfSense_get_interface_addresses($iface);
5094

    
5095
	if (isset($capable['caps']['vlanmtu']))
5096
		return true;
5097

    
5098
	return false;
5099
}
5100

    
5101
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5102
	global $g;
5103

    
5104
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5105

    
5106
	if(!empty($iface) && !empty($pppif)){
5107
		$cron_cmd = <<<EOD
5108
#!/bin/sh
5109
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5110
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5111

    
5112
EOD;
5113

    
5114
		@file_put_contents($cron_file, $cron_cmd);
5115
		chmod($cron_file, 0755);
5116
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5117
	} else
5118
		unlink_if_exists($cron_file);
5119
}
5120

    
5121
function get_interface_default_mtu($type = "ethernet") {
5122
	switch ($type) {
5123
	case "gre":
5124
		return 1476;
5125
		break;
5126
	case "gif":
5127
		return 1280;
5128
		break;
5129
	case "tun":
5130
	case "vlan":
5131
	case "tap":
5132
	case "ethernet":
5133
	default:
5134
		return 1500;
5135
		break;
5136
	}
5137

    
5138
	/* Never reached */
5139
	return 1500;
5140
}
5141

    
5142
function get_vip_descr($ipaddress) {
5143
	global $config;
5144

    
5145
	foreach ($config['virtualip']['vip'] as $vip) {
5146
		if ($vip['subnet'] == $ipaddress) {
5147
			return ($vip['descr']);
5148
		}
5149
	}
5150
	return "";
5151
}
5152

    
5153
function interfaces_staticarp_configure($if) {
5154
	global $config, $g;
5155
	if(isset($config['system']['developerspew'])) {
5156
		$mt = microtime();
5157
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5158
	}
5159

    
5160
	$ifcfg = $config['interfaces'][$if];
5161

    
5162
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5163
		return 0;
5164

    
5165
	/* Enable staticarp, if enabled */
5166
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5167
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5168
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5169
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5170

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

    
5174
			}
5175

    
5176
		}
5177
	} else {
5178
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5179
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5180
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5181
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5182
				if (isset($arpent['arp_table_static_entry'])) {
5183
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5184
				}
5185
			}
5186
		}
5187
	}
5188

    
5189
	return 0;
5190
}
5191

    
5192
function get_failover_interface($interface, $family = "all") {
5193
	global $config;
5194

    
5195
	/* shortcut to get_real_interface if we find it in the config */
5196
	if (is_array($config['interfaces'][$interface])) {
5197
		return get_real_interface($interface, $family);
5198
	}
5199

    
5200
	/* compare against gateway groups */
5201
	$a_groups = return_gateway_groups_array();
5202
	if (is_array($a_groups[$interface])) {
5203
		/* we found a gateway group, fetch the interface or vip */
5204
		if ($a_groups[$interface][0]['vip'] <> "")
5205
			return $a_groups[$interface][0]['vip'];
5206
		else
5207
			return $a_groups[$interface][0]['int'];
5208
	}
5209
	/* fall through to get_real_interface */
5210
	/* XXX: Really needed? */
5211
	return get_real_interface($interface, $family);
5212
}
5213

    
5214
function remove_ifindex($ifname) {
5215
	return preg_replace("/[0-9]+$/", "", $ifname);
5216
}
5217

    
5218
?>
(25-25/67)