Project

General

Profile

Download (135 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 if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
961
			$delayed_list[$if] = $ifname;
962
		} else {
963
			if ($g['booting'])
964
				printf(gettext("Configuring %s interface..."), $ifname);
965

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

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

    
980
	/* set up GRE virtual interfaces */
981
	interfaces_gre_configure(1);
982

    
983
	/* set up GIF virtual interfaces */
984
	interfaces_gif_configure(1);
985

    
986
	/* set up BRIDGe virtual interfaces */
987
	interfaces_bridge_configure(1);
988

    
989
	/* bring up vip interfaces */
990
	interfaces_vips_configure();
991

    
992
	/* set up GRE virtual interfaces */
993
	interfaces_gre_configure(2);
994

    
995
	/* set up GIF virtual interfaces */
996
	interfaces_gif_configure(2);
997

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

    
1004
		interface_configure($if, $reload);
1005

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

    
1010
	/* set up BRIDGe virtual interfaces */
1011
	interfaces_bridge_configure(2);
1012

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

    
1019
		interface_configure($if, $reload);
1020

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

    
1025
	/* configure interface groups */
1026
	interfaces_group_setup();
1027

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

    
1032
		/* reload IPsec tunnels */
1033
		vpn_ipsec_configure();
1034

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

    
1038
		/* restart dnsmasq */
1039
		services_dnsmasq_configure();
1040

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

    
1046
	return 0;
1047
}
1048

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

    
1054
function interface_vip_bring_down($vip) {
1055
	global $g;
1056

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

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

    
1083
	if (!isset($config['interfaces'][$interface]))
1084
		return;
1085

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

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

    
1097
	$realif = get_real_interface($interface);
1098

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

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

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

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

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

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

    
1215
	return;
1216
}
1217

    
1218
function interfaces_ptpid_used($ptpid) {
1219
	global $config;
1220

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

    
1226
	return false;
1227
}
1228

    
1229
function interfaces_ptpid_next() {
1230

    
1231
	$ptpid = 0;
1232
	while(interfaces_ptpid_used($ptpid))
1233
		$ptpid++;
1234

    
1235
	return $ptpid;
1236
}
1237

    
1238
function getMPDCRONSettings($pppif) {
1239
	global $config;
1240

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

    
1249
	return NULL;
1250
}
1251

    
1252
function handle_pppoe_reset($post_array) {
1253
	global $config, $g;
1254

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

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

    
1261
	$itemhash = getMPDCRONSettings($pppif);
1262

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1533
EOD;
1534

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

    
1539
EOD;
1540

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

    
1548
EOD;
1549

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

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

    
1560
EOD;
1561

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

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

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

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

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

    
1588
EOD;
1589

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

    
1594
EOD;
1595

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

    
1600
EOD;
1601

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

    
1607
EOD;
1608

    
1609

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

    
1614
EOD;
1615

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

    
1621
EOD;
1622

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

    
1627
EOD;
1628

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

    
1633
EOD;
1634

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

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

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

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

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

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

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

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

    
1692
EOD;
1693

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

    
1699
EOD;
1700
		}
1701

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

    
1705

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

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

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

    
1742
	/* fire up mpd */
1743
	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");
1744

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

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

    
1780
	return 1;
1781
}
1782

    
1783
function interfaces_carp_setup() {
1784
	global $g, $config;
1785

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

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

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

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

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

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

    
1827
		sleep(1);
1828

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

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

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

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

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

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

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

    
1880
				if (!empty($interface) && $interface != $proxyif)
1881
					continue;
1882

    
1883
				if (!is_array($paa[$proxyif]))
1884
					$paa[$proxyif] = array();
1885

    
1886
				$paa[$proxyif][] = $vipent;
1887
			}
1888
		}
1889
	}
1890

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

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

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

    
1971
function interface_reload_carps($cif) {
1972
	global $config;
1973

    
1974
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1975
	if (empty($carpifs))
1976
		return;
1977

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

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

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

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

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

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

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

    
2051
	/* invalidate interface cache */
2052
	get_interface_arr(true);
2053

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

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

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

    
2073
	interfaces_bring_up($vipif);
2074

    
2075
	return $vipif;
2076
}
2077

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

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

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

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

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

    
2149
	if(!is_interface_wireless($ifcfg['if']))
2150
		return;
2151

    
2152
	$baseif = interface_get_wireless_base($ifcfg['if']);
2153

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

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

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

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

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

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

    
2224
	// Clone wireless nic if needed.
2225
	interface_wireless_clone($if, $wl);
2226

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2376
	kill_hostapd($if);
2377
	mwexec(kill_wpasupplicant("{$if}"));
2378

    
2379
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2380
	conf_mount_rw();
2381

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

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

    
2436
EOD;
2437

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

    
2444
EOD;
2445

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

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

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

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

    
2473
			}
2474
			break;
2475
	}
2476

    
2477
	/*
2478
	 *    all variables are set, lets start up everything
2479
	 */
2480

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

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

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

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

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

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

    
2527
	fclose($fd_set);
2528
	conf_mount_ro();
2529

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

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

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

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

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

    
2563
		$wlregcmd_args = implode(" ", $wlregcmd);
2564

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

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

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

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

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

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

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

    
2617

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

    
2622
	return 0;
2623

    
2624
}
2625

    
2626
function kill_hostapd($interface) {
2627
	global $g;
2628

    
2629
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2630
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2631
}
2632

    
2633
function kill_wpasupplicant($interface) {
2634
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2635
}
2636

    
2637
function find_dhclient_process($interface) {
2638
	if ($interface)
2639
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2640
	else
2641
		$pid = 0;
2642

    
2643
	return intval($pid);
2644
}
2645

    
2646
function find_dhcp6c_process($interface) {
2647
	global $g;
2648

    
2649
	if ($interface)
2650
		if (isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2651
			$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2652
	else
2653
		return(false);
2654

    
2655
	return intval($pid);
2656
}
2657

    
2658
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2659
	global $config, $g;
2660
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2661
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2662

    
2663
	$wancfg = $config['interfaces'][$interface];
2664

    
2665
	if (!isset($wancfg['enable']))
2666
		return;
2667

    
2668
	$realif = get_real_interface($interface);
2669
	$realhwif_array = get_parent_interface($interface);
2670
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2671
	$realhwif = $realhwif_array[0];
2672

    
2673
	/* Disable Accepting router advertisements unless specifically requested */
2674
	if ($g['debug'])
2675
		log_error("Deny router advertisements for interface {$interface}");
2676
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2677

    
2678
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2679
		/* remove all IPv4 and IPv6 addresses */
2680
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2681
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2682

    
2683
		/* only bring down the interface when both v4 and v6 are set to NONE */
2684
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2685
			interface_bring_down($interface);
2686
		}
2687
	}
2688

    
2689
	/* wireless configuration? */
2690
	if (is_array($wancfg['wireless']))
2691
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2692

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

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

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

    
2731
	/* media */
2732
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2733
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2734
		if ($wancfg['media'])
2735
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2736
		if ($wancfg['mediaopt'])
2737
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2738
		mwexec($cmd);
2739
	}
2740
	if (!empty($wancfg['mtu']))
2741
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2742
	else {
2743
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2744
		if ($mtu != get_interface_mtu($realhwif))
2745
			pfSense_interface_mtu($realhwif, $mtu);
2746
	}
2747

    
2748
	$options = pfSense_get_interface_addresses($realhwif);
2749
	if (is_array($options) && isset($options['caps']['polling'])) {
2750
		if (isset($config['system']['polling']))
2751
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2752
		else
2753
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2754
	}
2755

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

    
2771
		if(isset($config['system']['disablesegmentationoffloading'])) {
2772
			if (isset($options['encaps']['tso4']))
2773
				$flags |= IFCAP_TSO;
2774
			if (isset($options['encaps']['tso6']))
2775
				$flags |= IFCAP_TSO;
2776
		} else {
2777
			if (!isset($options['caps']['tso4']))
2778
				$flags |= IFCAP_TSO;
2779
			if (!isset($options['caps']['tso6']))
2780
				$flags |= IFCAP_TSO;
2781
		}
2782

    
2783
		if(isset($config['system']['disablelargereceiveoffloading'])) {
2784
			if (isset($options['encaps']['lro']))
2785
				$flags |= IFCAP_LRO;
2786
		} else {
2787
			if (!isset($options['caps']['lro']))
2788
				$flags |= IFCAP_LRO;
2789
		}
2790

    
2791
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2792
		if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2793
			$flags |= IFCAP_POLLING;
2794
		}
2795
		pfSense_interface_capabilities($realhwif, -$flags);
2796
	}
2797

    
2798
	/* invalidate interface/ip/sn cache */
2799
	get_interface_arr(true);
2800
	unset($interface_ip_arr_cache[$realif]);
2801
	unset($interface_sn_arr_cache[$realif]);
2802
	unset($interface_ipv6_arr_cache[$realif]);
2803
	unset($interface_snv6_arr_cache[$realif]);
2804

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

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

    
2859
	if(does_interface_exist($wancfg['if']))
2860
		interfaces_bring_up($wancfg['if']);
2861

    
2862
	interface_netgraph_needed($interface);
2863

    
2864
	if (!$g['booting']) {
2865
		link_interface_to_vips($interface, "update");
2866

    
2867
		unset($gre);
2868
		$gre = link_interface_to_gre($interface);
2869
		if (!empty($gre))
2870
			array_walk($gre, 'interface_gre_configure');
2871

    
2872
		unset($gif);
2873
		$gif = link_interface_to_gif($interface);
2874
		if (!empty($gif))
2875
			array_walk($gif, 'interface_gif_configure');
2876

    
2877
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2878
			unset($bridgetmp);
2879
			$bridgetmp = link_interface_to_bridge($interface);
2880
			if (!empty($bridgetmp))
2881
				interface_bridge_add_member($bridgetmp, $realif);
2882
		}
2883

    
2884
		$grouptmp = link_interface_to_group($interface);
2885
		if (!empty($grouptmp))
2886
			array_walk($grouptmp, 'interface_group_add_member');
2887

    
2888
		if ($interface == "lan")
2889
			/* make new hosts file */
2890
			system_hosts_generate();
2891

    
2892
		if ($reloadall == true) {
2893

    
2894
			/* reconfigure static routes (kernel may have deleted them) */
2895
			system_routing_configure($interface);
2896

    
2897
			/* reload ipsec tunnels */
2898
			vpn_ipsec_configure();
2899

    
2900
			/* restart dnsmasq */
2901
			services_dnsmasq_configure();
2902

    
2903
			/* update dyndns */
2904
			send_event("service reload dyndns {$interface}");
2905

    
2906
			/* reload captive portal */
2907
			captiveportal_init_rules();
2908
		}
2909
	}
2910

    
2911
	return 0;
2912
}
2913

    
2914
function interface_track6_configure($interface = "lan", $wancfg) {
2915
	global $config, $g;
2916

    
2917
	if (!is_array($wancfg))
2918
		return;
2919

    
2920
	if (!isset($wancfg['enable']))
2921
		return;
2922

    
2923
	/* If the interface is not configured via another, exit */
2924
	if (empty($wancfg['track6-interface']))
2925
		return;
2926

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

    
2931
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
2932
	if (!isset($trackcfg['enable'])) {
2933
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
2934
		return;
2935
	}
2936

    
2937
	switch($trackcfg['ipaddrv6']) {
2938
		case "6to4":
2939
			if ($g['debug'])
2940
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2941
			interface_track6_6to4_configure($interface, $wancfg);
2942
			break;
2943
		case "6rd":
2944
			if ($g['debug'])
2945
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2946
			interface_track6_6rd_configure($interface, $wancfg);
2947
			break;
2948
		case "dhcp6":
2949
			if ($g['debug'])
2950
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2951
			interface_track6_dhcp6_configure($interface, $wancfg);
2952
			break;
2953
	}
2954

    
2955
	return 0;
2956
}
2957

    
2958

    
2959
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
2960
	global $config, $g;
2961

    
2962
	if (!is_array($lancfg))
2963
		return;
2964

    
2965
	/* If the interface is not configured via another, exit */
2966
	if (empty($lancfg['track6-interface']))
2967
		return;
2968

    
2969
	if (!is_numeric($lancfg['track6-prefix-id']))
2970
		$lancfg['track6-prefix-id'] = 0;
2971

    
2972
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2973
	if (empty($wancfg)) {
2974
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
2975
		return;
2976
	}
2977

    
2978
	$wanif = get_real_interface($lancfg['track6-interface']);
2979
	$ip4address = find_interface_ip($wanif);
2980
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
2981
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
2982
		return;
2983
	}
2984
	$hexwanv4 = return_hex_ipv4($ip4address);
2985

    
2986
	/* create the long prefix notation for math, save the prefix length */
2987
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
2988
	$rd6prefixlen = $rd6prefix[1];
2989
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
2990

    
2991
	/* binary presentation of the prefix for all 128 bits. */
2992
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
2993

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

    
2999
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3000
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3001
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3002
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3003
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3004
	/* fill the rest out with zeros */
3005
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3006

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

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

    
3014
	return 0;
3015
}
3016

    
3017
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3018
	global $config, $g;
3019

    
3020
	if (!is_array($lancfg))
3021
		return;
3022

    
3023
	/* If the interface is not configured via another, exit */
3024
	if (empty($lancfg['track6-interface']))
3025
		return;
3026

    
3027
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3028
	if (empty($wancfg)) {
3029
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3030
		return;
3031
	}
3032

    
3033
	if (!is_numeric($lancfg['track6-prefix-id']))
3034
		$lancfg['track6-prefix-id'] = 0;
3035

    
3036
	$wanif = get_real_interface($lancfg['track6-interface']);
3037
	$ip4address = find_interface_ip($wanif);
3038
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3039
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3040
		return;
3041
	}
3042
	$hexwanv4 = return_hex_ipv4($ip4address);
3043

    
3044
	/* create the long prefix notation for math, save the prefix length */
3045
	$sixto4prefix = "2002::";
3046
	$sixto4prefixlen = 16;
3047
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3048

    
3049
	/* binary presentation of the prefix for all 128 bits. */
3050
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3051

    
3052
	/* just save the left prefix length bits */
3053
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3054
	/* add the v4 address */
3055
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3056
	/* add the custom prefix id */
3057
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3058
	/* fill the rest out with zeros */
3059
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3060

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

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

    
3068
	return 0;
3069
}
3070

    
3071
function interface_track6_dhcp6_configure($interface = "lan", $lancfg) {
3072
	global $config, $g;
3073

    
3074
	if (!is_array($lancfg))
3075
		return;
3076

    
3077
	/* If the interface is not configured via another, exit */
3078
	if (empty($lancfg['track6-interface']))
3079
		return;
3080

    
3081
	if (!is_numeric($lancfg['track6-prefix-id']))
3082
		$lancfg['track6-prefix-id'] = 0;
3083

    
3084
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3085
	if (empty($wancfg)) {
3086
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3087
		return;
3088
	}
3089

    
3090
	$wanif = get_real_interface($lancfg['track6-interface']);
3091
	$ifcfgipv6 = find_interface_ipv6($wanif);
3092
	if (is_ipaddrv6($ifcfgipv6)) {
3093
		$dhcp6lanarr = explode(":", Net_IPv6::uncompress($ifcfgipv6));
3094
		$dhcp6lanarr[4] = 0;
3095
		$dhcp6lanarr[5] = 0;
3096
		$dhcp6lanarr[6] = 0;
3097
		$dhcp6lanarr[7] = 1;
3098
		$dhcp6lan =  Net_IPv6::compress(implode(":", $dhcp6lanarr));
3099
		$lanif = get_real_interface($interface);
3100
		if ($g['debug'])
3101
			log_error("dhcp6 {$interface} with ipv6 address {$dhcp6lan} based on {$lancfg['track6-interface']}");
3102
		mwexec("/sbin/ifconfig {$lanif} inet6 {$dhcp6lan} prefixlen 64");
3103
	}
3104

    
3105
	return 0;
3106
}
3107

    
3108
function interface_6rd_configure($interface = "wan", $wancfg) {
3109
	global $config, $g;
3110

    
3111
	/* because this is a tunnel interface we can only function
3112
	 *	with a public IPv4 address on the interface */
3113

    
3114
	if (!is_array($wancfg))
3115
		return;
3116

    
3117
	$wanif = get_real_interface($interface);
3118
	$ip4address = find_interface_ip($wanif);
3119
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3120
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3121
		return false;
3122
	}
3123
	$hexwanv4 = return_hex_ipv4($ip4address);
3124

    
3125
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3126
		$wancfg['prefix-6rd-v4plen'] = 0;
3127

    
3128
	/* create the long prefix notation for math, save the prefix length */
3129
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3130
	$rd6prefixlen = $rd6prefix[1];
3131
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3132

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

    
3136
	/* binary presentation of the prefix for all 128 bits. */
3137
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3138

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

    
3146
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3147
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3148

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

    
3156
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3157
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3158

    
3159
	/* XXX: need to extend to support variable prefix size for v4 */
3160
	$stfiface = "{$interface}_stf";
3161
	if (!does_interface_exist($stfiface)) {
3162
		$tmpstfiface = pfSense_interface_create("stf");
3163
		pfSense_interface_rename($tmpstfiface, $stfiface);
3164
	}
3165
	pfSense_interface_flags($stfiface, IFF_LINK2);
3166
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3167
	if ($g['debug'])
3168
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3169

    
3170
	/* write out a default router file */
3171
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3172
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3173

    
3174
	$ip4gateway = get_interface_gateway($interface);
3175
	if (is_ipaddrv4($ip4gateway))
3176
		mwexec("/sbin/route change -host " . $wancfg['gateway-6rd'] . " {$ip4gateway}");
3177

    
3178
	/* configure dependent interfaces */
3179
	if (!$g['booting'])
3180
		link_interface_to_track6($interface, "update");
3181

    
3182
	return 0;
3183
}
3184

    
3185
function interface_6to4_configure($interface = "wan", $wancfg){
3186
	global $config, $g;
3187

    
3188
	/* because this is a tunnel interface we can only function
3189
	 *	with a public IPv4 address on the interface */
3190

    
3191
	if (!is_array($wancfg))
3192
		return;
3193

    
3194
	$wanif = get_real_interface($interface);
3195
	$ip4address = find_interface_ip($wanif);
3196
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3197
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3198
		return false;
3199
	}
3200

    
3201
	/* create the long prefix notation for math, save the prefix length */
3202
	$stfprefixlen = 16;
3203
	$stfprefix = Net_IPv6::uncompress("2002::");
3204
	$stfarr = explode(":", $stfprefix);
3205
	$v4prefixlen = "0";
3206

    
3207
	/* we need the hex form of the interface IPv4 address */
3208
	$ip4arr = explode(".", $ip4address);
3209
	$hexwanv4 = "";
3210
	foreach($ip4arr as $octet)
3211
		$hexwanv4 .= sprintf("%02x", $octet);
3212

    
3213
	/* we need the hex form of the broker IPv4 address */
3214
	$ip4arr = explode(".", "192.88.99.1");
3215
	$hexbrv4 = "";
3216
	foreach($ip4arr as $octet)
3217
		$hexbrv4 .= sprintf("%02x", $octet);
3218

    
3219
	/* binary presentation of the prefix for all 128 bits. */
3220
	$stfprefixbin = "";
3221
	foreach($stfarr as $element) {
3222
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3223
	}
3224
	/* just save the left prefix length bits */
3225
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3226

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

    
3231
	/* for the local subnet too. */
3232
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3233
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3234

    
3235
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3236
	$stfbrarr = array();
3237
	$stfbrbinarr = array();
3238
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3239
	foreach($stfbrbinarr as $bin)
3240
		$stfbrarr[] = dechex(bindec($bin));
3241
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3242

    
3243
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3244
	$stflanarr = array();
3245
	$stflanbinarr = array();
3246
	$stflanbinarr = str_split($stflanbin, 16);
3247
	foreach($stflanbinarr as $bin)
3248
		$stflanarr[] = dechex(bindec($bin));
3249
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3250
	$stflanarr[7] = 1;
3251
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3252

    
3253
	/* setup the stf interface */
3254
	$stfiface = "{$interface}_stf";
3255
	if (!does_interface_exist($stfiface)) {
3256
		$tmpstfiface = pfSense_interface_create("stf");
3257
		pfSense_interface_rename($tmpstfiface, $stfiface);
3258
	}
3259
	pfSense_interface_flags($stfiface, IFF_LINK2);
3260
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3261

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

    
3265
	/* write out a default router file */
3266
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3267
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3268

    
3269
	$ip4gateway = get_interface_gateway($interface);
3270
	if (is_ipaddrv4($ip4gateway))
3271
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3272

    
3273
	if (!$g['booting'])
3274
		link_interface_to_track6($interface, "update");
3275

    
3276
	return 0;
3277
}
3278

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

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

    
3285
	$wanif = get_real_interface($interface);
3286
	$dhcp6cconf = "";
3287
	$dhcp6cconf .= "interface {$wanif} {\n";
3288

    
3289
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3290
	if($wancfg['ipaddrv6'] == "slaac") {
3291
		$dhcp6cconf .= "	information-only;\n";
3292
		$dhcp6cconf .= "	request domain-name-servers;\n";
3293
		$dhcp6cconf .= "	request domain-name;\n";
3294
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3295
		$dhcp6cconf .= "};\n";
3296
	} else {
3297

    
3298
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3299
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3300
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3301
		$dhcp6cconf .= "request domain-name-servers;\n";
3302
		$dhcp6cconf .= "request domain-name;\n";
3303
		$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3304

    
3305
		$dhcp6cconf .= "};\n";
3306
		$dhcp6cconf .= "id-assoc na 0 { };\n";
3307
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3308
			/* Setup the prefix delegation */
3309
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3310
			$iflist = get_configured_interface_with_descr(false, true);
3311
			$iflist = link_interface_to_track6($interface);
3312
			foreach ($iflist as $friendly => $ifcfg) {
3313
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3314
					if ($g['debug'])
3315
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3316
					$realif = get_real_interface($friendly);
3317
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3318
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3319
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3320
					$dhcp6cconf .= "	};\n";
3321
				}
3322
			}
3323
			unset($iflist, $ifcfg);
3324
			$dhcp6cconf .= "};\n";
3325
		}
3326
	}
3327
	/* wide-dhcp6c works for now. */
3328
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3329
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3330
		unset($dhcp6cconf);
3331
		return 1;
3332
	}
3333
	unset($dhcp6cconf);
3334

    
3335
	$dhcp6cscript = "#!/bin/sh\n";
3336
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3337
	$dhcp6cscript .= "/etc/rc.newwanipv6 {$wanif} \n";
3338
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3339
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3340
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3341
		unset($dhcp6cscript);
3342
		return 1;
3343
	}
3344
	unset($dhcp6cscript);
3345
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3346

    
3347

    
3348
	/* accept router advertisements for this interface */
3349
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3350
	log_error("Accept router advertisements on interface {$wanif} ");
3351
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3352

    
3353
	/* run a filter configure sync so that the filter rules allow traffic before we launch the client */
3354
	/* there reallyt is no good way around this i'm 'fraid */
3355
	if (!$g['booting'])
3356
		filter_configure_sync();
3357

    
3358
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3359
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$interface}.pid {$wanif}");
3360
	sleep(1);
3361
	unset($out);
3362
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3363
	if (!empty($out)) {
3364
		foreach($out as $line) {
3365
			if((stristr($line, "received")) && (!stristr($line, "unexpected"))) {
3366
				$parts = explode(" ", $line);
3367
				if(is_ipaddrv6($parts[3])) {
3368
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3369
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3370
					file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$parts[3]}\n");
3371
					break;
3372
				}
3373
			}
3374
		}
3375
		unset($out);
3376
	}
3377
	/* worst case is that the rc.newwanipv6 handles setting up the track6 interface */
3378
	if (!$g['booting'] && $wancfg['ippaddrv6'] != "slaac")
3379
		link_interface_to_track6($interface, "update");
3380

    
3381
	return 0;
3382
}
3383

    
3384
function interface_dhcp_configure($interface = "wan") {
3385
	global $config, $g;
3386

    
3387
	$wancfg = $config['interfaces'][$interface];
3388
	$wanif = $wancfg['if'];
3389
	if (empty($wancfg))
3390
		$wancfg = array();
3391

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

    
3399
	if ($wancfg['dhcphostname']) {
3400
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3401
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3402
	} else {
3403
		$dhclientconf_hostname = "";
3404
	}
3405

    
3406
	$wanif = get_real_interface($interface);
3407
	if (empty($wanif)) {
3408
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3409
		return 0;
3410
	}
3411
	$dhclientconf = "";
3412

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

    
3423
EOD;
3424

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

    
3434
EOD;
3435
}
3436
	fwrite($fd, $dhclientconf);
3437
	fclose($fd);
3438

    
3439
	/* bring wan interface up before starting dhclient */
3440
	if($wanif)
3441
		interfaces_bring_up($wanif);
3442
	else
3443
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3444

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

    
3448
	return 0;
3449
}
3450

    
3451
function interfaces_group_setup() {
3452
	global $config;
3453

    
3454
	if (!is_array($config['ifgroups']['ifgroupentry']))
3455
		return;
3456

    
3457
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3458
		interface_group_setup($groupar);
3459

    
3460
	return;
3461
}
3462

    
3463
function interface_group_setup(&$groupname /* The parameter is an array */) {
3464
	global $config;
3465

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

    
3475
	return;
3476
}
3477

    
3478
function interface_group_add_member($interface, $groupname) {
3479
	$interface = get_real_interface($interface);
3480
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3481
}
3482

    
3483
/* COMPAT Function */
3484
function convert_friendly_interface_to_real_interface_name($interface) {
3485
	return get_real_interface($interface);
3486
}
3487

    
3488
/* COMPAT Function */
3489
function get_real_wan_interface($interface = "wan") {
3490
	return get_real_interface($interface);
3491
}
3492

    
3493
/* COMPAT Function */
3494
function get_current_wan_address($interface = "wan") {
3495
	return get_interface_ip($interface);
3496
}
3497

    
3498
/*
3499
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3500
 */
3501
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3502
	global $config;
3503

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

    
3513
	/* XXX: For speed reasons reference directly the interface array */
3514
	$ifdescrs = &$config['interfaces'];
3515
	//$ifdescrs = get_configured_interface_list(false, true);
3516

    
3517
	foreach ($ifdescrs as $if => $ifname) {
3518
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3519
			return $if;
3520

    
3521
		if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3522
			return $if;
3523

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

    
3535
/* attempt to resolve interface to friendly descr */
3536
function convert_friendly_interface_to_friendly_descr($interface) {
3537
	global $config;
3538

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

    
3583
	return $ifdesc;
3584
}
3585

    
3586
function convert_real_interface_to_friendly_descr($interface) {
3587
	global $config;
3588

    
3589
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3590

    
3591
	if ($ifdesc) {
3592
		$iflist = get_configured_interface_with_descr(false, true);
3593
		return $iflist[$ifdesc];
3594
	}
3595

    
3596
	return $interface;
3597
}
3598

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

    
3611
	$parents = array();
3612
	//Check that we got a valid interface passed
3613
	$realif = get_real_interface($interface);
3614
	if ($realif == NULL)
3615
		return $parents;
3616

    
3617
	// If we got a real interface, find it's friendly assigned name
3618
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3619

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

    
3653
	if (empty($parents))
3654
		$parents[0] = $realif;
3655

    
3656
	return $parents;
3657
}
3658

    
3659
function interface_is_wireless_clone($wlif) {
3660
	if(!stristr($wlif, "_wlan")) {
3661
		return false;
3662
	} else {
3663
		return true;
3664
	}
3665
}
3666

    
3667
function interface_get_wireless_base($wlif) {
3668
	if(!stristr($wlif, "_wlan")) {
3669
		return $wlif;
3670
	} else {
3671
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3672
	}
3673
}
3674

    
3675
function interface_get_wireless_clone($wlif) {
3676
	if(!stristr($wlif, "_wlan")) {
3677
		return $wlif . "_wlan0";
3678
	} else {
3679
		return $wlif;
3680
	}
3681
}
3682

    
3683
function get_real_interface($interface = "wan") {
3684
	global $config;
3685

    
3686
	$wanif = NULL;
3687

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

    
3718
		if (empty($config['interfaces'][$interface]))
3719
			break;
3720

    
3721
		$cfg = &$config['interfaces'][$interface];
3722

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

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

    
3751
	return $wanif;
3752
}
3753

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

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

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

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

    
3843
/*
3844
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3845
 */
3846
function find_number_of_created_carp_interfaces() {
3847
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3848
}
3849

    
3850
function get_all_carp_interfaces() {
3851
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3852
	$ints = explode(" ", $ints);
3853
	return $ints;
3854
}
3855

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

    
3881
				if ($if)
3882
					return $if;
3883
			}
3884
		}
3885
	}
3886
}
3887

    
3888
function link_carp_interface_to_parent($interface) {
3889
	global $config;
3890

    
3891
	if ($interface == "")
3892
		return;
3893

    
3894
	$carp_ip = get_interface_ip($interface);
3895
	$carp_ipv6 = get_interface_ipv6($interface);
3896

    
3897
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
3898
		return;
3899

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

    
3922

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

    
3934
	if (!is_ipaddr($ip))
3935
		return;
3936

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

    
3955
	return $carp_ints;
3956
}
3957

    
3958
function link_interface_to_track6($int, $action = "") {
3959
	global $config;
3960

    
3961
	if (empty($int))
3962
		return;
3963

    
3964
	if (is_array($config['interfaces'])) {
3965
		$list = array();
3966
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
3967
			if (!isset($ifcfg['enable']))
3968
				continue;
3969
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
3970
				if ($action == "update")
3971
					interface_track6_configure($ifname, $ifcfg);
3972
				else if ($action == "")
3973
					$list[$ifname] = $ifcfg;
3974
			}
3975
		}
3976
		return $list;
3977
	}
3978
}
3979

    
3980
function link_interface_to_vlans($int, $action = "") {
3981
	global $config;
3982

    
3983
	if (empty($int))
3984
		return;
3985

    
3986
	if (is_array($config['vlans']['vlan'])) {
3987
		foreach ($config['vlans']['vlan'] as $vlan) {
3988
			if ($int == $vlan['if']) {
3989
				if ($action == "update") {
3990
					interfaces_bring_up($int);
3991
				} else if ($action == "")
3992
					return $vlan;
3993
			}
3994
		}
3995
	}
3996
}
3997

    
3998
function link_interface_to_vips($int, $action = "") {
3999
	global $config;
4000

    
4001
	if (is_array($config['virtualip']['vip'])) {
4002
		$result = array();
4003
		foreach ($config['virtualip']['vip'] as $vip) {
4004
			if ($int == $vip['interface']) {
4005
				if ($action == "update")
4006
					interfaces_vips_configure($int);
4007
				else
4008
					$result[] = $vip;
4009
			}
4010
		}
4011
		return $result;
4012
	}
4013
}
4014

    
4015
/****f* interfaces/link_interface_to_bridge
4016
 * NAME
4017
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4018
 * INPUTS
4019
 *   $ip
4020
 * RESULT
4021
 *   bridge[0-99]
4022
 ******/
4023
function link_interface_to_bridge($int) {
4024
	global $config;
4025

    
4026
	if (is_array($config['bridges']['bridged'])) {
4027
		foreach ($config['bridges']['bridged'] as $bridge) {
4028
			if (in_array($int, explode(',', $bridge['members'])))
4029
				return "{$bridge['bridgeif']}";
4030
		}
4031
	}
4032
}
4033

    
4034
function link_interface_to_group($int) {
4035
	global $config;
4036

    
4037
	$result = array();
4038

    
4039
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4040
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4041
			if (in_array($int, explode(" ", $group['members'])))
4042
				$result[$group['ifname']] = $int;
4043
		}
4044
	}
4045

    
4046
	return $result;
4047
}
4048

    
4049
function link_interface_to_gre($interface) {
4050
	global $config;
4051

    
4052
	$result = array();
4053

    
4054
	if (is_array($config['gres']['gre'])) {
4055
		foreach ($config['gres']['gre'] as $gre)
4056
			if($gre['if'] == $interface)
4057
				$result[] = $gre;
4058
	}
4059

    
4060
	return $result;
4061
}
4062

    
4063
function link_interface_to_gif($interface) {
4064
	global $config;
4065

    
4066
	$result = array();
4067

    
4068
	if (is_array($config['gifs']['gif'])) {
4069
		foreach ($config['gifs']['gif'] as $gif)
4070
			if($gif['if'] == $interface)
4071
				$result[] = $gif;
4072
	}
4073

    
4074
	return $result;
4075
}
4076

    
4077
/*
4078
 * find_interface_ip($interface): return the interface ip (first found)
4079
 */
4080
function find_interface_ip($interface, $flush = false)
4081
{
4082
	global $interface_ip_arr_cache;
4083
	global $interface_sn_arr_cache;
4084

    
4085
	$interface = str_replace("\n", "", $interface);
4086

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

    
4090
	/* Setup IP cache */
4091
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4092
		$ifinfo = pfSense_get_interface_addresses($interface);
4093
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4094
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4095
	}
4096

    
4097
	return $interface_ip_arr_cache[$interface];
4098
}
4099

    
4100
/*
4101
 * find_interface_ipv6($interface): return the interface ip (first found)
4102
 */
4103
function find_interface_ipv6($interface, $flush = false)
4104
{
4105
	global $interface_ipv6_arr_cache;
4106
	global $interface_snv6_arr_cache;
4107
	global $config;
4108

    
4109
	$interface = trim($interface);
4110
	$interface = get_real_interface($interface);
4111

    
4112
	if (!does_interface_exist($interface))
4113
		return;
4114

    
4115
	/* Setup IP cache */
4116
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4117
		$ifinfo = pfSense_get_interface_addresses($interface);
4118
		// FIXME: Add IPv6 support to the pfSense module
4119
		exec("/sbin/ifconfig {$interface} inet6", $output);
4120
		foreach($output as $line) {
4121
			if(preg_match("/inet6/", $line)) {
4122
				$parts = explode(" ", $line);
4123
				if(! preg_match("/fe80::/", $parts[1])) {
4124
					$ifinfo['ipaddrv6'] = $parts[1];
4125
					if($parts[2] == "-->") {
4126
						$parts[5] = "126";
4127
						$ifinfo['subnetbitsv6'] = $parts[5];
4128
					} else {
4129
						$ifinfo['subnetbitsv6'] = $parts[3];
4130
					}
4131
				}
4132
			}
4133
		}
4134
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4135
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4136
	}
4137

    
4138
	return $interface_ipv6_arr_cache[$interface];
4139
}
4140

    
4141
/*
4142
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4143
 */
4144
function find_interface_ipv6_ll($interface, $flush = false)
4145
{
4146
	global $interface_llv6_arr_cache;
4147
	global $config;
4148

    
4149
	$interface = str_replace("\n", "", $interface);
4150

    
4151
	if (!does_interface_exist($interface))
4152
		return;
4153

    
4154
	/* Setup IP cache */
4155
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4156
		$ifinfo = pfSense_get_interface_addresses($interface);
4157
		// FIXME: Add IPv6 support to the pfSense module
4158
		exec("/sbin/ifconfig {$interface} inet6", $output);
4159
		foreach($output as $line) {
4160
			if(preg_match("/inet6/", $line)) {
4161
				$parts = explode(" ", $line);
4162
				if(preg_match("/fe80::/", $parts[1])) {
4163
					$partsaddress = explode("%", $parts[1]);
4164
					$ifinfo['linklocal'] = $partsaddress[0];
4165
				}
4166
			}
4167
		}
4168
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4169
	}
4170
	return $interface_llv6_arr_cache[$interface];
4171
}
4172

    
4173
function find_interface_subnet($interface, $flush = false)
4174
{
4175
	global $interface_sn_arr_cache;
4176
	global $interface_ip_arr_cache;
4177

    
4178
	$interface = str_replace("\n", "", $interface);
4179
	if (does_interface_exist($interface) == false)
4180
		return;
4181

    
4182
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4183
		$ifinfo = pfSense_get_interface_addresses($interface);
4184
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4185
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4186
	}
4187

    
4188
	return $interface_sn_arr_cache[$interface];
4189
}
4190

    
4191
function find_interface_subnetv6($interface, $flush = false)
4192
{
4193
	global $interface_snv6_arr_cache;
4194
	global $interface_ipv6_arr_cache;
4195

    
4196
	$interface = str_replace("\n", "", $interface);
4197
	if (does_interface_exist($interface) == false)
4198
		return;
4199

    
4200
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4201
		$ifinfo = pfSense_get_interface_addresses($interface);
4202
		// FIXME: Add IPv6 support to the pfSense module
4203
		exec("/sbin/ifconfig {$interface} inet6", $output);
4204
		foreach($output as $line) {
4205
			if(preg_match("/inet6/", $line)) {
4206
				$parts = explode(" ", $line);
4207
				if(! preg_match("/fe80::/", $parts[1])) {
4208
					$ifinfo['ipaddrv6'] = $parts[1];
4209
					if($parts[2] == "-->") {
4210
						$parts[5] = "126";
4211
						$ifinfo['subnetbitsv6'] = $parts[5];
4212
					} else {
4213
						$ifinfo['subnetbitsv6'] = $parts[3];
4214
					}
4215
				}
4216
			}
4217
		}
4218
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4219
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4220
	}
4221

    
4222
	return $interface_snv6_arr_cache[$interface];
4223
}
4224

    
4225
function ip_in_interface_alias_subnet($interface, $ipalias) {
4226
	global $config;
4227

    
4228
	if (empty($interface) || !is_ipaddr($ipalias))
4229
		return false;
4230
	if (is_array($config['virtualip']['vip'])) {
4231
		foreach ($config['virtualip']['vip'] as $vip) {
4232
			switch ($vip['mode']) {
4233
			case "ipalias":
4234
				if ($vip['interface'] <> $interface)
4235
					break;
4236
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4237
					return true;
4238
				break;
4239
			}
4240
		}
4241
	}
4242

    
4243
	return false;
4244
}
4245

    
4246
function get_interface_ip($interface = "wan")
4247
{
4248
	$realif = get_failover_interface($interface);
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_ip($realif);
4259
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4260
		return $curip;
4261
	else
4262
		return null;
4263
}
4264

    
4265
function get_interface_ipv6($interface = "wan")
4266
{
4267
	global $config;
4268
	$realif = get_failover_interface($interface);
4269
	switch($config['interfaces'][$interface]['ipaddrv6']) {
4270
		case "6rd":
4271
		case "6to4":
4272
			$realif = "{$interface}_stf";
4273
			break;
4274
	}
4275
	if (!$realif) {
4276
		if (preg_match("/^carp/i", $interface))
4277
			$realif = $interface;
4278
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4279
			$realif = $interface;
4280
		else
4281
			return null;
4282
	}
4283

    
4284
	$curip = find_interface_ipv6($realif);
4285
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4286
		return $curip;
4287
	else
4288
		return null;
4289
}
4290

    
4291
function get_interface_linklocal($interface = "wan")
4292
{
4293
	$realif = get_failover_interface($interface);
4294
	if (!$realif) {
4295
		if (preg_match("/^carp/i", $interface))
4296
			$realif = $interface;
4297
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4298
			$realif = $interface;
4299
		else
4300
			return null;
4301
	}
4302

    
4303
	$curip = find_interface_ipv6_ll($realif);
4304
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4305
		return $curip;
4306
	else
4307
		return null;
4308
}
4309

    
4310
function get_interface_subnet($interface = "wan")
4311
{
4312
	$realif = get_real_interface($interface);
4313
	if (!$realif) {
4314
		if (preg_match("/^carp/i", $interface))
4315
			$realif = $interface;
4316
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4317
			$realif = $interface;
4318
		else
4319
			return null;
4320
	}
4321

    
4322
	$cursn = find_interface_subnet($realif);
4323
	if (!empty($cursn))
4324
		return $cursn;
4325

    
4326
	return null;
4327
}
4328

    
4329
function get_interface_subnetv6($interface = "wan")
4330
{
4331
	$realif = get_real_interface($interface);
4332
	if (!$realif) {
4333
		if (preg_match("/^carp/i", $interface))
4334
			$realif = $interface;
4335
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4336
			$realif = $interface;
4337
		else
4338
			return null;
4339
	}
4340

    
4341
	$cursn = find_interface_subnetv6($realif);
4342
	if (!empty($cursn))
4343
		return $cursn;
4344

    
4345
	return null;
4346
}
4347

    
4348
/* return outside interfaces with a gateway */
4349
function get_interfaces_with_gateway() {
4350
	global $config;
4351

    
4352
	$ints = array();
4353

    
4354
	/* loop interfaces, check config for outbound */
4355
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4356
		switch ($ifname['ipaddr']) {
4357
			case "dhcp":
4358
			case "ppp";
4359
			case "pppoe":
4360
			case "pptp":
4361
			case "l2tp":
4362
			case "ppp";
4363
				$ints[$ifdescr] = $ifdescr;
4364
			break;
4365
			default:
4366
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4367
				    !empty($ifname['gateway']))
4368
					$ints[$ifdescr] = $ifdescr;
4369
			break;
4370
		}
4371
	}
4372
	return $ints;
4373
}
4374

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

    
4379
	if (!empty($config['interfaces'][$friendly])) {
4380
		$ifname = &$config['interfaces'][$friendly];
4381
		switch ($ifname['ipaddr']) {
4382
			case "dhcp":
4383
			case "pppoe":
4384
			case "pptp":
4385
			case "l2tp":
4386
			case "ppp";
4387
				return true;
4388
			break;
4389
			default:
4390
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4391
					return true;
4392
				if (!empty($ifname['gateway']))
4393
					return true;
4394
			break;
4395
		}
4396
	}
4397

    
4398
	return false;
4399
}
4400

    
4401
/* return true if interface has a gateway */
4402
function interface_has_gatewayv6($friendly) {
4403
	global $config;
4404

    
4405
	if (!empty($config['interfaces'][$friendly])) {
4406
		$ifname = &$config['interfaces'][$friendly];
4407
		switch ($ifname['ipaddrv6']) {
4408
			case "slaac":
4409
			case "dhcp6":
4410
				return true;
4411
				break;
4412
			case "6to4":
4413
				return true;
4414
				break;
4415
			case "6rd":
4416
				return true;
4417
				break;
4418
			default:
4419
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4420
					return true;
4421
				if (!empty($ifname['gatewayv6']))
4422
					return true;
4423
				break;
4424
		}
4425
	}
4426

    
4427
	return false;
4428
}
4429

    
4430
/****f* interfaces/is_altq_capable
4431
 * NAME
4432
 *   is_altq_capable - Test if interface is capable of using ALTQ
4433
 * INPUTS
4434
 *   $int            - string containing interface name
4435
 * RESULT
4436
 *   boolean         - true or false
4437
 ******/
4438

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

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

    
4454
	if (in_array($int_family[0], $capable))
4455
		return true;
4456
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4457
		return true;
4458
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4459
		return true;
4460
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4461
		return true;
4462
	else
4463
		return false;
4464
}
4465

    
4466
/****f* interfaces/is_interface_wireless
4467
 * NAME
4468
 *   is_interface_wireless - Returns if an interface is wireless
4469
 * RESULT
4470
 *   $tmp       - Returns if an interface is wireless
4471
 ******/
4472
function is_interface_wireless($interface) {
4473
	global $config, $g;
4474

    
4475
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4476
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4477
		if (preg_match($g['wireless_regex'], $interface)) {
4478
			if (isset($config['interfaces'][$friendly]))
4479
				$config['interfaces'][$friendly]['wireless'] = array();
4480
			return true;
4481
		}
4482
		return false;
4483
	} else
4484
		return true;
4485
}
4486

    
4487
function get_wireless_modes($interface) {
4488
	/* return wireless modes and channels */
4489
	$wireless_modes = array();
4490

    
4491
	$cloned_interface = get_real_interface($interface);
4492

    
4493
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4494
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4495
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4496
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4497

    
4498
		$interface_channels = "";
4499
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4500
		$interface_channel_count = count($interface_channels);
4501

    
4502
		$c = 0;
4503
		while ($c < $interface_channel_count)
4504
		{
4505
			$channel_line = explode(",", $interface_channels["$c"]);
4506
			$wireless_mode = trim($channel_line[0]);
4507
			$wireless_channel = trim($channel_line[1]);
4508
			if(trim($wireless_mode) != "") {
4509
				/* if we only have 11g also set 11b channels */
4510
				if($wireless_mode == "11g") {
4511
					if(!isset($wireless_modes["11b"]))
4512
						$wireless_modes["11b"] = array();
4513
				} else if($wireless_mode == "11g ht") {
4514
					if(!isset($wireless_modes["11b"]))
4515
						$wireless_modes["11b"] = array();
4516
					if(!isset($wireless_modes["11g"]))
4517
						$wireless_modes["11g"] = array();
4518
					$wireless_mode = "11ng";
4519
				} else if($wireless_mode == "11a ht") {
4520
					if(!isset($wireless_modes["11a"]))
4521
						$wireless_modes["11a"] = array();
4522
					$wireless_mode = "11na";
4523
				}
4524
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4525
			}
4526
			$c++;
4527
		}
4528
	}
4529
	return($wireless_modes);
4530
}
4531

    
4532
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4533
function get_wireless_channel_info($interface) {
4534
	$wireless_channels = array();
4535

    
4536
	$cloned_interface = get_real_interface($interface);
4537

    
4538
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4539
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4540
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4541
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4542

    
4543
		$interface_channels = "";
4544
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4545

    
4546
		foreach ($interface_channels as $channel_line) {
4547
			$channel_line = explode(",", $channel_line);
4548
			if(!isset($wireless_channels[$channel_line[0]]))
4549
				$wireless_channels[$channel_line[0]] = $channel_line;
4550
		}
4551
	}
4552
	return($wireless_channels);
4553
}
4554

    
4555
/****f* interfaces/get_interface_mtu
4556
 * NAME
4557
 *   get_interface_mtu - Return the mtu of an interface
4558
 * RESULT
4559
 *   $tmp       - Returns the mtu of an interface
4560
 ******/
4561
function get_interface_mtu($interface) {
4562
	$mtu = pfSense_get_interface_addresses($interface);
4563
	return $mtu['mtu'];
4564
}
4565

    
4566
function get_interface_mac($interface) {
4567

    
4568
	$macinfo = pfSense_get_interface_addresses($interface);
4569
	return $macinfo["macaddr"];
4570
}
4571

    
4572
/****f* pfsense-utils/generate_random_mac_address
4573
 * NAME
4574
 *   generate_random_mac - generates a random mac address
4575
 * INPUTS
4576
 *   none
4577
 * RESULT
4578
 *   $mac - a random mac address
4579
 ******/
4580
function generate_random_mac_address() {
4581
	$mac = "02";
4582
	for($x=0; $x<5; $x++)
4583
		$mac .= ":" . dechex(rand(16, 255));
4584
	return $mac;
4585
}
4586

    
4587
/****f* interfaces/is_jumbo_capable
4588
 * NAME
4589
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4590
 * INPUTS
4591
 *   $int             - string containing interface name
4592
 * RESULT
4593
 *   boolean          - true or false
4594
 ******/
4595
function is_jumbo_capable($iface) {
4596
	$iface = trim($iface);
4597
	$capable = pfSense_get_interface_addresses($iface);
4598

    
4599
	if (isset($capable['caps']['vlanmtu']))
4600
		return true;
4601

    
4602
	return false;
4603
}
4604

    
4605
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4606
	global $g;
4607

    
4608
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4609

    
4610
	if(!empty($iface) && !empty($pppif)){
4611
		$cron_cmd = <<<EOD
4612
#!/bin/sh
4613
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4614
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
4615

    
4616
EOD;
4617

    
4618
		@file_put_contents($cron_file, $cron_cmd);
4619
		chmod($cron_file, 0755);
4620
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4621
	} else
4622
		unlink_if_exists($cron_file);
4623
}
4624

    
4625
function get_interface_default_mtu($type = "ethernet") {
4626
	switch ($type) {
4627
	case "gre":
4628
		return 1476;
4629
		break;
4630
	case "gif":
4631
		return 1280;
4632
		break;
4633
	case "tun":
4634
	case "vlan":
4635
	case "tap":
4636
	case "ethernet":
4637
	default:
4638
		return 1500;
4639
		break;
4640
	}
4641

    
4642
	/* Never reached */
4643
	return 1500;
4644
}
4645

    
4646
function get_vip_descr($ipaddress) {
4647
	global $config;
4648

    
4649
	foreach ($config['virtualip']['vip'] as $vip) {
4650
		if ($vip['subnet'] == $ipaddress) {
4651
			return ($vip['descr']);
4652
		}
4653
	}
4654
	return "";
4655
}
4656

    
4657
function interfaces_staticarp_configure($if) {
4658
	global $config, $g;
4659
	if(isset($config['system']['developerspew'])) {
4660
		$mt = microtime();
4661
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4662
	}
4663

    
4664
	$ifcfg = $config['interfaces'][$if];
4665

    
4666
	if (empty($if) || empty($ifcfg['if']))
4667
		return 0;
4668

    
4669
	/* Enable staticarp, if enabled */
4670
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4671
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4672
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4673
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4674

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

    
4678
			}
4679

    
4680
		}
4681
	} else {
4682
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4683
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4684
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4685
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
4686
				if (isset($arpent['arp_table_static_entry'])) {
4687
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
4688
				}
4689
			}
4690
		}
4691
	}
4692

    
4693
	return 0;
4694
}
4695

    
4696
function get_failover_interface($interface) {
4697
	global $config;
4698
	/* shortcut to get_real_interface if we find it in the config */
4699
	if(is_array($config['interfaces'][$interface])) {
4700
		$wanif = get_real_interface($interface);
4701
		return $wanif;
4702
	}
4703

    
4704
	/* compare against gateway groups */
4705
	$a_groups = return_gateway_groups_array();
4706
	if(is_array($a_groups[$interface])) {
4707
		/* we found a gateway group, fetch the interface or vip */
4708
		if($a_groups[$interface][0]['vip'] <> "")
4709
			$wanif = $a_groups[$interface][0]['vip'];
4710
		else
4711
			$wanif = $a_groups[$interface][0]['int'];
4712

    
4713
		return $wanif;
4714
	}
4715
	/* fall through to get_real_interface */
4716
	$wanif = get_real_interface($interface);
4717
	return $wanif;
4718
}
4719

    
4720
?>
(25-25/67)