Projet

Général

Profil

Télécharger (160 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / interfaces.inc @ 1ff56562

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
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
870
		//mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gre['tunnel-remote-net']));
871
		mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen 128");
872
	} else {
873
		mwexec("/sbin/ifconfig {$greif} " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
874
	}
875
	if (isset($gre['link0']))
876
		pfSense_interface_flags($greif, IFF_LINK0);
877
	if (isset($gre['link1']))
878
		pfSense_interface_flags($greif, IFF_LINK1);
879
	if (isset($gre['link2']))
880
		pfSense_interface_flags($greif, IFF_LINK2);
881

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

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

    
894
	interfaces_bring_up($greif);
895

    
896
	return $greif;
897
}
898

    
899
function interfaces_gif_configure($checkparent = 0, $realif = "") {
900
	global $config;
901

    
902
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
903
		foreach ($config['gifs']['gif'] as $i => $gif) {
904
			if (empty($gif['gifif']))
905
				$gre['gifif'] = "gif{$i}";
906
			if (!empty($realif) && $realif != $gif['gifif'])
907
				continue;
908

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

    
927
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
928
function interface_gif_configure(&$gif, $gifkey = "") {
929
	global $config, $g;
930

    
931
	if (!is_array($gif))
932
		return -1;
933

    
934
	$realif = get_real_interface($gif['if']);
935
	$ipaddr = $gif['ipaddr'];
936

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

    
956
	if ($g['booting'] || !(empty($gif['gifif']))) {
957
		pfSense_interface_destroy($gif['gifif']);
958
		pfSense_interface_create($gif['gifif']);
959
		$gifif = $gif['gifif'];
960
	} else
961
		$gifif = pfSense_interface_create("gif");
962

    
963
	/* Do not change the order here for more see gif(4) NOTES section. */
964
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} " . escapeshellarg($gif['remote-addr']));
965
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
966
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
967
		//mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gif['tunnel-remote-net']));
968
		mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen 128");
969
	} else {
970
		mwexec("/sbin/ifconfig {$gifif} " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
971
	}
972
	if (isset($gif['link0']))
973
		pfSense_interface_flags($gifif, IFF_LINK0);
974
	if (isset($gif['link1']))
975
		pfSense_interface_flags($gifif, IFF_LINK1);
976
	if($gifif)
977
		interfaces_bring_up($gifif);
978
	else
979
		log_error(gettext("could not bring gifif up -- variable not defined"));
980

    
981
	$iflist = get_configured_interface_list();
982
	foreach($iflist as $ifname) {
983
		if($config['interfaces'][$ifname]['if'] == $gifif) {
984
			if(get_interface_gateway($ifname)) {
985
				system_routing_configure($ifname);
986
				break;
987
			}
988
			if(get_interface_gateway_v6($ifname)) {
989
				system_routing_configure($ifname);
990
				break;
991
			}
992
		}
993
	}
994

    
995

    
996
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
997
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
998
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
999
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
1000

    
1001
	if (is_ipaddrv4($realifgw)) {
1002
		mwexec("/sbin/route change -host " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
1003
	}
1004
	if (is_ipaddrv6($realifgw)) {
1005
		mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
1006
	}
1007

    
1008
	interfaces_bring_up($gifif);
1009

    
1010
	return $gifif;
1011
}
1012

    
1013
function interfaces_configure() {
1014
	global $config, $g;
1015

    
1016
	if ($g['platform'] == 'jail')
1017
		return;
1018

    
1019
	/* Set up our loopback interface */
1020
	interfaces_loopback_configure();
1021

    
1022
	/* create the unconfigured wireless clones */
1023
	interfaces_create_wireless_clones();
1024

    
1025
	/* set up LAGG virtual interfaces */
1026
	interfaces_lagg_configure();
1027

    
1028
	/* set up VLAN virtual interfaces */
1029
	interfaces_vlan_configure();
1030

    
1031
	interfaces_qinq_configure();
1032

    
1033
	$iflist = get_configured_interface_with_descr();
1034
	$delayed_list = array();
1035
	$bridge_list = array();
1036
	$track6_list = array();
1037

    
1038
	/* This is needed to speedup interfaces on bootup. */
1039
	$reload = false;
1040
	if (!$g['booting'])
1041
		$reload = true;
1042

    
1043
	foreach($iflist as $if => $ifname) {
1044
		$realif = $config['interfaces'][$if]['if'];
1045
		if (strstr($realif, "bridge"))
1046
			$bridge_list[$if] = $ifname;
1047
		else if (strstr($realif, "gre"))
1048
			$delayed_list[$if] = $ifname;
1049
		else if (strstr($realif, "gif"))
1050
			$delayed_list[$if] = $ifname;
1051
		else if (strstr($realif, "ovpn")) {
1052
			//echo "Delaying OpenVPN interface configuration...done.\n";
1053
			continue;
1054
		} else if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
1055
			$track6_list[$if] = $ifname;
1056
		} else {
1057
			if ($g['booting'])
1058
				printf(gettext("Configuring %s interface..."), $ifname);
1059

    
1060
			if($g['debug'])
1061
				log_error(sprintf(gettext("Configuring %s"), $ifname));
1062
			interface_configure($if, $reload);
1063
			if ($g['booting'])
1064
				echo gettext( "done.") . "\n";
1065
		}
1066
	}
1067

    
1068
	/*
1069
	 * NOTE: The following function parameter consists of
1070
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
1071
	 *	2 - Do load gre/gif/bridge with parent/member as vip
1072
	 */
1073

    
1074
	/* set up GRE virtual interfaces */
1075
	interfaces_gre_configure(1);
1076

    
1077
	/* set up GIF virtual interfaces */
1078
	interfaces_gif_configure(1);
1079

    
1080
	/* set up BRIDGe virtual interfaces */
1081
	interfaces_bridge_configure(1);
1082

    
1083
	foreach ($track6_list as $if => $ifname) {
1084
		if ($g['booting'])
1085
			printf(gettext("Configuring %s interface..."), $ifname);
1086
		if ($g['debug'])
1087
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1088

    
1089
		interface_configure($if, $reload);
1090

    
1091
		if ($g['booting'])
1092
			echo gettext("done.") . "\n";
1093
	}
1094

    
1095
	/* bring up vip interfaces */
1096
	interfaces_vips_configure();
1097

    
1098
	/* set up GRE virtual interfaces */
1099
	interfaces_gre_configure(2);
1100

    
1101
	/* set up GIF virtual interfaces */
1102
	interfaces_gif_configure(2);
1103

    
1104
	foreach ($delayed_list as $if => $ifname) {
1105
		if ($g['booting'])
1106
			printf(gettext("Configuring %s interface..."), $ifname);
1107
		if ($g['debug'])
1108
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1109

    
1110
		interface_configure($if, $reload);
1111

    
1112
		if ($g['booting'])
1113
			echo gettext("done.") . "\n";
1114
	}
1115

    
1116
	/* set up BRIDGe virtual interfaces */
1117
	interfaces_bridge_configure(2);
1118

    
1119
	foreach ($bridge_list as $if => $ifname) {
1120
		if ($g['booting'])
1121
			printf(gettext("Configuring %s interface..."), $ifname);
1122
		if($g['debug'])
1123
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1124

    
1125
		interface_configure($if, $reload);
1126

    
1127
		if ($g['booting'])
1128
			echo gettext("done.") . "\n";
1129
	}
1130

    
1131
	/* configure interface groups */
1132
	interfaces_group_setup();
1133

    
1134
	if (!$g['booting']) {
1135
		/* reconfigure static routes (kernel may have deleted them) */
1136
		system_routing_configure();
1137

    
1138
		/* reload IPsec tunnels */
1139
		vpn_ipsec_configure();
1140

    
1141
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1142
		services_dhcpd_configure();
1143

    
1144
		/* restart dnsmasq or unbound */
1145
		if (isset($config['dnsmasq']['enable']))
1146
			services_dnsmasq_configure();
1147
		elseif (isset($config['unbound']['enable']))
1148
			services_unbound_configure();
1149
	}
1150

    
1151
	return 0;
1152
}
1153

    
1154
function interface_reconfigure($interface = "wan", $reloadall = false) {
1155
	interface_bring_down($interface);
1156
	interface_configure($interface, $reloadall);
1157
}
1158

    
1159
function interface_vip_bring_down($vip) {
1160
	global $g;
1161

    
1162
	$vipif = get_real_interface($vip['interface']);
1163
	switch ($vip['mode']) {
1164
	case "proxyarp":
1165
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1166
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1167
		break;
1168
	case "ipalias":
1169
		if (does_interface_exist($vipif)) {
1170
			if (is_ipaddrv6($vip['subnet']))
1171
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " -alias");
1172
			else
1173
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1174
		}
1175
		break;
1176
	case "carp":
1177
		/* XXX: Is enough to delete ip address? */
1178
		if (does_interface_exist($vipif))
1179
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1180
		break;
1181
	}
1182
}
1183

    
1184
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1185
	global $config, $g;
1186

    
1187
	if (!isset($config['interfaces'][$interface]))
1188
		return;
1189

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

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

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

    
1267
	$track6 = array();
1268
	switch ($ifcfg['ipaddrv6']) {
1269
	case "slaac":
1270
	case "dhcp6":
1271
		$pidv6 = find_dhcp6c_process($realif);
1272
		if($pidv6)
1273
			posix_kill($pidv6, SIGTERM);
1274
		sleep(3);
1275
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1276
		if (does_interface_exist($realifv6)) {
1277
			$ip6 = find_interface_ipv6($realifv6);
1278
			if (is_ipaddrv6($ip6) && $ip6 != "::")
1279
				mwexec("/sbin/ifconfig " . escapeshellarg($realifv6) . " inet6 {$ip6} delete", true);
1280
			if ($destroy == true)
1281
				pfSense_interface_flags($realif, -IFF_UP);
1282
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1283
		}
1284
		$track6 = link_interface_to_track6($interface);
1285
		break;
1286
	case "6rd":
1287
	case "6to4":
1288
		$realif = "{$interface}_stf";
1289
		if(does_interface_exist("$realif")) {
1290
			$ip6 = get_interface_ipv6($interface);
1291
			if (is_ipaddrv6($ip6))
1292
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1293
			if ($destroy == true)
1294
				pfSense_interface_flags($realif, -IFF_UP);
1295
		}
1296
		$track6 = link_interface_to_track6($interface);
1297
		break;
1298
	default:
1299
		if(does_interface_exist("$realif")) {
1300
			$ip6 = get_interface_ipv6($interface);
1301
			if (is_ipaddrv6($ip6))
1302
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1303
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1304
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1305
			if ($destroy == true)
1306
				pfSense_interface_flags($realif, -IFF_UP);
1307
			mwexec("/usr/sbin/arp -d -i " . escapeshellarg($realif) . " -a");
1308
		}
1309
		$track6 = link_interface_to_track6($interface);
1310
		break;
1311
	}
1312

    
1313
	if (!empty($track6) && is_array($track6)) {
1314
		if (!function_exists('services_dhcp_configure'))
1315
			require_once('services.inc');
1316
		/* Bring down radvd and dhcp6 on these interfaces */
1317
		services_dhcpd_configure('inet6', $track6);
1318
	}
1319

    
1320
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1321
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1322
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1323
	if (!empty($old_router)) {
1324
		log_error("Clearing states to old gateway {$old_router}.");
1325
		mwexec("/sbin/pfctl -i " . escapeshellarg($realif) . " -Fs -G {$old_router}");
1326
	}
1327

    
1328
	/* remove interface up file if it exists */
1329
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1330
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1331
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1332
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1333
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1334
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1335
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1336

    
1337
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1338
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1339
	if (is_array($ifcfg['wireless'])) {
1340
		kill_hostapd($realif);
1341
		mwexec(kill_wpasupplicant($realif));
1342
	}
1343

    
1344
	if ($destroy == true) {
1345
		if (preg_match("/^[a-z0-9]+^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1346
			pfSense_interface_destroy($realif);
1347
	}
1348

    
1349
	return;
1350
}
1351

    
1352
function interfaces_carp_set_maintenancemode($carp_maintenancemode){
1353
	global $config;
1354
	if (isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == false) {
1355
		unset($config["virtualip_carp_maintenancemode"]);
1356
		write_config("Leave CARP maintenance mode");
1357
	} else
1358
	if (!isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == true) {
1359
		$config["virtualip_carp_maintenancemode"] = true;
1360
		write_config("Enter CARP maintenance mode");
1361
	}
1362

    
1363
	$viparr = &$config['virtualip']['vip'];
1364
	foreach ($viparr as $vip) {
1365
		if ($vip['mode'] == "carp") {
1366
			interface_carp_configure($vip);
1367
		}
1368
	}
1369
}
1370

    
1371
function interfaces_ptpid_used($ptpid) {
1372
	global $config;
1373

    
1374
	if (is_array($config['ppps']['ppp']))
1375
		foreach ($config['ppps']['ppp'] as & $settings)
1376
			if ($ptpid == $settings['ptpid'])
1377
				return true;
1378

    
1379
	return false;
1380
}
1381

    
1382
function interfaces_ptpid_next() {
1383

    
1384
	$ptpid = 0;
1385
	while(interfaces_ptpid_used($ptpid))
1386
		$ptpid++;
1387

    
1388
	return $ptpid;
1389
}
1390

    
1391
function getMPDCRONSettings($pppif) {
1392
	global $config;
1393

    
1394
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1395
	if (is_array($config['cron']['item'])) {
1396
		foreach ($config['cron']['item'] as $i => $item) {
1397
			if (stripos($item['command'], $cron_cmd_file) !== false)
1398
				return array("ID" => $i, "ITEM" => $item);
1399
		}
1400
	}
1401

    
1402
	return NULL;
1403
}
1404

    
1405
function handle_pppoe_reset($post_array) {
1406
	global $config, $g;
1407

    
1408
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1409
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1410

    
1411
	if (!is_array($config['cron']['item']))
1412
		$config['cron']['item'] = array();
1413

    
1414
	$itemhash = getMPDCRONSettings($pppif);
1415

    
1416
	// reset cron items if necessary and return
1417
	if (empty($post_array['pppoe-reset-type'])) {
1418
		if (isset($itemhash))
1419
			unset($config['cron']['item'][$itemhash['ID']]);
1420
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1421
		return;
1422
	}
1423

    
1424
	if (empty($itemhash))
1425
		$itemhash = array();
1426
	$item = array();
1427
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1428
		$item['minute'] = $post_array['pppoe_resetminute'];
1429
		$item['hour'] = $post_array['pppoe_resethour'];
1430
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1431
			$date = explode("/", $post_array['pppoe_resetdate']);
1432
			$item['mday'] = $date[1];
1433
			$item['month'] = $date[0];
1434
		} else {
1435
			$item['mday'] = "*";
1436
			$item['month'] = "*";
1437
		}
1438
		$item['wday'] = "*";
1439
		$item['who'] = "root";
1440
		$item['command'] = $cron_cmd_file;
1441
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1442
		switch ($post_array['pppoe_pr_preset_val']) {
1443
		case "monthly":
1444
			$item['minute'] = "0";
1445
			$item['hour'] = "0";
1446
			$item['mday'] = "1";
1447
			$item['month'] = "*";
1448
			$item['wday'] = "*";
1449
			break;
1450
		case "weekly":
1451
			$item['minute'] = "0";
1452
			$item['hour'] = "0";
1453
			$item['mday'] = "*";
1454
			$item['month'] = "*";
1455
			$item['wday'] = "0";
1456
			break;
1457
		case "daily":
1458
			$item['minute'] = "0";
1459
			$item['hour'] = "0";
1460
			$item['mday'] = "*";
1461
			$item['month'] = "*";
1462
			$item['wday'] = "*";
1463
			break;
1464
		case "hourly":
1465
			$item['minute'] = "0";
1466
			$item['hour'] = "*";
1467
			$item['mday'] = "*";
1468
			$item['month'] = "*";
1469
			$item['wday'] = "*";
1470
			break;
1471
		} // end switch
1472
		$item['who'] = "root";
1473
		$item['command'] = $cron_cmd_file;
1474
	}
1475
	if (empty($item))
1476
		return;
1477
	if (isset($itemhash['ID']))
1478
		$config['cron']['item'][$itemhash['ID']] = $item;
1479
	else
1480
		$config['cron']['item'][] = $item;
1481
}
1482

    
1483
/*
1484
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1485
 * It writes the mpd config file to /var/etc every time the link is opened.
1486
 */
1487
function interface_ppps_configure($interface) {
1488
	global $config, $g;
1489

    
1490
	/* Return for unassigned interfaces. This is a minimum requirement. */
1491
	if (empty($config['interfaces'][$interface]))
1492
		return 0;
1493
	$ifcfg = $config['interfaces'][$interface];
1494
	if (!isset($ifcfg['enable']))
1495
		return 0;
1496

    
1497
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1498
	if(!is_dir("/var/spool/lock")) {
1499
		mkdir("/var/spool/lock", 0777, true);
1500
	}
1501
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1502
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1503
		@symlink("/usr/local/sbin/mpd.script", "{$g['varetc_path']}/mpd.script");
1504

    
1505
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1506
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1507
			if ($ifcfg['if'] == $ppp['if'])
1508
				break;
1509
		}
1510
	}
1511
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1512
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1513
		return 0;
1514
	}
1515
	$pppif = $ifcfg['if'];
1516
	if ($ppp['type'] == "ppp")
1517
		$type = "modem";
1518
	else
1519
		$type = $ppp['type'];
1520
	$upper_type = strtoupper($ppp['type']);
1521

    
1522
	if($g['booting']) {
1523
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1524
		echo "starting {$pppif} link...";
1525
		// Do not re-configure the interface if we are booting and it's already been started
1526
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1527
			return 0;
1528
	}
1529

    
1530
	$ports = explode(',',$ppp['ports']);
1531
	if ($type != "modem") {
1532
		foreach ($ports as $pid => $port) {
1533
			$ports[$pid] = get_real_interface($port);
1534
			if (empty($ports[$pid]))
1535
				return 0;
1536
		}
1537
	}
1538
	$localips = explode(',',$ppp['localip']);
1539
	$gateways = explode(',',$ppp['gateway']);
1540
	$subnets = explode(',',$ppp['subnet']);
1541

    
1542
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1543
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1544
	 */
1545
	foreach($ports as $pid => $port){
1546
		switch ($ppp['type']) {
1547
			case "pppoe":
1548
				/* Bring the parent interface up */
1549
				interfaces_bring_up($port);
1550
				pfSense_ngctl_attach(".", $port);
1551
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1552
				mwexec("ngctl msg {$port}: setautosrc 1");
1553
				break;
1554
			case "pptp":
1555
			case "l2tp":
1556
				/* configure interface */
1557
				if(is_ipaddr($localips[$pid])){
1558
					// Manually configure interface IP/subnet
1559
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1560
					interfaces_bring_up($port);
1561
				} else if (empty($localips[$pid]))
1562
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1563

    
1564
				if(!is_ipaddr($localips[$pid])){
1565
					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!");
1566
					$localips[$pid] = "0.0.0.0";
1567
				}
1568
				if(!is_ipaddr($gateways[$pid])){
1569
					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));
1570
					return 0;
1571
				}
1572
				pfSense_ngctl_attach(".", $port);
1573
				break;
1574
			case "ppp":
1575
				if (!file_exists("{$port}")) {
1576
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1577
					return 0;
1578
				}
1579
				break;
1580
			default:
1581
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1582
				break;
1583
		}
1584
	}
1585

    
1586
	if (is_array($ports) && count($ports) > 1)
1587
		$multilink = "enable";
1588
	else
1589
		$multilink = "disable";
1590

    
1591
	if ($type == "modem"){
1592
		if (is_ipaddr($ppp['localip']))
1593
			$localip = $ppp['localip'];
1594
		else
1595
			$localip = '0.0.0.0';
1596

    
1597
		if (is_ipaddr($ppp['gateway']))
1598
			$gateway = $ppp['gateway'];
1599
		else
1600
			$gateway = "10.64.64.{$pppid}";
1601
		$ranges = "{$localip}/0 {$gateway}/0";
1602

    
1603
		if (empty($ppp['apnum']))
1604
			$ppp['apnum'] = 1;
1605
	} else
1606
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1607

    
1608
	if (isset($ppp['ondemand']))
1609
		$ondemand = "enable";
1610
	else
1611
		$ondemand = "disable";
1612
	if (!isset($ppp['idletimeout']))
1613
		$ppp['idletimeout'] = 0;
1614

    
1615
	if (empty($ppp['username']) && $type == "modem"){
1616
		$ppp['username'] = "user";
1617
		$ppp['password'] = "none";
1618
	}
1619
	if (empty($ppp['password']) && $type == "modem")
1620
		$passwd = "none";
1621
	else
1622
		$passwd = base64_decode($ppp['password']);
1623

    
1624
	$bandwidths = explode(',',$ppp['bandwidth']);
1625
	$defaultmtu = "1492";
1626
	if (!empty($ifcfg['mtu']))
1627
		$defaultmtu = intval($ifcfg['mtu']);
1628
	$mtus = explode(',',$ppp['mtu']);
1629
	$mrus = explode(',',$ppp['mru']);
1630

    
1631
	if (isset($ppp['mrru']))
1632
		$mrrus = explode(',',$ppp['mrru']);
1633

    
1634
	// Construct the mpd.conf file
1635
	$mpdconf = <<<EOD
1636
startup:
1637
	# configure the console
1638
	set console close
1639
	# configure the web server
1640
	set web close
1641

    
1642
default:
1643
{$ppp['type']}client:
1644
	create bundle static {$interface}
1645
	set bundle enable ipv6cp
1646
	set iface name {$pppif}
1647

    
1648
EOD;
1649
	$setdefaultgw = false;
1650
	$founddefaultgw = false;
1651
	if (is_array($config['gateways']['gateway_item'])) {
1652
		foreach($config['gateways']['gateway_item'] as $gateway) {
1653
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1654
				$setdefaultgw = true;
1655
				break;
1656
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1657
				$founddefaultgw = true;
1658
				break;
1659
			}
1660
		}
1661
	}
1662

    
1663
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1664
		$setdefaultgw = true;
1665
		$mpdconf .= <<<EOD
1666
	set iface route default
1667

    
1668
EOD;
1669
	}
1670
	$mpdconf .= <<<EOD
1671
	set iface {$ondemand} on-demand
1672
	set iface idle {$ppp['idletimeout']}
1673

    
1674
EOD;
1675

    
1676
	if (isset($ppp['ondemand']))
1677
		$mpdconf .= <<<EOD
1678
	set iface addrs 10.10.1.1 10.10.1.2
1679

    
1680
EOD;
1681

    
1682
	if (isset($ppp['tcpmssfix']))
1683
		$tcpmss = "disable";
1684
	else
1685
		$tcpmss = "enable";
1686
		$mpdconf .= <<<EOD
1687
	set iface {$tcpmss} tcpmssfix
1688

    
1689
EOD;
1690

    
1691
	$mpdconf .= <<<EOD
1692
	set iface up-script /usr/local/sbin/ppp-linkup
1693
	set iface down-script /usr/local/sbin/ppp-linkdown
1694
	set ipcp ranges {$ranges}
1695

    
1696
EOD;
1697
	if (isset($ppp['vjcomp']))
1698
		$mpdconf .= <<<EOD
1699
	set ipcp no vjcomp
1700

    
1701
EOD;
1702

    
1703
	if (isset($config['system']['dnsallowoverride']))
1704
		$mpdconf .= <<<EOD
1705
	set ipcp enable req-pri-dns
1706
	set ipcp enable req-sec-dns
1707

    
1708
EOD;
1709
	if (!isset($ppp['verbose_log']))
1710
		$mpdconf .= <<<EOD
1711
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1712

    
1713
EOD;
1714
	foreach($ports as $pid => $port){
1715
		$port = get_real_interface($port);
1716
		$mpdconf .= <<<EOD
1717

    
1718
	create link static {$interface}_link{$pid} {$type}
1719
	set link action bundle {$interface}
1720
	set link {$multilink} multilink
1721
	set link keep-alive 10 60
1722
	set link max-redial 0
1723

    
1724
EOD;
1725
		if (isset($ppp['shortseq']))
1726
			$mpdconf .= <<<EOD
1727
	set link no shortseq
1728

    
1729
EOD;
1730

    
1731
		if (isset($ppp['acfcomp']))
1732
			$mpdconf .= <<<EOD
1733
	set link no acfcomp
1734

    
1735
EOD;
1736

    
1737
		if (isset($ppp['protocomp']))
1738
			$mpdconf .= <<<EOD
1739
	set link no protocomp
1740

    
1741
EOD;
1742

    
1743
		$mpdconf .= <<<EOD
1744
	set link disable chap pap
1745
	set link accept chap pap eap
1746
	set link disable incoming
1747

    
1748
EOD;
1749

    
1750

    
1751
		if (!empty($bandwidths[$pid]))
1752
			$mpdconf .= <<<EOD
1753
	set link bandwidth {$bandwidths[$pid]}
1754

    
1755
EOD;
1756

    
1757
		if (empty($mtus[$pid]))
1758
			$mtus[$pid] = $defaultmtu;
1759
			$mpdconf .= <<<EOD
1760
	set link mtu {$mtus[$pid]}
1761

    
1762
EOD;
1763

    
1764
		if (!empty($mrus[$pid]))
1765
			$mpdconf .= <<<EOD
1766
	set link mru {$mrus[$pid]}
1767

    
1768
EOD;
1769

    
1770
		if (!empty($mrrus[$pid]))
1771
			$mpdconf .= <<<EOD
1772
	set link mrru {$mrrus[$pid]}
1773

    
1774
EOD;
1775

    
1776
		$mpdconf .= <<<EOD
1777
	set auth authname "{$ppp['username']}"
1778
	set auth password {$passwd}
1779

    
1780
EOD;
1781
		if ($type == "modem") {
1782
			$mpdconf .= <<<EOD
1783
	set modem device {$ppp['ports']}
1784
	set modem script DialPeer
1785
	set modem idle-script Ringback
1786
	set modem watch -cd
1787
	set modem var \$DialPrefix "DT"
1788
	set modem var \$Telephone "{$ppp['phone']}"
1789

    
1790
EOD;
1791
		}
1792
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1793
			$mpdconf .= <<<EOD
1794
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1795

    
1796
EOD;
1797
		}
1798
		if (isset($ppp['initstr']) && $type == "modem") {
1799
			$initstr = base64_decode($ppp['initstr']);
1800
			$mpdconf .= <<<EOD
1801
	set modem var \$InitString "{$initstr}"
1802

    
1803
EOD;
1804
		}
1805
		if (isset($ppp['simpin']) && $type == "modem") {
1806
			if($ppp['pin-wait'] == "")
1807
				$ppp['pin-wait'] = 0;
1808
			$mpdconf .= <<<EOD
1809
	set modem var \$SimPin "{$ppp['simpin']}"
1810
	set modem var \$PinWait "{$ppp['pin-wait']}"
1811

    
1812
EOD;
1813
		}
1814
		if (isset($ppp['apn']) && $type == "modem") {
1815
			$mpdconf .= <<<EOD
1816
	set modem var \$APN "{$ppp['apn']}"
1817
	set modem var \$APNum "{$ppp['apnum']}"
1818

    
1819
EOD;
1820
		}
1821
		if ($type == "pppoe") {
1822
			// Send a null service name if none is set.
1823
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1824
			$mpdconf .= <<<EOD
1825
	set pppoe service "{$provider}"
1826

    
1827
EOD;
1828
		}
1829
		if ($type == "pppoe")
1830
			$mpdconf .= <<<EOD
1831
	set pppoe iface {$port}
1832

    
1833
EOD;
1834

    
1835
		if ($type == "pptp" || $type == "l2tp") {
1836
			$mpdconf .= <<<EOD
1837
	set {$type} self {$localips[$pid]}
1838
	set {$type} peer {$gateways[$pid]}
1839

    
1840
EOD;
1841
		}
1842

    
1843
		$mpdconf .= "\topen\n";
1844
	} //end foreach($port)
1845

    
1846

    
1847
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1848
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1849
		@symlink("{$g['conf_path']}/mpd_{$interface}.conf", "{$g['varetc_path']}/mpd_{$interface}.conf");
1850
	else {
1851
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1852
		if (!$fd) {
1853
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1854
			return 0;
1855
		}
1856
		// Write out mpd_ppp.conf
1857
		fwrite($fd, $mpdconf);
1858
		fclose($fd);
1859
		unset($mpdconf);
1860
	}
1861

    
1862
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1863
	if (isset($ppp['uptime'])) {
1864
		if (!file_exists("/conf/{$pppif}.log")) {
1865
			conf_mount_rw();
1866
			file_put_contents("/conf/{$pppif}.log", '');
1867
			conf_mount_ro();
1868
		}
1869
	} else {
1870
		if (file_exists("/conf/{$pppif}.log")) {
1871
			conf_mount_rw();
1872
			@unlink("/conf/{$pppif}.log");
1873
			conf_mount_ro();
1874
		}
1875
	}
1876

    
1877
	/* clean up old lock files */
1878
	foreach($ports as $port) {
1879
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1880
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1881
	}
1882

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

    
1887
	// Check for PPPoE periodic reset request
1888
	if ($type == "pppoe") {
1889
		if (!empty($ppp['pppoe-reset-type']))
1890
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1891
		else
1892
			interface_setup_pppoe_reset_file($ppp['if']);
1893
	}
1894
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1895
	$i = 0;
1896
	while($i < 10) {
1897
		exec("/sbin/ifconfig " . escapeshellarg($ppp['if']) . " 2>&1", $out, $ret);
1898
		if($ret == 0)
1899
			break;
1900
		sleep(1);
1901
		$i++;
1902
	}
1903

    
1904
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1905
	/* We should be able to launch the right version for each modem */
1906
	/* We can also guess the mondev from the manufacturer */
1907
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1908
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1909
	foreach($ports as $port) {
1910
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1911
			$mondev  = substr(basename($port), 0, -1);
1912
			$devlist = glob("/dev/{$mondev}?");
1913
			$mondev = basename(end($devlist));
1914
		}
1915
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1916
			$mondev  = substr(basename($port), 0, -1) . "1";
1917
		}
1918
		log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1919
		mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1920
	}
1921

    
1922
	return 1;
1923
}
1924

    
1925
function interfaces_carp_setup() {
1926
	global $g, $config;
1927

    
1928
	if (isset($config['system']['developerspew'])) {
1929
		$mt = microtime();
1930
		echo "interfaces_carp_setup() being called $mt\n";
1931
	}
1932

    
1933
	if ($g['booting']) {
1934
		echo gettext("Configuring CARP settings...");
1935
		mute_kernel_msgs();
1936
	}
1937

    
1938
	/* suck in configuration items */
1939
	if ($config['hasync']) {
1940
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1941
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1942
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1943
	} else {
1944
		unset($pfsyncinterface);
1945
		unset($pfsyncenabled);
1946
	}
1947

    
1948
	mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1949
	mwexec("/sbin/sysctl net.inet.carp.log=1", true);
1950

    
1951
	if (!empty($pfsyncinterface))
1952
		$carp_sync_int = get_real_interface($pfsyncinterface);
1953
	else
1954
		unset($carp_sync_int);
1955

    
1956
	/* setup pfsync interface */
1957
	if ($carp_sync_int and $pfsyncenabled) {
1958
		if (is_ipaddr($pfsyncpeerip))
1959
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1960
		else
1961
			$syncpeer = "-syncpeer";
1962

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

    
1965
		sleep(1);
1966

    
1967
		/* 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
1968
		 * for existing sessions.
1969
		 */
1970
		log_error("waiting for pfsync...");
1971
		$i = 0;
1972
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1973
			$i++;
1974
			sleep(1);
1975
		}
1976
		log_error("pfsync done in $i seconds.");
1977
		log_error("Configuring CARP settings finalize...");
1978
	} else {
1979
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1980
	}
1981

    
1982
	if($config['virtualip']['vip'])
1983
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1984
	else
1985
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1986

    
1987
	if ($g['booting']) {
1988
		unmute_kernel_msgs();
1989
		echo gettext("done.") . "\n";
1990
	}
1991
}
1992

    
1993
function interface_proxyarp_configure($interface = "") {
1994
	global $config, $g;
1995
	if(isset($config['system']['developerspew'])) {
1996
		$mt = microtime();
1997
		echo "interface_proxyarp_configure() being called $mt\n";
1998
	}
1999

    
2000
	/* kill any running choparp */
2001
	if (empty($interface))
2002
		killbyname("choparp");
2003
	else {
2004
		$vipif = get_real_interface($interface);
2005
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
2006
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
2007
	}
2008

    
2009
	$paa = array();
2010
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
2011

    
2012
		/* group by interface */
2013
		foreach ($config['virtualip']['vip'] as $vipent) {
2014
			if ($vipent['mode'] === "proxyarp") {
2015
				if ($vipent['interface'])
2016
					$proxyif = $vipent['interface'];
2017
				else
2018
					$proxyif = "wan";
2019

    
2020
				if (!empty($interface) && $interface != $proxyif)
2021
					continue;
2022

    
2023
				if (!is_array($paa[$proxyif]))
2024
					$paa[$proxyif] = array();
2025

    
2026
				$paa[$proxyif][] = $vipent;
2027
			}
2028
		}
2029
	}
2030

    
2031
	if (!empty($interface)) {
2032
		if (is_array($paa[$interface])) {
2033
			$paaifip = get_interface_ip($interface);
2034
			if (!is_ipaddr($paaifip))
2035
				return;
2036
			$args = get_real_interface($interface) . " auto";
2037
			foreach ($paa[$interface] as $paent) {
2038
				if (isset($paent['subnet']))
2039
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
2040
				else if (isset($paent['range']))
2041
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
2042
			}
2043
			mwexec_bg("/usr/local/sbin/choparp " . $args);
2044
		}
2045
	} else if (count($paa) > 0) {
2046
		foreach ($paa as $paif => $paents)  {
2047
			$paaifip = get_interface_ip($paif);
2048
			if (!is_ipaddr($paaifip))
2049
				continue;
2050
			$args = get_real_interface($paif) . " auto";
2051
			foreach ($paents as $paent) {
2052
				if (isset($paent['subnet']))
2053
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
2054
				else if (isset($paent['range']))
2055
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
2056
			}
2057
			mwexec_bg("/usr/local/sbin/choparp " . $args);
2058
		}
2059
	}
2060
}
2061

    
2062
function interface_ipalias_cleanup($interface, $inet = "inet4") {
2063
	global $g, $config;
2064

    
2065
	if (is_array($config['virtualip']['vip'])) {
2066
		foreach ($config['virtualip']['vip'] as $vip) {
2067
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
2068
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
2069
					interface_vip_bring_down($vip);
2070
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
2071
					interface_vip_bring_down($vip);
2072
			}
2073
		}
2074
	}
2075
}
2076

    
2077
function interfaces_vips_configure($interface = "") {
2078
	global $g, $config;
2079
	if(isset($config['system']['developerspew'])) {
2080
		$mt = microtime();
2081
		echo "interfaces_vips_configure() being called $mt\n";
2082
	}
2083
	$paa = array();
2084
	if(is_array($config['virtualip']['vip'])) {
2085
		$carp_setuped = false;
2086
		$anyproxyarp = false;
2087
		foreach ($config['virtualip']['vip'] as $vip) {
2088
			switch ($vip['mode']) {
2089
			case "proxyarp":
2090
				/* nothing it is handled on interface_proxyarp_configure() */
2091
				if ($interface <> "" && $vip['interface'] <> $interface)
2092
					continue;
2093
				$anyproxyarp = true;
2094
				break;
2095
			case "ipalias":
2096
				if ($interface <> "" && $vip['interface'] <> $interface)
2097
					continue;
2098
				interface_ipalias_configure($vip);
2099
				break;
2100
			case "carp":
2101
				if ($interface <> "" && $vip['interface'] <> $interface)
2102
					continue;
2103
				if ($carp_setuped == false)
2104
					$carp_setuped = true;
2105
				interface_carp_configure($vip);
2106
				break;
2107
			}
2108
		}
2109
		if ($carp_setuped == true)
2110
			interfaces_carp_setup();
2111
		if ($anyproxyarp == true)
2112
			interface_proxyarp_configure();
2113
	}
2114
}
2115

    
2116
function interface_ipalias_configure(&$vip) {
2117
	if ($vip['mode'] == "ipalias") {
2118
		$if = get_real_interface($vip['interface']);
2119
		$af = "inet";
2120
		if(is_ipaddrv6($vip['subnet']))
2121
			$af = "inet6";
2122
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
2123
	}
2124
}
2125

    
2126
function interface_reload_carps($cif) {
2127
	global $config;
2128

    
2129
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2130
	if (empty($carpifs))
2131
		return;
2132

    
2133
	$carps = explode(" ", $carpifs);
2134
	if(is_array($config['virtualip']['vip'])) {
2135
		$viparr = &$config['virtualip']['vip'];
2136
		foreach ($viparr as $vip) {
2137
			if (in_array($vip['carpif'], $carps)) {
2138
				switch ($vip['mode']) {
2139
				case "carp":
2140
					interface_vip_bring_down($vip);
2141
					sleep(1);
2142
					interface_carp_configure($vip);
2143
					break;
2144
				case "ipalias":
2145
					interface_vip_bring_down($vip);
2146
					sleep(1);
2147
					interface_ipalias_configure($vip);
2148
					break;
2149
				}
2150
			}
2151
		}
2152
	}
2153
}
2154

    
2155
function interface_carp_configure(&$vip) {
2156
	global $config, $g;
2157
	if(isset($config['system']['developerspew'])) {
2158
		$mt = microtime();
2159
		echo "interface_carp_configure() being called $mt\n";
2160
	}
2161

    
2162
	if ($vip['mode'] != "carp")
2163
		return;
2164

    
2165
	/* NOTE: Maybe its useless nowdays */
2166
	$realif = get_real_interface($vip['interface']);
2167
	if (!does_interface_exist($realif)) {
2168
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2169
		return;
2170
	}
2171

    
2172
	if (is_ipaddrv4($vip['subnet'])) {
2173
		/* Ensure CARP IP really exists prior to loading up. */
2174
		$ww_subnet_ip = find_interface_ip($realif);
2175
		$ww_subnet_bits = find_interface_subnet($realif);
2176
		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'])) {
2177
			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", "");
2178
			return;
2179
		}
2180
	} else if (is_ipaddrv6($vip['subnet'])) {
2181
		/* Ensure CARP IP really exists prior to loading up. */
2182
		$ww_subnet_ip = find_interface_ipv6($realif);
2183
		$ww_subnet_bits = find_interface_subnetv6($realif);
2184
		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'])) {
2185
			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", "");
2186
			return;
2187
		}
2188
	}
2189

    
2190
	$vip_password = $vip['password'];
2191
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2192
	if ($vip['password'] != "")
2193
		$password = " pass {$vip_password}";
2194

    
2195
	$advbase = "";
2196
	if (!empty($vip['advbase']))
2197
		$advbase = "advbase " . escapeshellarg($vip['advbase']);
2198

    
2199
	$carp_maintenancemode = isset($config["virtualip_carp_maintenancemode"]);
2200
	if ($carp_maintenancemode)
2201
		$advskew = "advskew 254";
2202
	else
2203
		$advskew = "advskew " . escapeshellarg($vip['advskew']);
2204
	
2205
	mwexec("/sbin/ifconfig {$realif} vhid " . escapeshellarg($vip['vhid']) . " {$advskew} {$advbase} {$password}");
2206

    
2207
	if (is_ipaddrv4($vip['subnet']))
2208
		mwexec("/sbin/ifconfig {$realif} " . escapeshellarg($vip['subnet']) . "/" . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2209
	else if (is_ipaddrv6($vip['subnet']))
2210
		mwexec("/sbin/ifconfig {$realif} inet6 " . escapeshellarg($vip['subnet']) . " prefixlen " . escapeshellarg($vip['subnet_bits']) . " vhid " . escapeshellarg($vip['vhid']));
2211

    
2212
	return $realif;
2213
}
2214

    
2215
function interface_wireless_clone($realif, $wlcfg) {
2216
	global $config, $g;
2217
	/*   Check to see if interface has been cloned as of yet.
2218
	 *   If it has not been cloned then go ahead and clone it.
2219
	 */
2220
	$needs_clone = false;
2221
	if(is_array($wlcfg['wireless']))
2222
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2223
	else
2224
		$wlcfg_mode = $wlcfg['mode'];
2225
	switch($wlcfg_mode) {
2226
	case "hostap":
2227
		$mode = "wlanmode hostap";
2228
		break;
2229
	case "adhoc":
2230
		$mode = "wlanmode adhoc";
2231
		break;
2232
	default:
2233
		$mode = "";
2234
		break;
2235
	}
2236
	$baseif = interface_get_wireless_base($wlcfg['if']);
2237
	if(does_interface_exist($realif)) {
2238
		exec("/sbin/ifconfig " . escapeshellarg($realif), $output, $ret);
2239
		$ifconfig_str = implode($output);
2240
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2241
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2242
			$needs_clone = true;
2243
		}
2244
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2245
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2246
			$needs_clone = true;
2247
		}
2248
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2249
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2250
			$needs_clone = true;
2251
		}
2252
	} else {
2253
		$needs_clone = true;
2254
	}
2255

    
2256
	if($needs_clone == true) {
2257
		/* remove previous instance if it exists */
2258
		if(does_interface_exist($realif))
2259
			pfSense_interface_destroy($realif);
2260

    
2261
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2262
		// Create the new wlan interface. FreeBSD returns the new interface name.
2263
		// example:  wlan2
2264
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2265
		if($ret <> 0) {
2266
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2267
			return false;
2268
		}
2269
		$newif = trim($out[0]);
2270
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2271
		pfSense_interface_rename($newif, $realif);
2272
		// FIXME: not sure what ngctl is for. Doesn't work.
2273
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2274
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2275
	}
2276
	return true;
2277
}
2278

    
2279
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2280
	global $config, $g;
2281

    
2282
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2283
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2284
				 'regdomain', 'regcountry', 'reglocation');
2285

    
2286
	if(!is_interface_wireless($ifcfg['if']))
2287
		return;
2288

    
2289
	$baseif = interface_get_wireless_base($ifcfg['if']);
2290

    
2291
	// Sync shared settings for assigned clones
2292
	$iflist = get_configured_interface_list(false, true);
2293
	foreach ($iflist as $if) {
2294
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2295
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2296
				foreach ($shared_settings as $setting) {
2297
					if ($sync_changes) {
2298
						if (isset($ifcfg['wireless'][$setting]))
2299
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2300
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2301
							unset($config['interfaces'][$if]['wireless'][$setting]);
2302
					} else {
2303
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2304
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2305
						else if (isset($ifcfg['wireless'][$setting]))
2306
							unset($ifcfg['wireless'][$setting]);
2307
					}
2308
				}
2309
				if (!$sync_changes)
2310
					break;
2311
			}
2312
		}
2313
	}
2314

    
2315
	// Read or write settings at shared area
2316
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2317
		foreach ($shared_settings as $setting) {
2318
			if ($sync_changes) {
2319
				if (isset($ifcfg['wireless'][$setting]))
2320
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2321
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2322
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2323
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2324
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2325
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2326
				else if (isset($ifcfg['wireless'][$setting]))
2327
					unset($ifcfg['wireless'][$setting]);
2328
			}
2329
		}
2330
	}
2331

    
2332
	// Sync the mode on the clone creation page with the configured mode on the interface
2333
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2334
		foreach ($config['wireless']['clone'] as &$clone) {
2335
			if ($clone['cloneif'] == $ifcfg['if']) {
2336
				if ($sync_changes) {
2337
					$clone['mode'] = $ifcfg['wireless']['mode'];
2338
				} else {
2339
					$ifcfg['wireless']['mode'] = $clone['mode'];
2340
				}
2341
				break;
2342
			}
2343
		}
2344
		unset($clone);
2345
	}
2346
}
2347

    
2348
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2349
	global $config, $g;
2350

    
2351
	/*    open up a shell script that will be used to output the commands.
2352
	 *    since wireless is changing a lot, these series of commands are fragile
2353
	 *    and will sometimes need to be verified by a operator by executing the command
2354
	 *    and returning the output of the command to the developers for inspection.  please
2355
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2356
	 */
2357

    
2358
	// Remove script file
2359
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2360

    
2361
	// Clone wireless nic if needed.
2362
	interface_wireless_clone($if, $wl);
2363

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

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

    
2371
	/* set values for /path/program */
2372
	$hostapd = "/usr/sbin/hostapd";
2373
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2374
	$ifconfig = "/sbin/ifconfig";
2375
	$sysctl = "/sbin/sysctl";
2376
	$killall = "/usr/bin/killall";
2377

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

    
2380
	$wlcmd = array();
2381
	$wl_sysctl = array();
2382
	/* Make sure it's up */
2383
	$wlcmd[] = "up";
2384
	/* Set a/b/g standard */
2385
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2386
	$wlcmd[] = "mode " . escapeshellarg($standard);
2387

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

    
2393
	/* Set ssid */
2394
	if($wlcfg['ssid'])
2395
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2396

    
2397
	/* Set 802.11g protection mode */
2398
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2399

    
2400
	/* set wireless channel value */
2401
	if(isset($wlcfg['channel'])) {
2402
		if($wlcfg['channel'] == "0") {
2403
			$wlcmd[] = "channel any";
2404
		} else {
2405
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2406
		}
2407
	}
2408

    
2409
	/* Set antenna diversity value */
2410
	if(isset($wlcfg['diversity']))
2411
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2412

    
2413
	/* Set txantenna value */
2414
	if(isset($wlcfg['txantenna']))
2415
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2416

    
2417
	/* Set rxantenna value */
2418
	if(isset($wlcfg['rxantenna']))
2419
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2420

    
2421
	/* set Distance value */
2422
	if($wlcfg['distance'])
2423
		$distance = escapeshellarg($wlcfg['distance']);
2424

    
2425
	/* Set wireless hostap mode */
2426
	if ($wlcfg['mode'] == "hostap") {
2427
		$wlcmd[] = "mediaopt hostap";
2428
	} else {
2429
		$wlcmd[] = "-mediaopt hostap";
2430
	}
2431

    
2432
	/* Set wireless adhoc mode */
2433
	if ($wlcfg['mode'] == "adhoc") {
2434
		$wlcmd[] = "mediaopt adhoc";
2435
	} else {
2436
		$wlcmd[] = "-mediaopt adhoc";
2437
	}
2438

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

    
2441
	/* handle hide ssid option */
2442
	if(isset($wlcfg['hidessid']['enable'])) {
2443
		$wlcmd[] = "hidessid";
2444
	} else {
2445
		$wlcmd[] = "-hidessid";
2446
	}
2447

    
2448
	/* handle pureg (802.11g) only option */
2449
	if(isset($wlcfg['pureg']['enable'])) {
2450
		$wlcmd[] = "mode 11g pureg";
2451
	} else {
2452
		$wlcmd[] = "-pureg";
2453
	}
2454

    
2455
	/* handle puren (802.11n) only option */
2456
	if(isset($wlcfg['puren']['enable'])) {
2457
		$wlcmd[] = "puren";
2458
	} else {
2459
		$wlcmd[] = "-puren";
2460
	}
2461

    
2462
	/* enable apbridge option */
2463
	if(isset($wlcfg['apbridge']['enable'])) {
2464
		$wlcmd[] = "apbridge";
2465
	} else {
2466
		$wlcmd[] = "-apbridge";
2467
	}
2468

    
2469
	/* handle turbo option */
2470
	if(isset($wlcfg['turbo']['enable'])) {
2471
		$wlcmd[] = "mediaopt turbo";
2472
	} else {
2473
		$wlcmd[] = "-mediaopt turbo";
2474
	}
2475

    
2476
	/* handle txpower setting */
2477
	/* if($wlcfg['txpower'] <> "")
2478
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2479
	*/
2480
	/* handle wme option */
2481
	if(isset($wlcfg['wme']['enable'])) {
2482
		$wlcmd[] = "wme";
2483
	} else {
2484
		$wlcmd[] = "-wme";
2485
	}
2486

    
2487
	/* set up wep if enabled */
2488
	$wepset = "";
2489
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2490
		switch($wlcfg['wpa']['auth_algs']) {
2491
			case "1":
2492
				$wepset .= "authmode open wepmode on ";
2493
				break;
2494
			case "2":
2495
				$wepset .= "authmode shared wepmode on ";
2496
				break;
2497
			case "3":
2498
				$wepset .= "authmode mixed wepmode on ";
2499
		}
2500
		$i = 1;
2501
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2502
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2503
			if (isset($wepkey['txkey'])) {
2504
				$wlcmd[] = "weptxkey {$i} ";
2505
			}
2506
			$i++;
2507
		}
2508
		$wlcmd[] = $wepset;
2509
	} else {
2510
		$wlcmd[] = "authmode open wepmode off ";
2511
	}
2512

    
2513
	kill_hostapd($if);
2514
	mwexec(kill_wpasupplicant("{$if}"));
2515

    
2516
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2517
	conf_mount_rw();
2518

    
2519
	switch ($wlcfg['mode']) {
2520
	case 'bss':
2521
		if (isset($wlcfg['wpa']['enable'])) {
2522
			$wpa .= <<<EOD
2523
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2524
ctrl_interface_group=0
2525
ap_scan=1
2526
#fast_reauth=1
2527
network={
2528
ssid="{$wlcfg['ssid']}"
2529
scan_ssid=1
2530
priority=5
2531
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2532
psk="{$wlcfg['wpa']['passphrase']}"
2533
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2534
group={$wlcfg['wpa']['wpa_pairwise']}
2535
}
2536
EOD;
2537

    
2538
			@file_put_contents("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", $wpa);
2539
			unset($wpa);
2540
		}
2541
		break;
2542
	case 'hostap':
2543
		if (!empty($wlcfg['wpa']['passphrase']))
2544
			$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2545
		else
2546
			$wpa_passphrase = "";
2547
		if (isset($wlcfg['wpa']['enable'])) {
2548
			$wpa .= <<<EOD
2549
interface={$if}
2550
driver=bsd
2551
logger_syslog=-1
2552
logger_syslog_level=0
2553
logger_stdout=-1
2554
logger_stdout_level=0
2555
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2556
ctrl_interface={$g['varrun_path']}/hostapd
2557
ctrl_interface_group=wheel
2558
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2559
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2560
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2561
ssid={$wlcfg['ssid']}
2562
debug={$wlcfg['wpa']['debug_mode']}
2563
auth_algs={$wlcfg['wpa']['auth_algs']}
2564
wpa={$wlcfg['wpa']['wpa_mode']}
2565
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2566
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2567
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2568
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2569
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2570
{$wpa_passphrase}
2571

    
2572
EOD;
2573

    
2574
			if (isset($wlcfg['wpa']['rsn_preauth'])) {
2575
				$wpa .= <<<EOD
2576
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2577
rsn_preauth=1
2578
rsn_preauth_interfaces={$if}
2579

    
2580
EOD;
2581
			}
2582
			if (is_array($wlcfg['wpa']['ieee8021x']) && isset($wlcfg['wpa']['ieee8021x']['enable'])) {
2583
				$wpa .= "ieee8021x=1\n";
2584

    
2585
			if (!empty($wlcfg['auth_server_addr']) && !empty($wlcfg['auth_server_shared_secret'])) {
2586
				$auth_server_port = "1812";
2587
				if (!empty($wlcfg['auth_server_port']) && is_numeric($wlcfg['auth_server_port']))
2588
					$auth_server_port = intval($wlcfg['auth_server_port']);
2589
				$wpa .= <<<EOD
2590

    
2591
auth_server_addr={$wlcfg['auth_server_addr']}
2592
auth_server_port={$auth_server_port}
2593
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2594

    
2595
EOD;
2596
				if (!empty($wlcfg['auth_server_addr2']) && !empty($wlcfg['auth_server_shared_secret2'])) {
2597
					$auth_server_port2 = "1812";
2598
					if (!empty($wlcfg['auth_server_port2']) && is_numeric($wlcfg['auth_server_port2']))
2599
						$auth_server_port2 = intval($wlcfg['auth_server_port2']);
2600

    
2601
					$wpa .= <<<EOD
2602
auth_server_addr={$wlcfg['auth_server_addr2']}
2603
auth_server_port={$auth_server_port2}
2604
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2605

    
2606
EOD;
2607
					}
2608
				}
2609
			}
2610

    
2611
			@file_put_contents("{$g['varetc_path']}/hostapd_{$if}.conf", $wpa);
2612
			unset($wpa);
2613
		}
2614
		break;
2615
	}
2616

    
2617
	/*
2618
	 *    all variables are set, lets start up everything
2619
	 */
2620

    
2621
	$baseif = interface_get_wireless_base($if);
2622
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2623
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2624

    
2625
	/* set sysctls for the wireless interface */
2626
	if (!empty($wl_sysctl)) {
2627
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2628
		foreach ($wl_sysctl as $wl_sysctl_line) {
2629
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2630
		}
2631
	}
2632

    
2633
	/* set ack timers according to users preference (if he/she has any) */
2634
	if($distance) {
2635
		fwrite($fd_set, "# Enable ATH distance settings\n");
2636
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2637
	}
2638

    
2639
	if (isset($wlcfg['wpa']['enable'])) {
2640
		if ($wlcfg['mode'] == "bss") {
2641
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2642
		}
2643
		if ($wlcfg['mode'] == "hostap") {
2644
			/* add line to script to restore old mac to make hostapd happy */
2645
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2646
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2647
				if (is_macaddr($if_oldmac))
2648
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2649
						" link " . escapeshellarg($if_oldmac) . "\n");
2650
			}
2651

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

    
2654
			/* add line to script to restore spoofed mac after running hostapd */
2655
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2656
				if ($wl['spoofmac'])
2657
					$if_curmac = $wl['spoofmac'];
2658
				else
2659
					$if_curmac = get_interface_mac($if);
2660
				if (is_macaddr($if_curmac))
2661
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2662
						" link " . escapeshellarg($if_curmac) . "\n");
2663
			}
2664
		}
2665
	}
2666

    
2667
	fclose($fd_set);
2668
	conf_mount_ro();
2669

    
2670
	/* Making sure regulatory settings have actually changed
2671
	 * before applying, because changing them requires bringing
2672
	 * down all wireless networks on the interface. */
2673
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2674
	$ifconfig_str = implode($output);
2675
	unset($output);
2676
	$reg_changing = false;
2677

    
2678
	/* special case for the debug country code */
2679
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2680
		$reg_changing = true;
2681
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2682
		$reg_changing = true;
2683
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2684
		$reg_changing = true;
2685
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2686
		$reg_changing = true;
2687
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2688
		$reg_changing = true;
2689

    
2690
	if ($reg_changing) {
2691
		/* set regulatory domain */
2692
		if($wlcfg['regdomain'])
2693
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2694

    
2695
		/* set country */
2696
		if($wlcfg['regcountry'])
2697
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2698

    
2699
		/* set location */
2700
		if($wlcfg['reglocation'])
2701
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2702

    
2703
		$wlregcmd_args = implode(" ", $wlregcmd);
2704

    
2705
		/* build a complete list of the wireless clones for this interface */
2706
		$clone_list = array();
2707
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2708
			$clone_list[] = interface_get_wireless_clone($baseif);
2709
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2710
			foreach ($config['wireless']['clone'] as $clone) {
2711
				if ($clone['if'] == $baseif)
2712
					$clone_list[] = $clone['cloneif'];
2713
			}
2714
		}
2715

    
2716
		/* find which clones are up and bring them down */
2717
		$clones_up = array();
2718
		foreach ($clone_list as $clone_if) {
2719
			$clone_status = pfSense_get_interface_addresses($clone_if);
2720
			if ($clone_status['status'] == 'up') {
2721
				$clones_up[] = $clone_if;
2722
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2723
			}
2724
		}
2725

    
2726
		/* apply the regulatory settings */
2727
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2728

    
2729
		/* bring the clones back up that were previously up */
2730
		foreach ($clones_up as $clone_if) {
2731
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2732

    
2733
			/*
2734
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2735
			 * is in infrastructure mode, and WPA is enabled.
2736
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2737
			 */
2738
			if ($clone_if != $if) {
2739
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2740
				if ( !empty($friendly_if)
2741
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2742
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2743
					mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($clone_if) . "_setup.sh");
2744
				}
2745
			}
2746
		}
2747
	}
2748

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

    
2753
	/* configure wireless */
2754
	$wlcmd_args = implode(" ", $wlcmd);
2755
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $wlcmd_args, false);
2756
	unset($wlcmd_args, $wlcmd);
2757

    
2758

    
2759
	sleep(1);
2760
	/* execute hostapd and wpa_supplicant if required in shell */
2761
	mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($if) . "_setup.sh");
2762

    
2763
	return 0;
2764

    
2765
}
2766

    
2767
function kill_hostapd($interface) {
2768
	global $g;
2769

    
2770
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2771
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2772
}
2773

    
2774
function kill_wpasupplicant($interface) {
2775
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2776
}
2777

    
2778
function find_dhclient_process($interface) {
2779
	if ($interface)
2780
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2781
	else
2782
		$pid = 0;
2783

    
2784
	return intval($pid);
2785
}
2786

    
2787
function find_dhcp6c_process($interface) {
2788
	global $g;
2789

    
2790
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2791
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2792
	else
2793
		return(false);
2794

    
2795
	return intval($pid);
2796
}
2797

    
2798
function interface_vlan_mtu_configured($realhwif, $mtu) {
2799
	global $config;
2800

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

    
2813
	return $mtu;
2814
}
2815

    
2816
function interface_virtual_create($interface) {
2817
	global $config;
2818

    
2819
	if (strstr($interface, "_vlan")) {
2820
		interfaces_vlan_configure($vlan);
2821
	} else if (substr($interface, 0, 3) == "gre") {
2822
		interfaces_gre_configure(0, $interface);
2823
	} else if (substr($interface, 0, 3) == "gif") {
2824
		interfaces_gif_configure(0, $interface);
2825
	} else if (substr($interface, 0, 5) == "ovpns") {
2826
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-server'])) {
2827
			foreach ($config['openvpn']['openvpn-server'] as $server) {
2828
				if ($interface == "ovpns{$server['vpnid']}") {
2829
					if (!function_exists('openvpn_resync'))
2830
						require_once('openvpn.inc');
2831
					log_error("OpenVPN: Resync server {$server['description']}");
2832
					openvpn_resync('server', $server);
2833
				}
2834
			}
2835
			unset($server);
2836
		}
2837
	} else if (substr($interface, 0, 5) == "ovpnc") {
2838
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-client'])) {
2839
			foreach ($config['openvpn']['openvpn-client'] as $client) {
2840
				if ($interface == "ovpnc{$client['vpnid']}") {
2841
					if (!function_exists('openvpn_resync'))
2842
						require_once('openvpn.inc');
2843
					log_error("OpenVPN: Resync server {$client['description']}");
2844
					openvpn_resync('client', $client);
2845
				}
2846
			}
2847
			unset($client);
2848
		}
2849
	} else if (substr($interface, 0, 4) == "lagg") {
2850
		interfaces_lagg_configure($interface);
2851
	} else if (substr($interface, 0, 6) == "bridge") {
2852
		interfaces_bridge_configure(0, $interface);
2853
	}
2854
}
2855

    
2856
function interface_vlan_adapt_mtu($vlanifs, $mtu) {
2857
	global $config;
2858

    
2859
	if (!is_array($vlanifs))
2860
		return;
2861

    
2862
	/* All vlans need to use the same mtu value as their parent. */
2863
	foreach ($vlanifs as $vlan) {
2864
		$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2865
		if (!empty($assignedport)) {
2866
			if (!empty($config['interfaces'][$assignedport]['mtu'])) {
2867
				/*
2868
				* XXX: This is really never going to happen just keep the code for safety and readbility.
2869
				* It never happens since interface_vlan_mtu_configured finds the biggest mtu on vlans.
2870
				* Also if it has a lower mtu configured just respect user choice.
2871
				*/
2872
				if (intval($config['interfaces'][$assignedport]['mtu']) > $mtu)
2873
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
2874
			} else {
2875
				if (get_interface_mtu($vlan['vlanif']) != $mtu)
2876
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
2877
			}
2878
		} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
2879
			pfSense_interface_mtu($vlan['vlanif'], $mtu);
2880
	}
2881
}
2882

    
2883
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2884
	global $config, $g;
2885
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2886
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2887

    
2888
	$wancfg = $config['interfaces'][$interface];
2889

    
2890
	if (!isset($wancfg['enable']))
2891
		return;
2892

    
2893
	$realif = get_real_interface($interface);
2894
	$realhwif_array = get_parent_interface($interface);
2895
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2896
	$realhwif = $realhwif_array[0];
2897

    
2898
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2899
		/* remove all IPv4 and IPv6 addresses */
2900
		$tmpifaces = pfSense_getall_interface_addresses($realif);
2901
		if (is_array($tmpifaces)) {
2902
			foreach ($tmpifaces as $tmpiface) {
2903
				if (is_ipaddrv6($tmpiface) || is_subnetv6($tmpiface)) {
2904
					if (!is_linklocal($tmpiface))
2905
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$tmpiface} delete");
2906
				} else {
2907
					if (is_subnetv4($tmpiface)) {
2908
						$tmpip = explode('/', $tmpiface);
2909
						$tmpip = $tmpip[0];
2910
					} else
2911
						$tmpip = $tmpiface;
2912
					pfSense_interface_deladdress($realif, $tmpip);
2913
				}
2914
			}
2915
		}
2916

    
2917
		/* only bring down the interface when both v4 and v6 are set to NONE */
2918
		if (empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6']))
2919
			interface_bring_down($interface);
2920
	}
2921

    
2922
	$interface_to_check = $realif;
2923
	switch ($wancfg['ipaddr']) {
2924
	case 'pppoe':
2925
	case 'l2tp':
2926
	case 'pptp':
2927
	case 'ppp':
2928
		$interface_to_check = $realhwif;
2929
		break;
2930
	}
2931

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

    
2936
	/* Disable Accepting router advertisements unless specifically requested */
2937
	if ($g['debug'])
2938
		log_error("Deny router advertisements for interface {$interface}");
2939
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2940

    
2941
	/* wireless configuration? */
2942
	if (is_array($wancfg['wireless']))
2943
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2944

    
2945
	$mac = get_interface_mac($realhwif);
2946
	/*
2947
	 * Don't try to reapply the spoofed MAC if it's already applied.
2948
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2949
	 * the interface config again, which attempts to spoof the MAC again,
2950
	 * which cycles the link again...
2951
	 */
2952
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2953
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2954
			" link " . escapeshellarg($wancfg['spoofmac']));
2955

    
2956
		/*
2957
		 * All vlans need to spoof their parent mac address, too.  see
2958
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2959
		 */
2960
		if (is_array($config['vlans']['vlan'])) {
2961
			foreach ($config['vlans']['vlan'] as $vlan) {
2962
				if ($vlan['if'] == $realhwif)
2963
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2964
					" link " . escapeshellarg($wancfg['spoofmac']));
2965
			}
2966
		}
2967
	}  else {
2968

    
2969
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2970
			/*   this is not a valid mac address.  generate a
2971
			 *   temporary mac address so the machine can get online.
2972
			 */
2973
			echo gettext("Generating new MAC address.");
2974
			$random_mac = generate_random_mac_address();
2975
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2976
				" link " . escapeshellarg($random_mac));
2977
			$wancfg['spoofmac'] = $random_mac;
2978
			write_config();
2979
			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");
2980
		}
2981
	}
2982

    
2983
	/* media */
2984
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2985
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2986
		if ($wancfg['media'])
2987
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2988
		if ($wancfg['mediaopt'])
2989
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2990
		mwexec($cmd);
2991
	}
2992
	$options = pfSense_get_interface_addresses($realhwif);
2993

    
2994
	/* skip vlans for checksumming and polling */
2995
	if (!stristr($realif, "_vlan") && is_array($options)) {
2996
		$flags_on = 0;
2997
		$flags_off = 0;
2998
		if(isset($config['system']['disablechecksumoffloading'])) {
2999
			if (isset($options['encaps']['txcsum']))
3000
				$flags_off |= IFCAP_TXCSUM;
3001
			if (isset($options['encaps']['rxcsum']))
3002
				$flags_off |= IFCAP_RXCSUM;
3003
		} else {
3004
			if (isset($options['caps']['txcsum']))
3005
				$flags_on |= IFCAP_TXCSUM;
3006
			if (isset($options['caps']['rxcsum']))
3007
				$flags_on |= IFCAP_RXCSUM;
3008
		}
3009

    
3010
		if(isset($config['system']['disablesegmentationoffloading']))
3011
			$flags_off |= IFCAP_TSO;
3012
		else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6']))
3013
			$flags_on |= IFCAP_TSO;
3014

    
3015
		if(isset($config['system']['disablelargereceiveoffloading']))
3016
			$flags_off |= IFCAP_LRO;
3017
		else if (isset($options['caps']['lro']))
3018
			$flags_on |= IFCAP_LRO;
3019

    
3020
		/* if the NIC supports polling *AND* it is enabled in the GUI */
3021
		if (!isset($config['system']['polling']))
3022
			$flags_off |= IFCAP_POLLING;
3023
		else if (isset($options['caps']['polling']))
3024
			$flags_on |= IFCAP_POLLING;
3025

    
3026
		pfSense_interface_capabilities($realhwif, -$flags_off);
3027
		pfSense_interface_capabilities($realhwif, $flags_on);
3028
	}
3029

    
3030
	/* invalidate interface/ip/sn cache */
3031
	get_interface_arr(true);
3032
	unset($interface_ip_arr_cache[$realif]);
3033
	unset($interface_sn_arr_cache[$realif]);
3034
	unset($interface_ipv6_arr_cache[$realif]);
3035
	unset($interface_snv6_arr_cache[$realif]);
3036

    
3037
	$tunnelif = substr($realif, 0, 3);
3038
	switch ($wancfg['ipaddr']) {
3039
	case 'dhcp':
3040
		interface_dhcp_configure($interface);
3041
		break;
3042
	case 'pppoe':
3043
	case 'l2tp':
3044
	case 'pptp':
3045
	case 'ppp':
3046
		interface_ppps_configure($interface);
3047
		break;
3048
	default:
3049
		/* XXX: Kludge for now related to #3280 */
3050
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
3051
			if (is_ipaddrv4($wancfg['ipaddr']) && $wancfg['subnet'] <> "")
3052
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
3053
		}
3054
		break;
3055
	}
3056

    
3057
	switch ($wancfg['ipaddrv6']) {
3058
	case 'slaac':
3059
	case 'dhcp6':
3060
		interface_dhcpv6_configure($interface, $wancfg);
3061
		break;
3062
	case '6rd':
3063
		interface_6rd_configure($interface, $wancfg);
3064
		break;
3065
	case '6to4':
3066
		interface_6to4_configure($interface, $wancfg);
3067
		break;
3068
	case 'track6':
3069
		interface_track6_configure($interface, $wancfg, $linkupevent);
3070
		break;
3071
	default:
3072
		/* XXX: Kludge for now related to #3280 */
3073
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
3074
			if (is_ipaddrv6($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
3075
				//pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
3076
				// FIXME: Add IPv6 Support to the pfSense module
3077
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$wancfg['ipaddrv6']} prefixlen " . escapeshellarg($wancfg['subnetv6']));
3078
			}
3079
		}
3080
		break;
3081
	}
3082

    
3083
	if (!empty($wancfg['mtu'])) {
3084
		if (stristr($realif, "_vlan")) {
3085
			$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
3086
			if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
3087
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
3088
			else
3089
				$parentmtu = interface_vlan_mtu_configured($realhwif, $wancfg['mtu']);
3090

    
3091
			if ($wancfg['mtu'] > $parentmtu) {
3092
				if (get_interface_mtu($realhwif) != $wancfg['mtu'])
3093
					pfSense_interface_mtu($realhwif, $wancfg['mtu']);
3094

    
3095
				/* All vlans need to use the same mtu value as their parent. */
3096
				interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $wancfg['mtu']);
3097
			} else
3098
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3099
		} else {
3100
			if ($wancfg['mtu'] != get_interface_mtu($realif))
3101
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3102

    
3103
			/* This case is needed when the parent of vlans is being configured */
3104
			interface_vlan_adapt_mtu(link_interface_to_vlans($realif), $wancfg['mtu']);
3105
		}
3106
		/* XXX: What about gre/gif/lagg/.. ? */
3107
	}
3108

    
3109
	if (does_interface_exist($wancfg['if']))
3110
		interfaces_bring_up($wancfg['if']);
3111

    
3112
	interface_netgraph_needed($interface);
3113

    
3114
	if (!$g['booting']) {
3115
		link_interface_to_vips($interface, "update");
3116

    
3117
		unset($gre);
3118
		$gre = link_interface_to_gre($interface);
3119
		if (!empty($gre))
3120
			array_walk($gre, 'interface_gre_configure');
3121

    
3122
		unset($gif);
3123
		$gif = link_interface_to_gif($interface);
3124
		if (!empty($gif))
3125
			array_walk($gif, 'interface_gif_configure');
3126

    
3127
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3128
			unset($bridgetmp);
3129
			$bridgetmp = link_interface_to_bridge($interface);
3130
			if (!empty($bridgetmp))
3131
				interface_bridge_add_member($bridgetmp, $realif);
3132
		}
3133

    
3134
		$grouptmp = link_interface_to_group($interface);
3135
		if (!empty($grouptmp))
3136
			array_walk($grouptmp, 'interface_group_add_member');
3137

    
3138
		if ($interface == "lan")
3139
			/* make new hosts file */
3140
			system_hosts_generate();
3141

    
3142
		if ($reloadall == true) {
3143

    
3144
			/* reconfigure static routes (kernel may have deleted them) */
3145
			system_routing_configure($interface);
3146

    
3147
			/* reload ipsec tunnels */
3148
			vpn_ipsec_configure();
3149

    
3150
			/* restart dnsmasq or unbound */
3151
			if (isset($config['dnsmasq']['enable']))
3152
				services_dnsmasq_configure();
3153
			elseif (isset($config['unbound']['enable']))
3154
				services_unbound_configure();
3155

    
3156
			/* update dyndns */
3157
			send_event("service reload dyndns {$interface}");
3158

    
3159
			/* XXX: which CPZONE? Needed? */
3160
			/* reload captive portal */
3161
			captiveportal_init_rules();
3162
		}
3163
	}
3164

    
3165
	interfaces_staticarp_configure($interface);
3166
	return 0;
3167
}
3168

    
3169
function interface_track6_configure($interface = "lan", $wancfg, $linkupevent = false) {
3170
	global $config, $g;
3171

    
3172
	if (!is_array($wancfg))
3173
		return;
3174

    
3175
	if (!isset($wancfg['enable']))
3176
		return;
3177

    
3178
	/* If the interface is not configured via another, exit */
3179
	if (empty($wancfg['track6-interface']))
3180
		return;
3181

    
3182
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3183
	$realif = get_real_interface($interface);
3184
	$linklocal = find_interface_ipv6_ll($realif);
3185
	if (!empty($linklocal))
3186
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3187
	/* XXX: This might break for good on a carp installation using link-local as network ips */
3188
	/* XXX: Probably should remove? */
3189
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3190

    
3191
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3192
	if (!isset($trackcfg['enable'])) {
3193
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3194
		return;
3195
	}
3196

    
3197
	switch($trackcfg['ipaddrv6']) {
3198
	case "6to4":
3199
		if ($g['debug'])
3200
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3201
		interface_track6_6to4_configure($interface, $wancfg);
3202
		break;
3203
	case "6rd":
3204
		if ($g['debug'])
3205
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3206
		interface_track6_6rd_configure($interface, $wancfg);
3207
		break;
3208
	case "dhcp6":
3209
		if ($linkupevent == true) {
3210
			/* 
3211
			 * NOTE: Usually come here from rc.linkup calling so just call directly intead of generating event
3212
			 * 	Instead of disrupting all other v4 configuration just restart DHCPv6 client for now
3213
			 *
3214
			 * XXX: Probably DHCPv6 client should handle this autmagically itself?
3215
			 */
3216
			$parentrealif = get_real_interface($wancfg['track6-interface']);
3217
			$pidv6 = find_dhcp6c_process($parentrealif);
3218
			if($pidv6)
3219
				posix_kill($pidv6, SIGHUP);
3220
		}
3221
		break;
3222
	}
3223

    
3224
	if (!$g['booting'] && $linkupevent == false) {
3225
		if (!function_exists('services_dhcpd_configure'))
3226
			require_once("services.inc");
3227

    
3228
		services_dhcpd_configure("inet6");
3229
	}
3230

    
3231
	return 0;
3232
}
3233

    
3234
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3235
	global $config, $g;
3236
	global $interface_ipv6_arr_cache;
3237
	global $interface_snv6_arr_cache;
3238

    
3239
	if (!is_array($lancfg))
3240
		return;
3241

    
3242
	/* If the interface is not configured via another, exit */
3243
	if (empty($lancfg['track6-interface']))
3244
		return;
3245

    
3246
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3247
	if (empty($wancfg)) {
3248
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3249
		return;
3250
	}
3251

    
3252
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3253
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3254
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3255
		return;
3256
	}
3257
	$hexwanv4 = return_hex_ipv4($ip4address);
3258

    
3259
	/* create the long prefix notation for math, save the prefix length */
3260
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3261
	$rd6prefixlen = $rd6prefix[1];
3262
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3263

    
3264
	/* binary presentation of the prefix for all 128 bits. */
3265
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3266

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

    
3272
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3273
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3274
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3275
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3276
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3277
	/* fill the rest out with zeros */
3278
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);
3279

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

    
3283
	$lanif = get_real_interface($interface);
3284
	$oip = find_interface_ipv6($lanif);
3285
	if (is_ipaddrv6($oip))
3286
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3287
	unset($interface_ipv6_arr_cache[$lanif]);
3288
	unset($interface_snv6_arr_cache[$lanif]);
3289
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3290
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3291

    
3292
	return 0;
3293
}
3294

    
3295
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3296
	global $config, $g;
3297
	global $interface_ipv6_arr_cache;
3298
	global $interface_snv6_arr_cache;
3299

    
3300
	if (!is_array($lancfg))
3301
		return;
3302

    
3303
	/* If the interface is not configured via another, exit */
3304
	if (empty($lancfg['track6-interface']))
3305
		return;
3306

    
3307
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3308
	if (empty($wancfg)) {
3309
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3310
		return;
3311
	}
3312

    
3313
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3314
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3315
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3316
		return;
3317
	}
3318
	$hexwanv4 = return_hex_ipv4($ip4address);
3319

    
3320
	/* create the long prefix notation for math, save the prefix length */
3321
	$sixto4prefix = "2002::";
3322
	$sixto4prefixlen = 16;
3323
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3324

    
3325
	/* binary presentation of the prefix for all 128 bits. */
3326
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3327

    
3328
	/* just save the left prefix length bits */
3329
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3330
	/* add the v4 address */
3331
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3332
	/* add the custom prefix id */
3333
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3334
	/* fill the rest out with zeros */
3335
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);
3336

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

    
3340
	$lanif = get_real_interface($interface);
3341
	$oip = find_interface_ipv6($lanif);
3342
	if (is_ipaddrv6($oip))
3343
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3344
	unset($interface_ipv6_arr_cache[$lanif]);
3345
	unset($interface_snv6_arr_cache[$lanif]);
3346
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3347
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3348

    
3349
	return 0;
3350
}
3351

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

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

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

    
3361
	if (!is_module_loaded('if_stf.ko'))
3362
		mwexec('/sbin/kldload if_stf.ko');
3363

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

    
3372
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3373
		$wancfg['prefix-6rd-v4plen'] = 0;
3374

    
3375
	/* create the long prefix notation for math, save the prefix length */
3376
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3377
	$rd6prefixlen = $rd6prefix[1];
3378
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3379

    
3380
	/* binary presentation of the prefix for all 128 bits. */
3381
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3382

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

    
3390
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3391
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3392

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

    
3395
	/* XXX: need to extend to support variable prefix size for v4 */
3396
	if (!is_module_loaded("if_stf"))
3397
		mwexec("/sbin/kldload if_stf.ko");
3398
	$stfiface = "{$interface}_stf";
3399
	if (does_interface_exist($stfiface))
3400
		pfSense_interface_destroy($stfiface);
3401
	$tmpstfiface = pfSense_interface_create("stf");
3402
	pfSense_interface_rename($tmpstfiface, $stfiface);
3403
	pfSense_interface_flags($stfiface, IFF_LINK2);
3404
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3405
	mwexec("/sbin/ifconfig {$stfiface} stfv4br " . escapeshellarg($wancfg['gateway-6rd']));
3406
	if ($wancfg['prefix-6rd-v4plen'] > 0 && $wancfg['prefix-6rd-v4plen'] < 32)
3407
		mwexec("/sbin/ifconfig {$stfiface} stfv4net {$ip4address}/{$wancfg['prefix-6rd-v4plen']}");
3408
	if ($g['debug'])
3409
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3410

    
3411
	/* write out a default router file */
3412
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3413
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3414

    
3415
	$ip4gateway = get_interface_gateway($interface);
3416
	if (is_ipaddrv4($ip4gateway))
3417
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3418

    
3419
	/* configure dependent interfaces */
3420
	if (!$g['booting'])
3421
		link_interface_to_track6($interface, "update");
3422

    
3423
	return 0;
3424
}
3425

    
3426
function interface_6to4_configure($interface = "wan", $wancfg){
3427
	global $config, $g;
3428

    
3429
	/* because this is a tunnel interface we can only function
3430
	 *	with a public IPv4 address on the interface */
3431

    
3432
	if (!is_array($wancfg))
3433
		return;
3434

    
3435
	$wanif = get_real_interface($interface);
3436
	$ip4address = find_interface_ip($wanif);
3437
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3438
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3439
		return false;
3440
	}
3441

    
3442
	/* create the long prefix notation for math, save the prefix length */
3443
	$stfprefixlen = 16;
3444
	$stfprefix = Net_IPv6::uncompress("2002::");
3445
	$stfarr = explode(":", $stfprefix);
3446
	$v4prefixlen = "0";
3447

    
3448
	/* we need the hex form of the interface IPv4 address */
3449
	$ip4arr = explode(".", $ip4address);
3450
	$hexwanv4 = "";
3451
	foreach($ip4arr as $octet)
3452
		$hexwanv4 .= sprintf("%02x", $octet);
3453

    
3454
	/* we need the hex form of the broker IPv4 address */
3455
	$ip4arr = explode(".", "192.88.99.1");
3456
	$hexbrv4 = "";
3457
	foreach($ip4arr as $octet)
3458
		$hexbrv4 .= sprintf("%02x", $octet);
3459

    
3460
	/* binary presentation of the prefix for all 128 bits. */
3461
	$stfprefixbin = "";
3462
	foreach($stfarr as $element) {
3463
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3464
	}
3465
	/* just save the left prefix length bits */
3466
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3467

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

    
3472
	/* for the local subnet too. */
3473
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3474
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);
3475

    
3476
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3477
	$stfbrarr = array();
3478
	$stfbrbinarr = array();
3479
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3480
	foreach($stfbrbinarr as $bin)
3481
		$stfbrarr[] = dechex(bindec($bin));
3482
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3483

    
3484
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3485
	$stflanarr = array();
3486
	$stflanbinarr = array();
3487
	$stflanbinarr = str_split($stflanbin, 16);
3488
	foreach($stflanbinarr as $bin)
3489
		$stflanarr[] = dechex(bindec($bin));
3490
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3491
	$stflanarr[7] = 1;
3492
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3493

    
3494
	/* setup the stf interface */
3495
	if (!is_module_loaded("if_stf"))
3496
		mwexec("/sbin/kldload if_stf.ko");
3497
	$stfiface = "{$interface}_stf";
3498
	if (does_interface_exist($stfiface))
3499
		pfSense_interface_destroy($stfiface);
3500
	$tmpstfiface = pfSense_interface_create("stf");
3501
	pfSense_interface_rename($tmpstfiface, $stfiface);
3502
	pfSense_interface_flags($stfiface, IFF_LINK2);
3503
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3504

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

    
3508
	/* write out a default router file */
3509
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3510
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3511

    
3512
	$ip4gateway = get_interface_gateway($interface);
3513
	if (is_ipaddrv4($ip4gateway))
3514
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3515

    
3516
	if (!$g['booting'])
3517
		link_interface_to_track6($interface, "update");
3518

    
3519
	return 0;
3520
}
3521

    
3522
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3523
	global $config, $g;
3524

    
3525
	if (!is_array($wancfg))
3526
		return;
3527

    
3528
	$wanif = get_real_interface($interface, "inet6");
3529
	$dhcp6cconf = "";
3530
	$dhcp6cconf .= "interface {$wanif} {\n";
3531

    
3532
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3533
	if($wancfg['ipaddrv6'] == "slaac") {
3534
		$dhcp6cconf .= "	information-only;\n";
3535
		$dhcp6cconf .= "	request domain-name-servers;\n";
3536
		$dhcp6cconf .= "	request domain-name;\n";
3537
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3538
		$dhcp6cconf .= "};\n";
3539
	} else {
3540
		/* skip address request if this is set */
3541
		if(!isset($wancfg['dhcp6prefixonly']))
3542
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3543
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3544
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3545

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

    
3550
		$dhcp6cconf .= "};\n";
3551

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

    
3555
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3556
			/* Setup the prefix delegation */
3557
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3558
			$preflen = 64 - $wancfg['dhcp6-ia-pd-len'];
3559
			if (isset($wancfg['dhcp6-ia-pd-send-hint']))
3560
				$dhcp6cconf .= "	prefix ::/{$preflen} infinity;\n";
3561
			$iflist = link_interface_to_track6($interface);
3562
			foreach ($iflist as $friendly => $ifcfg) {
3563
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3564
					if ($g['debug'])
3565
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3566
					$realif = get_real_interface($friendly);
3567
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3568
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3569
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3570
					$dhcp6cconf .= "	};\n";
3571
				}
3572
			}
3573
			unset($preflen, $iflist, $ifcfg);
3574
			$dhcp6cconf .= "};\n";
3575
		}
3576
	}
3577

    
3578
	// DHCP6 Config File Advanced
3579
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3580

    
3581
	// DHCP6 Config File Override
3582
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3583

    
3584
	/* wide-dhcp6c works for now. */
3585
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3586
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3587
		unset($dhcp6cconf);
3588
		return 1;
3589
	}
3590
	unset($dhcp6cconf);
3591

    
3592
	$dhcp6cscript = "#!/bin/sh\n";
3593
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3594
	$dhcp6cscript .= "\$dmips = \${new_domain_name_servers}\n";
3595
	$dhcp6cscript .= "\$dmnames = \${new_domain_name}\n";
3596
	$dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\$dmnames&dmips=\$dmips\"\n";
3597
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3598
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3599
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3600
		unset($dhcp6cscript);
3601
		return 1;
3602
	}
3603
	unset($dhcp6cscript);
3604
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3605

    
3606
	$rtsoldscript = "#!/bin/sh\n";
3607
	$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
3608
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
3609
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_defaultgwv6\n";
3610
	$rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
3611
	$rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
3612
	$rtsoldscript .= "\t/bin/sleep 1\n";
3613
	$rtsoldscript .= "fi\n";
3614
	$rtsoldscript .= "/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
3615
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Starting dhcp6 client for interface {$interface}({$wanif})\"\n";
3616
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3617
	if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) {
3618
		printf("Error: cannot open rtsold_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3619
		unset($rtsoldscript);
3620
		return 1;
3621
	}
3622
	unset($rtsoldscript);
3623
	@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
3624

    
3625
	/* accept router advertisements for this interface */
3626
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3627
	log_error("Accept router advertisements on interface {$wanif} ");
3628
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3629

    
3630
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3631
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3632
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3633
		sleep(2);
3634
	}
3635
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3636

    
3637
	/* NOTE: will be called from rtsold invoked script
3638
	 * link_interface_to_track6($interface, "update");
3639
	 */
3640

    
3641
	return 0;
3642
}
3643

    
3644
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3645
	global $g;
3646

    
3647
	$send_options = "";
3648
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3649
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_send_options']);
3650
		foreach ($options as $option) {
3651
			$send_options .= "\tsend " . trim($option) . ";\n";
3652
		}
3653
	}
3654

    
3655
	$request_options = "";
3656
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3657
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_request_options']);
3658
		foreach ($options as $option) {
3659
			$request_options .= "\trequest " . trim($option) . ";\n";
3660
		}
3661
	}
3662

    
3663
	$information_only = "";
3664
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3665
		$information_only = "\tinformation-only;\n";
3666

    
3667
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3668
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3669
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3670

    
3671
	$interface_statement  = "interface";
3672
	$interface_statement .= " {$wanif}";
3673
	$interface_statement .= " {\n";
3674
	$interface_statement .= "$send_options";
3675
	$interface_statement .= "$request_options";
3676
	$interface_statement .= "$information_only";
3677
	$interface_statement .= "$script";
3678
	$interface_statement .= "};\n";
3679

    
3680
	$id_assoc_statement_address = "";
3681
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3682
		$id_assoc_statement_address .= "id-assoc";
3683
		$id_assoc_statement_address .= " na";
3684
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3685
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3686
		$id_assoc_statement_address .= " { ";
3687

    
3688
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3689
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3690
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3691
			$id_assoc_statement_address .= "\n\taddress";
3692
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3693
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3694
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3695
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3696
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3697
			$id_assoc_statement_address .= ";\n";
3698
		}
3699

    
3700
		$id_assoc_statement_address  .= "};\n";
3701
	}
3702

    
3703
	$id_assoc_statement_prefix = "";
3704
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3705
		$id_assoc_statement_prefix .= "id-assoc";
3706
		$id_assoc_statement_prefix .= " pd";
3707
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3708
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3709
		$id_assoc_statement_prefix .= " { ";
3710

    
3711
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3712
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3713
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3714
			$id_assoc_statement_prefix .= "\n\tprefix";
3715
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3716
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3717
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3718
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3719
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3720
			$id_assoc_statement_prefix .= ";";
3721
		}
3722

    
3723
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3724
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3725
			$id_assoc_statement_prefix .= " {$wanif}";
3726
			$id_assoc_statement_prefix .= " {\n";
3727
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3728
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3729
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3730
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3731
			$id_assoc_statement_prefix .= "\t};";
3732
		}
3733

    
3734
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3735
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3736
			$id_assoc_statement_prefix .= "\n";
3737
		}
3738

    
3739
		$id_assoc_statement_prefix  .= "};\n";
3740
	}
3741

    
3742
	$authentication_statement = "";
3743
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3744
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3745
		$authentication_statement .= "authentication";
3746
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3747
		$authentication_statement .= " {\n";
3748
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3749
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3750
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3751
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3752
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3753
		$authentication_statement .= "};\n";
3754
	}
3755

    
3756
	$key_info_statement = "";
3757
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3758
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3759
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3760
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3761
		$key_info_statement .= "keyinfo";
3762
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3763
		$key_info_statement .= " {\n";
3764
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3765
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3766
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3767
		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'])) 
3768
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3769
		$key_info_statement .= "};\n";
3770
	}
3771

    
3772
	$dhcp6cconf  = $interface_statement;
3773
	$dhcp6cconf .= $id_assoc_statement_address;
3774
	$dhcp6cconf .= $id_assoc_statement_prefix;
3775
	$dhcp6cconf .= $authentication_statement;
3776
	$dhcp6cconf .= $key_info_statement;
3777

    
3778
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3779

    
3780
	return $dhcp6cconf;
3781
}
3782

    
3783

    
3784
function DHCP6_Config_File_Override($wancfg, $wanif) {
3785

    
3786
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3787
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3788

    
3789
	return $dhcp6cconf;
3790
}
3791

    
3792

    
3793
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3794

    
3795
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3796

    
3797
	return $dhcp6cconf;
3798
}
3799

    
3800

    
3801
function interface_dhcp_configure($interface = "wan") {
3802
	global $config, $g;
3803

    
3804
	$wancfg = $config['interfaces'][$interface];
3805
	$wanif = $wancfg['if'];
3806
	if (empty($wancfg))
3807
		$wancfg = array();
3808

    
3809
	/* generate dhclient_wan.conf */
3810
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3811
	if (!$fd) {
3812
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3813
		return 1;
3814
	}
3815

    
3816
	if ($wancfg['dhcphostname']) {
3817
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3818
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3819
	} else {
3820
		$dhclientconf_hostname = "";
3821
	}
3822

    
3823
	$wanif = get_real_interface($interface);
3824
	if (empty($wanif)) {
3825
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3826
		return 0;
3827
	}
3828
	$dhclientconf = "";
3829

    
3830
	$dhclientconf .= <<<EOD
3831
interface "{$wanif}" {
3832
timeout 60;
3833
retry 15;
3834
select-timeout 0;
3835
initial-interval 1;
3836
	{$dhclientconf_hostname}
3837
	script "/sbin/dhclient-script";
3838
EOD;
3839

    
3840
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3841
	$dhclientconf .= <<<EOD
3842

    
3843
	reject {$wancfg['dhcprejectfrom']};
3844
EOD;
3845
}
3846
	$dhclientconf .= <<<EOD
3847

    
3848
}
3849

    
3850
EOD;
3851

    
3852
	// DHCP Config File Advanced
3853
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3854

    
3855
if(is_ipaddr($wancfg['alias-address'])) {
3856
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3857
	$dhclientconf .= <<<EOD
3858
alias {
3859
	interface  "{$wanif}";
3860
	fixed-address {$wancfg['alias-address']};
3861
	option subnet-mask {$subnetmask};
3862
}
3863

    
3864
EOD;
3865
}
3866

    
3867
	// DHCP Config File Override
3868
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3869

    
3870
	fwrite($fd, $dhclientconf);
3871
	fclose($fd);
3872

    
3873
	/* bring wan interface up before starting dhclient */
3874
	if($wanif)
3875
		interfaces_bring_up($wanif);
3876
	else
3877
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3878

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

    
3882
	return 0;
3883
}
3884

    
3885
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3886

    
3887
	$hostname = "";
3888
	if ($wancfg['dhcphostname'] != '') {
3889
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3890
	}
3891

    
3892
	/* DHCP Protocol Timings */
3893
	$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");
3894
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3895
		$pt_variable = "{$Protocol_Timing}";
3896
		${$pt_variable} = "";
3897
		if ($wancfg[$Protocol_Timing] != "") {
3898
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3899
		}
3900
	}
3901

    
3902
	$send_options = "";
3903
	if ($wancfg['adv_dhcp_send_options'] != '') {
3904
		$options = split(",", $wancfg['adv_dhcp_send_options']);
3905
		foreach ($options as $option) {
3906
			$send_options .= "\tsend " . trim($option) . ";\n";
3907
		}
3908
	}
3909

    
3910
	$request_options = "";
3911
	if ($wancfg['adv_dhcp_request_options'] != '') {
3912
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3913
	}
3914

    
3915
	$required_options = "";
3916
	if ($wancfg['adv_dhcp_required_options'] != '') {
3917
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3918
	}
3919

    
3920
	$option_modifiers = "";
3921
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3922
		$modifiers = split(",", $wancfg['adv_dhcp_option_modifiers']);
3923
		foreach ($modifiers as $modifier) {
3924
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3925
		}
3926
	}
3927

    
3928
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3929
 	$dhclientconf .= "\n";
3930
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3931
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3932
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3933
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3934
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3935
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3936
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3937
 	$dhclientconf .= "\n";
3938
 	$dhclientconf .= "# DHCP Protocol Options\n";
3939
 	$dhclientconf .= "{$hostname}";
3940
 	$dhclientconf .= "{$send_options}";
3941
 	$dhclientconf .= "{$request_options}";
3942
 	$dhclientconf .= "{$required_options}";
3943
 	$dhclientconf .= "{$option_modifiers}";
3944
 	$dhclientconf .= "\n";
3945
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3946
 	$dhclientconf .= "}\n";
3947

    
3948
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3949

    
3950
	return $dhclientconf;
3951
}
3952

    
3953

    
3954
function DHCP_Config_File_Override($wancfg, $wanif) {
3955

    
3956
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3957
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3958

    
3959
	return $dhclientconf;
3960
}
3961

    
3962

    
3963
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3964

    
3965
	/* Apply Interface Substitutions */
3966
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3967

    
3968
	/* Apply Hostname Substitutions */
3969
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3970

    
3971
	/* Arrays of MAC Address Types, Cases, Delimiters */
3972
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3973
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3974
	$various_mac_cases      = array("U", "L");
3975
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3976

    
3977
	/* Apply MAC Address Substitutions */
3978
	foreach ($various_mac_types as $various_mac_type) {
3979
		foreach ($various_mac_cases as $various_mac_case) {
3980
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3981

    
3982
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3983
				if ($res !== false) {
3984

    
3985
					/* Get MAC Address as ASCII String With Colon (:) Celimiters */
3986
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3987
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3988

    
3989
					if ("$various_mac_type" == "mac_addr_hex") {
3990
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3991
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3992
						$dhcpclientconf_mac_hex = "";
3993
						$delimiter = "";
3994
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3995
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3996
							$delimiter = ":";
3997
						}
3998
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3999
					}
4000

    
4001
					/* MAC Address Delimiter Substitutions */
4002
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
4003

    
4004
					/* Apply MAC Address Substitutions */
4005
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
4006
				}
4007
			}
4008
		}
4009
	}
4010

    
4011
	return $dhclientconf;
4012
}
4013

    
4014
function interfaces_group_setup() {
4015
	global $config;
4016

    
4017
	if (!is_array($config['ifgroups']['ifgroupentry']))
4018
		return;
4019

    
4020
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
4021
		interface_group_setup($groupar);
4022

    
4023
	return;
4024
}
4025

    
4026
function interface_group_setup(&$groupname /* The parameter is an array */) {
4027
	global $config;
4028

    
4029
	if (!is_array($groupname))
4030
		return;
4031
	$members = explode(" ", $groupname['members']);
4032
	foreach($members as $ifs) {
4033
		$realif = get_real_interface($ifs);
4034
		if ($realif)
4035
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
4036
	}
4037

    
4038
	return;
4039
}
4040

    
4041
function is_interface_group($if) {
4042
	global $config;
4043

    
4044
	if (is_array($config['ifgroups']['ifgroupentry']))
4045
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
4046
			if ($groupentry['ifname'] === $if)
4047
				return true;
4048
		}
4049

    
4050
	return false;
4051
}
4052

    
4053
function interface_group_add_member($interface, $groupname) {
4054
	$interface = get_real_interface($interface);
4055
	mwexec("/sbin/ifconfig {$interface} group " . escapeshellarg($groupname), true);
4056
}
4057

    
4058
/* COMPAT Function */
4059
function convert_friendly_interface_to_real_interface_name($interface) {
4060
	return get_real_interface($interface);
4061
}
4062

    
4063
/* COMPAT Function */
4064
function get_real_wan_interface($interface = "wan") {
4065
	return get_real_interface($interface);
4066
}
4067

    
4068
/* COMPAT Function */
4069
function get_current_wan_address($interface = "wan") {
4070
	return get_interface_ip($interface);
4071
}
4072

    
4073
/*
4074
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
4075
 */
4076
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
4077
	global $config;
4078

    
4079
	/* XXX: For speed reasons reference directly the interface array */
4080
	$ifdescrs = &$config['interfaces'];
4081
	//$ifdescrs = get_configured_interface_list(false, true);
4082

    
4083
	foreach ($ifdescrs as $if => $ifname) {
4084
		if ($if == $interface || $ifname['if'] == $interface)
4085
			return $if;
4086

    
4087
		if (get_real_interface($if) == $interface)
4088
			return $if;
4089

    
4090
		$int = get_parent_interface($if, true);
4091
		if (is_array($int)) {
4092
			foreach ($int as $iface) {
4093
				if ($iface == $interface)
4094
					return $if;
4095
			}
4096
		}
4097
	}
4098

    
4099
	if ($interface == "enc0")
4100
		return 'IPSec';
4101

    
4102
	return NULL;
4103
}
4104

    
4105
/* attempt to resolve interface to friendly descr */
4106
function convert_friendly_interface_to_friendly_descr($interface) {
4107
	global $config;
4108

    
4109
	switch ($interface) {
4110
	case "l2tp":
4111
		$ifdesc = "L2TP";
4112
		break;
4113
	case "pptp":
4114
		$ifdesc = "PPTP";
4115
		break;
4116
	case "pppoe":
4117
		$ifdesc = "PPPoE";
4118
		break;
4119
	case "openvpn":
4120
		$ifdesc = "OpenVPN";
4121
		break;
4122
	case "enc0":
4123
	case "ipsec":
4124
		$ifdesc = "IPsec";
4125
		break;
4126
	default:
4127
		if (isset($config['interfaces'][$interface])) {
4128
			if (empty($config['interfaces'][$interface]['descr']))
4129
				$ifdesc = strtoupper($interface);
4130
			else
4131
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4132
			break;
4133
		} else if (stristr($interface, "_vip")) {
4134
			if (is_array($config['virtualip']['vip'])) {
4135
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4136
					if ($vip['mode'] == "carp")  {
4137
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4138
							return "{$vip['subnet']} - {$vip['descr']}";
4139
					}
4140
				}
4141
			}
4142
		} else {
4143
			/* if list */
4144
			$ifdescrs = get_configured_interface_with_descr(false, true);
4145
			foreach ($ifdescrs as $if => $ifname) {
4146
				if ($if == $interface || $ifname == $interface)
4147
					return $ifname;
4148
			}
4149
		}
4150
		break;
4151
	}
4152

    
4153
	return $ifdesc;
4154
}
4155

    
4156
function convert_real_interface_to_friendly_descr($interface) {
4157
	global $config;
4158

    
4159
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4160

    
4161
	if ($ifdesc) {
4162
		$iflist = get_configured_interface_with_descr(false, true);
4163
		return $iflist[$ifdesc];
4164
	}
4165

    
4166
	return $interface;
4167
}
4168

    
4169
/*
4170
 *  get_parent_interface($interface):
4171
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4172
 *				or virtual interface (i.e. vlan)
4173
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4174
 *			-- returns $interface passed in if $interface parent is not found
4175
 *			-- returns empty array if an invalid interface is passed
4176
 *	(Only handles ppps and vlans now.)
4177
 */
4178
function get_parent_interface($interface, $avoidrecurse = false) {
4179
	global $config;
4180

    
4181
	$parents = array();
4182
	//Check that we got a valid interface passed
4183
	$realif = get_real_interface($interface);
4184
	if ($realif == NULL)
4185
		return $parents;
4186

    
4187
	// If we got a real interface, find it's friendly assigned name
4188
	if ($interface == $realif && $avoidrecurse == false)
4189
		$interface = convert_real_interface_to_friendly_interface_name($interface);
4190

    
4191
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4192
		$ifcfg = $config['interfaces'][$interface];
4193
		switch ($ifcfg['ipaddr']) {
4194
			case "ppp":
4195
			case "pppoe":
4196
			case "pptp":
4197
			case "l2tp":
4198
				if (empty($parents))
4199
					if (is_array($config['ppps']['ppp']))
4200
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4201
							if ($ifcfg['if'] == $ppp['if']) {
4202
								$ports = explode(',', $ppp['ports']);
4203
								foreach ($ports as $pid => $parent_if)
4204
									$parents[$pid] = get_real_interface($parent_if);
4205
								break;
4206
							}
4207
						}
4208
				break;
4209
			case "dhcp":
4210
			case "static":
4211
			default:
4212
				// Handle _vlans
4213
				if (stristr($realif,"_vlan"))
4214
					if (is_array($config['vlans']['vlan']))
4215
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
4216
							if ($ifcfg['if'] == $vlan['vlanif']){
4217
								$parents[0] = $vlan['if'];
4218
								break;
4219
							}
4220
				break;
4221
		}
4222
	}
4223

    
4224
	if (empty($parents))
4225
		$parents[0] = $realif;
4226

    
4227
	return $parents;
4228
}
4229

    
4230
function interface_is_wireless_clone($wlif) {
4231
	if(!stristr($wlif, "_wlan")) {
4232
		return false;
4233
	} else {
4234
		return true;
4235
	}
4236
}
4237

    
4238
function interface_get_wireless_base($wlif) {
4239
	if(!stristr($wlif, "_wlan")) {
4240
		return $wlif;
4241
	} else {
4242
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4243
	}
4244
}
4245

    
4246
function interface_get_wireless_clone($wlif) {
4247
	if(!stristr($wlif, "_wlan")) {
4248
		return $wlif . "_wlan0";
4249
	} else {
4250
		return $wlif;
4251
	}
4252
}
4253

    
4254
function get_real_interface($interface = "wan", $family = "all", $realv6iface = false, $flush = true) {
4255
	global $config, $g;
4256

    
4257
	$wanif = NULL;
4258

    
4259
	switch ($interface) {
4260
	case "l2tp":
4261
		$wanif = "l2tp";
4262
		break;
4263
	case "pptp":
4264
		$wanif = "pptp";
4265
		break;
4266
	case "pppoe":
4267
		$wanif = "pppoe";
4268
		break;
4269
	case "openvpn":
4270
		$wanif = "openvpn";
4271
		break;
4272
	case "ipsec":
4273
	case "enc0":
4274
		$wanif = "enc0";
4275
		break;
4276
	case "ppp":
4277
		$wanif = "ppp";
4278
		break;
4279
	default:
4280
		// If a real interface was alread passed simply
4281
		// pass the real interface back.  This encourages
4282
		// the usage of this function in more cases so that
4283
		// we can combine logic for more flexibility.
4284
		if(does_interface_exist($interface, $flush)) {
4285
			$wanif = $interface;
4286
			break;
4287
		}
4288

    
4289
		if (empty($config['interfaces'][$interface]))
4290
			break;
4291

    
4292
		$cfg = &$config['interfaces'][$interface];
4293

    
4294
		if ($family == "inet6") {
4295
			switch ($cfg['ipaddrv6']) {
4296
			case "6rd":
4297
			case "6to4":
4298
				$wanif = "{$interface}_stf";
4299
				break;
4300
			case 'pppoe':
4301
			case 'ppp':
4302
			case 'l2tp':
4303
			case 'pptp':
4304
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4305
					$wanif = interface_get_wireless_clone($cfg['if']);
4306
				else
4307
					$wanif = $cfg['if'];
4308
				break;
4309
			default:
4310
				switch ($cfg['ipaddr']) {
4311
				case 'pppoe':
4312
				case 'ppp':
4313
				case 'l2tp':
4314
				case 'pptp':
4315
					if (isset($cfg['dhcp6usev4iface']) && $realv6iface === false)
4316
						$wanif = $cfg['if'];
4317
					else {
4318
						$parents = get_parent_interface($interface);
4319
						if (!empty($parents[0]))
4320
							$wanif = $parents[0];
4321
						else
4322
							$wanif = $cfg['if'];
4323
					}
4324
					break;
4325
				default:
4326
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4327
						$wanif = interface_get_wireless_clone($cfg['if']);
4328
					else
4329
						$wanif = $cfg['if'];
4330
					break;
4331
				}
4332
				break;
4333
			}
4334
		} else {
4335
			// Wireless cloned NIC support (FreeBSD 8+)
4336
			// interface name format: $parentnic_wlanparentnic#
4337
			// example: ath0_wlan0
4338
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4339
				$wanif = interface_get_wireless_clone($cfg['if']);
4340
			else
4341
				$wanif = $cfg['if'];
4342
		}
4343
		break;
4344
	}
4345

    
4346
	return $wanif;
4347
}
4348

    
4349
/* Guess the physical interface by providing a IP address */
4350
function guess_interface_from_ip($ipaddress) {
4351
	if(! is_ipaddr($ipaddress)) {
4352
		return false;
4353
	}
4354
	if(is_ipaddrv4($ipaddress)) {
4355
		/* create a route table we can search */
4356
		exec("netstat -rnWf inet", $output, $ret);
4357
		foreach($output as $line) {
4358
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
4359
				$fields = preg_split("/[ ]+/", $line);
4360
				if(ip_in_subnet($ipaddress, $fields[0])) {
4361
					return $fields[6];
4362
				}
4363
			}
4364
		}
4365
	}
4366
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
4367
	if(is_ipaddrv6($ipaddress)) {
4368
		/* create a route table we can search */
4369
		exec("netstat -rnWf inet6", $output, $ret);
4370
		foreach($output as $line) {
4371
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
4372
				$fields = preg_split("/[ ]+/", $line);
4373
				if(ip_in_subnet($ipaddress, $fields[0])) {
4374
					return $fields[6];
4375
				}
4376
			}
4377
		}
4378
	}
4379
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
4380
	if(empty($ret)) {
4381
		return false;
4382
	}
4383
	return $ret;
4384
}
4385

    
4386
/*
4387
 * find_ip_interface($ip): return the interface where an ip is defined
4388
 *   (or if $bits is specified, where an IP within the subnet is defined)
4389
 */
4390
function find_ip_interface($ip, $bits = null) {
4391
	if (!is_ipaddr($ip))
4392
		return false;
4393

    
4394
	$isv6ip = is_ipaddrv6($ip);
4395

    
4396
	/* if list */
4397
	$ifdescrs = get_configured_interface_list();
4398

    
4399
	foreach ($ifdescrs as $ifdescr => $ifname) {
4400
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4401
		if (is_null($ifip))
4402
			continue;
4403
		if (is_null($bits)) {
4404
			if ($ip == $ifip) {
4405
				$int = get_real_interface($ifname);
4406
				return $int;
4407
			}
4408
		}
4409
		else {
4410
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4411
				$int = get_real_interface($ifname);
4412
				return $int;
4413
			}
4414
		}
4415
	}
4416

    
4417
	return false;
4418
}
4419

    
4420
/*
4421
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4422
 *   (or if $bits is specified, where an IP within the subnet is found)
4423
 */
4424
function find_virtual_ip_alias($ip, $bits = null) {
4425
	global $config;
4426

    
4427
	if (!is_array($config['virtualip']['vip'])) {
4428
		return false;
4429
	}
4430
	if (!is_ipaddr($ip))
4431
		return false;
4432

    
4433
	$isv6ip = is_ipaddrv6($ip);
4434

    
4435
	foreach ($config['virtualip']['vip'] as $vip) {
4436
		if ($vip['mode'] === "ipalias") {
4437
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4438
				continue;
4439
			if (is_null($bits)) {
4440
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4441
					return $vip;
4442
				}
4443
			}
4444
			else {
4445
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4446
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4447
					return $vip;
4448
				}
4449
			}
4450
		}
4451
	}
4452
	return false;
4453
}
4454

    
4455
/*
4456
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4457
 */
4458
function find_number_of_created_carp_interfaces() {
4459
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4460
}
4461

    
4462
function get_all_carp_interfaces() {
4463
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
4464
	$ints = explode(" ", $ints);
4465
	return $ints;
4466
}
4467

    
4468
/*
4469
 * find_carp_interface($ip): return the carp interface where an ip is defined
4470
 */
4471
function find_carp_interface($ip) {
4472
	global $config;
4473
	if (is_array($config['virtualip']['vip'])) {
4474
		foreach ($config['virtualip']['vip'] as $vip) {
4475
			if ($vip['mode'] == "carp") {
4476
				if(is_ipaddrv4($ip)) {
4477
					$carp_ip = get_interface_ip($vip['interface']);
4478
				}
4479
				if(is_ipaddrv6($ip)) {
4480
					$carp_ip = get_interface_ipv6($vip['interface']);
4481
				}
4482
				exec("/sbin/ifconfig", $output, $return);
4483
				foreach($output as $line) {
4484
					$elements = preg_split("/[ ]+/i", $line);
4485
					if(strstr($elements[0], "vip"))
4486
						$curif = str_replace(":", "", $elements[0]);
4487
					if(stristr($line, $ip)) {
4488
						$if = $curif;
4489
						continue;
4490
					}
4491
				}
4492

    
4493
				if ($if)
4494
					return $if;
4495
			}
4496
		}
4497
	}
4498
}
4499

    
4500
function link_carp_interface_to_parent($interface) {
4501
	global $config;
4502

    
4503
	if (empty($interface))
4504
		return;
4505

    
4506
	$carp_ip = get_interface_ip($interface);
4507
	$carp_ipv6 = get_interface_ipv6($interface);
4508

    
4509
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4510
		return;
4511

    
4512
	/* if list */
4513
	$ifdescrs = get_configured_interface_list();
4514
	foreach ($ifdescrs as $ifdescr => $ifname) {
4515
		/* check IPv4 */
4516
		if(is_ipaddrv4($carp_ip)) {
4517
			$interfaceip = get_interface_ip($ifname);
4518
			$subnet_bits = get_interface_subnet($ifname);
4519
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4520
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4521
				return $ifname;
4522
		}
4523
		/* Check IPv6 */
4524
		if(is_ipaddrv6($carp_ipv6)) {
4525
			$interfaceipv6 = get_interface_ipv6($ifname);
4526
			$prefixlen = get_interface_subnetv6($ifname);
4527
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4528
				return $ifname;
4529
		}
4530
	}
4531
	return "";
4532
}
4533

    
4534

    
4535
/****f* interfaces/link_ip_to_carp_interface
4536
 * NAME
4537
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4538
 * INPUTS
4539
 *   $ip
4540
 * RESULT
4541
 *   $carp_ints
4542
 ******/
4543
function link_ip_to_carp_interface($ip) {
4544
	global $config;
4545

    
4546
	if (!is_ipaddr($ip))
4547
		return;
4548

    
4549
	$carp_ints = "";
4550
	if (is_array($config['virtualip']['vip'])) {
4551
		$first = 0;
4552
		$carp_int = array();
4553
		foreach ($config['virtualip']['vip'] as $vip) {
4554
			if ($vip['mode'] == "carp") {
4555
				$carp_ip = $vip['subnet'];
4556
				$carp_sn = $vip['subnet_bits'];
4557
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4558
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4559
					$carp_int[] = get_real_interface($vip['interface']);
4560
				}
4561
			}
4562
		}
4563
		if (!empty($carp_int))
4564
			$carp_ints = implode(" ", array_unique($carp_int));
4565
	}
4566

    
4567
	return $carp_ints;
4568
}
4569

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

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

    
4576
	if (is_array($config['interfaces'])) {
4577
		$list = array();
4578
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4579
			if (!isset($ifcfg['enable']))
4580
				continue;
4581
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4582
				if ($action == "update")
4583
					interface_track6_configure($ifname, $ifcfg);
4584
				else if ($action == "")
4585
					$list[$ifname] = $ifcfg;
4586
			}
4587
		}
4588
		return $list;
4589
	}
4590
}
4591

    
4592
function link_interface_to_vlans($int, $action = "") {
4593
	global $config;
4594

    
4595
	if (empty($int))
4596
		return;
4597

    
4598
	if (is_array($config['vlans']['vlan'])) {
4599
		$ifaces = array();
4600
		foreach ($config['vlans']['vlan'] as $vlan) {
4601
			if ($int == $vlan['if']) {
4602
				if ($action == "update") {
4603
					interfaces_bring_up($int);
4604
				} else if ($action == "")
4605
					$ifaces[$vlan['tag']] = $vlan;
4606
			}
4607
		}
4608
		if (!empty($ifaces))
4609
			return $ifaces;
4610
	}
4611
}
4612

    
4613
function link_interface_to_vips($int, $action = "") {
4614
	global $config;
4615

    
4616
	if (is_array($config['virtualip']['vip'])) {
4617
		$result = array();
4618
		foreach ($config['virtualip']['vip'] as $vip) {
4619
			if ($int == $vip['interface']) {
4620
				if ($action == "update")
4621
					interfaces_vips_configure($int);
4622
				else
4623
					$result[] = $vip;
4624
			}
4625
		}
4626
		return $result;
4627
	}
4628
}
4629

    
4630
/****f* interfaces/link_interface_to_bridge
4631
 * NAME
4632
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4633
 * INPUTS
4634
 *   $ip
4635
 * RESULT
4636
 *   bridge[0-99]
4637
 ******/
4638
function link_interface_to_bridge($int) {
4639
	global $config;
4640

    
4641
	if (is_array($config['bridges']['bridged'])) {
4642
		foreach ($config['bridges']['bridged'] as $bridge) {
4643
			if (in_array($int, explode(',', $bridge['members'])))
4644
				return "{$bridge['bridgeif']}";
4645
		}
4646
	}
4647
}
4648

    
4649
function link_interface_to_group($int) {
4650
	global $config;
4651

    
4652
	$result = array();
4653

    
4654
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4655
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4656
			if (in_array($int, explode(" ", $group['members'])))
4657
				$result[$group['ifname']] = $int;
4658
		}
4659
	}
4660

    
4661
	return $result;
4662
}
4663

    
4664
function link_interface_to_gre($interface) {
4665
	global $config;
4666

    
4667
	$result = array();
4668

    
4669
	if (is_array($config['gres']['gre'])) {
4670
		foreach ($config['gres']['gre'] as $gre)
4671
			if($gre['if'] == $interface)
4672
				$result[] = $gre;
4673
	}
4674

    
4675
	return $result;
4676
}
4677

    
4678
function link_interface_to_gif($interface) {
4679
	global $config;
4680

    
4681
	$result = array();
4682

    
4683
	if (is_array($config['gifs']['gif'])) {
4684
		foreach ($config['gifs']['gif'] as $gif)
4685
			if($gif['if'] == $interface)
4686
				$result[] = $gif;
4687
	}
4688

    
4689
	return $result;
4690
}
4691

    
4692
/*
4693
 * find_interface_ip($interface): return the interface ip (first found)
4694
 */
4695
function find_interface_ip($interface, $flush = false) {
4696
	global $interface_ip_arr_cache;
4697
	global $interface_sn_arr_cache;
4698

    
4699
	$interface = str_replace("\n", "", $interface);
4700

    
4701
	if (!does_interface_exist($interface))
4702
		return;
4703

    
4704
	/* Setup IP cache */
4705
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4706
		$ifinfo = pfSense_get_interface_addresses($interface);
4707
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4708
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4709
	}
4710

    
4711
	return $interface_ip_arr_cache[$interface];
4712
}
4713

    
4714
/*
4715
 * find_interface_ipv6($interface): return the interface ip (first found)
4716
 */
4717
function find_interface_ipv6($interface, $flush = false) {
4718
	global $interface_ipv6_arr_cache;
4719
	global $interface_snv6_arr_cache;
4720
	global $config;
4721

    
4722
	$interface = trim($interface);
4723
	$interface = get_real_interface($interface);
4724

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

    
4728
	/* Setup IP cache */
4729
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4730
		$ifinfo = pfSense_get_interface_addresses($interface);
4731
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4732
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4733
	}
4734

    
4735
	return $interface_ipv6_arr_cache[$interface];
4736
}
4737

    
4738
/*
4739
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4740
 */
4741
function find_interface_ipv6_ll($interface, $flush = false) {
4742
	global $interface_llv6_arr_cache;
4743
	global $config;
4744

    
4745
	$interface = str_replace("\n", "", $interface);
4746

    
4747
	if (!does_interface_exist($interface))
4748
		return;
4749

    
4750
	/* Setup IP cache */
4751
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4752
		$ifinfo = pfSense_getall_interface_addresses($interface);
4753
		foreach($ifinfo as $line) {
4754
			if (strstr($line, ":")) {
4755
				$parts = explode("/", $line);
4756
				if(is_linklocal($parts[0])) {
4757
					$ifinfo['linklocal'] = $parts[0];
4758
				}
4759
			}
4760
		}
4761
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4762
	}
4763
	return $interface_llv6_arr_cache[$interface];
4764
}
4765

    
4766
function find_interface_subnet($interface, $flush = false) {
4767
	global $interface_sn_arr_cache;
4768
	global $interface_ip_arr_cache;
4769

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

    
4774
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4775
		$ifinfo = pfSense_get_interface_addresses($interface);
4776
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4777
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4778
	}
4779

    
4780
	return $interface_sn_arr_cache[$interface];
4781
}
4782

    
4783
function find_interface_subnetv6($interface, $flush = false) {
4784
	global $interface_snv6_arr_cache;
4785
	global $interface_ipv6_arr_cache;
4786

    
4787
	$interface = str_replace("\n", "", $interface);
4788
	if (does_interface_exist($interface) == false)
4789
		return;
4790

    
4791
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4792
		$ifinfo = pfSense_get_interface_addresses($interface);
4793
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4794
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4795
	}
4796

    
4797
	return $interface_snv6_arr_cache[$interface];
4798
}
4799

    
4800
function ip_in_interface_alias_subnet($interface, $ipalias) {
4801
	global $config;
4802

    
4803
	if (empty($interface) || !is_ipaddr($ipalias))
4804
		return false;
4805
	if (is_array($config['virtualip']['vip'])) {
4806
		foreach ($config['virtualip']['vip'] as $vip) {
4807
			switch ($vip['mode']) {
4808
			case "ipalias":
4809
				if ($vip['interface'] <> $interface)
4810
					break;
4811
				$subnet = is_ipaddrv6($ipalias) ? gen_subnetv6($vip['subnet'], $vip['subnet_bits']) : gen_subnet($vip['subnet'], $vip['subnet_bits']);
4812
				if (ip_in_subnet($ipalias, $subnet . "/" . $vip['subnet_bits']))
4813
					return true;
4814
				break;
4815
			}
4816
		}
4817
	}
4818

    
4819
	return false;
4820
}
4821

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

    
4831
	$curip = find_interface_ip($realif);
4832
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4833
		return $curip;
4834
	else
4835
		return null;
4836
}
4837

    
4838
function get_interface_ipv6($interface = "wan", $flush = false) {
4839
	global $config;
4840

    
4841
	$realif = get_failover_interface($interface, "inet6");
4842
	if (!$realif) {
4843
		if (strstr($interface, "_vip"))
4844
			return get_configured_carp_interface_list($interface, "inet6");
4845
		else
4846
			return null;
4847
	}
4848

    
4849
	/*
4850
	 * NOTE: On the case when only the prefix is requested,
4851
	 * the communication on WAN will be done over link-local.
4852
	 */
4853
	if (is_array($config['interfaces'][$interface])) {
4854
		switch ($config['interfaces'][$interface]['ipaddr']) {
4855
		case 'pppoe':
4856
		case 'l2tp':
4857
		case 'pptp':
4858
		case 'ppp':
4859
			if ($config['interfaces'][$interface]['ipaddrv6'] == 'dhcp6')
4860
				$realif = get_real_interface($interface, "inet6", true);
4861
			break;
4862
		}
4863
		if (isset($config['interfaces'][$interface]['dhcp6prefixonly'])) {
4864
			$curip = find_interface_ipv6_ll($realif, $flush);
4865
			if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4866
				return $curip;
4867
		}
4868
	}
4869

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

    
4877
function get_interface_linklocal($interface = "wan") {
4878

    
4879
	$realif = get_failover_interface($interface, "inet6");
4880
	if (!$realif) {
4881
		if (strstr($interface, "_vip")) {
4882
			list($interface, $vhid) = explode("_vip", $interface);
4883
			$realif = get_real_interface($interface);
4884
		} else
4885
			return null;
4886
	}
4887

    
4888
	$curip = find_interface_ipv6_ll($realif);
4889
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4890
		return $curip;
4891
	else
4892
		return null;
4893
}
4894

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

    
4905
	$cursn = find_interface_subnet($realif);
4906
	if (!empty($cursn))
4907
		return $cursn;
4908

    
4909
	return null;
4910
}
4911

    
4912
function get_interface_subnetv6($interface = "wan") {
4913
	global $config;
4914

    
4915
	$realif = get_real_interface($interface, "inet6");
4916
	if (!$realif) {
4917
		if (strstr($interface, "_vip")) {
4918
			list($interface, $vhid) = explode("_vip", $interface);
4919
			$realif = get_real_interface($interface);
4920
		} else
4921
			return null;
4922
	}
4923

    
4924
	$cursn = find_interface_subnetv6($realif);
4925
	if (!empty($cursn))
4926
		return $cursn;
4927

    
4928
	return null;
4929
}
4930

    
4931
/* return outside interfaces with a gateway */
4932
function get_interfaces_with_gateway() {
4933
	global $config;
4934

    
4935
	$ints = array();
4936

    
4937
	/* loop interfaces, check config for outbound */
4938
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4939
		switch ($ifname['ipaddr']) {
4940
			case "dhcp":
4941
			case "ppp";
4942
			case "pppoe":
4943
			case "pptp":
4944
			case "l2tp":
4945
			case "ppp";
4946
				$ints[$ifdescr] = $ifdescr;
4947
			break;
4948
			default:
4949
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4950
				    !empty($ifname['gateway']))
4951
					$ints[$ifdescr] = $ifdescr;
4952
			break;
4953
		}
4954
	}
4955
	return $ints;
4956
}
4957

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

    
4962
	if (!empty($config['interfaces'][$friendly])) {
4963
		$ifname = &$config['interfaces'][$friendly];
4964
		switch ($ifname['ipaddr']) {
4965
			case "dhcp":
4966
			case "pppoe":
4967
			case "pptp":
4968
			case "l2tp":
4969
			case "ppp";
4970
				return true;
4971
			break;
4972
			default:
4973
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4974
					return true;
4975
				$tunnelif = substr($ifname['if'], 0, 3);
4976
				if ($tunnelif == "gif" || $tunnelif == "gre")
4977
					return true;
4978
				if (!empty($ifname['gateway']))
4979
					return true;
4980
			break;
4981
		}
4982
	}
4983

    
4984
	return false;
4985
}
4986

    
4987
/* return true if interface has a gateway */
4988
function interface_has_gatewayv6($friendly) {
4989
	global $config;
4990

    
4991
	if (!empty($config['interfaces'][$friendly])) {
4992
		$ifname = &$config['interfaces'][$friendly];
4993
		switch ($ifname['ipaddrv6']) {
4994
			case "slaac":
4995
			case "dhcp6":
4996
			case "6to4":
4997
			case "6rd":
4998
				return true;
4999
				break;
5000
			default:
5001
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
5002
					return true;
5003
				$tunnelif = substr($ifname['if'], 0, 3);
5004
				if ($tunnelif == "gif" || $tunnelif == "gre")
5005
					return true;
5006
				if (!empty($ifname['gatewayv6']))
5007
					return true;
5008
				break;
5009
		}
5010
	}
5011

    
5012
	return false;
5013
}
5014

    
5015
/****f* interfaces/is_altq_capable
5016
 * NAME
5017
 *   is_altq_capable - Test if interface is capable of using ALTQ
5018
 * INPUTS
5019
 *   $int            - string containing interface name
5020
 * RESULT
5021
 *   boolean         - true or false
5022
 ******/
5023

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

    
5037
	$int_family = remove_ifindex($int);
5038

    
5039
	if (in_array($int_family, $capable))
5040
		return true;
5041
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
5042
		return true;
5043
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
5044
		return true;
5045
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
5046
		return true;
5047
	else
5048
		return false;
5049
}
5050

    
5051
/****f* interfaces/is_interface_wireless
5052
 * NAME
5053
 *   is_interface_wireless - Returns if an interface is wireless
5054
 * RESULT
5055
 *   $tmp       - Returns if an interface is wireless
5056
 ******/
5057
function is_interface_wireless($interface) {
5058
	global $config, $g;
5059

    
5060
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
5061
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
5062
		if (preg_match($g['wireless_regex'], $interface)) {
5063
			if (isset($config['interfaces'][$friendly]))
5064
				$config['interfaces'][$friendly]['wireless'] = array();
5065
			return true;
5066
		}
5067
		return false;
5068
	} else
5069
		return true;
5070
}
5071

    
5072
function get_wireless_modes($interface) {
5073
	/* return wireless modes and channels */
5074
	$wireless_modes = array();
5075

    
5076
	$cloned_interface = get_real_interface($interface);
5077

    
5078
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5079
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
5080
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5081
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
5082

    
5083
		$interface_channels = "";
5084
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5085
		$interface_channel_count = count($interface_channels);
5086

    
5087
		$c = 0;
5088
		while ($c < $interface_channel_count) {
5089
			$channel_line = explode(",", $interface_channels["$c"]);
5090
			$wireless_mode = trim($channel_line[0]);
5091
			$wireless_channel = trim($channel_line[1]);
5092
			if(trim($wireless_mode) != "") {
5093
				/* if we only have 11g also set 11b channels */
5094
				if($wireless_mode == "11g") {
5095
					if(!isset($wireless_modes["11b"]))
5096
						$wireless_modes["11b"] = array();
5097
				} else if($wireless_mode == "11g ht") {
5098
					if(!isset($wireless_modes["11b"]))
5099
						$wireless_modes["11b"] = array();
5100
					if(!isset($wireless_modes["11g"]))
5101
						$wireless_modes["11g"] = array();
5102
					$wireless_mode = "11ng";
5103
				} else if($wireless_mode == "11a ht") {
5104
					if(!isset($wireless_modes["11a"]))
5105
						$wireless_modes["11a"] = array();
5106
					$wireless_mode = "11na";
5107
				}
5108
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
5109
			}
5110
			$c++;
5111
		}
5112
	}
5113
	return($wireless_modes);
5114
}
5115

    
5116
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5117
function get_wireless_channel_info($interface) {
5118
	$wireless_channels = array();
5119

    
5120
	$cloned_interface = get_real_interface($interface);
5121

    
5122
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5123
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5124
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5125
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5126

    
5127
		$interface_channels = "";
5128
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5129

    
5130
		foreach ($interface_channels as $channel_line) {
5131
			$channel_line = explode(",", $channel_line);
5132
			if(!isset($wireless_channels[$channel_line[0]]))
5133
				$wireless_channels[$channel_line[0]] = $channel_line;
5134
		}
5135
	}
5136
	return($wireless_channels);
5137
}
5138

    
5139
/****f* interfaces/get_interface_mtu
5140
 * NAME
5141
 *   get_interface_mtu - Return the mtu of an interface
5142
 * RESULT
5143
 *   $tmp       - Returns the mtu of an interface
5144
 ******/
5145
function get_interface_mtu($interface) {
5146
	$mtu = pfSense_get_interface_addresses($interface);
5147
	return $mtu['mtu'];
5148
}
5149

    
5150
function get_interface_mac($interface) {
5151

    
5152
	$macinfo = pfSense_get_interface_addresses($interface);
5153
	return $macinfo["macaddr"];
5154
}
5155

    
5156
/****f* pfsense-utils/generate_random_mac_address
5157
 * NAME
5158
 *   generate_random_mac - generates a random mac address
5159
 * INPUTS
5160
 *   none
5161
 * RESULT
5162
 *   $mac - a random mac address
5163
 ******/
5164
function generate_random_mac_address() {
5165
	$mac = "02";
5166
	for($x=0; $x<5; $x++)
5167
		$mac .= ":" . dechex(rand(16, 255));
5168
	return $mac;
5169
}
5170

    
5171
/****f* interfaces/is_jumbo_capable
5172
 * NAME
5173
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5174
 * INPUTS
5175
 *   $int             - string containing interface name
5176
 * RESULT
5177
 *   boolean          - true or false
5178
 ******/
5179
function is_jumbo_capable($iface) {
5180
	$iface = trim($iface);
5181
	$capable = pfSense_get_interface_addresses($iface);
5182

    
5183
	if (isset($capable['caps']['vlanmtu']))
5184
		return true;
5185

    
5186
	return false;
5187
}
5188

    
5189
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5190
	global $g;
5191

    
5192
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5193

    
5194
	if(!empty($iface) && !empty($pppif)){
5195
		$cron_cmd = <<<EOD
5196
#!/bin/sh
5197
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5198
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5199

    
5200
EOD;
5201

    
5202
		@file_put_contents($cron_file, $cron_cmd);
5203
		chmod($cron_file, 0755);
5204
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5205
	} else
5206
		unlink_if_exists($cron_file);
5207
}
5208

    
5209
function get_interface_default_mtu($type = "ethernet") {
5210
	switch ($type) {
5211
	case "gre":
5212
		return 1476;
5213
		break;
5214
	case "gif":
5215
		return 1280;
5216
		break;
5217
	case "tun":
5218
	case "vlan":
5219
	case "tap":
5220
	case "ethernet":
5221
	default:
5222
		return 1500;
5223
		break;
5224
	}
5225

    
5226
	/* Never reached */
5227
	return 1500;
5228
}
5229

    
5230
function get_vip_descr($ipaddress) {
5231
	global $config;
5232

    
5233
	foreach ($config['virtualip']['vip'] as $vip) {
5234
		if ($vip['subnet'] == $ipaddress) {
5235
			return ($vip['descr']);
5236
		}
5237
	}
5238
	return "";
5239
}
5240

    
5241
function interfaces_staticarp_configure($if) {
5242
	global $config, $g;
5243
	if(isset($config['system']['developerspew'])) {
5244
		$mt = microtime();
5245
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5246
	}
5247

    
5248
	$ifcfg = $config['interfaces'][$if];
5249

    
5250
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5251
		return 0;
5252

    
5253
	/* Enable staticarp, if enabled */
5254
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5255
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5256
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5257
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5258

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

    
5262
			}
5263

    
5264
		}
5265
	} else {
5266
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5267
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5268
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5269
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5270
				if (isset($arpent['arp_table_static_entry'])) {
5271
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5272
				}
5273
			}
5274
		}
5275
	}
5276

    
5277
	return 0;
5278
}
5279

    
5280
function get_failover_interface($interface, $family = "all") {
5281
	global $config;
5282

    
5283
	/* shortcut to get_real_interface if we find it in the config */
5284
	if (is_array($config['interfaces'][$interface])) {
5285
		return get_real_interface($interface, $family);
5286
	}
5287

    
5288
	/* compare against gateway groups */
5289
	$a_groups = return_gateway_groups_array();
5290
	if (is_array($a_groups[$interface])) {
5291
		/* we found a gateway group, fetch the interface or vip */
5292
		if ($a_groups[$interface][0]['vip'] <> "")
5293
			return $a_groups[$interface][0]['vip'];
5294
		else
5295
			return $a_groups[$interface][0]['int'];
5296
	}
5297
	/* fall through to get_real_interface */
5298
	/* XXX: Really needed? */
5299
	return get_real_interface($interface, $family);
5300
}
5301

    
5302
function remove_ifindex($ifname) {
5303
	return preg_replace("/[0-9]+$/", "", $ifname);
5304
}
5305

    
5306
?>
(25-25/67)