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
	log_error("Deny router advertisements for interface {$interface}");
2675
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2676

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2861
	interface_netgraph_needed($interface);
2862

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

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

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

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

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

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

    
2891
		if ($reloadall == true) {
2892

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

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

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

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

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

    
2910
	return 0;
2911
}
2912

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

    
2916
	$wancfg = $config['interfaces'][$interface];
2917
	if (empty($config['interfaces'][$interface]))
2918
		return;
2919

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

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

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

    
2947
	return 0;
2948
}
2949

    
2950

    
2951
function interface_track6_6rd_configure($interface = "lan") {
2952
	global $config, $g;
2953

    
2954
	$lancfg = $config['interfaces'][$interface];
2955
	if (empty($config['interfaces'][$interface]))
2956
		return;
2957

    
2958
	/* If the interface is not configured via another, exit */
2959
	if (empty($lancfg['track6-interface']))
2960
		return;
2961

    
2962
	if (!is_numeric($lancfg['track6-prefix-id']))
2963
		$lancfg['track6-prefix-id'] = 0;
2964

    
2965
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2966
	if (empty($wancfg))
2967
		return;
2968

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

    
2977
	/* create the long prefix notation for math, save the prefix length */
2978
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
2979
	$rd6prefixlen = $rd6prefix[1];
2980
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
2981

    
2982
	/* binary presentation of the prefix for all 128 bits. */
2983
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
2984

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

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

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

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

    
3005
	return 0;
3006
}
3007

    
3008
function interface_track6_6to4_configure($interface = "lan") {
3009
	global $config, $g;
3010

    
3011
	$lancfg = $config['interfaces'][$interface];
3012
	if (empty($config['interfaces'][$interface]))
3013
		return;
3014

    
3015
	/* If the interface is not configured via another, exit */
3016
	if (empty($lancfg['track6-interface']))
3017
		return;
3018

    
3019
	if (!is_numeric($lancfg['track6-prefix-id']))
3020
		$lancfg['track6-prefix-id'] = 0;
3021

    
3022
	$wanif = get_real_interface($lancfg['track6-interface']);
3023
	if (!$wanif)
3024
		return;
3025
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3026
	if (empty($wancfg))
3027
		$wancfg = array();
3028

    
3029
	$ip4address = find_interface_ip($wanif);
3030
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3031
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3032
		return;
3033
	}
3034
	$hexwanv4 = return_hex_ipv4($ip4address);
3035

    
3036
	/* create the long prefix notation for math, save the prefix length */
3037
	$sixto4prefix = "2002::";
3038
	$sixto4prefixlen = 16;
3039
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3040

    
3041
	/* binary presentation of the prefix for all 128 bits. */
3042
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3043

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

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

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

    
3060
	return 0;
3061
}
3062

    
3063
function interface_track6_dhcp6_configure($interface = "lan") {
3064
	global $config, $g;
3065

    
3066
	$lancfg = $config['interfaces'][$interface];
3067
	if (empty($config['interfaces'][$interface]))
3068
		return;
3069

    
3070
	/* If the interface is not configured via another, exit */
3071
	if (empty($lancfg['track6-interface']))
3072
		return;
3073

    
3074
	if (!is_numeric($lancfg['track6-prefix-id']))
3075
		$lancfg['track6-prefix-id'] = 0;
3076

    
3077
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3078
	if (empty($wancfg))
3079
		$wancfg = array();
3080

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

    
3095
	return 0;
3096
}
3097

    
3098
function interface_6rd_configure($interface = "wan") {
3099
	global $config, $g;
3100

    
3101
	/* because this is a tunnel interface we can only function
3102
	 *	with a public IPv4 address on the interface */
3103

    
3104
	$wancfg = $config['interfaces'][$interface];
3105
	if (empty($wancfg))
3106
		return;
3107

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

    
3117
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3118
		$wancfg['prefix-6rd-v4plen'] = 0;
3119

    
3120
	/* create the long prefix notation for math, save the prefix length */
3121
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3122
	$rd6prefixlen = $rd6prefix[1];
3123
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3124

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

    
3128
	/* binary presentation of the prefix for all 128 bits. */
3129
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3130

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

    
3138
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3139
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3140

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

    
3148
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3149
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3150

    
3151
	/* XXX: need to extend to support variable prefix size for v4 */
3152
	$tmpstfiface = pfSense_interface_create("stf");
3153
	$stfiface = "{$interface}_stf";
3154
	pfSense_interface_rename($tmpstfiface, $stfiface);
3155
	pfSense_interface_flags($stfiface, IFF_LINK2);
3156
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3157
	if ($g['debug'])
3158
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3159

    
3160
	/* write out a default router file */
3161
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3162
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3163

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

    
3167
	/* configure dependent interfaces */
3168
	if (!$g['booting']) {
3169
		/* XXX: Really necessary? */
3170
		$iflist = get_configured_interface_with_descr(false, true);
3171
		foreach($iflist as $if => $ifname) {
3172
			if ($config['interfaces'][$if]['track6-interface'] == $interface)
3173
				interface_track6_configure($if);
3174
		}
3175
		unset($iflist);
3176
	}
3177

    
3178
	return 0;
3179
}
3180

    
3181
function interface_6to4_configure($interface = "wan"){
3182
	global $config, $g;
3183

    
3184
	/* because this is a tunnel interface we can only function
3185
	 *	with a public IPv4 address on the interface */
3186

    
3187
	$wancfg = $config['interfaces'][$interface];
3188
	$wanif = $wancfg['if'];
3189
	if (empty($wancfg))
3190
		$wancfg = array();
3191

    
3192
	$wanif = get_real_interface($interface);
3193

    
3194
	$ip4address = find_interface_ip($wanif);
3195
	$ip4gateway = get_interface_gateway($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
	pfSense_interface_destroy($stfiface);
3256
	$tmpstfiface = pfSense_interface_create("stf");
3257
	pfSense_interface_rename($tmpstfiface, $stfiface);
3258
	pfSense_interface_flags($stfiface, IFF_LINK2);
3259
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3260

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

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

    
3268
	if (is_ipaddrv4($ip4gateway)) {
3269
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3270
	}
3271

    
3272
	if (!$g['booting']) {
3273
		/* configure dependent interfaces */
3274
		$iflist = get_configured_interface_with_descr(false, true);
3275
		foreach($iflist as $if => $ifname) {
3276
			if($config['interfaces'][$if]['track6-interface'] == $interface)
3277
				interface_track6_configure($if);
3278
		}
3279
		unset($iflist);
3280
	}
3281

    
3282
	return 0;
3283
}
3284

    
3285
function interface_dhcpv6_configure($interface = "wan") {
3286
	global $config, $g;
3287

    
3288
	$wancfg = $config['interfaces'][$interface];
3289
	if (empty($config['interfaces'][$interface]))
3290
		return;
3291

    
3292
	$wanif = get_real_interface($interface);
3293

    
3294
	$dhcp6cconf = "";
3295
	$dhcp6cconf .= "interface {$wanif} {\n";
3296

    
3297
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3298
	if($wancfg['ipaddrv6'] == "slaac") {
3299
		$dhcp6cconf .= "	information-only;\n";
3300
		$dhcp6cconf .= "	request domain-name-servers;\n";
3301
		$dhcp6cconf .= "	request domain-name;\n";
3302
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3303
		$dhcp6cconf .= "};\n";
3304
	} else {
3305

    
3306
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3307
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3308
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3309
		$dhcp6cconf .= "request domain-name-servers;\n";
3310
		$dhcp6cconf .= "request domain-name;\n";
3311
		$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3312

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

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

    
3355

    
3356
	/* accept router advertisements for this interface */
3357
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3358
	log_error("Accept router advertisements on interface {$wanif} ");
3359
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3360

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

    
3366
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3367
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$interface}.pid {$wanif}");
3368
	sleep(1);
3369
	unset($out);
3370
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3371
	if (!empty($out)) {
3372
		foreach($out as $line) {
3373
			if((stristr($line, "received")) && (!stristr($line, "unexpected"))) {
3374
				$parts = explode(" ", $line);
3375
				if(is_ipaddrv6($parts[3])) {
3376
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3377
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3378
					file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$parts[3]}\n");
3379
					break;
3380
				}
3381
			}
3382
		}
3383
	}
3384
	/* worst case is that the rc.newwanipv6 handles setting up the track6 interface */
3385
	if (!$g['booting'] && $wancfg['ippaddrv6'] != "slaac") {
3386
		/* configure dependent interfaces */
3387
		/* XXX: Really necessary? */
3388
		$iflist = get_configured_interface_with_descr(false, true);
3389
		foreach($iflist as $if => $ifname) {
3390
			if ($config['interfaces'][$if]['track6-interface'] == $interface)
3391
				interface_track6_configure($if);
3392
		}
3393
		unset($iflist);
3394
	}
3395

    
3396
	return 0;
3397
}
3398

    
3399
function interface_dhcp_configure($interface = "wan") {
3400
	global $config, $g;
3401

    
3402
	$wancfg = $config['interfaces'][$interface];
3403
	$wanif = $wancfg['if'];
3404
	if (empty($wancfg))
3405
		$wancfg = array();
3406

    
3407
	/* generate dhclient_wan.conf */
3408
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3409
	if (!$fd) {
3410
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3411
		return 1;
3412
	}
3413

    
3414
	if ($wancfg['dhcphostname']) {
3415
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3416
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3417
	} else {
3418
		$dhclientconf_hostname = "";
3419
	}
3420

    
3421
	$wanif = get_real_interface($interface);
3422
	if (empty($wanif)) {
3423
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3424
		return 0;
3425
	}
3426
	$dhclientconf = "";
3427

    
3428
	$dhclientconf .= <<<EOD
3429
interface "{$wanif}" {
3430
timeout 60;
3431
retry 15;
3432
select-timeout 0;
3433
initial-interval 1;
3434
	{$dhclientconf_hostname}
3435
	script "/sbin/dhclient-script";
3436
}
3437

    
3438
EOD;
3439

    
3440
if(is_ipaddr($wancfg['alias-address'])) {
3441
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3442
	$dhclientconf .= <<<EOD
3443
alias {
3444
	interface  "{$wanif}";
3445
	fixed-address {$wancfg['alias-address']};
3446
	option subnet-mask {$subnetmask};
3447
}
3448

    
3449
EOD;
3450
}
3451
	fwrite($fd, $dhclientconf);
3452
	fclose($fd);
3453

    
3454
	/* bring wan interface up before starting dhclient */
3455
	if($wanif)
3456
		interfaces_bring_up($wanif);
3457
	else
3458
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3459

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

    
3463
	return 0;
3464
}
3465

    
3466
function interfaces_group_setup() {
3467
	global $config;
3468

    
3469
	if (!is_array($config['ifgroups']['ifgroupentry']))
3470
		return;
3471

    
3472
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3473
		interface_group_setup($groupar);
3474

    
3475
	return;
3476
}
3477

    
3478
function interface_group_setup(&$groupname /* The parameter is an array */) {
3479
	global $config;
3480

    
3481
	if (!is_array($groupname))
3482
		return;
3483
	$members = explode(" ", $groupname['members']);
3484
	foreach($members as $ifs) {
3485
		$realif = get_real_interface($ifs);
3486
		if ($realif)
3487
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3488
	}
3489

    
3490
	return;
3491
}
3492

    
3493
function interface_group_add_member($interface, $groupname) {
3494
	$interface = get_real_interface($interface);
3495
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3496
}
3497

    
3498
/* COMPAT Function */
3499
function convert_friendly_interface_to_real_interface_name($interface) {
3500
	return get_real_interface($interface);
3501
}
3502

    
3503
/* COMPAT Function */
3504
function get_real_wan_interface($interface = "wan") {
3505
	return get_real_interface($interface);
3506
}
3507

    
3508
/* COMPAT Function */
3509
function get_current_wan_address($interface = "wan") {
3510
	return get_interface_ip($interface);
3511
}
3512

    
3513
/*
3514
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3515
 */
3516
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3517
	global $config;
3518

    
3519
	if (stristr($interface, "_vip")) {
3520
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
3521
			if ($vip['mode'] == "carp")  {
3522
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3523
					return $vip['interface'];
3524
			}
3525
		}
3526
	}
3527

    
3528
	/* XXX: For speed reasons reference directly the interface array */
3529
	$ifdescrs = &$config['interfaces'];
3530
	//$ifdescrs = get_configured_interface_list(false, true);
3531

    
3532
	foreach ($ifdescrs as $if => $ifname) {
3533
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3534
			return $if;
3535

    
3536
		if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3537
			return $if;
3538

    
3539
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3540
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3541
		/*
3542
		$int = get_parent_interface($if);
3543
		if ($int[0] == $interface)
3544
			return $ifname;
3545
		 */
3546
	}
3547
	return NULL;
3548
}
3549

    
3550
/* attempt to resolve interface to friendly descr */
3551
function convert_friendly_interface_to_friendly_descr($interface) {
3552
	global $config;
3553

    
3554
	switch ($interface) {
3555
	case "l2tp":
3556
		$ifdesc = "L2TP";
3557
		break;
3558
	case "pptp":
3559
		$ifdesc = "PPTP";
3560
		break;
3561
	case "pppoe":
3562
		$ifdesc = "PPPoE";
3563
		break;
3564
	case "openvpn":
3565
		$ifdesc = "OpenVPN";
3566
		break;
3567
	case "enc0":
3568
	case "ipsec":
3569
		$ifdesc = "IPsec";
3570
		break;
3571
	default:
3572
		if (isset($config['interfaces'][$interface])) {
3573
			if (empty($config['interfaces'][$interface]['descr']))
3574
				$ifdesc = strtoupper($interface);
3575
			else
3576
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3577
			break;
3578
		} else if (stristr($interface, "_vip")) {
3579
			if (is_array($config['virtualip']['vip'])) {
3580
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3581
					if ($vip['mode'] == "carp")  {
3582
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3583
							return "{$vip['subnet']} - {$vip['descr']}";
3584
					}
3585
				}
3586
			}
3587
		} else {
3588
			/* if list */
3589
			$ifdescrs = get_configured_interface_with_descr(false, true);
3590
			foreach ($ifdescrs as $if => $ifname) {
3591
				if ($if == $interface || $ifname == $interface)
3592
					return $ifname;
3593
			}
3594
		}
3595
		break;
3596
	}
3597

    
3598
	return $ifdesc;
3599
}
3600

    
3601
function convert_real_interface_to_friendly_descr($interface) {
3602
	global $config;
3603

    
3604
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3605

    
3606
	if ($ifdesc) {
3607
		$iflist = get_configured_interface_with_descr(false, true);
3608
		return $iflist[$ifdesc];
3609
	}
3610

    
3611
	return $interface;
3612
}
3613

    
3614
/*
3615
 *  get_parent_interface($interface):
3616
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3617
 *				or virtual interface (i.e. vlan)
3618
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3619
 *			-- returns $interface passed in if $interface parent is not found
3620
 *			-- returns empty array if an invalid interface is passed
3621
 *	(Only handles ppps and vlans now.)
3622
 */
3623
function get_parent_interface($interface) {
3624
	global $config;
3625

    
3626
	$parents = array();
3627
	//Check that we got a valid interface passed
3628
	$realif = get_real_interface($interface);
3629
	if ($realif == NULL)
3630
		return $parents;
3631

    
3632
	// If we got a real interface, find it's friendly assigned name
3633
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3634

    
3635
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3636
		$ifcfg = $config['interfaces'][$interface];
3637
		switch ($ifcfg['ipaddr']) {
3638
			case "ppp":
3639
			case "pppoe":
3640
			case "pptp":
3641
			case "l2tp":
3642
				if (empty($parents))
3643
					if (is_array($config['ppps']['ppp']))
3644
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3645
							if ($ifcfg['if'] == $ppp['if']) {
3646
								$ports = explode(',', $ppp['ports']);
3647
								foreach ($ports as $pid => $parent_if)
3648
									$parents[$pid] = get_real_interface($parent_if);
3649
								break;
3650
							}
3651
						}
3652
				break;
3653
			case "dhcp":
3654
			case "static":
3655
			default:
3656
				// Handle _vlans
3657
				if (strstr($realif,"_vlan"))
3658
					if (is_array($config['vlans']['vlan']))
3659
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3660
							if ($ifcfg['if'] == $vlan['vlanif']){
3661
								$parents[0] = $vlan['if'];
3662
								break;
3663
							}
3664
				break;
3665
		}
3666
	}
3667

    
3668
	if (empty($parents))
3669
		$parents[0] = $realif;
3670

    
3671
	return $parents;
3672
}
3673

    
3674
function interface_is_wireless_clone($wlif) {
3675
	if(!stristr($wlif, "_wlan")) {
3676
		return false;
3677
	} else {
3678
		return true;
3679
	}
3680
}
3681

    
3682
function interface_get_wireless_base($wlif) {
3683
	if(!stristr($wlif, "_wlan")) {
3684
		return $wlif;
3685
	} else {
3686
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3687
	}
3688
}
3689

    
3690
function interface_get_wireless_clone($wlif) {
3691
	if(!stristr($wlif, "_wlan")) {
3692
		return $wlif . "_wlan0";
3693
	} else {
3694
		return $wlif;
3695
	}
3696
}
3697

    
3698
function get_real_interface($interface = "wan") {
3699
	global $config;
3700

    
3701
	$wanif = NULL;
3702

    
3703
	switch ($interface) {
3704
	case "l2tp":
3705
		$wanif = "l2tp";
3706
		break;
3707
	case "pptp":
3708
		$wanif = "pptp";
3709
		break;
3710
	case "pppoe":
3711
		$wanif = "pppoe";
3712
		break;
3713
	case "openvpn":
3714
		$wanif = "openvpn";
3715
		break;
3716
	case "ipsec":
3717
	case "enc0":
3718
		$wanif = "enc0";
3719
		break;
3720
	case "ppp":
3721
		$wanif = "ppp";
3722
		break;
3723
	default:
3724
		// If a real interface was alread passed simply
3725
		// pass the real interface back.  This encourages
3726
		// the usage of this function in more cases so that
3727
		// we can combine logic for more flexibility.
3728
		if(does_interface_exist($interface)) {
3729
			$wanif = $interface;
3730
			break;
3731
		}
3732

    
3733
		if (empty($config['interfaces'][$interface]))
3734
			break;
3735

    
3736
		$cfg = &$config['interfaces'][$interface];
3737

    
3738
		// Wireless cloned NIC support (FreeBSD 8+)
3739
		// interface name format: $parentnic_wlanparentnic#
3740
		// example: ath0_wlan0
3741
		if (is_interface_wireless($cfg['if'])) {
3742
			$wanif = interface_get_wireless_clone($cfg['if']);
3743
			break;
3744
		}
3745
		/*
3746
		if (empty($cfg['if'])) {
3747
			$wancfg = $cfg['if'];
3748
			break;
3749
		}
3750
		*/
3751

    
3752
		switch ($cfg['ipaddr']) {
3753
			case "pppoe":
3754
			case "pptp":
3755
			case "l2tp":
3756
			case "ppp":
3757
				$wanif = $cfg['if'];
3758
				break;
3759
			default:
3760
				$wanif = $cfg['if'];
3761
				break;
3762
		}
3763
		break;
3764
	}
3765

    
3766
	return $wanif;
3767
}
3768

    
3769
/* Guess the physical interface by providing a IP address */
3770
function guess_interface_from_ip($ipaddress) {
3771
	if(! is_ipaddr($ipaddress)) {
3772
		return false;
3773
	}
3774
	if(is_ipaddrv4($ipaddress)) {
3775
		/* create a route table we can search */
3776
		exec("netstat -rnWf inet", $output, $ret);
3777
		foreach($output as $line) {
3778
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3779
				$fields = preg_split("/[ ]+/", $line);
3780
				if(ip_in_subnet($ipaddress, $fields[0])) {
3781
					return $fields[6];
3782
				}
3783
			}
3784
		}
3785
	}
3786
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3787
	if(is_ipaddrv6($ipaddress)) {
3788
		/* create a route table we can search */
3789
		exec("netstat -rnWf inet6", $output, $ret);
3790
		foreach($output as $line) {
3791
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3792
				$fields = preg_split("/[ ]+/", $line);
3793
				if(ip_in_subnet($ipaddress, $fields[0])) {
3794
					return $fields[6];
3795
				}
3796
			}
3797
		}
3798
	}
3799
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3800
	if(empty($ret)) {
3801
		return false;
3802
	}
3803
	return $ret;
3804
}
3805

    
3806
/*
3807
 * find_ip_interface($ip): return the interface where an ip is defined
3808
 *   (or if $bits is specified, where an IP within the subnet is defined)
3809
 */
3810
function find_ip_interface($ip, $bits = null)
3811
{
3812
	/* if list */
3813
	$ifdescrs = get_configured_interface_list();
3814

    
3815
	foreach ($ifdescrs as $ifdescr => $ifname) {
3816
		if ($bits === null) {
3817
			if ($ip == get_interface_ip($ifname)) {
3818
				$int = get_real_interface($ifname);
3819
				return $int;
3820
			}
3821
		}
3822
		else {
3823
			if (ip_in_subnet(get_interface_ip($ifname), $ip . "/" . $bits)) {
3824
				$int = get_real_interface($ifname);
3825
				return $int;
3826
			}
3827
		}
3828
	}
3829
	return false;
3830
}
3831

    
3832
/*
3833
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
3834
 *   (or if $bits is specified, where an IP within the subnet is found)
3835
 */
3836
function find_virtual_ip_alias($ip, $bits = null) {
3837
	global $config;
3838
	if (!is_array($config['virtualip']['vip'])) {
3839
		return false;
3840
	}
3841
	foreach ($config['virtualip']['vip'] as $vip) {
3842
		if ($vip['mode'] === "ipalias") {
3843
			if ($bits === null) {
3844
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
3845
					return $vip;
3846
				}
3847
			}
3848
			else {
3849
				if (check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits'])) {
3850
					return $vip;
3851
				}
3852
			}
3853
		}
3854
	}
3855
	return false;
3856
}
3857

    
3858
/*
3859
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3860
 */
3861
function find_number_of_created_carp_interfaces() {
3862
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3863
}
3864

    
3865
function get_all_carp_interfaces() {
3866
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3867
	$ints = explode(" ", $ints);
3868
	return $ints;
3869
}
3870

    
3871
/*
3872
 * find_carp_interface($ip): return the carp interface where an ip is defined
3873
 */
3874
function find_carp_interface($ip) {
3875
	global $config;
3876
	if (is_array($config['virtualip']['vip'])) {
3877
		foreach ($config['virtualip']['vip'] as $vip) {
3878
			if ($vip['mode'] == "carp") {
3879
				if(is_ipaddrv4($ip)) {
3880
					$carp_ip = get_interface_ip($vip['interface']);
3881
				}
3882
				if(is_ipaddrv6($ip)) {
3883
					$carp_ip = get_interface_ipv6($vip['interface']);
3884
				}
3885
				exec("/sbin/ifconfig", $output, $return);
3886
				foreach($output as $line) {
3887
					$elements = preg_split("/[ ]+/i", $line);
3888
					if(strstr($elements[0], "vip"))
3889
						$curif = str_replace(":", "", $elements[0]);
3890
					if(stristr($line, $ip)) {
3891
						$if = $curif;
3892
						continue;
3893
					}
3894
				}
3895

    
3896
				if ($if)
3897
					return $if;
3898
			}
3899
		}
3900
	}
3901
}
3902

    
3903
function link_carp_interface_to_parent($interface) {
3904
	global $config;
3905

    
3906
	if ($interface == "")
3907
		return;
3908

    
3909
	$carp_ip = get_interface_ip($interface);
3910
	$carp_ipv6 = get_interface_ipv6($interface);
3911

    
3912
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
3913
		return;
3914

    
3915
	/* if list */
3916
	$ifdescrs = get_configured_interface_list();
3917
	foreach ($ifdescrs as $ifdescr => $ifname) {
3918
		/* check IPv4 */
3919
		if(is_ipaddrv4($carp_ip)) {
3920
			$interfaceip = get_interface_ip($ifname);
3921
			$subnet_bits = get_interface_subnet($ifname);
3922
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3923
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3924
				return $ifname;
3925
		}
3926
		/* Check IPv6 */
3927
		if(is_ipaddrv6($carp_ipv6)) {
3928
			$interfaceipv6 = get_interface_ipv6($ifname);
3929
			$prefixlen = get_interface_subnetv6($ifname);
3930
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
3931
				return $ifname;
3932
		}
3933
	}
3934
	return "";
3935
}
3936

    
3937

    
3938
/****f* interfaces/link_ip_to_carp_interface
3939
 * NAME
3940
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3941
 * INPUTS
3942
 *   $ip
3943
 * RESULT
3944
 *   $carp_ints
3945
 ******/
3946
function link_ip_to_carp_interface($ip) {
3947
	global $config;
3948

    
3949
	if (!is_ipaddr($ip))
3950
		return;
3951

    
3952
	$carp_ints = "";
3953
	if (is_array($config['virtualip']['vip'])) {
3954
		$first = 0;
3955
		$carp_int = array();
3956
		foreach ($config['virtualip']['vip'] as $vip) {
3957
			if ($vip['mode'] == "carp") {
3958
				$carp_ip = $vip['subnet'];
3959
				$carp_sn = $vip['subnet_bits'];
3960
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
3961
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
3962
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
3963
				}
3964
			}
3965
		}
3966
		if (!empty($carp_int))
3967
			$carp_ints = implode(" ", array_unique($carp_int));
3968
	}
3969

    
3970
	return $carp_ints;
3971
}
3972

    
3973
function link_interface_to_vlans($int, $action = "") {
3974
	global $config;
3975

    
3976
	if (empty($int))
3977
		return;
3978

    
3979
	if (is_array($config['vlans']['vlan'])) {
3980
		foreach ($config['vlans']['vlan'] as $vlan) {
3981
			if ($int == $vlan['if']) {
3982
				if ($action == "update") {
3983
					interfaces_bring_up($int);
3984
				} else if ($action == "")
3985
					return $vlan;
3986
			}
3987
		}
3988
	}
3989
}
3990

    
3991
function link_interface_to_vips($int, $action = "") {
3992
	global $config;
3993

    
3994
	if (is_array($config['virtualip']['vip'])) {
3995
		$result = array();
3996
		foreach ($config['virtualip']['vip'] as $vip) {
3997
			if ($int == $vip['interface']) {
3998
				if ($action == "update")
3999
					interfaces_vips_configure($int);
4000
				else
4001
					$result[] = $vip;
4002
			}
4003
		}
4004
		return $result;
4005
	}
4006
}
4007

    
4008
/****f* interfaces/link_interface_to_bridge
4009
 * NAME
4010
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4011
 * INPUTS
4012
 *   $ip
4013
 * RESULT
4014
 *   bridge[0-99]
4015
 ******/
4016
function link_interface_to_bridge($int) {
4017
	global $config;
4018

    
4019
	if (is_array($config['bridges']['bridged'])) {
4020
		foreach ($config['bridges']['bridged'] as $bridge) {
4021
			if (in_array($int, explode(',', $bridge['members'])))
4022
				return "{$bridge['bridgeif']}";
4023
		}
4024
	}
4025
}
4026

    
4027
function link_interface_to_group($int) {
4028
	global $config;
4029

    
4030
	$result = array();
4031

    
4032
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4033
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4034
			if (in_array($int, explode(" ", $group['members'])))
4035
				$result[$group['ifname']] = $int;
4036
		}
4037
	}
4038

    
4039
	return $result;
4040
}
4041

    
4042
function link_interface_to_gre($interface) {
4043
	global $config;
4044

    
4045
	$result = array();
4046

    
4047
	if (is_array($config['gres']['gre'])) {
4048
		foreach ($config['gres']['gre'] as $gre)
4049
			if($gre['if'] == $interface)
4050
				$result[] = $gre;
4051
	}
4052

    
4053
	return $result;
4054
}
4055

    
4056
function link_interface_to_gif($interface) {
4057
	global $config;
4058

    
4059
	$result = array();
4060

    
4061
	if (is_array($config['gifs']['gif'])) {
4062
		foreach ($config['gifs']['gif'] as $gif)
4063
			if($gif['if'] == $interface)
4064
				$result[] = $gif;
4065
	}
4066

    
4067
	return $result;
4068
}
4069

    
4070
/*
4071
 * find_interface_ip($interface): return the interface ip (first found)
4072
 */
4073
function find_interface_ip($interface, $flush = false)
4074
{
4075
	global $interface_ip_arr_cache;
4076
	global $interface_sn_arr_cache;
4077

    
4078
	$interface = str_replace("\n", "", $interface);
4079

    
4080
	if (!does_interface_exist($interface))
4081
		return;
4082

    
4083
	/* Setup IP cache */
4084
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4085
		$ifinfo = pfSense_get_interface_addresses($interface);
4086
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4087
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4088
	}
4089

    
4090
	return $interface_ip_arr_cache[$interface];
4091
}
4092

    
4093
/*
4094
 * find_interface_ipv6($interface): return the interface ip (first found)
4095
 */
4096
function find_interface_ipv6($interface, $flush = false)
4097
{
4098
	global $interface_ipv6_arr_cache;
4099
	global $interface_snv6_arr_cache;
4100
	global $config;
4101

    
4102
	$interface = trim($interface);
4103
	$interface = get_real_interface($interface);
4104

    
4105
	if (!does_interface_exist($interface))
4106
		return;
4107

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

    
4131
	return $interface_ipv6_arr_cache[$interface];
4132
}
4133

    
4134
/*
4135
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4136
 */
4137
function find_interface_ipv6_ll($interface, $flush = false)
4138
{
4139
	global $interface_llv6_arr_cache;
4140
	global $config;
4141

    
4142
	$interface = str_replace("\n", "", $interface);
4143

    
4144
	if (!does_interface_exist($interface))
4145
		return;
4146

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

    
4166
function find_interface_subnet($interface, $flush = false)
4167
{
4168
	global $interface_sn_arr_cache;
4169
	global $interface_ip_arr_cache;
4170

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

    
4175
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4176
		$ifinfo = pfSense_get_interface_addresses($interface);
4177
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4178
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4179
	}
4180

    
4181
	return $interface_sn_arr_cache[$interface];
4182
}
4183

    
4184
function find_interface_subnetv6($interface, $flush = false)
4185
{
4186
	global $interface_snv6_arr_cache;
4187
	global $interface_ipv6_arr_cache;
4188

    
4189
	$interface = str_replace("\n", "", $interface);
4190
	if (does_interface_exist($interface) == false)
4191
		return;
4192

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

    
4215
	return $interface_snv6_arr_cache[$interface];
4216
}
4217

    
4218
function ip_in_interface_alias_subnet($interface, $ipalias) {
4219
	global $config;
4220

    
4221
	if (empty($interface) || !is_ipaddr($ipalias))
4222
		return false;
4223
	if (is_array($config['virtualip']['vip'])) {
4224
		foreach ($config['virtualip']['vip'] as $vip) {
4225
			switch ($vip['mode']) {
4226
			case "ipalias":
4227
				if ($vip['interface'] <> $interface)
4228
					break;
4229
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4230
					return true;
4231
				break;
4232
			}
4233
		}
4234
	}
4235

    
4236
	return false;
4237
}
4238

    
4239
function get_interface_ip($interface = "wan")
4240
{
4241
	$realif = get_failover_interface($interface);
4242
	if (!$realif) {
4243
		if (preg_match("/^carp/i", $interface))
4244
			$realif = $interface;
4245
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4246
			$realif = $interface;
4247
		else
4248
			return null;
4249
	}
4250

    
4251
	$curip = find_interface_ip($realif);
4252
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4253
		return $curip;
4254
	else
4255
		return null;
4256
}
4257

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

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

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

    
4296
	$curip = find_interface_ipv6_ll($realif);
4297
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4298
		return $curip;
4299
	else
4300
		return null;
4301
}
4302

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

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

    
4319
	return null;
4320
}
4321

    
4322
function get_interface_subnetv6($interface = "wan")
4323
{
4324
	$realif = get_real_interface($interface);
4325
	if (!$realif) {
4326
		if (preg_match("/^carp/i", $interface))
4327
			$realif = $interface;
4328
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4329
			$realif = $interface;
4330
		else
4331
			return null;
4332
	}
4333

    
4334
	$cursn = find_interface_subnetv6($realif);
4335
	if (!empty($cursn))
4336
		return $cursn;
4337

    
4338
	return null;
4339
}
4340

    
4341
/* return outside interfaces with a gateway */
4342
function get_interfaces_with_gateway() {
4343
	global $config;
4344

    
4345
	$ints = array();
4346

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

    
4368
/* return true if interface has a gateway */
4369
function interface_has_gateway($friendly) {
4370
	global $config;
4371

    
4372
	if (!empty($config['interfaces'][$friendly])) {
4373
		$ifname = &$config['interfaces'][$friendly];
4374
		switch ($ifname['ipaddr']) {
4375
			case "dhcp":
4376
			case "pppoe":
4377
			case "pptp":
4378
			case "l2tp":
4379
			case "ppp";
4380
				return true;
4381
			break;
4382
			default:
4383
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4384
					return true;
4385
				if (!empty($ifname['gateway']))
4386
					return true;
4387
			break;
4388
		}
4389
	}
4390

    
4391
	return false;
4392
}
4393

    
4394
/* return true if interface has a gateway */
4395
function interface_has_gatewayv6($friendly) {
4396
	global $config;
4397

    
4398
	if (!empty($config['interfaces'][$friendly])) {
4399
		$ifname = &$config['interfaces'][$friendly];
4400
		switch ($ifname['ipaddrv6']) {
4401
			case "slaac":
4402
			case "dhcp6":
4403
				return true;
4404
				break;
4405
			case "6to4":
4406
				return true;
4407
				break;
4408
			case "6rd":
4409
				return true;
4410
				break;
4411
			default:
4412
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4413
					return true;
4414
				if (!empty($ifname['gatewayv6']))
4415
					return true;
4416
				break;
4417
		}
4418
	}
4419

    
4420
	return false;
4421
}
4422

    
4423
/****f* interfaces/is_altq_capable
4424
 * NAME
4425
 *   is_altq_capable - Test if interface is capable of using ALTQ
4426
 * INPUTS
4427
 *   $int            - string containing interface name
4428
 * RESULT
4429
 *   boolean         - true or false
4430
 ******/
4431

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

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

    
4447
	if (in_array($int_family[0], $capable))
4448
		return true;
4449
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4450
		return true;
4451
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4452
		return true;
4453
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4454
		return true;
4455
	else
4456
		return false;
4457
}
4458

    
4459
/****f* interfaces/is_interface_wireless
4460
 * NAME
4461
 *   is_interface_wireless - Returns if an interface is wireless
4462
 * RESULT
4463
 *   $tmp       - Returns if an interface is wireless
4464
 ******/
4465
function is_interface_wireless($interface) {
4466
	global $config, $g;
4467

    
4468
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4469
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4470
		if (preg_match($g['wireless_regex'], $interface)) {
4471
			if (isset($config['interfaces'][$friendly]))
4472
				$config['interfaces'][$friendly]['wireless'] = array();
4473
			return true;
4474
		}
4475
		return false;
4476
	} else
4477
		return true;
4478
}
4479

    
4480
function get_wireless_modes($interface) {
4481
	/* return wireless modes and channels */
4482
	$wireless_modes = array();
4483

    
4484
	$cloned_interface = get_real_interface($interface);
4485

    
4486
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4487
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4488
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4489
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4490

    
4491
		$interface_channels = "";
4492
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4493
		$interface_channel_count = count($interface_channels);
4494

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

    
4525
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4526
function get_wireless_channel_info($interface) {
4527
	$wireless_channels = array();
4528

    
4529
	$cloned_interface = get_real_interface($interface);
4530

    
4531
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4532
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4533
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4534
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4535

    
4536
		$interface_channels = "";
4537
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4538

    
4539
		foreach ($interface_channels as $channel_line) {
4540
			$channel_line = explode(",", $channel_line);
4541
			if(!isset($wireless_channels[$channel_line[0]]))
4542
				$wireless_channels[$channel_line[0]] = $channel_line;
4543
		}
4544
	}
4545
	return($wireless_channels);
4546
}
4547

    
4548
/****f* interfaces/get_interface_mtu
4549
 * NAME
4550
 *   get_interface_mtu - Return the mtu of an interface
4551
 * RESULT
4552
 *   $tmp       - Returns the mtu of an interface
4553
 ******/
4554
function get_interface_mtu($interface) {
4555
	$mtu = pfSense_get_interface_addresses($interface);
4556
	return $mtu['mtu'];
4557
}
4558

    
4559
function get_interface_mac($interface) {
4560

    
4561
	$macinfo = pfSense_get_interface_addresses($interface);
4562
	return $macinfo["macaddr"];
4563
}
4564

    
4565
/****f* pfsense-utils/generate_random_mac_address
4566
 * NAME
4567
 *   generate_random_mac - generates a random mac address
4568
 * INPUTS
4569
 *   none
4570
 * RESULT
4571
 *   $mac - a random mac address
4572
 ******/
4573
function generate_random_mac_address() {
4574
	$mac = "02";
4575
	for($x=0; $x<5; $x++)
4576
		$mac .= ":" . dechex(rand(16, 255));
4577
	return $mac;
4578
}
4579

    
4580
/****f* interfaces/is_jumbo_capable
4581
 * NAME
4582
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4583
 * INPUTS
4584
 *   $int             - string containing interface name
4585
 * RESULT
4586
 *   boolean          - true or false
4587
 ******/
4588
function is_jumbo_capable($iface) {
4589
	$iface = trim($iface);
4590
	$capable = pfSense_get_interface_addresses($iface);
4591

    
4592
	if (isset($capable['caps']['vlanmtu']))
4593
		return true;
4594

    
4595
	return false;
4596
}
4597

    
4598
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4599
	global $g;
4600

    
4601
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4602

    
4603
	if(!empty($iface) && !empty($pppif)){
4604
		$cron_cmd = <<<EOD
4605
#!/bin/sh
4606
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4607
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
4608

    
4609
EOD;
4610

    
4611
		@file_put_contents($cron_file, $cron_cmd);
4612
		chmod($cron_file, 0755);
4613
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4614
	} else
4615
		unlink_if_exists($cron_file);
4616
}
4617

    
4618
function get_interface_default_mtu($type = "ethernet") {
4619
	switch ($type) {
4620
	case "gre":
4621
		return 1476;
4622
		break;
4623
	case "gif":
4624
		return 1280;
4625
		break;
4626
	case "tun":
4627
	case "vlan":
4628
	case "tap":
4629
	case "ethernet":
4630
	default:
4631
		return 1500;
4632
		break;
4633
	}
4634

    
4635
	/* Never reached */
4636
	return 1500;
4637
}
4638

    
4639
function get_vip_descr($ipaddress) {
4640
	global $config;
4641

    
4642
	foreach ($config['virtualip']['vip'] as $vip) {
4643
		if ($vip['subnet'] == $ipaddress) {
4644
			return ($vip['descr']);
4645
		}
4646
	}
4647
	return "";
4648
}
4649

    
4650
function interfaces_staticarp_configure($if) {
4651
	global $config, $g;
4652
	if(isset($config['system']['developerspew'])) {
4653
		$mt = microtime();
4654
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4655
	}
4656

    
4657
	$ifcfg = $config['interfaces'][$if];
4658

    
4659
	if (empty($if) || empty($ifcfg['if']))
4660
		return 0;
4661

    
4662
	/* Enable staticarp, if enabled */
4663
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4664
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4665
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4666
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4667

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

    
4671
			}
4672

    
4673
		}
4674
	} else {
4675
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4676
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4677
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4678
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
4679
				if (isset($arpent['arp_table_static_entry'])) {
4680
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
4681
				}
4682
			}
4683
		}
4684
	}
4685

    
4686
	return 0;
4687
}
4688

    
4689
function get_failover_interface($interface) {
4690
	global $config;
4691
	/* shortcut to get_real_interface if we find it in the config */
4692
	if(is_array($config['interfaces'][$interface])) {
4693
		$wanif = get_real_interface($interface);
4694
		return $wanif;
4695
	}
4696

    
4697
	/* compare against gateway groups */
4698
	$a_groups = return_gateway_groups_array();
4699
	if(is_array($a_groups[$interface])) {
4700
		/* we found a gateway group, fetch the interface or vip */
4701
		if($a_groups[$interface][0]['vip'] <> "")
4702
			$wanif = $a_groups[$interface][0]['vip'];
4703
		else
4704
			$wanif = $a_groups[$interface][0]['int'];
4705

    
4706
		return $wanif;
4707
	}
4708
	/* fall through to get_real_interface */
4709
	$wanif = get_real_interface($interface);
4710
	return $wanif;
4711
}
4712

    
4713
?>
(25-25/67)