Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
68
	return $interface_arr_cache;
69
}
70

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

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

    
81
	$ints = get_interface_arr(true);
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
		$realif = "{$vip['interface']}_vip{$vip['vhid']}";
102
		if (!does_interface_exist($realif)) {
103
			return false;
104
		}
105
		break;
106
	case "ipalias":
107
		$realif = get_real_interface($vip['interface']);
108
		if (!does_interface_exist($realif)) {
109
			return false;
110
		}
111
		break;
112
	case "proxyarp":
113
		/* XXX: Implement this */
114
	default:
115
		return false;
116
	}
117

    
118
	$ifacedata = pfSense_getall_interface_addresses($realif);
119
	foreach ($ifacedata as $vipips) {
120
		if ($vipips == "{$vip['subnet']}/{$vip['subnet_bits']}")
121
			return true;
122
	}
123

    
124
	return false;
125
}
126

    
127
function interface_netgraph_needed($interface = "wan") {
128
	global $config;
129

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

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

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

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

    
206
function interfaces_loopback_configure() {
207
	global $g;
208

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

    
220
function interfaces_vlan_configure() {
221
	global $config, $g;
222
	if($g['booting'])
223
		echo gettext("Configuring VLAN interfaces...");
224
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
225
		foreach ($config['vlans']['vlan'] as $vlan) {
226
			if(empty($vlan['vlanif']))
227
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
228
			/* XXX: Maybe we should report any errors?! */
229
			interface_vlan_configure($vlan);
230
		}
231
	}
232
	if($g['booting'])
233
		echo gettext("done.") . "\n";
234
}
235

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

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

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

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

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

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

    
267
	interfaces_bring_up($vlanif);
268

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

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

    
275
	return $vlanif;
276
}
277

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

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

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

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

    
298
	$vlanif = interface_vlan_configure($vlan);
299

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

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

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

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

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

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

    
351
	return $vlanif;
352
}
353

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

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

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

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

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

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

    
394
	return $vlanif;
395
}
396

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

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

    
403
	$iflist = get_configured_interface_list();
404

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

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

    
424
}
425

    
426
function interfaces_bridge_configure($checkmember = 0) {
427
	global $config;
428

    
429
	$i = 0;
430
	if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
431
		foreach ($config['bridges']['bridged'] as $bridge) {
432
			if(empty($bridge['bridgeif']))
433
				$bridge['bridgeif'] = "bridge{$i}";
434
			/* XXX: Maybe we should report any errors?! */
435
			interface_bridge_configure($bridge, $checkmember);
436
			$i++;
437
		}
438
	}
439
}
440

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

    
444
	if (!is_array($bridge))
445
		return;
446

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

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

    
456
	/* Calculate smaller mtu and enforce it */
457
	$smallermtu = 0;
458
	$commonrx = true;
459
	$commontx = true;
460
	$foundgif = false;
461
	foreach ($members as $member) {
462
		$realif = get_real_interface($member);
463
		$opts = pfSense_get_interface_addresses($realif);
464
		$mtu = $opts['mtu'];
465
		if (substr($realif, 0, 3) == "gif") {
466
			$foundgif = true;
467
			if ($checkmember == 1)
468
				return;
469
			if ($mtu <= 1500)
470
				continue;
471
		}
472
		if (!isset($opts['encaps']['txcsum']))
473
			$commontx = false;
474
		if (!isset($opts['encaps']['rxcsum']))
475
			$commonrx = false;
476
		if (!isset($opts['encaps']['tso4']))
477
			$commontso4 = false;
478
		if (!isset($opts['encaps']['tso6']))
479
			$commontso6 = false;
480
		if (!isset($opts['encaps']['lro']))
481
			$commonlro = false;
482
		if ($smallermtu == 0 && !empty($mtu))
483
			$smallermtu = $mtu;
484
		else if (!empty($mtu) && $mtu < $smallermtu)
485
			$smallermtu = $mtu;
486
	}
487
	if ($foundgif == false && $checkmember == 2)
488
		return;
489

    
490
	/* Just in case anything is not working well */
491
	if ($smallermtu == 0)
492
		$smallermtu = 1500;
493

    
494
	$flags = 0;
495
	if ($commonrx === false)
496
		$flags |= IFCAP_RXCSUM;
497
	if ($commontx === false)
498
		$flags |= IFCAP_TXCSUM;
499
	if ($commontso4 === false)
500
		$flags |= IFCAP_TSO4;
501
	if ($commontso6 === false)
502
		$flags |= IFCAP_TSO6;
503
	if ($commonlro === false)
504
		$flags |= IFCAP_LRO;
505

    
506
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
507
		pfSense_interface_destroy($bridge['bridgeif']);
508
		pfSense_interface_create($bridge['bridgeif']);
509
		$bridgeif = escapeshellarg($bridge['bridgeif']);
510
	} else {
511
		$bridgeif = pfSense_interface_create("bridge");
512
		$bridge['bridgeif'] = $bridgeif;
513
	}
514

    
515
	$checklist = get_configured_interface_list();
516

    
517
	/* Add interfaces to bridge */
518
	foreach ($members as $member) {
519
		if (empty($checklist[$member]))
520
			continue;
521
		$realif = get_real_interface($member);
522
		if (!$realif) {
523
			log_error(gettext("realif not defined in interfaces bridge - up"));
524
			continue;
525
		}
526
		/* make sure the parent interface is up */
527
		pfSense_interface_mtu($realif, $smallermtu);
528
		pfSense_interface_capabilities($realif, -$flags);
529
		interfaces_bring_up($realif);
530
		pfSense_bridge_add_member($bridge['bridgeif'], $realif);
531
	}
532

    
533
	if (isset($bridge['enablestp'])) {
534
		/* Choose spanning tree proto */
535
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
536

    
537
		if (!empty($bridge['stp'])) {
538
			$stpifs = explode(',', $bridge['stp']);
539
			foreach ($stpifs as $stpif) {
540
				$realif = get_real_interface($stpif);
541
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
542
			}
543
		}
544
		if (!empty($bridge['maxage']))
545
			mwexec("/sbin/ifconfig {$bridgeif} maxage " . escapeshellarg($bridge['maxage']));
546
		if (!empty($bridge['fwdelay']))
547
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay " . escapeshellarg($bridge['fwdelay']));
548
		if (!empty($bridge['hellotime']))
549
			mwexec("/sbin/ifconfig {$bridgeif} hellotime " . escapeshellarg($bridge['hellotime']));
550
		if (!empty($bridge['priority']))
551
			mwexec("/sbin/ifconfig {$bridgeif} priority " . escapeshellarg($bridge['priority']));
552
		if (!empty($bridge['holdcnt']))
553
			mwexec("/sbin/ifconfig {$bridgeif} holdcnt " . escapeshellarg($bridge['holdcnt']));
554
		if (!empty($bridge['ifpriority'])) {
555
			$pconfig = explode(",", $bridge['ifpriority']);
556
			$ifpriority = array();
557
			foreach ($pconfig as $cfg) {
558
				$embcfg = explode_assoc(":", $cfg);
559
				foreach ($embcfg as $key => $value)
560
					$ifpriority[$key] = $value;
561
			}
562
			foreach ($ifpriority as $key => $value) {
563
				$realif = get_real_interface($key);
564
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} " . escapeshellarg($value));
565
			}
566
		}
567
		if (!empty($bridge['ifpathcost'])) {
568
			$pconfig = explode(",", $bridge['ifpathcost']);
569
			$ifpathcost = array();
570
			foreach ($pconfig as $cfg) {
571
				$embcfg = explode_assoc(":", $cfg);
572
				foreach ($embcfg as $key => $value)
573
					$ifpathcost[$key] = $value;
574
			}
575
			foreach ($ifpathcost as $key => $value) {
576
				$realif = get_real_interface($key);
577
				mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} " . escapeshellarg($value));
578
			}
579
		}
580
	}
581

    
582
	if ($bridge['maxaddr'] <> "")
583
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
584
	if ($bridge['timeout'] <> "")
585
		mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
586
	if ($bridge['span'] <> "") {
587
		$realif = get_real_interface($bridge['span']);
588
		mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
589
	}
590
	if (!empty($bridge['edge'])) {
591
		$edgeifs = explode(',', $bridge['edge']);
592
		foreach ($edgeifs as $edgeif) {
593
			$realif = get_real_interface($edgeif);
594
			mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
595
		}
596
	}
597
	if (!empty($bridge['autoedge'])) {
598
		$edgeifs = explode(',', $bridge['autoedge']);
599
		foreach ($edgeifs as $edgeif) {
600
			$realif = get_real_interface($edgeif);
601
			mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
602
		}
603
	}
604
	if (!empty($bridge['ptp'])) {
605
		$ptpifs = explode(',', $bridge['ptp']);
606
		foreach ($ptpifs as $ptpif) {
607
			$realif = get_real_interface($ptpif);
608
			mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
609
		}
610
	}
611
	if (!empty($bridge['autoptp'])) {
612
		$ptpifs = explode(',', $bridge['autoptp']);
613
		foreach ($ptpifs as $ptpif) {
614
			$realif = get_real_interface($ptpif);
615
			mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
616
		}
617
	}
618
	if (!empty($bridge['static'])) {
619
		$stickyifs = explode(',', $bridge['static']);
620
		foreach ($stickyifs as $stickyif) {
621
			$realif = get_real_interface($stickyif);
622
			mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
623
		}
624
	}
625
	if (!empty($bridge['private'])) {
626
		$privateifs = explode(',', $bridge['private']);
627
		foreach ($privateifs as $privateif) {
628
			$realif = get_real_interface($privateif);
629
			mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
630
		}
631
	}
632

    
633
	if ($bridge['bridgeif'])
634
		interfaces_bring_up($bridge['bridgeif']);
635
	else
636
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
637
}
638

    
639
function interface_bridge_add_member($bridgeif, $interface) {
640

    
641
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
642
		return;
643

    
644
	$mtu = get_interface_mtu($bridgeif);
645
	$mtum = get_interface_mtu($interface);
646

    
647
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
648
		pfSense_interface_mtu($interface, $mtu);
649

    
650
	$options = pfSense_get_interface_addresses($bridgeif);
651
	$flags = 0;
652
	if (!isset($options['encaps']['txcsum']))
653
		$flags |= IFCAP_TXCSUM;
654

    
655
	if (!isset($options['encaps']['rxcsum']))
656
		$flags |= IFCAP_RXCSUM;
657

    
658
	pfSense_interface_capabilities($interface, -$flags);
659

    
660
	interfaces_bring_up($interface);
661
	pfSense_bridge_add_member($bridgeif, $interface);
662
}
663

    
664
function interfaces_lagg_configure() {
665
	global $config, $g;
666
	if($g['booting'])
667
		echo gettext("Configuring LAGG interfaces...");
668
	$i = 0;
669
	if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
670
		foreach ($config['laggs']['lagg'] as $lagg) {
671
			if(empty($lagg['laggif']))
672
				$lagg['laggif'] = "lagg{$i}";
673
			/* XXX: Maybe we should report any errors?! */
674
			interface_lagg_configure($lagg);
675
			$i++;
676
		}
677
	}
678
	if($g['booting'])
679
		echo gettext("done.") . "\n";
680
}
681

    
682
function interface_lagg_configure(&$lagg) {
683
	global $config, $g;
684

    
685
	if (!is_array($lagg))
686
		return -1;
687

    
688
	$members = explode(',', $lagg['members']);
689
	if (!count($members))
690
		return -1;
691

    
692
	if ($g['booting'] || !(empty($lagg['laggif']))) {
693
		pfSense_interface_destroy($lagg['laggif']);
694
		pfSense_interface_create($lagg['laggif']);
695
		$laggif = $lagg['laggif'];
696
	} else
697
		$laggif = pfSense_interface_create("lagg");
698

    
699
	/* Calculate smaller mtu and enforce it */
700
	$smallermtu = 0;
701
	foreach ($members as $member) {
702
		$opts = pfSense_get_interface_addresses($member);
703
		$mtu = $opts['mtu'];
704
		if (!isset($opts['encaps']['txcsum']))
705
			$commontx = false;
706
		if (!isset($opts['encaps']['rxcsum']))
707
			$commonrx = false;
708
		if (!isset($opts['encaps']['tso4']))
709
			$commontso4 = false;
710
		if (!isset($opts['encaps']['tso6']))
711
			$commontso6 = false;
712
		if (!isset($opts['encaps']['lro']))
713
			$commonlro = false;
714
		if ($smallermtu == 0 && !empty($mtu))
715
			$smallermtu = $mtu;
716
		else if (!empty($mtu) && $mtu < $smallermtu)
717
			$smallermtu = $mtu;
718
	}
719

    
720
	/* Just in case anything is not working well */
721
	if ($smallermtu == 0)
722
		$smallermtu = 1500;
723

    
724
	$flags = 0;
725
	if ($commonrx === false)
726
		$flags |= IFCAP_RXCSUM;
727
	if ($commontx === false)
728
		$flags |= IFCAP_TXCSUM;
729
	if ($commontso4 === false)
730
		$flags |= IFCAP_TSO4;
731
	if ($commontso6 === false)
732
		$flags |= IFCAP_TSO6;
733
	if ($commonlro === false)
734
		$flags |= IFCAP_LRO;
735

    
736
	$checklist = get_interface_list();
737

    
738
	foreach ($members as $member) {
739
		if (!array_key_exists($member, $checklist))
740
			continue;
741
		/* make sure the parent interface is up */
742
		pfSense_interface_mtu($member, $smallermtu);
743
		pfSense_interface_capabilities($member, -$flags);
744
		interfaces_bring_up($member);
745
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
746
	}
747

    
748
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
749

    
750
	interfaces_bring_up($laggif);
751

    
752
	return $laggif;
753
}
754

    
755
function interfaces_gre_configure($checkparent = 0) {
756
	global $config;
757

    
758
	if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
759
		foreach ($config['gres']['gre'] as $i => $gre) {
760
			if(empty($gre['greif']))
761
				$gre['greif'] = "gre{$i}";
762
			if ($checkparent == 1 && strstr($gre['if'], "_vip"))
763
				continue;
764
			if ($checkparent == 2 && !strstr($gre['if'], "_vip"))
765
				continue;
766
			/* XXX: Maybe we should report any errors?! */
767
			interface_gre_configure($gre);
768
		}
769
	}
770
}
771

    
772
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
773
function interface_gre_configure(&$gre, $grekey = "") {
774
	global $config, $g;
775

    
776
	if (!is_array($gre))
777
		return -1;
778

    
779
	$realif = get_real_interface($gre['if']);
780
	$realifip = get_interface_ip($gre['if']);
781

    
782
	/* make sure the parent interface is up */
783
	interfaces_bring_up($realif);
784

    
785
	if ($g['booting'] || !(empty($gre['greif']))) {
786
		pfSense_interface_destroy($gre['greif']);
787
		pfSense_interface_create($gre['greif']);
788
		$greif = $gre['greif'];
789
	} else
790
		$greif = pfSense_interface_create("gre");
791

    
792
	/* Do not change the order here for more see gre(4) NOTES section. */
793
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
794
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
795
		mwexec("/sbin/ifconfig {$greif} inet6 {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} prefixlen /{$gre['tunnel-remote-net']} ");
796
	} else {
797
		mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
798
	}
799
	if (isset($gre['link0']) && $gre['link0'])
800
		pfSense_interface_flags($greif, IFF_LINK0);
801
	if (isset($gre['link1']) && $gre['link1'])
802
		pfSense_interface_flags($greif, IFF_LINK1);
803
	if (isset($gre['link2']) && $gre['link2'])
804
		pfSense_interface_flags($greif, IFF_LINK2);
805

    
806
	if($greif)
807
		interfaces_bring_up($greif);
808
	else
809
		log_error(gettext("Could not bring greif up -- variable not defined."));
810

    
811
	if (isset($gre['link1']) && $gre['link1'])
812
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
813
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
814
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
815
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
816
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
817

    
818
	return $greif;
819
}
820

    
821
function interfaces_gif_configure($checkparent = 0) {
822
	global $config;
823

    
824
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
825
		foreach ($config['gifs']['gif'] as $i => $gif) {
826
			if(empty($gif['gifif']))
827
				$gre['gifif'] = "gif{$i}";
828
			if ($checkparent == 1 && strstr($gif['if'], "_vip"))
829
				continue;
830
			if ($checkparent == 2 && !strstr($gif['if'], "_vip"))
831
				continue;
832
			/* XXX: Maybe we should report any errors?! */
833
			interface_gif_configure($gif);
834
		}
835
	}
836
}
837

    
838
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
839
function interface_gif_configure(&$gif, $gifkey = "") {
840
	global $config, $g;
841

    
842
	if (!is_array($gif))
843
		return -1;
844

    
845
	$realif = get_real_interface($gif['if']);
846
	$ipaddr = $gif['ipaddr'];
847

    
848
	if (is_ipaddrv4($gif['remote-addr'])) {
849
		if (is_ipaddrv4($ipaddr))
850
			$realifip = $ipaddr;
851
		else
852
			$realifip = get_interface_ip($gif['if']);
853
		$realifgw = get_interface_gateway($gif['if']);
854
	} else if (is_ipaddrv6($gif['remote-addr'])) {
855
		if (is_ipaddrv6($ipaddr))
856
			$realifip = $ipaddr;
857
		else
858
			$realifip = get_interface_ipv6($gif['if']);
859
		$realifgw = get_interface_gatewayv6($gif['if']);
860
	}
861
	/* make sure the parent interface is up */
862
	if($realif)
863
		interfaces_bring_up($realif);
864
	else
865
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
866

    
867
	if ($g['booting'] || !(empty($gif['gifif']))) {
868
		pfSense_interface_destroy($gif['gifif']);
869
		pfSense_interface_create($gif['gifif']);
870
		$gifif = $gif['gifif'];
871
	} else
872
		$gifif = pfSense_interface_create("gif");
873

    
874
	/* Do not change the order here for more see gif(4) NOTES section. */
875
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
876
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
877
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen /{$gif['tunnel-remote-net']} ");
878
	} else {
879
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
880
	}
881
	if (isset($gif['link0']) && $gif['link0'])
882
		pfSense_interface_flags($gifif, IFF_LINK0);
883
	if (isset($gif['link1']) && $gif['link1'])
884
		pfSense_interface_flags($gifif, IFF_LINK1);
885
	if($gifif)
886
		interfaces_bring_up($gifif);
887
	else
888
		log_error(gettext("could not bring gifif up -- variable not defined"));
889

    
890
	$iflist = get_configured_interface_list();
891
	foreach($iflist as $ifname) {
892
		if($config['interfaces'][$ifname]['if'] == $gifif) {
893
			if(get_interface_gateway($ifname)) {
894
				system_routing_configure($ifname);
895
				break;
896
			}
897
			if(get_interface_gateway_v6($ifname)) {
898
				system_routing_configure($ifname);
899
				break;
900
			}
901
		}
902
	}
903

    
904

    
905
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
906
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
907
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
908
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
909

    
910
	if (is_ipaddrv4($realifgw)) {
911
		mwexec("route change -host {$gif['remote-addr']} {$realifgw}");
912
	}
913
	if (is_ipaddrv6($realifgw)) {
914
		mwexec("route change -host -inet6 {$gif['remote-addr']} {$realifgw}");
915
	}
916

    
917
	return $gifif;
918
}
919

    
920
function interfaces_configure() {
921
	global $config, $g;
922

    
923
	if ($g['platform'] == 'jail')
924
		return;
925

    
926
	/* Set up our loopback interface */
927
	interfaces_loopback_configure();
928

    
929
	/* create the unconfigured wireless clones */
930
	interfaces_create_wireless_clones();
931

    
932
	/* set up LAGG virtual interfaces */
933
	interfaces_lagg_configure();
934

    
935
	/* set up VLAN virtual interfaces */
936
	interfaces_vlan_configure();
937

    
938
	interfaces_qinq_configure();
939

    
940
	$iflist = get_configured_interface_with_descr();
941
	$delayed_list = array();
942
	$bridge_list = array();
943

    
944
	/* This is needed to speedup interfaces on bootup. */
945
	$reload = false;
946
	if (!$g['booting'])
947
		$reload = true;
948

    
949
	foreach($iflist as $if => $ifname) {
950
		$realif = $config['interfaces'][$if]['if'];
951
		if (strstr($realif, "bridge"))
952
			$bridge_list[$if] = $ifname;
953
		else if (strstr($realif, "gre"))
954
			$delayed_list[$if] = $ifname;
955
		else if (strstr($realif, "gif"))
956
			$delayed_list[$if] = $ifname;
957
		else if (strstr($realif, "ovpn")) {
958
			//echo "Delaying OpenVPN interface configuration...done.\n";
959
			continue;
960
		} else {
961
			if ($g['booting'])
962
				printf(gettext("Configuring %s interface..."), $ifname);
963

    
964
			if($g['debug'])
965
				log_error(sprintf(gettext("Configuring %s"), $ifname));
966
			interface_configure($if, $reload);
967
			if ($g['booting'])
968
				echo gettext( "done.") . "\n";
969
		}
970
	}
971

    
972
	/*
973
	 * NOTE: The following function parameter consists of
974
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
975
	 *	2 - Do load gre/gif/bridge with parent/member as vip
976
	 */
977

    
978
	/* set up GRE virtual interfaces */
979
	interfaces_gre_configure(1);
980

    
981
	/* set up GIF virtual interfaces */
982
	interfaces_gif_configure(1);
983

    
984
	/* set up BRIDGe virtual interfaces */
985
	interfaces_bridge_configure(1);
986

    
987
	/* bring up vip interfaces */
988
	interfaces_vips_configure();
989

    
990
	/* set up GRE virtual interfaces */
991
	interfaces_gre_configure(2);
992

    
993
	/* set up GIF virtual interfaces */
994
	interfaces_gif_configure(2);
995

    
996
	foreach ($delayed_list as $if => $ifname) {
997
		if ($g['booting'])
998
			printf(gettext("Configuring %s interface..."), $ifname);
999
		if ($g['debug'])
1000
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1001

    
1002
		interface_configure($if, $reload);
1003

    
1004
		if ($g['booting'])
1005
			echo gettext("done.") . "\n";
1006
	}
1007

    
1008
	/* set up BRIDGe virtual interfaces */
1009
	interfaces_bridge_configure(2);
1010

    
1011
	foreach ($bridge_list as $if => $ifname) {
1012
		if ($g['booting'])
1013
			printf(gettext("Configuring %s interface..."), $ifname);
1014
		if($g['debug'])
1015
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1016

    
1017
		interface_configure($if, $reload);
1018

    
1019
		if ($g['booting'])
1020
			echo gettext("done.") . "\n";
1021
	}
1022

    
1023
	/* configure interface groups */
1024
	interfaces_group_setup();
1025

    
1026
	if (!$g['booting']) {
1027
		/* reconfigure static routes (kernel may have deleted them) */
1028
		system_routing_configure();
1029

    
1030
		/* reload IPsec tunnels */
1031
		vpn_ipsec_configure();
1032

    
1033
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1034
		services_dhcpd_configure();
1035

    
1036
		/* restart dnsmasq */
1037
		services_dnsmasq_configure();
1038

    
1039
		/* reload captive portal */
1040
		if (function_exists('captiveportal_init_rules'))
1041
			captiveportal_init_rules();
1042
	}
1043

    
1044
	return 0;
1045
}
1046

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

    
1052
function interface_vip_bring_down($vip) {
1053
	global $g;
1054

    
1055
	switch ($vip['mode']) {
1056
	case "proxyarp":
1057
		$vipif = get_real_interface($vip['interface']);
1058
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1059
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1060
		break;
1061
	case "ipalias":
1062
		$vipif = get_real_interface($vip['interface']);
1063
		if (does_interface_exist($vipif)) {
1064
			if (is_ipaddrv6($vip['subnet']))
1065
				mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} -alias");
1066
			else
1067
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1068
		}
1069
		break;
1070
	case "carp":
1071
		$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
1072
		if (does_interface_exist($vipif))
1073
			pfSense_interface_destroy($vipif);
1074
		break;
1075
	}
1076
}
1077

    
1078
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1079
	global $config, $g;
1080

    
1081
	if (!isset($config['interfaces'][$interface]))
1082
		return;
1083

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

    
1087
	if ($ifacecfg === false)
1088
		$ifcfg = $config['interfaces'][$interface];
1089
	else if (!is_array($ifacecfg))
1090
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1091
	else
1092
		$ifcfg = $ifacecfg;
1093
		
1094

    
1095
	$realif = get_real_interface($interface);
1096

    
1097
	switch ($ifcfg['ipaddr']) {
1098
	case "ppp":
1099
	case "pppoe":
1100
	case "pptp":
1101
	case "l2tp":
1102
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1103
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1104
				if ($realif == $ppp['if']) {
1105
					if (isset($ppp['ondemand']) && !$destroy){
1106
						send_event("interface reconfigure {$interface}");
1107
						break;
1108
					}
1109
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1110
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1111
						sleep(2);
1112
					}
1113
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1114
					break;
1115
				}
1116
			}
1117
		}
1118
		break;
1119
	case "dhcp":
1120
		$pid = find_dhclient_process($realif);
1121
		if($pid)
1122
			mwexec("/bin/kill {$pid}");
1123
		sleep(1);
1124
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1125
		if(does_interface_exist("$realif")) {
1126
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1127
			if ($destroy == true)
1128
				pfSense_interface_flags($realif, -IFF_UP);
1129
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1130
		}
1131
		break;
1132
	default:
1133
		if(does_interface_exist("$realif")) {
1134
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1135
			if ($destroy == true)
1136
				pfSense_interface_flags($realif, -IFF_UP);
1137
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1138
		}
1139
		break;
1140
	}
1141

    
1142
	switch ($ifcfg['ipaddrv6']) {
1143
	case "slaac":
1144
	case "dhcp6":
1145
		$pidv6 = find_dhcp6c_process($realif);
1146
		if($pidv6)
1147
			mwexec("/bin/kill {$pidv6}");
1148
		sleep(3);
1149
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1150
		if (does_interface_exist("$realif")) {
1151
			$ip6 = get_interface_ipv6($interface);
1152
			if (is_ipaddrv6($ip6))
1153
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1154
			if ($destroy == true)
1155
				pfSense_interface_flags($realif, -IFF_UP);
1156
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1157
		}
1158
		break;
1159
	case "6rd":
1160
	case "6to4":
1161
		$realif = "stf0";
1162
		if(does_interface_exist("$realif")) {
1163
			$ip6 = get_interface_ipv6($interface);
1164
			if (is_ipaddrv6($ip6))
1165
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1166
			if ($destroy == true)
1167
				pfSense_interface_flags($realif, -IFF_UP);
1168
		}
1169
		break;
1170
	default:
1171
		if(does_interface_exist("$realif")) {
1172
			$ip6 = get_interface_ipv6($interface);
1173
			if (is_ipaddrv6($ip6))
1174
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1175
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1176
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1177
			if ($destroy == true)
1178
				pfSense_interface_flags($realif, -IFF_UP);
1179
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1180
		}
1181
		break;
1182
	}
1183

    
1184
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1185
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1186
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1187
	if (!empty($old_router)) {
1188
		log_error("Clearing states to old gateway {$old_router}.");
1189
		mwexec("/sbin/pfctl -b 0.0.0.0/32 -b {$old_router}/32");
1190
	}
1191

    
1192
	/* remove interface up file if it exists */
1193
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1194
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1195
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1196
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1197
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1198
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1199
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1200

    
1201
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1202
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1203
	if (is_array($ifcfg['wireless'])) {
1204
		mwexec(kill_hostapd($realif));
1205
		mwexec(kill_wpasupplicant($realif));
1206
	}
1207

    
1208
	if ($destroy == true) {
1209
		if (preg_match("/^[a-z0-9]+_vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|^stf/i", $realif))
1210
			pfSense_interface_destroy($realif);
1211
	}
1212

    
1213
	return;
1214
}
1215

    
1216
function interfaces_ptpid_used($ptpid) {
1217
	global $config;
1218

    
1219
	if (is_array($config['ppps']['ppp']))
1220
		foreach ($config['ppps']['ppp'] as & $settings)
1221
			if ($ptpid == $settings['ptpid'])
1222
				return true;
1223

    
1224
	return false;
1225
}
1226

    
1227
function interfaces_ptpid_next() {
1228

    
1229
	$ptpid = 0;
1230
	while(interfaces_ptpid_used($ptpid))
1231
		$ptpid++;
1232

    
1233
	return $ptpid;
1234
}
1235

    
1236
function getMPDCRONSettings($pppif) {
1237
	global $config;
1238

    
1239
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1240
	if (is_array($config['cron']['item'])) {
1241
		foreach ($config['cron']['item'] as $i => $item) {
1242
			if (stripos($item['command'], $cron_cmd_file) !== false)
1243
				return array("ID" => $i, "ITEM" => $item);
1244
		}
1245
	}
1246

    
1247
	return NULL;
1248
}
1249

    
1250
function handle_pppoe_reset($post_array) {
1251
	global $config, $g;
1252

    
1253
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1254
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1255

    
1256
	if (!is_array($config['cron']['item']))
1257
		$config['cron']['item'] = array();
1258

    
1259
	$itemhash = getMPDCRONSettings($pppif);
1260

    
1261
	// reset cron items if necessary and return
1262
	if (empty($post_array['pppoe-reset-type'])) {
1263
		if (isset($itemhash))
1264
			unset($config['cron']['item'][$itemhash['ID']]);
1265
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1266
		return;
1267
	}
1268

    
1269
	if (empty($itemhash))
1270
		$itemhash = array();
1271
	$item = array();
1272
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1273
		$item['minute'] = $post_array['pppoe_resetminute'];
1274
		$item['hour'] = $post_array['pppoe_resethour'];
1275
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1276
			$date = explode("/", $post_array['pppoe_resetdate']);
1277
			$item['mday'] = $date[1];
1278
			$item['month'] = $date[0];
1279
		} else {
1280
			$item['mday'] = "*";
1281
			$item['month'] = "*";
1282
		}
1283
		$item['wday'] = "*";
1284
		$item['who'] = "root";
1285
		$item['command'] = $cron_cmd_file;
1286
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1287
		switch ($post_array['pppoe_pr_preset_val']) {
1288
		case "monthly":
1289
			$item['minute'] = "0";
1290
			$item['hour'] = "0";
1291
			$item['mday'] = "1";
1292
			$item['month'] = "*";
1293
			$item['wday'] = "*";
1294
			break;
1295
	        case "weekly":
1296
			$item['minute'] = "0";
1297
			$item['hour'] = "0";
1298
			$item['mday'] = "*";
1299
			$item['month'] = "*";
1300
			$item['wday'] = "0";
1301
			break;
1302
		case "daily":
1303
			$item['minute'] = "0";
1304
			$item['hour'] = "0";
1305
			$item['mday'] = "*";
1306
			$item['month'] = "*";
1307
			$item['wday'] = "*";
1308
			break;
1309
		case "hourly":
1310
			$item['minute'] = "0";
1311
			$item['hour'] = "*";
1312
			$item['mday'] = "*";
1313
			$item['month'] = "*";
1314
			$item['wday'] = "*";
1315
			break;
1316
		} // end switch
1317
		$item['who'] = "root";
1318
		$item['command'] = $cron_cmd_file;
1319
	}
1320
	if (empty($item))
1321
		return;
1322
	if (isset($item['ID']))
1323
		$config['cron']['item'][$item['ID']] = $item;
1324
	else
1325
		$config['cron']['item'][] = $item;
1326
}
1327

    
1328
/*
1329
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1330
 * It writes the mpd config file to /var/etc every time the link is opened.
1331
 */
1332
function interface_ppps_configure($interface) {
1333
	global $config, $g;
1334

    
1335
	/* Return for unassigned interfaces. This is a minimum requirement. */
1336
	if (empty($config['interfaces'][$interface]))
1337
		return 0;
1338
	$ifcfg = $config['interfaces'][$interface];
1339
	if (!isset($ifcfg['enable']))
1340
		return 0;
1341

    
1342
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1343
	if(!is_dir("/var/spool/lock")) {
1344
		exec("/bin/mkdir -p /var/spool/lock");
1345
		exec("/bin/chmod a+rw /var/spool/lock/.");
1346
	}
1347
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1348
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1349
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1350

    
1351
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1352
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1353
			if ($ifcfg['if'] == $ppp['if'])
1354
				break;
1355
		}
1356
	}
1357
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1358
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1359
		return 0;
1360
	}
1361
	$pppif = $ifcfg['if'];
1362
	if ($ppp['type'] == "ppp")
1363
		$type = "modem";
1364
	else
1365
		$type = $ppp['type'];
1366
	$upper_type = strtoupper($ppp['type']);
1367

    
1368
	if($g['booting']) {
1369
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1370
		echo "starting {$pppif} link...";
1371
		// Do not re-configure the interface if we are booting and it's already been started
1372
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1373
			return 0;
1374
	}
1375

    
1376
	$ports = explode(',',$ppp['ports']);
1377
	if ($type != "modem") {
1378
		foreach ($ports as $pid => $port) {
1379
			$ports[$pid] = get_real_interface($port);
1380
			if (empty($ports[$pid]))
1381
				return 0;
1382
		}
1383
	}
1384
	$localips = explode(',',$ppp['localip']);
1385
	$gateways = explode(',',$ppp['gateway']);
1386
	$subnets = explode(',',$ppp['subnet']);
1387

    
1388
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1389
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1390
	 */
1391
	foreach($ports as $pid => $port){
1392
		switch ($ppp['type']) {
1393
			case "pppoe":
1394
				/* Bring the parent interface up */
1395
				interfaces_bring_up($port);
1396
				pfSense_ngctl_attach(".", $port);
1397
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1398
				mwexec("ngctl msg {$port}: setautosrc 1");
1399
				break;
1400
			case "pptp":
1401
			case "l2tp":
1402
				/* configure interface */
1403
				if(is_ipaddr($localips[$pid])){
1404
					// Manually configure interface IP/subnet
1405
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1406
					interfaces_bring_up($port);
1407
				} else if (empty($localips[$pid]))
1408
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1409

    
1410
				if(!is_ipaddr($localips[$pid])){
1411
					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!");
1412
					$localips[$pid] = "0.0.0.0";
1413
				}
1414
				/* XXX: This needs to go away soon! [It's commented out!] */
1415
				/* Configure the gateway (remote IP ) */
1416
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1417
					/* XXX: Fix later
1418
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1419
					if(!is_ipaddr($gateways[$pid])) {
1420
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1421
						return 0;
1422
					}
1423
					*/
1424
				}
1425
				if(!is_ipaddr($gateways[$pid])){
1426
					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));
1427
					return 0;
1428
				}
1429
				pfSense_ngctl_attach(".", $port);
1430
				break;
1431
			case "ppp":
1432
				if (!file_exists("{$port}")) {
1433
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1434
					return 0;
1435
				}
1436
				break;
1437
			default:
1438
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1439
				break;
1440
		}
1441
	}
1442

    
1443
	if (is_array($ports) && count($ports) > 1)
1444
		$multilink = "enable";
1445
	else
1446
		$multilink = "disable";
1447

    
1448
	if ($type == "modem"){
1449
		if (is_ipaddr($ppp['localip']))
1450
			$localip = $ppp['localip'];
1451
		else
1452
			$localip = '0.0.0.0';
1453

    
1454
		if (is_ipaddr($ppp['gateway']))
1455
			$gateway = $ppp['gateway'];
1456
		else
1457
			$gateway = "10.64.64.{$pppid}";
1458
		$ranges = "{$localip}/0 {$gateway}/0";
1459

    
1460
		if (empty($ppp['apnum']))
1461
			$ppp['apnum'] = 1;
1462
	} else
1463
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1464

    
1465
	if (isset($ppp['ondemand']))
1466
		$ondemand = "enable";
1467
	else
1468
		$ondemand = "disable";
1469
	if (!isset($ppp['idletimeout']))
1470
		$ppp['idletimeout'] = 0;
1471

    
1472
	if (empty($ppp['username']) && $type == "modem"){
1473
		$ppp['username'] = "user";
1474
		$ppp['password'] = "none";
1475
	}
1476
	if (empty($ppp['password']) && $type == "modem")
1477
		$passwd = "none";
1478
	else
1479
		$passwd = base64_decode($ppp['password']);
1480

    
1481
	$bandwidths = explode(',',$ppp['bandwidth']);
1482
	$defaultmtu = "1492";
1483
	if (!empty($ifcfg['mtu']))
1484
		$defaultmtu = intval($ifcfg['mtu']);
1485
	$mtus = explode(',',$ppp['mtu']);
1486
	$mrus = explode(',',$ppp['mru']);
1487

    
1488
	if (isset($ppp['mrru']))
1489
		$mrrus = explode(',',$ppp['mrru']);
1490

    
1491
	// Construct the mpd.conf file
1492
	$mpdconf = <<<EOD
1493
startup:
1494
	# configure the console
1495
	set console close
1496
	# configure the web server
1497
	set web close
1498

    
1499
default:
1500
{$ppp['type']}client:
1501
	create bundle static {$interface}
1502
	set bundle enable ipv6cp
1503
	set iface name {$pppif}
1504

    
1505
EOD;
1506
	$setdefaultgw = false;
1507
	$founddefaultgw = false;
1508
	if (is_array($config['gateways']['gateway_item'])) {
1509
		foreach($config['gateways']['gateway_item'] as $gateway) {
1510
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1511
				$setdefaultgw = true;
1512
				break;
1513
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1514
				$founddefaultgw = true;
1515
				break;
1516
			}
1517
		}
1518
	}
1519

    
1520
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1521
		$setdefaultgw = true;
1522
		$mpdconf .= <<<EOD
1523
	set iface route default
1524

    
1525
EOD;
1526
	}
1527
	$mpdconf .= <<<EOD
1528
	set iface {$ondemand} on-demand
1529
	set iface idle {$ppp['idletimeout']}
1530

    
1531
EOD;
1532

    
1533
	if (isset($ppp['ondemand']))
1534
		$mpdconf .= <<<EOD
1535
	set iface addrs 10.10.1.1 10.10.1.2
1536

    
1537
EOD;
1538

    
1539
	if (isset($ppp['tcpmssfix']))
1540
		$tcpmss = "disable";
1541
	else
1542
		$tcpmss = "enable";
1543
		$mpdconf .= <<<EOD
1544
	set iface {$tcpmss} tcpmssfix
1545

    
1546
EOD;
1547

    
1548
	$mpdconf .= <<<EOD
1549
	set iface up-script /usr/local/sbin/ppp-linkup
1550
	set iface down-script /usr/local/sbin/ppp-linkdown
1551
	set ipcp ranges {$ranges}
1552

    
1553
EOD;
1554
	if (isset($ppp['vjcomp']))
1555
		$mpdconf .= <<<EOD
1556
	set ipcp no vjcomp
1557

    
1558
EOD;
1559

    
1560
	if (isset($config['system']['dnsallowoverride']))
1561
		$mpdconf .= <<<EOD
1562
	set ipcp enable req-pri-dns
1563
	set ipcp enable req-sec-dns
1564

    
1565
EOD;
1566
	if (!isset($ppp['verbose_log']))
1567
		$mpdconf .= <<<EOD
1568
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1569

    
1570
EOD;
1571
	foreach($ports as $pid => $port){
1572
		$port = get_real_interface($port);
1573
		$mpdconf .= <<<EOD
1574

    
1575
	create link static {$interface}_link{$pid} {$type}
1576
	set link action bundle {$interface}
1577
	set link {$multilink} multilink
1578
	set link keep-alive 10 60
1579
	set link max-redial 0
1580

    
1581
EOD;
1582
		if (isset($ppp['shortseq']))
1583
			$mpdconf .= <<<EOD
1584
	set link no shortseq
1585

    
1586
EOD;
1587

    
1588
		if (isset($ppp['acfcomp']))
1589
			$mpdconf .= <<<EOD
1590
	set link no acfcomp
1591

    
1592
EOD;
1593

    
1594
		if (isset($ppp['protocomp']))
1595
			$mpdconf .= <<<EOD
1596
	set link no protocomp
1597

    
1598
EOD;
1599

    
1600
		$mpdconf .= <<<EOD
1601
	set link disable chap pap
1602
	set link accept chap pap eap
1603
	set link disable incoming
1604

    
1605
EOD;
1606

    
1607

    
1608
		if (!empty($bandwidths[$pid]))
1609
			$mpdconf .= <<<EOD
1610
	set link bandwidth {$bandwidths[$pid]}
1611

    
1612
EOD;
1613

    
1614
		if (empty($mtus[$pid]))
1615
			$mtus[$pid] = $defaultmtu;
1616
			$mpdconf .= <<<EOD
1617
	set link mtu {$mtus[$pid]}
1618

    
1619
EOD;
1620

    
1621
		if (!empty($mrus[$pid]))
1622
			$mpdconf .= <<<EOD
1623
	set link mru {$mrus[$pid]}
1624

    
1625
EOD;
1626

    
1627
		if (!empty($mrrus[$pid]))
1628
			$mpdconf .= <<<EOD
1629
	set link mrru {$mrrus[$pid]}
1630

    
1631
EOD;
1632

    
1633
		$mpdconf .= <<<EOD
1634
	set auth authname "{$ppp['username']}"
1635
	set auth password {$passwd}
1636

    
1637
EOD;
1638
		if ($type == "modem") {
1639
			$mpdconf .= <<<EOD
1640
	set modem device {$ppp['ports']}
1641
	set modem script DialPeer
1642
	set modem idle-script Ringback
1643
	set modem watch -cd
1644
	set modem var \$DialPrefix "DT"
1645
	set modem var \$Telephone "{$ppp['phone']}"
1646

    
1647
EOD;
1648
		}
1649
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1650
			$mpdconf .= <<<EOD
1651
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1652

    
1653
EOD;
1654
		}
1655
		if (isset($ppp['initstr']) && $type == "modem") {
1656
			$initstr = base64_decode($ppp['initstr']);
1657
			$mpdconf .= <<<EOD
1658
	set modem var \$InitString "{$initstr}"
1659

    
1660
EOD;
1661
		}
1662
		if (isset($ppp['simpin']) && $type == "modem") {
1663
			if($ppp['pin-wait'] == "")
1664
				$ppp['pin-wait'] = 0;
1665
			$mpdconf .= <<<EOD
1666
	set modem var \$SimPin "{$ppp['simpin']}"
1667
	set modem var \$PinWait "{$ppp['pin-wait']}"
1668

    
1669
EOD;
1670
		}
1671
		if (isset($ppp['apn']) && $type == "modem") {
1672
			$mpdconf .= <<<EOD
1673
	set modem var \$APN "{$ppp['apn']}"
1674
	set modem var \$APNum "{$ppp['apnum']}"
1675

    
1676
EOD;
1677
		}
1678
		if ($type == "pppoe") {
1679
			// Send a null service name if none is set.
1680
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1681
			$mpdconf .= <<<EOD
1682
	set pppoe service "{$provider}"
1683

    
1684
EOD;
1685
		}
1686
		if ($type == "pppoe")
1687
			$mpdconf .= <<<EOD
1688
	set pppoe iface {$port}
1689

    
1690
EOD;
1691

    
1692
		if ($type == "pptp" || $type == "l2tp") {
1693
			$mpdconf .= <<<EOD
1694
	set {$type} self {$localips[$pid]}
1695
	set {$type} peer {$gateways[$pid]}
1696

    
1697
EOD;
1698
		}
1699

    
1700
		$mpdconf .= "\topen\n";
1701
	} //end foreach($port)
1702

    
1703

    
1704
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1705
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1706
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1707
	else {
1708
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1709
		if (!$fd) {
1710
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1711
			return 0;
1712
		}
1713
		// Write out mpd_ppp.conf
1714
		fwrite($fd, $mpdconf);
1715
		fclose($fd);
1716
		unset($mpdconf);
1717
	}
1718

    
1719
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1720
	if (isset($ppp['uptime'])) {
1721
		if (!file_exists("/conf/{$pppif}.log")) {
1722
			conf_mount_rw();
1723
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1724
			conf_mount_ro();
1725
		}
1726
	} else {
1727
		if (file_exists("/conf/{$pppif}.log")) {
1728
			conf_mount_rw();
1729
			mwexec("rm -f /conf/{$pppif}.log");
1730
			conf_mount_ro();
1731
		}
1732
	}
1733

    
1734
	/* clean up old lock files */
1735
	foreach($ports as $port) {
1736
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1737
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1738
	}
1739

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

    
1743
	// Check for PPPoE periodic reset request
1744
	if ($type == "pppoe") {
1745
		if (!empty($ppp['pppoe-reset-type']))
1746
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1747
		else
1748
			interface_setup_pppoe_reset_file($ppp['if']);
1749
	}
1750
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1751
	$i = 0;
1752
	while($i < 10) {
1753
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1754
		if($ret == 0)
1755
			break;
1756
		sleep(1);
1757
		$i++;
1758
	}
1759

    
1760
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1761
	/* We should be able to launch the right version for each modem */
1762
	/* We can also guess the mondev from the manufacturer */
1763
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1764
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1765
	foreach($ports as $port) {
1766
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1767
			$mondev  = substr(basename($port), 0, -1);
1768
			$devlist = glob("/dev/{$mondev}?");
1769
			$mondev = basename(end($devlist));
1770
		}
1771
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1772
			$mondev  = substr(basename($port), 0, -1) . "1";
1773
		}
1774
		log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1775
		mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1776
	}
1777

    
1778
	return 1;
1779
}
1780

    
1781
function interfaces_carp_setup() {
1782
	global $g, $config;
1783

    
1784
	if (isset($config['system']['developerspew'])) {
1785
		$mt = microtime();
1786
		echo "interfaces_carp_setup() being called $mt\n";
1787
	}
1788

    
1789
	if ($g['booting']) {
1790
		echo gettext("Configuring CARP settings...");
1791
		mute_kernel_msgs();
1792
	}
1793

    
1794
	/* suck in configuration items */
1795
	if ($config['hasync']) {
1796
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1797
		$balanacing = $config['hasync']['balancing'];
1798
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1799
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1800
	} else {
1801
		unset($pfsyncinterface);
1802
		unset($balanacing);
1803
		unset($pfsyncenabled);
1804
	}
1805

    
1806
	if ($balanacing) {
1807
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1808
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1809
	} else
1810
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1811

    
1812
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1813
	if (!empty($pfsyncinterface))
1814
		$carp_sync_int = get_real_interface($pfsyncinterface);
1815
	else
1816
		unset($carp_sync_int);
1817

    
1818
	/* setup pfsync interface */
1819
	if ($carp_sync_int and $pfsyncenabled) {
1820
		if (is_ipaddr($pfsyncpeerip))
1821
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);
1822
		else
1823
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);
1824

    
1825
		sleep(1);
1826

    
1827
		/* 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
1828
		 * for existing sessions.
1829
		 */
1830
		log_error("waiting for pfsync...");
1831
		$i = 0;
1832
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1833
			$i++;
1834
			sleep(1);
1835
		}
1836
		log_error("pfsync done in $i seconds.");
1837
		log_error("Configuring CARP settings finalize...");
1838
	}
1839

    
1840
	if($config['virtualip']['vip'])
1841
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1842
	else
1843
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1844

    
1845
	if ($g['booting']) {
1846
		unmute_kernel_msgs();
1847
		echo gettext("done.") . "\n";
1848
	}
1849
}
1850

    
1851
function interface_proxyarp_configure($interface = "") {
1852
	global $config, $g;
1853
	if(isset($config['system']['developerspew'])) {
1854
		$mt = microtime();
1855
		echo "interface_proxyarp_configure() being called $mt\n";
1856
	}
1857

    
1858
	/* kill any running choparp */
1859
	if (empty($interface))
1860
		killbyname("choparp");
1861
	else {
1862
		$vipif = get_real_interface($interface);
1863
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1864
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1865
	}
1866

    
1867
	$paa = array();
1868
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1869

    
1870
		/* group by interface */
1871
		foreach ($config['virtualip']['vip'] as $vipent) {
1872
			if ($vipent['mode'] === "proxyarp") {
1873
				if ($vipent['interface'])
1874
					$proxyif = $vipent['interface'];
1875
				else
1876
					$proxyif = "wan";
1877

    
1878
				if (!empty($interface) && $interface != $proxyif)
1879
					continue;
1880

    
1881
				if (!is_array($paa[$proxyif]))
1882
					$paa[$proxyif] = array();
1883

    
1884
				$paa[$proxyif][] = $vipent;
1885
			}
1886
		}
1887
	}
1888

    
1889
	if (!empty($interface)) {
1890
		if (is_array($paa[$interface])) {
1891
			$paaifip = get_interface_ip($interface);
1892
			if (!is_ipaddr($paaifip))
1893
				return;
1894
			$args = get_real_interface($interface) . " auto";
1895
			foreach ($paa[$interface] as $paent) {
1896
				if (isset($paent['subnet']))
1897
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1898
				else if (isset($paent['range']))
1899
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1900
			}
1901
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1902
		}
1903
	} else if (count($paa) > 0) {
1904
		foreach ($paa as $paif => $paents)  {
1905
			$paaifip = get_interface_ip($paif);
1906
			if (!is_ipaddr($paaifip))
1907
				continue;
1908
			$args = get_real_interface($paif) . " auto";
1909
			foreach ($paents as $paent) {
1910
				if (isset($paent['subnet']))
1911
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1912
				else if (isset($paent['range']))
1913
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1914
			}
1915
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1916
		}
1917
	}
1918
}
1919

    
1920
function interfaces_vips_configure($interface = "") {
1921
	global $g, $config;
1922
	if(isset($config['system']['developerspew'])) {
1923
		$mt = microtime();
1924
		echo "interfaces_vips_configure() being called $mt\n";
1925
	}
1926
	$paa = array();
1927
	if(is_array($config['virtualip']['vip'])) {
1928
		$carp_setuped = false;
1929
		$anyproxyarp = false;
1930
		foreach ($config['virtualip']['vip'] as $vip) {
1931
			switch ($vip['mode']) {
1932
			case "proxyarp":
1933
				/* nothing it is handled on interface_proxyarp_configure() */
1934
				if ($interface <> "" && $vip['interface'] <> $interface)
1935
					continue;
1936
				$anyproxyarp = true;
1937
				break;
1938
			case "ipalias":
1939
				if ($interface <> "" && $vip['interface'] <> $interface)
1940
					continue;
1941
				interface_ipalias_configure($vip);
1942
				break;
1943
			case "carp":
1944
				if ($interface <> "" && $vip['interface'] <> $interface)
1945
					continue;
1946
				if ($carp_setuped == false)
1947
					$carp_setuped = true;
1948
				interface_carp_configure($vip);
1949
				break;
1950
			}
1951
		}
1952
		if ($carp_setuped == true)
1953
			interfaces_carp_setup();
1954
		if ($anyproxyarp == true)
1955
			interface_proxyarp_configure();
1956
	}
1957
}
1958

    
1959
function interface_ipalias_configure(&$vip) {
1960
	if ($vip['mode'] == "ipalias") {
1961
		$if = get_real_interface($vip['interface']);
1962
		$af = "inet";
1963
		if(is_ipaddrv6($vip['subnet']))
1964
			$af = "inet6";
1965
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
1966
	}
1967
}
1968

    
1969
function interface_reload_carps($cif) {
1970
	global $config;
1971

    
1972
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1973
	if (empty($carpifs))
1974
		return;
1975

    
1976
	$carps = explode(" ", $carpifs);
1977
	if(is_array($config['virtualip']['vip'])) {
1978
		$viparr = &$config['virtualip']['vip'];
1979
		foreach ($viparr as $vip) {
1980
			if (in_array($vip['carpif'], $carps)) {
1981
				switch ($vip['mode']) {
1982
				case "carp":
1983
					interface_vip_bring_down($vip);
1984
					sleep(1);
1985
					interface_carp_configure($vip);
1986
					break;
1987
				case "ipalias":
1988
					interface_vip_bring_down($vip);
1989
					sleep(1);
1990
					interface_ipalias_configure($vip);
1991
					break;
1992
				}
1993
			}
1994
		}
1995
	}
1996
}
1997

    
1998
function interface_carp_configure(&$vip) {
1999
	global $config, $g;
2000
	if(isset($config['system']['developerspew'])) {
2001
		$mt = microtime();
2002
		echo "interface_carp_configure() being called $mt\n";
2003
	}
2004

    
2005
	if ($vip['mode'] != "carp")
2006
		return;
2007

    
2008
	/*
2009
	 * ensure the interface containing the VIP really exists
2010
	 * prevents a panic if the interface is missing or invalid
2011
	 */
2012
	$realif = get_real_interface($vip['interface']);
2013
	if (!does_interface_exist($realif)) {
2014
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2015
		return;
2016
	}
2017

    
2018
	if(is_ipaddrv4($vip['subnet'])) {
2019
		/* Ensure CARP IP really exists prior to loading up. */
2020
		$ww_subnet_ip = find_interface_ip($realif);
2021
		$ww_subnet_bits = find_interface_subnet($realif);
2022
		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'])) {
2023
			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", "");
2024
			return;
2025
		}
2026
	}
2027
	if(is_ipaddrv6($vip['subnet'])) {
2028
		/* Ensure CARP IP really exists prior to loading up. */
2029
		$ww_subnet_ip = find_interface_ipv6($realif);
2030
		$ww_subnet_bits = find_interface_subnetv6($realif);
2031
		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'])) {
2032
			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", "");
2033
			return;
2034
		}
2035
	}
2036

    
2037
	// set the vip interface to the vhid
2038
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2039

    
2040
	/* create the carp interface and setup */
2041
	if (does_interface_exist($vipif)) {
2042
		pfSense_interface_flags($vipif, -IFF_UP);
2043
	} else {
2044
		$carpif = pfSense_interface_create("carp");
2045
		pfSense_interface_rename($carpif, $vipif);
2046
		pfSense_ngctl_name("{$carpif}:", $vipif);
2047
	}
2048

    
2049
	/* invalidate interface cache */
2050
	get_interface_arr(true);
2051

    
2052
	$vip_password = $vip['password'];
2053
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2054
	if ($vip['password'] != "")
2055
		$password = " pass {$vip_password}";
2056

    
2057
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2058
	$advbase = "";
2059
	if (!empty($vip['advbase']))
2060
		$advbase = "advbase {$vip['advbase']}";
2061

    
2062
	if(is_ipaddrv4($vip['subnet'])) {
2063
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2064
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2065
	}
2066
	if(is_ipaddrv6($vip['subnet'])) {
2067
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2068
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2069
	}
2070

    
2071
	interfaces_bring_up($vipif);
2072

    
2073
	return $vipif;
2074
}
2075

    
2076
function interface_wireless_clone($realif, $wlcfg) {
2077
	global $config, $g;
2078
	/*   Check to see if interface has been cloned as of yet.
2079
	 *   If it has not been cloned then go ahead and clone it.
2080
	 */
2081
	$needs_clone = false;
2082
	if(is_array($wlcfg['wireless']))
2083
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2084
	else
2085
		$wlcfg_mode = $wlcfg['mode'];
2086
	switch($wlcfg_mode) {
2087
		 case "hostap":
2088
			$mode = "wlanmode hostap";
2089
			break;
2090
		 case "adhoc":
2091
			$mode = "wlanmode adhoc";
2092
			break;
2093
		 default:
2094
			$mode = "";
2095
			break;
2096
	}
2097
	$baseif = interface_get_wireless_base($wlcfg['if']);
2098
	if(does_interface_exist($realif)) {
2099
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2100
		$ifconfig_str = implode($output);
2101
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2102
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2103
			$needs_clone = true;
2104
		}
2105
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2106
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2107
			$needs_clone = true;
2108
		}
2109
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2110
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2111
			$needs_clone = true;
2112
		}
2113
	} else {
2114
		$needs_clone = true;
2115
	}
2116

    
2117
	if($needs_clone == true) {
2118
		/* remove previous instance if it exists */
2119
		if(does_interface_exist($realif))
2120
			pfSense_interface_destroy($realif);
2121

    
2122
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2123
		// Create the new wlan interface. FreeBSD returns the new interface name.
2124
		// example:  wlan2
2125
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2126
		if($ret <> 0) {
2127
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2128
			return false;
2129
		}
2130
		$newif = trim($out[0]);
2131
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2132
		pfSense_interface_rename($newif, $realif);
2133
		// FIXME: not sure what ngctl is for. Doesn't work.
2134
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2135
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2136
	}
2137
	return true;
2138
}
2139

    
2140
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2141
	global $config, $g;
2142

    
2143
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2144
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2145
	                         'regdomain', 'regcountry', 'reglocation');
2146

    
2147
	if(!is_interface_wireless($ifcfg['if']))
2148
		return;
2149

    
2150
	$baseif = interface_get_wireless_base($ifcfg['if']);
2151

    
2152
	// Sync shared settings for assigned clones
2153
	$iflist = get_configured_interface_list(false, true);
2154
	foreach ($iflist as $if) {
2155
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2156
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2157
				foreach ($shared_settings as $setting) {
2158
					if ($sync_changes) {
2159
						if (isset($ifcfg['wireless'][$setting]))
2160
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2161
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2162
							unset($config['interfaces'][$if]['wireless'][$setting]);
2163
					} else {
2164
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2165
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2166
						else if (isset($ifcfg['wireless'][$setting]))
2167
							unset($ifcfg['wireless'][$setting]);
2168
					}
2169
				}
2170
				if (!$sync_changes)
2171
					break;
2172
			}
2173
		}
2174
	}
2175

    
2176
	// Read or write settings at shared area
2177
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2178
		foreach ($shared_settings as $setting) {
2179
			if ($sync_changes) {
2180
				if (isset($ifcfg['wireless'][$setting]))
2181
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2182
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2183
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2184
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2185
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2186
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2187
				else if (isset($ifcfg['wireless'][$setting]))
2188
					unset($ifcfg['wireless'][$setting]);
2189
			}
2190
		}
2191
	}
2192

    
2193
	// Sync the mode on the clone creation page with the configured mode on the interface
2194
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2195
		foreach ($config['wireless']['clone'] as &$clone) {
2196
			if ($clone['cloneif'] == $ifcfg['if']) {
2197
				if ($sync_changes) {
2198
					$clone['mode'] = $ifcfg['wireless']['mode'];
2199
				} else {
2200
					$ifcfg['wireless']['mode'] = $clone['mode'];
2201
				}
2202
				break;
2203
			}
2204
		}
2205
		unset($clone);
2206
	}
2207
}
2208

    
2209
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2210
	global $config, $g;
2211

    
2212
	/*    open up a shell script that will be used to output the commands.
2213
	 *    since wireless is changing a lot, these series of commands are fragile
2214
	 *    and will sometimes need to be verified by a operator by executing the command
2215
	 *    and returning the output of the command to the developers for inspection.  please
2216
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2217
	 */
2218

    
2219
	// Remove script file
2220
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2221

    
2222
	// Clone wireless nic if needed.
2223
	interface_wireless_clone($if, $wl);
2224

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

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

    
2232
	/* set values for /path/program */
2233
	$hostapd = "/usr/sbin/hostapd";
2234
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2235
	$ifconfig = "/sbin/ifconfig";
2236
	$sysctl = "/sbin/sysctl";
2237
	$killall = "/usr/bin/killall";
2238

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

    
2241
	$wlcmd = array();
2242
	$wl_sysctl = array();
2243
	/* Make sure it's up */
2244
	$wlcmd[] = "up";
2245
	/* Set a/b/g standard */
2246
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2247
	$wlcmd[] = "mode " . escapeshellarg($standard);
2248

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

    
2254
	/* Set ssid */
2255
	if($wlcfg['ssid'])
2256
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2257

    
2258
	/* Set 802.11g protection mode */
2259
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2260

    
2261
	/* set wireless channel value */
2262
	if(isset($wlcfg['channel'])) {
2263
		if($wlcfg['channel'] == "0") {
2264
			$wlcmd[] = "channel any";
2265
		} else {
2266
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2267
		}
2268
	}
2269

    
2270
	/* Set antenna diversity value */
2271
	if(isset($wlcfg['diversity']))
2272
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2273

    
2274
	/* Set txantenna value */
2275
	if(isset($wlcfg['txantenna']))
2276
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2277

    
2278
	/* Set rxantenna value */
2279
	if(isset($wlcfg['rxantenna']))
2280
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2281

    
2282
	/* set Distance value */
2283
	if($wlcfg['distance'])
2284
		$distance = escapeshellarg($wlcfg['distance']);
2285

    
2286
	/* Set wireless hostap mode */
2287
	if ($wlcfg['mode'] == "hostap") {
2288
		$wlcmd[] = "mediaopt hostap";
2289
	} else {
2290
		$wlcmd[] = "-mediaopt hostap";
2291
	}
2292

    
2293
	/* Set wireless adhoc mode */
2294
	if ($wlcfg['mode'] == "adhoc") {
2295
		$wlcmd[] = "mediaopt adhoc";
2296
	} else {
2297
		$wlcmd[] = "-mediaopt adhoc";
2298
	}
2299

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

    
2302
	/* handle hide ssid option */
2303
	if(isset($wlcfg['hidessid']['enable'])) {
2304
		$wlcmd[] = "hidessid";
2305
	} else {
2306
		$wlcmd[] = "-hidessid";
2307
	}
2308

    
2309
	/* handle pureg (802.11g) only option */
2310
	if(isset($wlcfg['pureg']['enable'])) {
2311
		$wlcmd[] = "mode 11g pureg";
2312
	} else {
2313
		$wlcmd[] = "-pureg";
2314
	}
2315

    
2316
	/* handle puren (802.11n) only option */
2317
	if(isset($wlcfg['puren']['enable'])) {
2318
		$wlcmd[] = "puren";
2319
	} else {
2320
		$wlcmd[] = "-puren";
2321
	}
2322

    
2323
	/* enable apbridge option */
2324
	if(isset($wlcfg['apbridge']['enable'])) {
2325
		$wlcmd[] = "apbridge";
2326
	} else {
2327
		$wlcmd[] = "-apbridge";
2328
	}
2329

    
2330
	/* handle turbo option */
2331
	if(isset($wlcfg['turbo']['enable'])) {
2332
		$wlcmd[] = "mediaopt turbo";
2333
	} else {
2334
		$wlcmd[] = "-mediaopt turbo";
2335
	}
2336

    
2337
	/* handle txpower setting */
2338
	/* if($wlcfg['txpower'] <> "")
2339
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2340
	*/
2341
	/* handle wme option */
2342
	if(isset($wlcfg['wme']['enable'])) {
2343
		$wlcmd[] = "wme";
2344
	} else {
2345
		$wlcmd[] = "-wme";
2346
	}
2347

    
2348
	/* set up wep if enabled */
2349
	$wepset = "";
2350
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2351
		switch($wlcfg['wpa']['auth_algs']) {
2352
			case "1":
2353
				$wepset .= "authmode open wepmode on ";
2354
				break;
2355
			case "2":
2356
				$wepset .= "authmode shared wepmode on ";
2357
				break;
2358
			case "3":
2359
				$wepset .= "authmode mixed wepmode on ";
2360
		}
2361
		$i = 1;
2362
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2363
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2364
			if (isset($wepkey['txkey'])) {
2365
				$wlcmd[] = "weptxkey {$i} ";
2366
			}
2367
			$i++;
2368
		}
2369
		$wlcmd[] = $wepset;
2370
	} else {
2371
		$wlcmd[] = "authmode open wepmode off ";
2372
	}
2373

    
2374
	mwexec(kill_hostapd("{$if}"));
2375
	mwexec(kill_wpasupplicant("{$if}"));
2376

    
2377
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2378
	conf_mount_rw();
2379

    
2380
	switch ($wlcfg['mode']) {
2381
		case 'bss':
2382
			if (isset($wlcfg['wpa']['enable'])) {
2383
				$wpa .= <<<EOD
2384
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2385
ctrl_interface_group=0
2386
ap_scan=1
2387
#fast_reauth=1
2388
network={
2389
ssid="{$wlcfg['ssid']}"
2390
scan_ssid=1
2391
priority=5
2392
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2393
psk="{$wlcfg['wpa']['passphrase']}"
2394
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2395
group={$wlcfg['wpa']['wpa_pairwise']}
2396
}
2397
EOD;
2398

    
2399
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2400
				fwrite($fd, "{$wpa}");
2401
				fclose($fd);
2402
			}
2403
			break;
2404
		case 'hostap':
2405
			if($wlcfg['wpa']['passphrase'])
2406
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2407
			else
2408
				$wpa_passphrase = "";
2409
			if (isset($wlcfg['wpa']['enable'])) {
2410
				$wpa .= <<<EOD
2411
interface={$if}
2412
driver=bsd
2413
logger_syslog=-1
2414
logger_syslog_level=0
2415
logger_stdout=-1
2416
logger_stdout_level=0
2417
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2418
ctrl_interface={$g['varrun_path']}/hostapd
2419
ctrl_interface_group=wheel
2420
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2421
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2422
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2423
ssid={$wlcfg['ssid']}
2424
debug={$wlcfg['wpa']['debug_mode']}
2425
auth_algs={$wlcfg['wpa']['auth_algs']}
2426
wpa={$wlcfg['wpa']['wpa_mode']}
2427
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2428
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2429
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2430
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2431
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2432
{$wpa_passphrase}
2433

    
2434
EOD;
2435

    
2436
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2437
	$wpa .= <<<EOD
2438
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2439
rsn_preauth=1
2440
rsn_preauth_interfaces={$if}
2441

    
2442
EOD;
2443

    
2444
}
2445
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2446
					$auth_server_port = "1812";
2447
					if($wlcfg['auth_server_port'])
2448
						$auth_server_port = $wlcfg['auth_server_port'];
2449
					$auth_server_port2 = "1812";
2450
					if($wlcfg['auth_server_port2'])
2451
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2452
					$wpa .= <<<EOD
2453

    
2454
ieee8021x=1
2455
auth_server_addr={$wlcfg['auth_server_addr']}
2456
auth_server_port={$auth_server_port}
2457
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2458
auth_server_addr={$wlcfg['auth_server_addr2']}
2459
auth_server_port={$auth_server_port2}
2460
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2461

    
2462
EOD;
2463
				} else {
2464
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2465
				}
2466

    
2467
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2468
				fwrite($fd, "{$wpa}");
2469
				fclose($fd);
2470

    
2471
			}
2472
			break;
2473
	}
2474

    
2475
	/*
2476
	 *    all variables are set, lets start up everything
2477
	 */
2478

    
2479
	$baseif = interface_get_wireless_base($if);
2480
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2481
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2482

    
2483
	/* set sysctls for the wireless interface */
2484
	if (!empty($wl_sysctl)) {
2485
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2486
		foreach ($wl_sysctl as $wl_sysctl_line) {
2487
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2488
		}
2489
	}
2490

    
2491
	/* set ack timers according to users preference (if he/she has any) */
2492
	if($distance) {
2493
		fwrite($fd_set, "# Enable ATH distance settings\n");
2494
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2495
	}
2496

    
2497
	if (isset($wlcfg['wpa']['enable'])) {
2498
		if ($wlcfg['mode'] == "bss") {
2499
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2500
		}
2501
		if ($wlcfg['mode'] == "hostap") {
2502
			/* add line to script to restore old mac to make hostapd happy */
2503
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2504
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2505
				if (is_macaddr($if_oldmac))
2506
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2507
						" link " . escapeshellarg($if_oldmac) . "\n");
2508
			}
2509

    
2510
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2511

    
2512
			/* add line to script to restore spoofed mac after running hostapd */
2513
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2514
				if ($wl['spoofmac'])
2515
					$if_curmac = $wl['spoofmac'];
2516
				else
2517
					$if_curmac = get_interface_mac($if);
2518
				if (is_macaddr($if_curmac))
2519
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2520
						" link " . escapeshellarg($if_curmac) . "\n");
2521
			}
2522
		}
2523
	}
2524

    
2525
	fclose($fd_set);
2526
	conf_mount_ro();
2527

    
2528
	/* Making sure regulatory settings have actually changed
2529
	 * before applying, because changing them requires bringing
2530
	 * down all wireless networks on the interface. */
2531
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2532
	$ifconfig_str = implode($output);
2533
	unset($output);
2534
	$reg_changing = false;
2535

    
2536
	/* special case for the debug country code */
2537
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2538
		$reg_changing = true;
2539
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2540
		$reg_changing = true;
2541
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2542
		$reg_changing = true;
2543
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2544
		$reg_changing = true;
2545
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2546
		$reg_changing = true;
2547

    
2548
	if ($reg_changing) {
2549
		/* set regulatory domain */
2550
		if($wlcfg['regdomain'])
2551
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2552

    
2553
		/* set country */
2554
		if($wlcfg['regcountry'])
2555
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2556

    
2557
		/* set location */
2558
		if($wlcfg['reglocation'])
2559
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2560

    
2561
		$wlregcmd_args = implode(" ", $wlregcmd);
2562

    
2563
		/* build a complete list of the wireless clones for this interface */
2564
		$clone_list = array();
2565
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2566
			$clone_list[] = interface_get_wireless_clone($baseif);
2567
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2568
			foreach ($config['wireless']['clone'] as $clone) {
2569
				if ($clone['if'] == $baseif)
2570
					$clone_list[] = $clone['cloneif'];
2571
			}
2572
		}
2573

    
2574
		/* find which clones are up and bring them down */
2575
		$clones_up = array();
2576
		foreach ($clone_list as $clone_if) {
2577
			$clone_status = pfSense_get_interface_addresses($clone_if);
2578
			if ($clone_status['status'] == 'up') {
2579
				$clones_up[] = $clone_if;
2580
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2581
			}
2582
		}
2583

    
2584
		/* apply the regulatory settings */
2585
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2586

    
2587
		/* bring the clones back up that were previously up */
2588
		foreach ($clones_up as $clone_if) {
2589
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2590

    
2591
			/*
2592
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2593
			 * is in infrastructure mode, and WPA is enabled.
2594
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2595
			 */
2596
			if ($clone_if != $if) {
2597
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2598
				if ( !empty($friendly_if)
2599
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2600
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2601
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2602
				}
2603
			}
2604
		}
2605
	}
2606

    
2607
	/* The mode must be specified in a separate command before ifconfig
2608
	 * will allow the mode and channel at the same time in the next. */
2609
	mwexec("/sbin/ifconfig {$if} mode " . escapeshellarg($standard));
2610

    
2611
	/* configure wireless */
2612
	$wlcmd_args = implode(" ", $wlcmd);
2613
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2614

    
2615

    
2616
	sleep(1);
2617
	/* execute hostapd and wpa_supplicant if required in shell */
2618
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2619

    
2620
	return 0;
2621

    
2622
}
2623

    
2624
function kill_hostapd($interface) {
2625
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2626
}
2627

    
2628
function kill_wpasupplicant($interface) {
2629
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2630
}
2631

    
2632
function find_dhclient_process($interface) {
2633
	if ($interface)
2634
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2635
	else
2636
		$pid = 0;
2637

    
2638
	return intval($pid);
2639
}
2640

    
2641
function find_dhcp6c_process($interface) {
2642
	global $g;
2643

    
2644
	if ($interface)
2645
		if (isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2646
			$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2647
	else
2648
		return(false);
2649

    
2650
	return intval($pid);
2651
}
2652

    
2653
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2654
	global $config, $g;
2655
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2656
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2657

    
2658
	$wancfg = $config['interfaces'][$interface];
2659

    
2660
	if (!isset($wancfg['enable']))
2661
		return;
2662

    
2663
	$realif = get_real_interface($interface);
2664
	$realhwif_array = get_parent_interface($interface);
2665
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2666
	$realhwif = $realhwif_array[0];
2667

    
2668
	/* Disable Accepting router advertisements unless specifically requested */
2669
	log_error("Deny router advertisements for interface {$interface}");
2670
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2671

    
2672
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2673
		/* remove all IPv4 and IPv6 addresses */
2674
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2675
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2676

    
2677
		/* only bring down the interface when both v4 and v6 are set to NONE */
2678
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2679
			interface_bring_down($interface);
2680
		}
2681
	}
2682

    
2683
	/* wireless configuration? */
2684
	if (is_array($wancfg['wireless']))
2685
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2686

    
2687
	$mac = get_interface_mac($realhwif);
2688
	/*
2689
	 * Don't try to reapply the spoofed MAC if it's already applied.
2690
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2691
	 * the interface config again, which attempts to spoof the MAC again,
2692
	 * which cycles the link again...
2693
	 */
2694
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2695
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2696
			" link " . escapeshellarg($wancfg['spoofmac']));
2697

    
2698
		/*
2699
		 * All vlans need to spoof their parent mac address, too.  see
2700
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2701
		 */
2702
		if (is_array($config['vlans']['vlan'])) {
2703
			foreach ($config['vlans']['vlan'] as $vlan) {
2704
				if ($vlan['if'] == $realhwif)
2705
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2706
					" link " . escapeshellarg($wancfg['spoofmac']));
2707
			}
2708
		}
2709
	}  else {
2710

    
2711
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2712
			/*   this is not a valid mac address.  generate a
2713
			 *   temporary mac address so the machine can get online.
2714
			 */
2715
			echo gettext("Generating new MAC address.");
2716
			$random_mac = generate_random_mac_address();
2717
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2718
				" link " . escapeshellarg($random_mac));
2719
			$wancfg['spoofmac'] = $random_mac;
2720
			write_config();
2721
			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");
2722
		}
2723
	}
2724

    
2725
	/* media */
2726
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2727
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2728
		if ($wancfg['media'])
2729
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2730
		if ($wancfg['mediaopt'])
2731
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2732
		mwexec($cmd);
2733
	}
2734
	if (!empty($wancfg['mtu']))
2735
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2736
	else {
2737
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2738
		if ($mtu != get_interface_mtu($realhwif))
2739
			pfSense_interface_mtu($realhwif, $mtu);
2740
	}
2741

    
2742
	$options = pfSense_get_interface_addresses($realhwif);
2743
	if (is_array($options) && isset($options['caps']['polling'])) {
2744
		if (isset($config['system']['polling']))
2745
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2746
		else
2747
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2748
	}
2749

    
2750
	/* skip vlans for checksumming and polling */
2751
	if (!stristr($realhwif, "vlan") && is_array($options)) {
2752
		$flags = 0;
2753
		if(isset($config['system']['disablechecksumoffloading'])) {
2754
			if (isset($options['encaps']['txcsum']))
2755
				$flags |= IFCAP_TXCSUM;
2756
			if (isset($options['encaps']['rxcsum']))
2757
				$flags |= IFCAP_RXCSUM;
2758
		} else {
2759
			if (!isset($options['caps']['txcsum']))
2760
				$flags |= IFCAP_TXCSUM;
2761
			if (!isset($options['caps']['rxcsum']))
2762
				$flags |= IFCAP_RXCSUM;
2763
		}
2764

    
2765
		if(isset($config['system']['disablesegmentationoffloading'])) {
2766
			if (isset($options['encaps']['tso4']))
2767
				$flags |= IFCAP_TSO;
2768
			if (isset($options['encaps']['tso6']))
2769
				$flags |= IFCAP_TSO;
2770
		} else {
2771
			if (!isset($options['caps']['tso4']))
2772
				$flags |= IFCAP_TSO;
2773
			if (!isset($options['caps']['tso6']))
2774
				$flags |= IFCAP_TSO;
2775
		}
2776

    
2777
		if(isset($config['system']['disablelargereceiveoffloading'])) {
2778
			if (isset($options['encaps']['lro']))
2779
				$flags |= IFCAP_LRO;
2780
		} else {
2781
			if (!isset($options['caps']['lro']))
2782
				$flags |= IFCAP_LRO;
2783
		}
2784

    
2785
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2786
		if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2787
			$flags |= IFCAP_POLLING;
2788
		}
2789
		pfSense_interface_capabilities($realhwif, -$flags);
2790
	}
2791

    
2792
	/* invalidate interface/ip/sn cache */
2793
	get_interface_arr(true);
2794
	unset($interface_ip_arr_cache[$realif]);
2795
	unset($interface_sn_arr_cache[$realif]);
2796
	unset($interface_ipv6_arr_cache[$realif]);
2797
	unset($interface_snv6_arr_cache[$realif]);
2798

    
2799
	switch ($wancfg['ipaddr']) {
2800
		case 'dhcp':
2801
			interface_dhcp_configure($interface);
2802
			break;
2803
		case 'pppoe':
2804
		case 'l2tp':
2805
		case 'pptp':
2806
		case 'ppp':
2807
			interface_ppps_configure($interface);
2808
			break;
2809
		default:
2810
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2811
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2812
			} else if (substr($realif, 0, 3) == "gre") {
2813
				if (is_array($config['gres']['gre'])) {
2814
					foreach ($config['gres']['gre'] as $gre)
2815
						if ($gre['greif'] == $realif)
2816
							interface_gre_configure($gre);
2817
				}
2818
			} else if (substr($realif, 0, 3) == "gif") {
2819
				if (is_array($config['gifs']['gif'])) {
2820
					foreach ($config['gifs']['gif'] as $gif)
2821
						if($gif['gifif'] == $realif)
2822
							interface_gif_configure($gif);
2823
				}
2824
			} else if (substr($realif, 0, 4) == "ovpn") {
2825
				/* XXX: Should be done anything?! */
2826
			}
2827
			break;
2828
	}
2829

    
2830
	switch ($wancfg['ipaddrv6']) {
2831
		case 'slaac':
2832
		case 'dhcp6':
2833
			interface_dhcpv6_configure($interface);
2834
			break;
2835
		case '6rd':
2836
			interface_6rd_configure($interface);
2837
			break;
2838
		case '6to4':
2839
			interface_6to4_configure($interface);
2840
			break;
2841
		case 'track6':
2842
			interface_track6_configure($interface);
2843
			break;
2844
		default:
2845
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2846
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2847
				// FIXME: Add IPv6 Support to the pfSense module
2848
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2849
			}
2850
			break;
2851
	}
2852

    
2853
	if(does_interface_exist($wancfg['if']))
2854
		interfaces_bring_up($wancfg['if']);
2855

    
2856
	interface_netgraph_needed($interface);
2857

    
2858
	if (!$g['booting']) {
2859
		link_interface_to_vips($interface, "update");
2860

    
2861
		unset($gre);
2862
		$gre = link_interface_to_gre($interface);
2863
		if (!empty($gre))
2864
			array_walk($gre, 'interface_gre_configure');
2865

    
2866
		unset($gif);
2867
		$gif = link_interface_to_gif($interface);
2868
		if (!empty($gif))
2869
			array_walk($gif, 'interface_gif_configure');
2870

    
2871
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2872
			unset($bridgetmp);
2873
			$bridgetmp = link_interface_to_bridge($interface);
2874
			if (!empty($bridgetmp))
2875
				interface_bridge_add_member($bridgetmp, $realif);
2876
		}
2877

    
2878
		$grouptmp = link_interface_to_group($interface);
2879
		if (!empty($grouptmp))
2880
			array_walk($grouptmp, 'interface_group_add_member');
2881

    
2882
		if ($interface == "lan")
2883
			/* make new hosts file */
2884
			system_hosts_generate();
2885

    
2886
		if ($reloadall == true) {
2887

    
2888
			/* reconfigure static routes (kernel may have deleted them) */
2889
			system_routing_configure($interface);
2890

    
2891
			/* reload ipsec tunnels */
2892
			vpn_ipsec_configure();
2893

    
2894
			/* restart dnsmasq */
2895
			services_dnsmasq_configure();
2896

    
2897
			/* update dyndns */
2898
			send_event("service reload dyndns {$interface}");
2899

    
2900
			/* reload captive portal */
2901
			captiveportal_init_rules();
2902
		}
2903
	}
2904

    
2905
	return 0;
2906
}
2907

    
2908
function interface_track6_configure($interface = "lan") {
2909
	global $config, $g;
2910

    
2911
	$wancfg = $config['interfaces'][$interface];
2912
	if (empty($config['interfaces'][$interface]))
2913
		return;
2914

    
2915
	/* If the interface is not configured via another, exit */
2916
	if (empty($wancfg['track6-interface']))
2917
		return;
2918

    
2919
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
2920
	$realif = get_real_interface($interface);
2921
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
2922

    
2923
	$type = $config['interfaces'][$wancfg['track6-interface']]['ipaddrv6'];
2924
	switch($type) {
2925
		case "6to4":
2926
			if ($g['debug'])
2927
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2928
			interface_track6_6to4_configure($interface);
2929
			break;
2930
		case "6rd":
2931
			if ($g['debug'])
2932
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2933
			interface_track6_6rd_configure($interface);
2934
			break;
2935
		case "dhcp6":
2936
			if ($g['debug'])
2937
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2938
			interface_track6_dhcp6_configure($interface);
2939
			break;
2940
	}
2941

    
2942
	return 0;
2943
}
2944

    
2945

    
2946
function interface_track6_6rd_configure($interface = "lan") {
2947
	global $config, $g;
2948

    
2949
	$lancfg = $config['interfaces'][$interface];
2950
	if (empty($config['interfaces'][$interface]))
2951
		return;
2952

    
2953
	/* If the interface is not configured via another, exit */
2954
	if (empty($lancfg['track6-interface']))
2955
		return;
2956

    
2957
	if (!is_numeric($lancfg['track6-prefix-id']))
2958
		$lancfg['track6-prefix-id'] = 0;
2959

    
2960
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2961
	if (empty($wancfg))
2962
		return;
2963

    
2964
	$wanif = get_real_interface($lancfg['track6-interface']);
2965
	$ip4address = find_interface_ip($wanif);
2966
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
2967
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
2968
		return;
2969
	}
2970
	$hexwanv4 = return_hex_ipv4($ip4address);
2971

    
2972
	/* create the long prefix notation for math, save the prefix length */
2973
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
2974
	$rd6prefixlen = $rd6prefix[1];
2975
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
2976

    
2977
	/* binary presentation of the prefix for all 128 bits. */
2978
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
2979

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

    
2985
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
2986
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
2987
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
2988
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
2989
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
2990
	/* fill the rest out with zeros */
2991
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
2992

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

    
2996
	$lanif = get_real_interface($interface);
2997
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
2998
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
2999

    
3000
	return 0;
3001
}
3002

    
3003
function interface_track6_6to4_configure($interface = "lan") {
3004
	global $config, $g;
3005

    
3006
	$lancfg = $config['interfaces'][$interface];
3007
	if (empty($config['interfaces'][$interface]))
3008
		return;
3009

    
3010
	/* If the interface is not configured via another, exit */
3011
	if (empty($lancfg['track6-interface']))
3012
		return;
3013

    
3014
	if (!is_numeric($lancfg['track6-prefix-id']))
3015
		$lancfg['track6-prefix-id'] = 0;
3016

    
3017
	$wanif = get_real_interface($lancfg['track6-interface']);
3018
	if (!$wanif)
3019
		return;
3020
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3021
	if (empty($wancfg))
3022
		$wancfg = array();
3023

    
3024
	$ip4address = find_interface_ip($wanif);
3025
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3026
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3027
		return;
3028
	}
3029
	$hexwanv4 = return_hex_ipv4($ip4address);
3030

    
3031
	/* create the long prefix notation for math, save the prefix length */
3032
	$sixto4prefix = "2002::";
3033
	$sixto4prefixlen = 16;
3034
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3035

    
3036
	/* binary presentation of the prefix for all 128 bits. */
3037
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3038

    
3039
	/* just save the left prefix length bits */
3040
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3041
	/* add the v4 address */
3042
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3043
	/* add the custom prefix id */
3044
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3045
	/* fill the rest out with zeros */
3046
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3047

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

    
3051
	$lanif = get_real_interface($interface);
3052
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3053
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3054

    
3055
	return 0;
3056
}
3057

    
3058
function interface_track6_dhcp6_configure($interface = "lan") {
3059
	global $config, $g;
3060

    
3061
	$lancfg = $config['interfaces'][$interface];
3062
	if (empty($config['interfaces'][$interface]))
3063
		return;
3064

    
3065
	/* If the interface is not configured via another, exit */
3066
	if (empty($lancfg['track6-interface']))
3067
		return;
3068

    
3069
	if (!is_numeric($lancfg['track6-prefix-id']))
3070
		$lancfg['track6-prefix-id'] = 0;
3071

    
3072
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3073
	if (empty($wancfg))
3074
		$wancfg = array();
3075

    
3076
	$wanif = get_real_interface($lancfg['track6-interface']);
3077
	$ifcfgipv6 = find_interface_ipv6($wanif);
3078
	if (is_ipaddrv6($ifcfgipv6)) {
3079
		$dhcp6lanarr = explode(":", Net_IPv6::uncompress($ifcfgipv6));
3080
		$dhcp6lanarr[4] = 0;
3081
		$dhcp6lanarr[5] = 0;
3082
		$dhcp6lanarr[6] = 0;
3083
		$dhcp6lanarr[7] = 1;
3084
		$dhcp6lan =  Net_IPv6::compress(implode(":", $dhcp6lanarr));
3085
		$lanif = get_real_interface($interface);
3086
		log_error("dhcp6 {$interface} with ipv6 address {$dhcp6lan} based on {$lancfg['track6-interface']}");
3087
		mwexec("/sbin/ifconfig {$lanif} inet6 {$dhcp6lan} prefixlen 64");
3088
	}
3089

    
3090
	return 0;
3091
}
3092

    
3093
function interface_6rd_configure($interface = "wan") {
3094
	global $config, $g;
3095

    
3096
	/* because this is a tunnel interface we can only function
3097
	 *	with a public IPv4 address on the interface */
3098

    
3099
	$wancfg = $config['interfaces'][$interface];
3100
	if (empty($wancfg))
3101
		return;
3102

    
3103
	$wanif = get_real_interface($interface);
3104
	$ip4address = find_interface_ip($wanif);
3105
	$ip4gateway = get_interface_gateway($wanif);
3106
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3107
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3108
		return false;
3109
	}
3110
	$hexwanv4 = return_hex_ipv4($ip4address);
3111

    
3112
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3113
		$wancfg['prefix-6rd-v4plen'] = 0;
3114

    
3115
	/* create the long prefix notation for math, save the prefix length */
3116
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3117
	$rd6prefixlen = $rd6prefix[1];
3118
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3119

    
3120
	/* we need the hex form of the broker IPv4 address */
3121
	$hexbrv4 = return_hex_ipv4($wancfg['gateway-6rd']);
3122

    
3123
	/* binary presentation of the prefix for all 128 bits. */
3124
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3125

    
3126
	/* just save the left prefix length bits */
3127
	$rd6brprefixbin = substr($rd6prefixbin, 0, $rd6prefixlen);
3128
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3129
	$rd6brprefixbin .= substr(sprintf("%032b", hexdec($hexbrv4)), $wancfg['prefix-6rd-v4plen'], 32);
3130
	/* fill out the rest with 0's */
3131
	$rd6brprefixbin = str_pad($rd6brprefixbin, 128, "0", STR_PAD_RIGHT);;
3132

    
3133
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3134
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3135

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

    
3143
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3144
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3145

    
3146
	/* stf approach only works when embedding the entire 32 bits of the v4 */
3147
	mwexec("/sbin/ifconfig stf0 create");
3148
	pfSense_interface_flags("stf0", IFF_LINK2);
3149
	mwexec("/sbin/ifconfig stf0 inet6 {$rd6prefix}/{$rd6prefixlen}");
3150
	if ($g['debug'])
3151
		log_error("Created 6rd interface stf0 {$rd6prefix}/{$rd6prefixlen}");
3152

    
3153
	/* write out a default router file */
3154
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3155
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3156

    
3157
	if (is_ipaddrv4($ip4gateway))
3158
		mwexec("/sbin/route change -host " . $wancfg['gateway-6rd'] . " {$ip4gateway}");
3159

    
3160
	/* configure dependent interfaces */
3161
	/* XXX: Really necessary? */
3162
	$iflist = get_configured_interface_with_descr(false, true);
3163
	foreach($iflist as $if => $ifname) {
3164
		if ($config['interfaces'][$if]['track6-interface'] == $interface)
3165
			interface_track6_configure($if);
3166
	}
3167

    
3168
	return 0;
3169
}
3170

    
3171
function interface_6to4_configure($interface = "wan"){
3172
	global $config, $g;
3173
	$iflist = get_configured_interface_with_descr(false, true);
3174

    
3175
	/* because this is a tunnel interface we can only function
3176
	 *	with a public IPv4 address on the interface */
3177

    
3178
	$wancfg = $config['interfaces'][$interface];
3179
	$wanif = $wancfg['if'];
3180
	if (empty($wancfg))
3181
		$wancfg = array();
3182

    
3183
	$wanif = get_real_interface($interface);
3184

    
3185
	$ip4address = find_interface_ip($wanif);
3186
	$ip4gateway = get_interface_gateway($wanif);
3187
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3188
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3189
		return false;
3190
	}
3191

    
3192
	/* create the long prefix notation for math, save the prefix length */
3193
	$stfprefixlen = 16;
3194
	$stfprefix = Net_IPv6::uncompress("2002::");
3195
	$stfarr = explode(":", $stfprefix);
3196
	$v4prefixlen = "0";
3197

    
3198
	/* we need the hex form of the interface IPv4 address */
3199
	$ip4arr = explode(".", $ip4address);
3200
	$hexwanv4 = "";
3201
	foreach($ip4arr as $octet)
3202
		$hexwanv4 .= sprintf("%02x", $octet);
3203

    
3204
	/* we need the hex form of the broker IPv4 address */
3205
	$ip4arr = explode(".", "192.88.99.1");
3206
	$hexbrv4 = "";
3207
	foreach($ip4arr as $octet)
3208
		$hexbrv4 .= sprintf("%02x", $octet);
3209

    
3210
	/* binary presentation of the prefix for all 128 bits. */
3211
	$stfprefixbin = "";
3212
	foreach($stfarr as $element) {
3213
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3214
	}
3215
	/* just save the left prefix length bits */
3216
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3217

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

    
3222
	/* for the local subnet too. */
3223
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3224
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3225

    
3226
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3227
	$stfbrarr = array();
3228
	$stfbrbinarr = array();
3229
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3230
	foreach($stfbrbinarr as $bin)
3231
		$stfbrarr[] = dechex(bindec($bin));
3232
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3233

    
3234
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3235
	$stflanarr = array();
3236
	$stflanbinarr = array();
3237
	$stflanbinarr = str_split($stflanbin, 16);
3238
	foreach($stflanbinarr as $bin)
3239
		$stflanarr[] = dechex(bindec($bin));
3240
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3241
	$stflanarr[7] = 1;
3242
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3243

    
3244
	/* setup the stf interface */
3245
	mwexec("/sbin/ifconfig stf0 destroy");
3246
	mwexec("/sbin/ifconfig stf0 create");
3247
	pfSense_interface_flags("stf0", IFF_LINK2);
3248
	mwexec("/sbin/ifconfig stf0 inet6 {$stflanpr} prefixlen 16");
3249

    
3250
	log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for stf0, route {$stfbrgw}");
3251

    
3252
	/* write out a default router file */
3253
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3254
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3255

    
3256
	if (is_ipaddrv4($ip4gateway)) {
3257
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3258
	}
3259

    
3260
	/* configure dependent interfaces */
3261
	foreach($iflist as $if => $ifname) {
3262
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3263
			interface_track6_configure($if);
3264
	}
3265

    
3266
	return 0;
3267
}
3268

    
3269
function interface_dhcpv6_configure($interface = "wan") {
3270
	global $config, $g;
3271

    
3272
	$wancfg = $config['interfaces'][$interface];
3273
	if (empty($config['interfaces'][$interface]))
3274
		return;
3275

    
3276
	$wanif = get_real_interface($interface);
3277

    
3278
	$dhcp6cconf = "";
3279
	$dhcp6cconf .= "interface {$wanif} {\n";
3280

    
3281
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3282
	if($wancfg['ipaddrv6'] == "slaac") {
3283
		$dhcp6cconf .= "	information-only;\n";
3284
		$dhcp6cconf .= "	request domain-name-servers;\n";
3285
		$dhcp6cconf .= "	request domain-name;\n";
3286
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3287
		$dhcp6cconf .= "};\n";
3288
	} else {
3289

    
3290
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3291
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3292
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3293
		$dhcp6cconf .= "request domain-name-servers;\n";
3294
		$dhcp6cconf .= "request domain-name;\n";
3295
		$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3296

    
3297
		$dhcp6cconf .= "};\n";
3298
		$dhcp6cconf .= "id-assoc na 0 { };\n";
3299
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3300
			/* Setup the prefix delegation */
3301
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3302
			$iflist = get_configured_interface_with_descr(false, true);
3303
			foreach($iflist as $friendly => $ifdescr) {
3304
				if($config['interfaces'][$friendly]['track6-interface'] != $interface)
3305
					continue;
3306
				if (is_numeric($config['interfaces'][$friendly]['track6-prefix-id'])) {
3307
					log_error("setting up $ifdescr - {$config['interfaces'][$friendly]['track6-prefix-id']}");
3308
					$realif = get_real_interface($friendly);
3309
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3310
					$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['track6-prefix-id']};\n";
3311
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3312
					$dhcp6cconf .= "	};\n";
3313
				}
3314
			}
3315
			$dhcp6cconf .= "};\n";
3316
		}
3317
	}
3318
	/* wide-dhcp6c works for now. */
3319
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3320
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3321
		unet($dhcp6cconf);
3322
		return 1;
3323
	}
3324
	unet($dhcp6cconf);
3325

    
3326
	$dhcp6cscript = "#!/bin/sh\n";
3327
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3328
	$dhcp6cscript .= "/etc/rc.newwanipv6 {$wanif} \n";
3329
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3330
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3331
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3332
		unet($dhcp6cscript);
3333
		return 1;
3334
	}
3335
	unet($dhcp6cscript);
3336
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3337

    
3338

    
3339
	/* accept router advertisements for this interface */
3340
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3341
	log_error("Accept router advertisements on interface {$wanif} ");
3342
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3343

    
3344
	/* run a filter configure sync so that the filter rules allow traffic before we launch the client */
3345
	/* there reallyt is no good way around this i'm 'fraid */
3346
	filter_configure_sync();
3347

    
3348
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3349
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$interface}.pid {$wanif}");
3350
	sleep(1);
3351
	unset($out);
3352
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3353
	if (!empty($out)) {
3354
		foreach($out as $line) {
3355
			if((stristr($line, "received")) && (!stristr($line, "unexpected"))) {
3356
				$parts = explode(" ", $line);
3357
				if(is_ipaddrv6($parts[3])) {
3358
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3359
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3360
					file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$parts[3]}\n");
3361
					break;
3362
				}
3363
			}
3364
		}
3365
	}
3366
	/* worst case is that the rc.newwanipv6 handles setting up the track6 interface */
3367
	if ($wancfg['ippaddrv6'] != "slaac") {
3368
		/* configure dependent interfaces */
3369
		/* XXX: Really necessary? */
3370
		$iflist = get_configured_interface_with_descr(false, true);
3371
		foreach($iflist as $if => $ifname) {
3372
			if ($config['interfaces'][$if]['track6-interface'] == $interface)
3373
				interface_track6_configure($if);
3374
		}
3375
	}
3376

    
3377
	return 0;
3378
}
3379

    
3380
function interface_dhcp_configure($interface = "wan") {
3381
	global $config, $g;
3382

    
3383
	$wancfg = $config['interfaces'][$interface];
3384
	$wanif = $wancfg['if'];
3385
	if (empty($wancfg))
3386
		$wancfg = array();
3387

    
3388
	/* generate dhclient_wan.conf */
3389
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3390
	if (!$fd) {
3391
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3392
		return 1;
3393
	}
3394

    
3395
	if ($wancfg['dhcphostname']) {
3396
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3397
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3398
	} else {
3399
		$dhclientconf_hostname = "";
3400
	}
3401

    
3402
	$wanif = get_real_interface($interface);
3403
	if (empty($wanif)) {
3404
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3405
		return 0;
3406
	}
3407
	$dhclientconf = "";
3408

    
3409
	$dhclientconf .= <<<EOD
3410
interface "{$wanif}" {
3411
timeout 60;
3412
retry 15;
3413
select-timeout 0;
3414
initial-interval 1;
3415
	{$dhclientconf_hostname}
3416
	script "/sbin/dhclient-script";
3417
}
3418

    
3419
EOD;
3420

    
3421
if(is_ipaddr($wancfg['alias-address'])) {
3422
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3423
	$dhclientconf .= <<<EOD
3424
alias {
3425
	interface  "{$wanif}";
3426
	fixed-address {$wancfg['alias-address']};
3427
	option subnet-mask {$subnetmask};
3428
}
3429

    
3430
EOD;
3431
}
3432
	fwrite($fd, $dhclientconf);
3433
	fclose($fd);
3434

    
3435
	/* bring wan interface up before starting dhclient */
3436
	if($wanif)
3437
		interfaces_bring_up($wanif);
3438
	else
3439
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3440

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

    
3444
	return 0;
3445
}
3446

    
3447
function interfaces_group_setup() {
3448
	global $config;
3449

    
3450
	if (!is_array($config['ifgroups']['ifgroupentry']))
3451
		return;
3452

    
3453
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3454
		interface_group_setup($groupar);
3455

    
3456
	return;
3457
}
3458

    
3459
function interface_group_setup(&$groupname /* The parameter is an array */) {
3460
	global $config;
3461

    
3462
	if (!is_array($groupname))
3463
		return;
3464
	$members = explode(" ", $groupname['members']);
3465
	foreach($members as $ifs) {
3466
		$realif = get_real_interface($ifs);
3467
		if ($realif)
3468
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3469
	}
3470

    
3471
	return;
3472
}
3473

    
3474
function interface_group_add_member($interface, $groupname) {
3475
	$interface = get_real_interface($interface);
3476
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3477
}
3478

    
3479
/* COMPAT Function */
3480
function convert_friendly_interface_to_real_interface_name($interface) {
3481
	return get_real_interface($interface);
3482
}
3483

    
3484
/* COMPAT Function */
3485
function get_real_wan_interface($interface = "wan") {
3486
	return get_real_interface($interface);
3487
}
3488

    
3489
/* COMPAT Function */
3490
function get_current_wan_address($interface = "wan") {
3491
	return get_interface_ip($interface);
3492
}
3493

    
3494
/*
3495
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3496
 */
3497
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3498
	global $config;
3499

    
3500
	if (stristr($interface, "_vip")) {
3501
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
3502
			if ($vip['mode'] == "carp")  {
3503
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3504
					return $vip['interface'];
3505
			}
3506
		}
3507
	}
3508

    
3509
	/* XXX: For speed reasons reference directly the interface array */
3510
	$ifdescrs = &$config['interfaces'];
3511
	//$ifdescrs = get_configured_interface_list(false, true);
3512

    
3513
	foreach ($ifdescrs as $if => $ifname) {
3514
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3515
			return $if;
3516

    
3517
		if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3518
			return $if;
3519

    
3520
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3521
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3522
		/*
3523
		$int = get_parent_interface($if);
3524
		if ($int[0] == $interface)
3525
			return $ifname;
3526
		 */
3527
	}
3528
	return NULL;
3529
}
3530

    
3531
/* attempt to resolve interface to friendly descr */
3532
function convert_friendly_interface_to_friendly_descr($interface) {
3533
	global $config;
3534

    
3535
	switch ($interface) {
3536
	case "l2tp":
3537
		$ifdesc = "L2TP";
3538
		break;
3539
	case "pptp":
3540
		$ifdesc = "PPTP";
3541
		break;
3542
	case "pppoe":
3543
		$ifdesc = "PPPoE";
3544
		break;
3545
	case "openvpn":
3546
		$ifdesc = "OpenVPN";
3547
		break;
3548
	case "enc0":
3549
	case "ipsec":
3550
		$ifdesc = "IPsec";
3551
		break;
3552
	default:
3553
		if (isset($config['interfaces'][$interface])) {
3554
			if (empty($config['interfaces'][$interface]['descr']))
3555
				$ifdesc = strtoupper($interface);
3556
			else
3557
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3558
			break;
3559
		} else if (stristr($interface, "_vip")) {
3560
			if (is_array($config['virtualip']['vip'])) {
3561
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3562
					if ($vip['mode'] == "carp")  {
3563
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3564
							return "{$vip['subnet']} - {$vip['descr']}";
3565
					}
3566
				}
3567
			}
3568
		} else {
3569
			/* if list */
3570
			$ifdescrs = get_configured_interface_with_descr(false, true);
3571
			foreach ($ifdescrs as $if => $ifname) {
3572
				if ($if == $interface || $ifname == $interface)
3573
					return $ifname;
3574
			}
3575
		}
3576
		break;
3577
	}
3578

    
3579
	return $ifdesc;
3580
}
3581

    
3582
function convert_real_interface_to_friendly_descr($interface) {
3583
	global $config;
3584

    
3585
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3586

    
3587
	if ($ifdesc) {
3588
		$iflist = get_configured_interface_with_descr(false, true);
3589
		return $iflist[$ifdesc];
3590
	}
3591

    
3592
	return $interface;
3593
}
3594

    
3595
/*
3596
 *  get_parent_interface($interface):
3597
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3598
 *				or virtual interface (i.e. vlan)
3599
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3600
 *			-- returns $interface passed in if $interface parent is not found
3601
 *			-- returns empty array if an invalid interface is passed
3602
 *	(Only handles ppps and vlans now.)
3603
 */
3604
function get_parent_interface($interface) {
3605
	global $config;
3606

    
3607
	$parents = array();
3608
	//Check that we got a valid interface passed
3609
	$realif = get_real_interface($interface);
3610
	if ($realif == NULL)
3611
		return $parents;
3612

    
3613
	// If we got a real interface, find it's friendly assigned name
3614
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3615

    
3616
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3617
		$ifcfg = $config['interfaces'][$interface];
3618
		switch ($ifcfg['ipaddr']) {
3619
			case "ppp":
3620
			case "pppoe":
3621
			case "pptp":
3622
			case "l2tp":
3623
				if (empty($parents))
3624
					if (is_array($config['ppps']['ppp']))
3625
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3626
							if ($ifcfg['if'] == $ppp['if']) {
3627
								$ports = explode(',', $ppp['ports']);
3628
								foreach ($ports as $pid => $parent_if)
3629
									$parents[$pid] = get_real_interface($parent_if);
3630
								break;
3631
							}
3632
						}
3633
				break;
3634
			case "dhcp":
3635
			case "static":
3636
			default:
3637
				// Handle _vlans
3638
				if (strstr($realif,"_vlan"))
3639
					if (is_array($config['vlans']['vlan']))
3640
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3641
							if ($ifcfg['if'] == $vlan['vlanif']){
3642
								$parents[0] = $vlan['if'];
3643
								break;
3644
							}
3645
				break;
3646
		}
3647
	}
3648

    
3649
	if (empty($parents))
3650
		$parents[0] = $realif;
3651

    
3652
	return $parents;
3653
}
3654

    
3655
function interface_is_wireless_clone($wlif) {
3656
	if(!stristr($wlif, "_wlan")) {
3657
		return false;
3658
	} else {
3659
		return true;
3660
	}
3661
}
3662

    
3663
function interface_get_wireless_base($wlif) {
3664
	if(!stristr($wlif, "_wlan")) {
3665
		return $wlif;
3666
	} else {
3667
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3668
	}
3669
}
3670

    
3671
function interface_get_wireless_clone($wlif) {
3672
	if(!stristr($wlif, "_wlan")) {
3673
		return $wlif . "_wlan0";
3674
	} else {
3675
		return $wlif;
3676
	}
3677
}
3678

    
3679
function get_real_interface($interface = "wan") {
3680
	global $config;
3681

    
3682
	$wanif = NULL;
3683

    
3684
	switch ($interface) {
3685
	case "l2tp":
3686
		$wanif = "l2tp";
3687
		break;
3688
	case "pptp":
3689
		$wanif = "pptp";
3690
		break;
3691
	case "pppoe":
3692
		$wanif = "pppoe";
3693
		break;
3694
	case "openvpn":
3695
		$wanif = "openvpn";
3696
		break;
3697
	case "ipsec":
3698
	case "enc0":
3699
		$wanif = "enc0";
3700
		break;
3701
	case "ppp":
3702
		$wanif = "ppp";
3703
		break;
3704
	default:
3705
		// If a real interface was alread passed simply
3706
		// pass the real interface back.  This encourages
3707
		// the usage of this function in more cases so that
3708
		// we can combine logic for more flexibility.
3709
		if(does_interface_exist($interface)) {
3710
			$wanif = $interface;
3711
			break;
3712
		}
3713

    
3714
		if (empty($config['interfaces'][$interface]))
3715
			break;
3716

    
3717
		$cfg = &$config['interfaces'][$interface];
3718

    
3719
		// Wireless cloned NIC support (FreeBSD 8+)
3720
		// interface name format: $parentnic_wlanparentnic#
3721
		// example: ath0_wlan0
3722
		if (is_interface_wireless($cfg['if'])) {
3723
			$wanif = interface_get_wireless_clone($cfg['if']);
3724
			break;
3725
		}
3726
		/*
3727
		if (empty($cfg['if'])) {
3728
			$wancfg = $cfg['if'];
3729
			break;
3730
		}
3731
		*/
3732

    
3733
		switch ($cfg['ipaddr']) {
3734
			case "pppoe":
3735
			case "pptp":
3736
			case "l2tp":
3737
			case "ppp":
3738
				$wanif = $cfg['if'];
3739
				break;
3740
			default:
3741
				$wanif = $cfg['if'];
3742
				break;
3743
		}
3744
		break;
3745
	}
3746

    
3747
	return $wanif;
3748
}
3749

    
3750
/* Guess the physical interface by providing a IP address */
3751
function guess_interface_from_ip($ipaddress) {
3752
	if(! is_ipaddr($ipaddress)) {
3753
		return false;
3754
	}
3755
	if(is_ipaddrv4($ipaddress)) {
3756
		/* create a route table we can search */
3757
		exec("netstat -rnWf inet", $output, $ret);
3758
		foreach($output as $line) {
3759
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3760
				$fields = preg_split("/[ ]+/", $line);
3761
				if(ip_in_subnet($ipaddress, $fields[0])) {
3762
					return $fields[6];
3763
				}
3764
			}
3765
		}
3766
	}
3767
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3768
	if(is_ipaddrv6($ipaddress)) {
3769
		/* create a route table we can search */
3770
		exec("netstat -rnWf inet6", $output, $ret);
3771
		foreach($output as $line) {
3772
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3773
				$fields = preg_split("/[ ]+/", $line);
3774
				if(ip_in_subnet($ipaddress, $fields[0])) {
3775
					return $fields[6];
3776
				}
3777
			}
3778
		}
3779
	}
3780
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3781
	if(empty($ret)) {
3782
		return false;
3783
	}
3784
	return $ret;
3785
}
3786

    
3787
/*
3788
 * find_ip_interface($ip): return the interface where an ip is defined
3789
 *   (or if $bits is specified, where an IP within the subnet is defined)
3790
 */
3791
function find_ip_interface($ip, $bits = null)
3792
{
3793
	/* if list */
3794
	$ifdescrs = get_configured_interface_list();
3795

    
3796
	foreach ($ifdescrs as $ifdescr => $ifname) {
3797
		if ($bits === null) {
3798
			if ($ip == get_interface_ip($ifname)) {
3799
				$int = get_real_interface($ifname);
3800
				return $int;
3801
			}
3802
		}
3803
		else {
3804
			if (ip_in_subnet(get_interface_ip($ifname), $ip . "/" . $bits)) {
3805
				$int = get_real_interface($ifname);
3806
				return $int;
3807
			}
3808
		}
3809
	}
3810
	return false;
3811
}
3812

    
3813
/*
3814
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
3815
 *   (or if $bits is specified, where an IP within the subnet is found)
3816
 */
3817
function find_virtual_ip_alias($ip, $bits = null) {
3818
	global $config;
3819
	if (!is_array($config['virtualip']['vip'])) {
3820
		return false;
3821
	}
3822
	foreach ($config['virtualip']['vip'] as $vip) {
3823
		if ($vip['mode'] === "ipalias") {
3824
			if ($bits === null) {
3825
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
3826
					return $vip;
3827
				}
3828
			}
3829
			else {
3830
				if (check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits'])) {
3831
					return $vip;
3832
				}
3833
			}
3834
		}
3835
	}
3836
	return false;
3837
}
3838

    
3839
/*
3840
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3841
 */
3842
function find_number_of_created_carp_interfaces() {
3843
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3844
}
3845

    
3846
function get_all_carp_interfaces() {
3847
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3848
	$ints = explode(" ", $ints);
3849
	return $ints;
3850
}
3851

    
3852
/*
3853
 * find_carp_interface($ip): return the carp interface where an ip is defined
3854
 */
3855
function find_carp_interface($ip) {
3856
	global $config;
3857
	if (is_array($config['virtualip']['vip'])) {
3858
		foreach ($config['virtualip']['vip'] as $vip) {
3859
			if ($vip['mode'] == "carp") {
3860
				if(is_ipaddrv4($ip)) {
3861
					$carp_ip = get_interface_ip($vip['interface']);
3862
				}
3863
				if(is_ipaddrv6($ip)) {
3864
					$carp_ip = get_interface_ipv6($vip['interface']);
3865
				}
3866
				exec("/sbin/ifconfig", $output, $return);
3867
				foreach($output as $line) {
3868
					$elements = preg_split("/[ ]+/i", $line);
3869
					if(strstr($elements[0], "vip"))
3870
						$curif = str_replace(":", "", $elements[0]);
3871
					if(stristr($line, $ip)) {
3872
						$if = $curif;
3873
						continue;
3874
					}
3875
				}
3876

    
3877
				if ($if)
3878
					return $if;
3879
			}
3880
		}
3881
	}
3882
}
3883

    
3884
function link_carp_interface_to_parent($interface) {
3885
	global $config;
3886

    
3887
	if ($interface == "")
3888
		return;
3889

    
3890
	$carp_ip = get_interface_ip($interface);
3891
	$carp_ipv6 = get_interface_ipv6($interface);
3892

    
3893
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
3894
		return;
3895

    
3896
	/* if list */
3897
	$ifdescrs = get_configured_interface_list();
3898
	foreach ($ifdescrs as $ifdescr => $ifname) {
3899
		/* check IPv4 */
3900
		if(is_ipaddrv4($carp_ip)) {
3901
			$interfaceip = get_interface_ip($ifname);
3902
			$subnet_bits = get_interface_subnet($ifname);
3903
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3904
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3905
				return $ifname;
3906
		}
3907
		/* Check IPv6 */
3908
		if(is_ipaddrv6($carp_ipv6)) {
3909
			$interfaceipv6 = get_interface_ipv6($ifname);
3910
			$prefixlen = get_interface_subnetv6($ifname);
3911
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
3912
				return $ifname;
3913
		}
3914
	}
3915
	return "";
3916
}
3917

    
3918

    
3919
/****f* interfaces/link_ip_to_carp_interface
3920
 * NAME
3921
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3922
 * INPUTS
3923
 *   $ip
3924
 * RESULT
3925
 *   $carp_ints
3926
 ******/
3927
function link_ip_to_carp_interface($ip) {
3928
	global $config;
3929

    
3930
	if (!is_ipaddr($ip))
3931
		return;
3932

    
3933
	$carp_ints = "";
3934
	if (is_array($config['virtualip']['vip'])) {
3935
		$first = 0;
3936
		$carp_int = array();
3937
		foreach ($config['virtualip']['vip'] as $vip) {
3938
			if ($vip['mode'] == "carp") {
3939
				$carp_ip = $vip['subnet'];
3940
				$carp_sn = $vip['subnet_bits'];
3941
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
3942
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
3943
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
3944
				}
3945
			}
3946
		}
3947
		if (!empty($carp_int))
3948
			$carp_ints = implode(" ", array_unique($carp_int));
3949
	}
3950

    
3951
	return $carp_ints;
3952
}
3953

    
3954
function link_interface_to_vlans($int, $action = "") {
3955
	global $config;
3956

    
3957
	if (empty($int))
3958
		return;
3959

    
3960
	if (is_array($config['vlans']['vlan'])) {
3961
		foreach ($config['vlans']['vlan'] as $vlan) {
3962
			if ($int == $vlan['if']) {
3963
				if ($action == "update") {
3964
					interfaces_bring_up($int);
3965
				} else if ($action == "")
3966
					return $vlan;
3967
			}
3968
		}
3969
	}
3970
}
3971

    
3972
function link_interface_to_vips($int, $action = "") {
3973
	global $config;
3974

    
3975
	if (is_array($config['virtualip']['vip'])) {
3976
		$result = array();
3977
		foreach ($config['virtualip']['vip'] as $vip) {
3978
			if ($int == $vip['interface']) {
3979
				if ($action == "update")
3980
					interfaces_vips_configure($int);
3981
				else
3982
					$result[] = $vip;
3983
			}
3984
		}
3985
		return $result;
3986
	}
3987
}
3988

    
3989
/****f* interfaces/link_interface_to_bridge
3990
 * NAME
3991
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3992
 * INPUTS
3993
 *   $ip
3994
 * RESULT
3995
 *   bridge[0-99]
3996
 ******/
3997
function link_interface_to_bridge($int) {
3998
	global $config;
3999

    
4000
	if (is_array($config['bridges']['bridged'])) {
4001
		foreach ($config['bridges']['bridged'] as $bridge) {
4002
			if (in_array($int, explode(',', $bridge['members'])))
4003
				return "{$bridge['bridgeif']}";
4004
		}
4005
	}
4006
}
4007

    
4008
function link_interface_to_group($int) {
4009
	global $config;
4010

    
4011
	$result = array();
4012

    
4013
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4014
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4015
			if (in_array($int, explode(" ", $group['members'])))
4016
				$result[$group['ifname']] = $int;
4017
		}
4018
	}
4019

    
4020
	return $result;
4021
}
4022

    
4023
function link_interface_to_gre($interface) {
4024
	global $config;
4025

    
4026
	$result = array();
4027

    
4028
	if (is_array($config['gres']['gre'])) {
4029
		foreach ($config['gres']['gre'] as $gre)
4030
			if($gre['if'] == $interface)
4031
				$result[] = $gre;
4032
	}
4033

    
4034
	return $result;
4035
}
4036

    
4037
function link_interface_to_gif($interface) {
4038
	global $config;
4039

    
4040
	$result = array();
4041

    
4042
	if (is_array($config['gifs']['gif'])) {
4043
		foreach ($config['gifs']['gif'] as $gif)
4044
			if($gif['if'] == $interface)
4045
				$result[] = $gif;
4046
	}
4047

    
4048
	return $result;
4049
}
4050

    
4051
/*
4052
 * find_interface_ip($interface): return the interface ip (first found)
4053
 */
4054
function find_interface_ip($interface, $flush = false)
4055
{
4056
	global $interface_ip_arr_cache;
4057
	global $interface_sn_arr_cache;
4058

    
4059
	$interface = str_replace("\n", "", $interface);
4060

    
4061
	if (!does_interface_exist($interface))
4062
		return;
4063

    
4064
	/* Setup IP cache */
4065
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4066
		$ifinfo = pfSense_get_interface_addresses($interface);
4067
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4068
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4069
	}
4070

    
4071
	return $interface_ip_arr_cache[$interface];
4072
}
4073

    
4074
/*
4075
 * find_interface_ipv6($interface): return the interface ip (first found)
4076
 */
4077
function find_interface_ipv6($interface, $flush = false)
4078
{
4079
	global $interface_ipv6_arr_cache;
4080
	global $interface_snv6_arr_cache;
4081
	global $config;
4082

    
4083
	$interface = trim($interface);
4084
	$interface = get_real_interface($interface);
4085

    
4086
	if (!does_interface_exist($interface))
4087
		return;
4088

    
4089
	/* Setup IP cache */
4090
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4091
		$ifinfo = pfSense_get_interface_addresses($interface);
4092
		// FIXME: Add IPv6 support to the pfSense module
4093
		exec("/sbin/ifconfig {$interface} inet6", $output);
4094
		foreach($output as $line) {
4095
			if(preg_match("/inet6/", $line)) {
4096
				$parts = explode(" ", $line);
4097
				if(! preg_match("/fe80::/", $parts[1])) {
4098
					$ifinfo['ipaddrv6'] = $parts[1];
4099
					if($parts[2] == "-->") {
4100
						$parts[5] = "126";
4101
						$ifinfo['subnetbitsv6'] = $parts[5];
4102
					} else {
4103
						$ifinfo['subnetbitsv6'] = $parts[3];
4104
					}
4105
				}
4106
			}
4107
		}
4108
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4109
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4110
	}
4111

    
4112
	return $interface_ipv6_arr_cache[$interface];
4113
}
4114

    
4115
/*
4116
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4117
 */
4118
function find_interface_ipv6_ll($interface, $flush = false)
4119
{
4120
	global $interface_llv6_arr_cache;
4121
	global $config;
4122

    
4123
	$interface = str_replace("\n", "", $interface);
4124

    
4125
	if (!does_interface_exist($interface))
4126
		return;
4127

    
4128
	/* Setup IP cache */
4129
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4130
		$ifinfo = pfSense_get_interface_addresses($interface);
4131
		// FIXME: Add IPv6 support to the pfSense module
4132
		exec("/sbin/ifconfig {$interface} inet6", $output);
4133
		foreach($output as $line) {
4134
			if(preg_match("/inet6/", $line)) {
4135
				$parts = explode(" ", $line);
4136
				if(preg_match("/fe80::/", $parts[1])) {
4137
					$partsaddress = explode("%", $parts[1]);
4138
					$ifinfo['linklocal'] = $partsaddress[0];
4139
				}
4140
			}
4141
		}
4142
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4143
	}
4144
	return $interface_llv6_arr_cache[$interface];
4145
}
4146

    
4147
function find_interface_subnet($interface, $flush = false)
4148
{
4149
	global $interface_sn_arr_cache;
4150
	global $interface_ip_arr_cache;
4151

    
4152
	$interface = str_replace("\n", "", $interface);
4153
	if (does_interface_exist($interface) == false)
4154
		return;
4155

    
4156
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4157
		$ifinfo = pfSense_get_interface_addresses($interface);
4158
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4159
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4160
	}
4161

    
4162
	return $interface_sn_arr_cache[$interface];
4163
}
4164

    
4165
function find_interface_subnetv6($interface, $flush = false)
4166
{
4167
	global $interface_snv6_arr_cache;
4168
	global $interface_ipv6_arr_cache;
4169

    
4170
	$interface = str_replace("\n", "", $interface);
4171
	if (does_interface_exist($interface) == false)
4172
		return;
4173

    
4174
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4175
		$ifinfo = pfSense_get_interface_addresses($interface);
4176
		// FIXME: Add IPv6 support to the pfSense module
4177
		exec("/sbin/ifconfig {$interface} inet6", $output);
4178
		foreach($output as $line) {
4179
			if(preg_match("/inet6/", $line)) {
4180
				$parts = explode(" ", $line);
4181
				if(! preg_match("/fe80::/", $parts[1])) {
4182
					$ifinfo['ipaddrv6'] = $parts[1];
4183
					if($parts[2] == "-->") {
4184
						$parts[5] = "126";
4185
						$ifinfo['subnetbitsv6'] = $parts[5];
4186
					} else {
4187
						$ifinfo['subnetbitsv6'] = $parts[3];
4188
					}
4189
				}
4190
			}
4191
		}
4192
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4193
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4194
	}
4195

    
4196
	return $interface_snv6_arr_cache[$interface];
4197
}
4198

    
4199
function ip_in_interface_alias_subnet($interface, $ipalias) {
4200
	global $config;
4201

    
4202
	if (empty($interface) || !is_ipaddr($ipalias))
4203
		return false;
4204
	if (is_array($config['virtualip']['vip'])) {
4205
		foreach ($config['virtualip']['vip'] as $vip) {
4206
			switch ($vip['mode']) {
4207
			case "ipalias":
4208
				if ($vip['interface'] <> $interface)
4209
					break;
4210
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4211
					return true;
4212
				break;
4213
			}
4214
		}
4215
	}
4216

    
4217
	return false;
4218
}
4219

    
4220
function get_interface_ip($interface = "wan")
4221
{
4222
	$realif = get_failover_interface($interface);
4223
	if (!$realif) {
4224
		if (preg_match("/^carp/i", $interface))
4225
			$realif = $interface;
4226
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4227
			$realif = $interface;
4228
		else
4229
			return null;
4230
	}
4231

    
4232
	$curip = find_interface_ip($realif);
4233
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4234
		return $curip;
4235
	else
4236
		return null;
4237
}
4238

    
4239
function get_interface_ipv6($interface = "wan")
4240
{
4241
	global $config;
4242
	$realif = get_failover_interface($interface);
4243
	switch($config['interfaces'][$interface]['ipaddrv6']) {
4244
		case "6rd":
4245
		case "6to4":
4246
			$realif = "stf0";
4247
			break;
4248
	}
4249
	if (!$realif) {
4250
		if (preg_match("/^carp/i", $interface))
4251
			$realif = $interface;
4252
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4253
			$realif = $interface;
4254
		else
4255
			return null;
4256
	}
4257

    
4258
	$curip = find_interface_ipv6($realif);
4259
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4260
		return $curip;
4261
	else
4262
		return null;
4263
}
4264

    
4265
function get_interface_linklocal($interface = "wan")
4266
{
4267
	$realif = get_failover_interface($interface);
4268
	if (!$realif) {
4269
		if (preg_match("/^carp/i", $interface))
4270
			$realif = $interface;
4271
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4272
			$realif = $interface;
4273
		else
4274
			return null;
4275
	}
4276

    
4277
	$curip = find_interface_ipv6_ll($realif);
4278
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4279
		return $curip;
4280
	else
4281
		return null;
4282
}
4283

    
4284
function get_interface_subnet($interface = "wan")
4285
{
4286
	$realif = get_real_interface($interface);
4287
	if (!$realif) {
4288
		if (preg_match("/^carp/i", $interface))
4289
			$realif = $interface;
4290
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4291
			$realif = $interface;
4292
		else
4293
			return null;
4294
	}
4295

    
4296
	$cursn = find_interface_subnet($realif);
4297
	if (!empty($cursn))
4298
		return $cursn;
4299

    
4300
	return null;
4301
}
4302

    
4303
function get_interface_subnetv6($interface = "wan")
4304
{
4305
	$realif = get_real_interface($interface);
4306
	if (!$realif) {
4307
		if (preg_match("/^carp/i", $interface))
4308
			$realif = $interface;
4309
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4310
			$realif = $interface;
4311
		else
4312
			return null;
4313
	}
4314

    
4315
	$cursn = find_interface_subnetv6($realif);
4316
	if (!empty($cursn))
4317
		return $cursn;
4318

    
4319
	return null;
4320
}
4321

    
4322
/* return outside interfaces with a gateway */
4323
function get_interfaces_with_gateway() {
4324
	global $config;
4325

    
4326
	$ints = array();
4327

    
4328
	/* loop interfaces, check config for outbound */
4329
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4330
		switch ($ifname['ipaddr']) {
4331
			case "dhcp":
4332
			case "ppp";
4333
			case "pppoe":
4334
			case "pptp":
4335
			case "l2tp":
4336
			case "ppp";
4337
				$ints[$ifdescr] = $ifdescr;
4338
			break;
4339
			default:
4340
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4341
				    !empty($ifname['gateway']))
4342
					$ints[$ifdescr] = $ifdescr;
4343
			break;
4344
		}
4345
	}
4346
	return $ints;
4347
}
4348

    
4349
/* return true if interface has a gateway */
4350
function interface_has_gateway($friendly) {
4351
	global $config;
4352

    
4353
	if (!empty($config['interfaces'][$friendly])) {
4354
		$ifname = &$config['interfaces'][$friendly];
4355
		switch ($ifname['ipaddr']) {
4356
			case "dhcp":
4357
			case "pppoe":
4358
			case "pptp":
4359
			case "l2tp":
4360
			case "ppp";
4361
				return true;
4362
			break;
4363
			default:
4364
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4365
					return true;
4366
				if (!empty($ifname['gateway']))
4367
					return true;
4368
			break;
4369
		}
4370
	}
4371

    
4372
	return false;
4373
}
4374

    
4375
/* return true if interface has a gateway */
4376
function interface_has_gatewayv6($friendly) {
4377
	global $config;
4378

    
4379
	if (!empty($config['interfaces'][$friendly])) {
4380
		$ifname = &$config['interfaces'][$friendly];
4381
		switch ($ifname['ipaddrv6']) {
4382
			case "slaac":
4383
			case "dhcp6":
4384
				return true;
4385
				break;
4386
			case "6to4":
4387
				return true;
4388
				break;
4389
			case "6rd":
4390
				return true;
4391
				break;
4392
			default:
4393
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4394
					return true;
4395
				if (!empty($ifname['gatewayv6']))
4396
					return true;
4397
				break;
4398
		}
4399
	}
4400

    
4401
	return false;
4402
}
4403

    
4404
/****f* interfaces/is_altq_capable
4405
 * NAME
4406
 *   is_altq_capable - Test if interface is capable of using ALTQ
4407
 * INPUTS
4408
 *   $int            - string containing interface name
4409
 * RESULT
4410
 *   boolean         - true or false
4411
 ******/
4412

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

    
4426
	$int_family = preg_split("/[0-9]+/", $int);
4427

    
4428
	if (in_array($int_family[0], $capable))
4429
		return true;
4430
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4431
		return true;
4432
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4433
		return true;
4434
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4435
		return true;
4436
	else
4437
		return false;
4438
}
4439

    
4440
/****f* interfaces/is_interface_wireless
4441
 * NAME
4442
 *   is_interface_wireless - Returns if an interface is wireless
4443
 * RESULT
4444
 *   $tmp       - Returns if an interface is wireless
4445
 ******/
4446
function is_interface_wireless($interface) {
4447
	global $config, $g;
4448

    
4449
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4450
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4451
		if (preg_match($g['wireless_regex'], $interface)) {
4452
			if (isset($config['interfaces'][$friendly]))
4453
				$config['interfaces'][$friendly]['wireless'] = array();
4454
			return true;
4455
		}
4456
		return false;
4457
	} else
4458
		return true;
4459
}
4460

    
4461
function get_wireless_modes($interface) {
4462
	/* return wireless modes and channels */
4463
	$wireless_modes = array();
4464

    
4465
	$cloned_interface = get_real_interface($interface);
4466

    
4467
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4468
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4469
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4470
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4471

    
4472
		$interface_channels = "";
4473
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4474
		$interface_channel_count = count($interface_channels);
4475

    
4476
		$c = 0;
4477
		while ($c < $interface_channel_count)
4478
		{
4479
			$channel_line = explode(",", $interface_channels["$c"]);
4480
			$wireless_mode = trim($channel_line[0]);
4481
			$wireless_channel = trim($channel_line[1]);
4482
			if(trim($wireless_mode) != "") {
4483
				/* if we only have 11g also set 11b channels */
4484
				if($wireless_mode == "11g") {
4485
					if(!isset($wireless_modes["11b"]))
4486
						$wireless_modes["11b"] = array();
4487
				} else if($wireless_mode == "11g ht") {
4488
					if(!isset($wireless_modes["11b"]))
4489
						$wireless_modes["11b"] = array();
4490
					if(!isset($wireless_modes["11g"]))
4491
						$wireless_modes["11g"] = array();
4492
					$wireless_mode = "11ng";
4493
				} else if($wireless_mode == "11a ht") {
4494
					if(!isset($wireless_modes["11a"]))
4495
						$wireless_modes["11a"] = array();
4496
					$wireless_mode = "11na";
4497
				}
4498
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4499
			}
4500
			$c++;
4501
		}
4502
	}
4503
	return($wireless_modes);
4504
}
4505

    
4506
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4507
function get_wireless_channel_info($interface) {
4508
	$wireless_channels = array();
4509

    
4510
	$cloned_interface = get_real_interface($interface);
4511

    
4512
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4513
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4514
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4515
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4516

    
4517
		$interface_channels = "";
4518
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4519

    
4520
		foreach ($interface_channels as $channel_line) {
4521
			$channel_line = explode(",", $channel_line);
4522
			if(!isset($wireless_channels[$channel_line[0]]))
4523
				$wireless_channels[$channel_line[0]] = $channel_line;
4524
		}
4525
	}
4526
	return($wireless_channels);
4527
}
4528

    
4529
/****f* interfaces/get_interface_mtu
4530
 * NAME
4531
 *   get_interface_mtu - Return the mtu of an interface
4532
 * RESULT
4533
 *   $tmp       - Returns the mtu of an interface
4534
 ******/
4535
function get_interface_mtu($interface) {
4536
	$mtu = pfSense_get_interface_addresses($interface);
4537
	return $mtu['mtu'];
4538
}
4539

    
4540
function get_interface_mac($interface) {
4541

    
4542
	$macinfo = pfSense_get_interface_addresses($interface);
4543
	return $macinfo["macaddr"];
4544
}
4545

    
4546
/****f* pfsense-utils/generate_random_mac_address
4547
 * NAME
4548
 *   generate_random_mac - generates a random mac address
4549
 * INPUTS
4550
 *   none
4551
 * RESULT
4552
 *   $mac - a random mac address
4553
 ******/
4554
function generate_random_mac_address() {
4555
	$mac = "02";
4556
	for($x=0; $x<5; $x++)
4557
		$mac .= ":" . dechex(rand(16, 255));
4558
	return $mac;
4559
}
4560

    
4561
/****f* interfaces/is_jumbo_capable
4562
 * NAME
4563
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4564
 * INPUTS
4565
 *   $int             - string containing interface name
4566
 * RESULT
4567
 *   boolean          - true or false
4568
 ******/
4569
function is_jumbo_capable($iface) {
4570
	$iface = trim($iface);
4571
	$capable = pfSense_get_interface_addresses($iface);
4572

    
4573
	if (isset($capable['caps']['vlanmtu']))
4574
		return true;
4575

    
4576
	return false;
4577
}
4578

    
4579
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4580
	global $g;
4581

    
4582
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4583

    
4584
	if(!empty($iface) && !empty($pppif)){
4585
		$cron_cmd = <<<EOD
4586
#!/bin/sh
4587
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4588
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
4589

    
4590
EOD;
4591

    
4592
		@file_put_contents($cron_file, $cron_cmd);
4593
		chmod($cron_file, 0755);
4594
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4595
	} else
4596
		unlink_if_exists($cron_file);
4597
}
4598

    
4599
function get_interface_default_mtu($type = "ethernet") {
4600
	switch ($type) {
4601
	case "gre":
4602
		return 1476;
4603
		break;
4604
	case "gif":
4605
		return 1280;
4606
		break;
4607
	case "tun":
4608
	case "vlan":
4609
	case "tap":
4610
	case "ethernet":
4611
	default:
4612
		return 1500;
4613
		break;
4614
	}
4615

    
4616
	/* Never reached */
4617
	return 1500;
4618
}
4619

    
4620
function get_vip_descr($ipaddress) {
4621
	global $config;
4622

    
4623
	foreach ($config['virtualip']['vip'] as $vip) {
4624
		if ($vip['subnet'] == $ipaddress) {
4625
			return ($vip['descr']);
4626
		}
4627
	}
4628
	return "";
4629
}
4630

    
4631
function interfaces_staticarp_configure($if) {
4632
	global $config, $g;
4633
	if(isset($config['system']['developerspew'])) {
4634
		$mt = microtime();
4635
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4636
	}
4637

    
4638
	$ifcfg = $config['interfaces'][$if];
4639

    
4640
	if (empty($if) || empty($ifcfg['if']))
4641
		return 0;
4642

    
4643
	/* Enable staticarp, if enabled */
4644
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4645
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4646
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4647
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4648

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

    
4652
			}
4653

    
4654
		}
4655
	} else {
4656
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4657
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4658
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4659
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
4660
				if (isset($arpent['arp_table_static_entry'])) {
4661
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
4662
				}
4663
			}
4664
		}
4665
	}
4666

    
4667
	return 0;
4668
}
4669

    
4670
function get_failover_interface($interface) {
4671
	global $config;
4672
	/* shortcut to get_real_interface if we find it in the config */
4673
	if(is_array($config['interfaces'][$interface])) {
4674
		$wanif = get_real_interface($interface);
4675
		return $wanif;
4676
	}
4677

    
4678
	/* compare against gateway groups */
4679
	$a_groups = return_gateway_groups_array();
4680
	if(is_array($a_groups[$interface])) {
4681
		/* we found a gateway group, fetch the interface or vip */
4682
		if($a_groups[$interface][0]['vip'] <> "")
4683
			$wanif = $a_groups[$interface][0]['vip'];
4684
		else
4685
			$wanif = $a_groups[$interface][0]['int'];
4686

    
4687
		return $wanif;
4688
	}
4689
	/* fall through to get_real_interface */
4690
	$wanif = get_real_interface($interface);
4691
	return $wanif;
4692
}
4693

    
4694
?>
(25-25/67)