Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
68
	return $interface_arr_cache;
69
}
70

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

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

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

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

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

    
98

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

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

    
124
	return false;
125
}
126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
267
	interfaces_bring_up($vlanif);
268

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

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

    
275
	return $vlanif;
276
}
277

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

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

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

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

    
298
	$vlanif = interface_vlan_configure($vlan);
299

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

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

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

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

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

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

    
351
	return $vlanif;
352
}
353

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

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

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

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

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

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

    
394
	return $vlanif;
395
}
396

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

    
400
	if($g['booting'])
401
		echo gettext("Creating other wireless clone interfaces...");
402
	if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
403
		foreach ($config['wireless']['clone'] as $clone) {
404
			if(empty($clone['cloneif']))
405
				continue;
406
			if(does_interface_exist($clone['cloneif']))
407
				continue;
408
			/* XXX: Maybe we should report any errors?! */
409
			if(interface_wireless_clone($clone['cloneif'], $clone))
410
				if($g['booting'])
411
					echo " " . $clone['cloneif'];
412
		}
413
	}
414
	if($g['booting'])
415
		echo " " . gettext("done.") . "\n";
416

    
417
}
418

    
419
function interfaces_bridge_configure($checkmember = 0) {
420
	global $config;
421

    
422
	$i = 0;
423
	if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
424
		foreach ($config['bridges']['bridged'] as $bridge) {
425
			if(empty($bridge['bridgeif']))
426
				$bridge['bridgeif'] = "bridge{$i}";
427
			/* XXX: Maybe we should report any errors?! */
428
			interface_bridge_configure($bridge, $checkmember);
429
			$i++;
430
		}
431
	}
432
}
433

    
434
function interface_bridge_configure(&$bridge, $checkmember = 0) {
435
	global $config, $g;
436

    
437
	if (!is_array($bridge))
438
	        return -1;
439

    
440
	if (empty($bridge['members'])) {
441
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
442
		return -1;
443
	}
444

    
445
	$members = explode(',', $bridge['members']);
446
	if (!count($members))
447
		return -1;
448

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

    
483
	/* Just in case anything is not working well */
484
	if ($smallermtu == 0)
485
		$smallermtu = 1500;
486

    
487
	$flags = 0;
488
	if ($commonrx === false)
489
		$flags |= IFCAP_RXCSUM;
490
	if ($commontx === false)
491
		$flags |= IFCAP_TXCSUM;
492
	if ($commontso4 === false)
493
		$flags |= IFCAP_TSO4;
494
	if ($commontso6 === false)
495
		$flags |= IFCAP_TSO6;
496
	if ($commonlro === false)
497
		$flags |= IFCAP_LRO;
498

    
499
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
500
		pfSense_interface_destroy($bridge['bridgeif']);
501
		pfSense_interface_create($bridge['bridgeif']);
502
		$bridgeif = escapeshellarg($bridge['bridgeif']);
503
	} else
504
		$bridgeif = pfSense_interface_create("bridge");
505

    
506
	$checklist = get_configured_interface_list();
507

    
508
	/* Add interfaces to bridge */
509
	foreach ($members as $member) {
510
		if (!array_key_exists($member, $checklist))
511
			continue;
512
		$realif1 = get_real_interface($member);
513
		$realif =  escapeshellarg($realif1);
514
		if (!$realif) {
515
			log_error(gettext("realif not defined in interfaces bridge - up"));
516
			continue;
517
		}
518
		/* make sure the parent interface is up */
519
		pfSense_interface_mtu($realif1, $smallermtu);
520
		pfSense_interface_capabilities($realif1, -$flags);
521
		interfaces_bring_up($realif1);
522
		pfSense_bridge_add_member($bridgeif, $realif1);
523
	}
524

    
525
	if (isset($bridge['enablestp'])) {
526
		/* Choose spanning tree proto */
527
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
528

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

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

    
625
	if($bridgeif)
626
		interfaces_bring_up($bridgeif);
627
	else
628
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
629

    
630
	return $bridgeif;
631
}
632

    
633
function interface_bridge_add_member($bridgeif, $interface) {
634

    
635
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
636
		return;
637

    
638
	$mtu = get_interface_mtu($bridgeif);
639
	$mtum = get_interface_mtu($interface);
640

    
641
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
642
		pfSense_interface_mtu($interface, $mtu);
643

    
644
	$options = pfSense_get_interface_addresses($bridgeif);
645
	$flags = 0;
646
	if (!isset($options['encaps']['txcsum']))
647
		$flags |= IFCAP_TXCSUM;
648

    
649
	if (!isset($options['encaps']['rxcsum']))
650
		$flags |= IFCAP_RXCSUM;
651

    
652
	pfSense_interface_capabilities($interface, -$flags);
653

    
654
	interfaces_bring_up($interface);
655
	pfSense_bridge_add_member($bridgeif, $interface);
656
}
657

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

    
676
function interface_lagg_configure(&$lagg) {
677
	global $config, $g;
678

    
679
	if (!is_array($lagg))
680
		return -1;
681

    
682
	$members = explode(',', $lagg['members']);
683
	if (!count($members))
684
		return -1;
685

    
686
	if ($g['booting'] || !(empty($lagg['laggif']))) {
687
		pfSense_interface_destroy($lagg['laggif']);
688
		pfSense_interface_create($lagg['laggif']);
689
		$laggif = $lagg['laggif'];
690
	} else
691
		$laggif = pfSense_interface_create("lagg");
692

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

    
714
	/* Just in case anything is not working well */
715
	if ($smallermtu == 0)
716
		$smallermtu = 1500;
717

    
718
	$flags = 0;
719
	if ($commonrx === false)
720
		$flags |= IFCAP_RXCSUM;
721
	if ($commontx === false)
722
		$flags |= IFCAP_TXCSUM;
723
	if ($commontso4 === false)
724
		$flags |= IFCAP_TSO4;
725
	if ($commontso6 === false)
726
		$flags |= IFCAP_TSO6;
727
	if ($commonlro === false)
728
		$flags |= IFCAP_LRO;
729

    
730
	$checklist = get_interface_list();
731

    
732
	foreach ($members as $member) {
733
		if (!array_key_exists($member, $checklist))
734
			continue;
735
		/* make sure the parent interface is up */
736
		pfSense_interface_mtu($member, $smallermtu);
737
		pfSense_interface_capabilities($member, -$flags);
738
		interfaces_bring_up($member);
739
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
740
	}
741

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

    
744
	interfaces_bring_up($laggif);
745

    
746
	return $laggif;
747
}
748

    
749
function interfaces_gre_configure($checkparent = 0) {
750
	global $config;
751

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

    
766
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
767
function interface_gre_configure(&$gre, $grekey = "") {
768
	global $config, $g;
769

    
770
	if (!is_array($gre))
771
		return -1;
772

    
773
	$realif = get_real_interface($gre['if']);
774
	$realifip = get_interface_ip($gre['if']);
775

    
776
	/* make sure the parent interface is up */
777
	interfaces_bring_up($realif);
778

    
779
	if ($g['booting'] || !(empty($gre['greif']))) {
780
		pfSense_interface_destroy($gre['greif']);
781
		pfSense_interface_create($gre['greif']);
782
		$greif = $gre['greif'];
783
	} else
784
		$greif = pfSense_interface_create("gre");
785

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

    
800
	if($greif)
801
		interfaces_bring_up($greif);
802
	else
803
		log_error(gettext("Could not bring greif up -- variable not defined."));
804

    
805
	if (isset($gre['link1']) && $gre['link1'])
806
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
807
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
808
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
809
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
810
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
811

    
812
	return $greif;
813
}
814

    
815
function interfaces_gif_configure($checkparent = 0) {
816
	global $config;
817

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

    
832
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
833
function interface_gif_configure(&$gif, $gifkey = "") {
834
	global $config, $g;
835

    
836
	if (!is_array($gif))
837
		return -1;
838

    
839
	$realif = get_real_interface($gif['if']);
840
	$ipaddr = $gif['ipaddr'];
841

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

    
861
	if ($g['booting'] || !(empty($gif['gifif']))) {
862
		pfSense_interface_destroy($gif['gifif']);
863
		pfSense_interface_create($gif['gifif']);
864
		$gifif = $gif['gifif'];
865
	} else
866
		$gifif = pfSense_interface_create("gif");
867

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

    
884
	$iflist = get_configured_interface_list();
885
	foreach($iflist as $ifname) {
886
		if($config['interfaces'][$ifname]['if'] == $gifif) {
887
			if(get_interface_gateway($ifname)) {
888
				system_routing_configure($ifname);
889
				break;
890
			}
891
			if(get_interface_gateway_v6($ifname)) {
892
				system_routing_configure($ifname);
893
				break;
894
			}
895
		}
896
	}
897

    
898

    
899
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
900
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
901
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
902
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
903

    
904
	if (is_ipaddrv4($realifgw)) {
905
		mwexec("route change -host {$gif['remote-addr']} {$realifgw}");
906
	}
907
	if (is_ipaddrv6($realifgw)) {
908
		mwexec("route change -host -inet6 {$gif['remote-addr']} {$realifgw}");
909
	}
910

    
911
	return $gifif;
912
}
913

    
914
function interfaces_configure() {
915
	global $config, $g;
916

    
917
	if ($g['platform'] == 'jail')
918
		return;
919

    
920
	/* Set up our loopback interface */
921
	interfaces_loopback_configure();
922

    
923
	/* set up LAGG virtual interfaces */
924
	interfaces_lagg_configure();
925

    
926
	/* set up VLAN virtual interfaces */
927
	interfaces_vlan_configure();
928

    
929
	interfaces_qinq_configure();
930

    
931
	$iflist = get_configured_interface_with_descr();
932
	$delayed_list = array();
933
	$bridge_list = array();
934

    
935
	/* This is needed to speedup interfaces on bootup. */
936
	$reload = false;
937
	if (!$g['booting'])
938
		$reload = true;
939

    
940
	foreach($iflist as $if => $ifname) {
941
		$realif = $config['interfaces'][$if]['if'];
942
		if (strstr($realif, "bridge"))
943
			$bridge_list[$if] = $ifname;
944
		else if (strstr($realif, "gre"))
945
			$delayed_list[$if] = $ifname;
946
		else if (strstr($realif, "gif"))
947
			$delayed_list[$if] = $ifname;
948
		else if (strstr($realif, "ovpn")) {
949
			//echo "Delaying OpenVPN interface configuration...done.\n";
950
			continue;
951
		} else {
952
			if ($g['booting'])
953
				printf(gettext("Configuring %s interface..."), $ifname);
954

    
955
			if($g['debug'])
956
				log_error(sprintf(gettext("Configuring %s"), $ifname));
957
			interface_configure($if, $reload);
958
			if ($g['booting'])
959
				echo gettext( "done.") . "\n";
960
		}
961
	}
962

    
963
	/* create the unconfigured wireless clones */
964
	interfaces_create_wireless_clones();
965

    
966
	/*
967
	 * NOTE: The following function parameter consists of
968
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
969
	 *	2 - Do load gre/gif/bridge with parent/member as vip
970
	 */
971

    
972
	/* set up GRE virtual interfaces */
973
	interfaces_gre_configure(1);
974

    
975
	/* set up GIF virtual interfaces */
976
	interfaces_gif_configure(1);
977

    
978
	/* set up BRIDGe virtual interfaces */
979
	interfaces_bridge_configure(1);
980

    
981
	/* bring up vip interfaces */
982
	interfaces_vips_configure();
983

    
984
	/* set up GRE virtual interfaces */
985
	interfaces_gre_configure(2);
986

    
987
	/* set up GIF virtual interfaces */
988
	interfaces_gif_configure(2);
989

    
990
	foreach ($delayed_list as $if => $ifname) {
991
		if ($g['booting'])
992
			printf(gettext("Configuring %s interface..."), $ifname);
993
		if ($g['debug'])
994
			log_error(sprintf(gettext("Configuring %s"), $ifname));
995

    
996
		interface_configure($if, $reload);
997

    
998
		if ($g['booting'])
999
			echo gettext("done.") . "\n";
1000
	}
1001

    
1002
	/* set up BRIDGe virtual interfaces */
1003
	interfaces_bridge_configure(2);
1004

    
1005
	foreach ($bridge_list as $if => $ifname) {
1006
		if ($g['booting'])
1007
			printf(gettext("Configuring %s interface..."), $ifname);
1008
		if($g['debug'])
1009
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1010

    
1011
		interface_configure($if, $reload);
1012

    
1013
		if ($g['booting'])
1014
			echo gettext("done.") . "\n";
1015
	}
1016

    
1017
	/* configure interface groups */
1018
	interfaces_group_setup();
1019

    
1020
	if (!$g['booting']) {
1021
		/* reconfigure static routes (kernel may have deleted them) */
1022
		system_routing_configure();
1023

    
1024
		/* reload IPsec tunnels */
1025
		vpn_ipsec_configure();
1026

    
1027
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1028
		services_dhcpd_configure();
1029

    
1030
		/* restart dnsmasq */
1031
		services_dnsmasq_configure();
1032

    
1033
		/* reload captive portal */
1034
		if (function_exists('captiveportal_init_rules'))
1035
			captiveportal_init_rules();
1036
	}
1037

    
1038
	return 0;
1039
}
1040

    
1041
function interface_reconfigure($interface = "wan", $reloadall = false) {
1042
	interface_bring_down($interface);
1043
	interface_configure($interface, $reloadall);
1044
}
1045

    
1046
function interface_vip_bring_down($vip) {
1047
	global $g;
1048

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

    
1072
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1073
	global $config, $g;
1074

    
1075
	if (!isset($config['interfaces'][$interface]))
1076
		return;
1077

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

    
1081
	if ($ifacecfg === false)
1082
		$ifcfg = $config['interfaces'][$interface];
1083
	else if (!is_array($ifacecfg))
1084
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1085
	else
1086
		$ifcfg = $ifacecfg;
1087
		
1088

    
1089
	$realif = get_real_interface($interface);
1090

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

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

    
1178
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1179
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1180
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1181
	if (!empty($old_router)) {
1182
		log_error("Clearing states to old gateway {$old_router}.");
1183
		mwexec("/sbin/pfctl -b 0.0.0.0/32 -b {$old_router}/32");
1184
	}
1185

    
1186
	/* remove interface up file if it exists */
1187
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1188
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1189
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1190
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1191
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1192
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1193
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1194

    
1195
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1196
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1197
	if (is_array($ifcfg['wireless'])) {
1198
		mwexec(kill_hostapd($realif));
1199
		mwexec(kill_wpasupplicant($realif));
1200
	}
1201

    
1202
	if ($destroy == true) {
1203
		if (preg_match("/^[a-z0-9]+_vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|^stf/i", $realif))
1204
			pfSense_interface_destroy($realif);
1205
	}
1206

    
1207
	return;
1208
}
1209

    
1210
function interfaces_ptpid_used($ptpid) {
1211
	global $config;
1212

    
1213
	if (is_array($config['ppps']['ppp']))
1214
		foreach ($config['ppps']['ppp'] as & $settings)
1215
			if ($ptpid == $settings['ptpid'])
1216
				return true;
1217

    
1218
	return false;
1219
}
1220

    
1221
function interfaces_ptpid_next() {
1222

    
1223
	$ptpid = 0;
1224
	while(interfaces_ptpid_used($ptpid))
1225
		$ptpid++;
1226

    
1227
	return $ptpid;
1228
}
1229

    
1230
function getMPDCRONSettings($pppif) {
1231
	global $config;
1232

    
1233
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1234
	if (is_array($config['cron']['item'])) {
1235
		foreach ($config['cron']['item'] as $i => $item) {
1236
			if (stripos($item['command'], $cron_cmd_file) !== false)
1237
				return array("ID" => $i, "ITEM" => $item);
1238
		}
1239
	}
1240

    
1241
	return NULL;
1242
}
1243

    
1244
function handle_pppoe_reset($post_array) {
1245
	global $config, $g;
1246

    
1247
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1248
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1249

    
1250
	if (!is_array($config['cron']['item']))
1251
		$config['cron']['item'] = array();
1252

    
1253
	$itemhash = getMPDCRONSettings($pppif);
1254

    
1255
	// reset cron items if necessary and return
1256
	if (empty($post_array['pppoe-reset-type'])) {
1257
		if (isset($itemhash))
1258
			unset($config['cron']['item'][$itemhash['ID']]);
1259
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1260
		return;
1261
	}
1262

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

    
1322
/*
1323
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1324
 * It writes the mpd config file to /var/etc every time the link is opened.
1325
 */
1326
function interface_ppps_configure($interface) {
1327
	global $config, $g;
1328

    
1329
	/* Return for unassigned interfaces. This is a minimum requirement. */
1330
	if (empty($config['interfaces'][$interface]))
1331
		return 0;
1332
	$ifcfg = $config['interfaces'][$interface];
1333
	if (!isset($ifcfg['enable']))
1334
		return 0;
1335

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

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

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

    
1370
	$ports = explode(',',$ppp['ports']);
1371
	if ($type != "modem") {
1372
		foreach ($ports as $pid => $port) {
1373
			$ports[$pid] = get_real_interface($port);
1374
			if (empty($ports[$pid]))
1375
				return 0;
1376
		}
1377
	}
1378
	$localips = explode(',',$ppp['localip']);
1379
	$gateways = explode(',',$ppp['gateway']);
1380
	$subnets = explode(',',$ppp['subnet']);
1381

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

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

    
1437
	if (is_array($ports) && count($ports) > 1)
1438
		$multilink = "enable";
1439
	else
1440
		$multilink = "disable";
1441

    
1442
	if ($type == "modem"){
1443
		if (is_ipaddr($ppp['localip']))
1444
			$localip = $ppp['localip'];
1445
		else
1446
			$localip = '0.0.0.0';
1447

    
1448
		if (is_ipaddr($ppp['gateway']))
1449
			$gateway = $ppp['gateway'];
1450
		else
1451
			$gateway = "10.64.64.{$pppid}";
1452
		$ranges = "{$localip}/0 {$gateway}/0";
1453

    
1454
		if (empty($ppp['apnum']))
1455
			$ppp['apnum'] = 1;
1456
	} else
1457
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1458

    
1459
	if (isset($ppp['ondemand']))
1460
		$ondemand = "enable";
1461
	else
1462
		$ondemand = "disable";
1463
	if (!isset($ppp['idletimeout']))
1464
		$ppp['idletimeout'] = 0;
1465

    
1466
	if (empty($ppp['username']) && $type == "modem"){
1467
		$ppp['username'] = "user";
1468
		$ppp['password'] = "none";
1469
	}
1470
	if (empty($ppp['password']) && $type == "modem")
1471
		$passwd = "none";
1472
	else
1473
		$passwd = base64_decode($ppp['password']);
1474

    
1475
	$bandwidths = explode(',',$ppp['bandwidth']);
1476
	$defaultmtu = "1492";
1477
	if (!empty($ifcfg['mtu']))
1478
		$defaultmtu = intval($ifcfg['mtu']);
1479
	$mtus = explode(',',$ppp['mtu']);
1480
	$mrus = explode(',',$ppp['mru']);
1481

    
1482
	if (isset($ppp['mrru']))
1483
		$mrrus = explode(',',$ppp['mrru']);
1484

    
1485
	// Construct the mpd.conf file
1486
	$mpdconf = <<<EOD
1487
startup:
1488
	# configure the console
1489
	set console close
1490
	# configure the web server
1491
	set web close
1492

    
1493
default:
1494
{$ppp['type']}client:
1495
	create bundle static {$interface}
1496
	set bundle enable ipv6cp
1497
	set iface name {$pppif}
1498

    
1499
EOD;
1500
	$setdefaultgw = false;
1501
	$founddefaultgw = false;
1502
	if (is_array($config['gateways']['gateway_item'])) {
1503
		foreach($config['gateways']['gateway_item'] as $gateway) {
1504
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1505
				$setdefaultgw = true;
1506
				break;
1507
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1508
				$founddefaultgw = true;
1509
				break;
1510
			}
1511
		}
1512
	}
1513

    
1514
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1515
		$setdefaultgw = true;
1516
		$mpdconf .= <<<EOD
1517
	set iface route default
1518

    
1519
EOD;
1520
	}
1521
	$mpdconf .= <<<EOD
1522
	set iface {$ondemand} on-demand
1523
	set iface idle {$ppp['idletimeout']}
1524

    
1525
EOD;
1526

    
1527
	if (isset($ppp['ondemand']))
1528
		$mpdconf .= <<<EOD
1529
	set iface addrs 10.10.1.1 10.10.1.2
1530

    
1531
EOD;
1532

    
1533
	if (isset($ppp['tcpmssfix']))
1534
		$tcpmss = "disable";
1535
	else
1536
		$tcpmss = "enable";
1537
		$mpdconf .= <<<EOD
1538
	set iface {$tcpmss} tcpmssfix
1539

    
1540
EOD;
1541

    
1542
	$mpdconf .= <<<EOD
1543
	set iface up-script /usr/local/sbin/ppp-linkup
1544
	set iface down-script /usr/local/sbin/ppp-linkdown
1545
	set ipcp ranges {$ranges}
1546

    
1547
EOD;
1548
	if (isset($ppp['vjcomp']))
1549
		$mpdconf .= <<<EOD
1550
	set ipcp no vjcomp
1551

    
1552
EOD;
1553

    
1554
	if (isset($config['system']['dnsallowoverride']))
1555
		$mpdconf .= <<<EOD
1556
	set ipcp enable req-pri-dns
1557
	set ipcp enable req-sec-dns
1558

    
1559
EOD;
1560
	if (!isset($ppp['verbose_log']))
1561
		$mpdconf .= <<<EOD
1562
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1563

    
1564
EOD;
1565
	foreach($ports as $pid => $port){
1566
		$port = get_real_interface($port);
1567
		$mpdconf .= <<<EOD
1568

    
1569
	create link static {$interface}_link{$pid} {$type}
1570
	set link action bundle {$interface}
1571
	set link {$multilink} multilink
1572
	set link keep-alive 10 60
1573
	set link max-redial 0
1574

    
1575
EOD;
1576
		if (isset($ppp['shortseq']))
1577
			$mpdconf .= <<<EOD
1578
	set link no shortseq
1579

    
1580
EOD;
1581

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

    
1586
EOD;
1587

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

    
1592
EOD;
1593

    
1594
		$mpdconf .= <<<EOD
1595
	set link disable chap pap
1596
	set link accept chap pap eap
1597
	set link disable incoming
1598

    
1599
EOD;
1600

    
1601

    
1602
		if (!empty($bandwidths[$pid]))
1603
			$mpdconf .= <<<EOD
1604
	set link bandwidth {$bandwidths[$pid]}
1605

    
1606
EOD;
1607

    
1608
		if (empty($mtus[$pid]))
1609
			$mtus[$pid] = $defaultmtu;
1610
			$mpdconf .= <<<EOD
1611
	set link mtu {$mtus[$pid]}
1612

    
1613
EOD;
1614

    
1615
		if (!empty($mrus[$pid]))
1616
			$mpdconf .= <<<EOD
1617
	set link mru {$mrus[$pid]}
1618

    
1619
EOD;
1620

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

    
1625
EOD;
1626

    
1627
		$mpdconf .= <<<EOD
1628
	set auth authname "{$ppp['username']}"
1629
	set auth password {$passwd}
1630

    
1631
EOD;
1632
		if ($type == "modem") {
1633
			$mpdconf .= <<<EOD
1634
	set modem device {$ppp['ports']}
1635
	set modem script DialPeer
1636
	set modem idle-script Ringback
1637
	set modem watch -cd
1638
	set modem var \$DialPrefix "DT"
1639
	set modem var \$Telephone "{$ppp['phone']}"
1640

    
1641
EOD;
1642
		}
1643
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1644
			$mpdconf .= <<<EOD
1645
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1646

    
1647
EOD;
1648
		}
1649
		if (isset($ppp['initstr']) && $type == "modem") {
1650
			$initstr = base64_decode($ppp['initstr']);
1651
			$mpdconf .= <<<EOD
1652
	set modem var \$InitString "{$initstr}"
1653

    
1654
EOD;
1655
		}
1656
		if (isset($ppp['simpin']) && $type == "modem") {
1657
			if($ppp['pin-wait'] == "")
1658
				$ppp['pin-wait'] = 0;
1659
			$mpdconf .= <<<EOD
1660
	set modem var \$SimPin "{$ppp['simpin']}"
1661
	set modem var \$PinWait "{$ppp['pin-wait']}"
1662

    
1663
EOD;
1664
		}
1665
		if (isset($ppp['apn']) && $type == "modem") {
1666
			$mpdconf .= <<<EOD
1667
	set modem var \$APN "{$ppp['apn']}"
1668
	set modem var \$APNum "{$ppp['apnum']}"
1669

    
1670
EOD;
1671
		}
1672
		if ($type == "pppoe") {
1673
			// Send a null service name if none is set.
1674
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1675
			$mpdconf .= <<<EOD
1676
	set pppoe service "{$provider}"
1677

    
1678
EOD;
1679
		}
1680
		if ($type == "pppoe")
1681
			$mpdconf .= <<<EOD
1682
	set pppoe iface {$port}
1683

    
1684
EOD;
1685

    
1686
		if ($type == "pptp" || $type == "l2tp") {
1687
			$mpdconf .= <<<EOD
1688
	set {$type} self {$localips[$pid]}
1689
	set {$type} peer {$gateways[$pid]}
1690

    
1691
EOD;
1692
		}
1693

    
1694
		$mpdconf .= "\topen\n";
1695
	} //end foreach($port)
1696

    
1697

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

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

    
1728
	/* clean up old lock files */
1729
	foreach($ports as $port) {
1730
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1731
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1732
	}
1733

    
1734
	/* fire up mpd */
1735
	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");
1736

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

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

    
1772
	return 1;
1773
}
1774

    
1775
function interfaces_carp_setup() {
1776
	global $g, $config;
1777

    
1778
	if (isset($config['system']['developerspew'])) {
1779
		$mt = microtime();
1780
		echo "interfaces_carp_setup() being called $mt\n";
1781
	}
1782

    
1783
	if ($g['booting']) {
1784
		echo gettext("Configuring CARP settings...");
1785
		mute_kernel_msgs();
1786
	}
1787

    
1788
	/* suck in configuration items */
1789
	if ($config['hasync']) {
1790
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1791
		$balanacing = $config['hasync']['balancing'];
1792
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1793
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1794
	} else {
1795
		unset($pfsyncinterface);
1796
		unset($balanacing);
1797
		unset($pfsyncenabled);
1798
	}
1799

    
1800
	if ($balanacing) {
1801
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1802
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1803
	} else
1804
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1805

    
1806
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1807
	if (!empty($pfsyncinterface))
1808
		$carp_sync_int = get_real_interface($pfsyncinterface);
1809
	else
1810
		unset($carp_sync_int);
1811

    
1812
	/* setup pfsync interface */
1813
	if ($carp_sync_int and $pfsyncenabled) {
1814
		if (is_ipaddr($pfsyncpeerip))
1815
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);
1816
		else
1817
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);
1818

    
1819
		sleep(1);
1820

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

    
1834
	if($config['virtualip']['vip'])
1835
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1836
	else
1837
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1838

    
1839
	if ($g['booting']) {
1840
		unmute_kernel_msgs();
1841
		echo gettext("done.") . "\n";
1842
	}
1843
}
1844

    
1845
function interface_proxyarp_configure($interface = "") {
1846
	global $config, $g;
1847
	if(isset($config['system']['developerspew'])) {
1848
		$mt = microtime();
1849
		echo "interface_proxyarp_configure() being called $mt\n";
1850
	}
1851

    
1852
	/* kill any running choparp */
1853
	if (empty($interface))
1854
		killbyname("choparp");
1855
	else {
1856
		$vipif = get_real_interface($interface);
1857
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1858
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1859
	}
1860

    
1861
	$paa = array();
1862
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1863

    
1864
		/* group by interface */
1865
		foreach ($config['virtualip']['vip'] as $vipent) {
1866
			if ($vipent['mode'] === "proxyarp") {
1867
				if ($vipent['interface'])
1868
					$proxyif = $vipent['interface'];
1869
				else
1870
					$proxyif = "wan";
1871

    
1872
				if (!empty($interface) && $interface != $proxyif)
1873
					continue;
1874

    
1875
				if (!is_array($paa[$proxyif]))
1876
					$paa[$proxyif] = array();
1877

    
1878
				$paa[$proxyif][] = $vipent;
1879
			}
1880
		}
1881
	}
1882

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

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

    
1953
function interface_ipalias_configure(&$vip) {
1954
	if ($vip['mode'] == "ipalias") {
1955
		$if = get_real_interface($vip['interface']);
1956
		$af = "inet";
1957
		if(is_ipaddrv6($vip['subnet']))
1958
			$af = "inet6";
1959
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
1960
	}
1961
}
1962

    
1963
function interface_reload_carps($cif) {
1964
	global $config;
1965

    
1966
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1967
	if (empty($carpifs))
1968
		return;
1969

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

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

    
1999
	if ($vip['mode'] != "carp")
2000
		return;
2001

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

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

    
2031
	// set the vip interface to the vhid
2032
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2033

    
2034
	/* create the carp interface and setup */
2035
	if (does_interface_exist($vipif)) {
2036
		pfSense_interface_flags($vipif, -IFF_UP);
2037
	} else {
2038
		$carpif = pfSense_interface_create("carp");
2039
		pfSense_interface_rename($carpif, $vipif);
2040
		pfSense_ngctl_name("{$carpif}:", $vipif);
2041
	}
2042

    
2043
	/* invalidate interface cache */
2044
	get_interface_arr(true);
2045

    
2046
	$vip_password = $vip['password'];
2047
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2048
	if ($vip['password'] != "")
2049
		$password = " pass {$vip_password}";
2050

    
2051
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2052
	$advbase = "";
2053
	if (!empty($vip['advbase']))
2054
		$advbase = "advbase {$vip['advbase']}";
2055

    
2056
	if(is_ipaddrv4($vip['subnet'])) {
2057
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2058
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2059
	}
2060
	if(is_ipaddrv6($vip['subnet'])) {
2061
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2062
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2063
	}
2064

    
2065
	interfaces_bring_up($vipif);
2066

    
2067
	return $vipif;
2068
}
2069

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

    
2111
	if($needs_clone == true) {
2112
		/* remove previous instance if it exists */
2113
		if(does_interface_exist($realif))
2114
			pfSense_interface_destroy($realif);
2115

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

    
2134
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2135
	global $config, $g;
2136

    
2137
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2138
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2139
	                         'regdomain', 'regcountry', 'reglocation');
2140

    
2141
	if(!is_interface_wireless($ifcfg['if']))
2142
		return;
2143

    
2144
	$baseif = interface_get_wireless_base($ifcfg['if']);
2145

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

    
2170
	// Read or write settings at shared area
2171
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2172
		foreach ($shared_settings as $setting) {
2173
			if ($sync_changes) {
2174
				if (isset($ifcfg['wireless'][$setting]))
2175
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2176
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2177
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2178
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2179
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2180
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2181
				else if (isset($ifcfg['wireless'][$setting]))
2182
					unset($ifcfg['wireless'][$setting]);
2183
			}
2184
		}
2185
	}
2186

    
2187
	// Sync the mode on the clone creation page with the configured mode on the interface
2188
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2189
		foreach ($config['wireless']['clone'] as &$clone) {
2190
			if ($clone['cloneif'] == $ifcfg['if']) {
2191
				if ($sync_changes) {
2192
					$clone['mode'] = $ifcfg['wireless']['mode'];
2193
				} else {
2194
					$ifcfg['wireless']['mode'] = $clone['mode'];
2195
				}
2196
				break;
2197
			}
2198
		}
2199
		unset($clone);
2200
	}
2201
}
2202

    
2203
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2204
	global $config, $g;
2205

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

    
2213
	// Remove script file
2214
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2215

    
2216
	// Clone wireless nic if needed.
2217
	interface_wireless_clone($if, $wl);
2218

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

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

    
2226
	/* set values for /path/program */
2227
	$hostapd = "/usr/sbin/hostapd";
2228
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2229
	$ifconfig = "/sbin/ifconfig";
2230
	$sysctl = "/sbin/sysctl";
2231
	$killall = "/usr/bin/killall";
2232

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

    
2235
	$wlcmd = array();
2236
	$wl_sysctl = array();
2237
	/* Make sure it's up */
2238
	$wlcmd[] = "up";
2239
	/* Set a/b/g standard */
2240
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2241
	$wlcmd[] = "mode " . escapeshellarg($standard);
2242

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

    
2248
	/* Set ssid */
2249
	if($wlcfg['ssid'])
2250
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2251

    
2252
	/* Set 802.11g protection mode */
2253
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2254

    
2255
	/* set wireless channel value */
2256
	if(isset($wlcfg['channel'])) {
2257
		if($wlcfg['channel'] == "0") {
2258
			$wlcmd[] = "channel any";
2259
		} else {
2260
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2261
		}
2262
	}
2263

    
2264
	/* Set antenna diversity value */
2265
	if(isset($wlcfg['diversity']))
2266
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2267

    
2268
	/* Set txantenna value */
2269
	if(isset($wlcfg['txantenna']))
2270
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2271

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

    
2276
	/* set Distance value */
2277
	if($wlcfg['distance'])
2278
		$distance = escapeshellarg($wlcfg['distance']);
2279

    
2280
	/* Set wireless hostap mode */
2281
	if ($wlcfg['mode'] == "hostap") {
2282
		$wlcmd[] = "mediaopt hostap";
2283
	} else {
2284
		$wlcmd[] = "-mediaopt hostap";
2285
	}
2286

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

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

    
2296
	/* handle hide ssid option */
2297
	if(isset($wlcfg['hidessid']['enable'])) {
2298
		$wlcmd[] = "hidessid";
2299
	} else {
2300
		$wlcmd[] = "-hidessid";
2301
	}
2302

    
2303
	/* handle pureg (802.11g) only option */
2304
	if(isset($wlcfg['pureg']['enable'])) {
2305
		$wlcmd[] = "mode 11g pureg";
2306
	} else {
2307
		$wlcmd[] = "-pureg";
2308
	}
2309

    
2310
	/* handle puren (802.11n) only option */
2311
	if(isset($wlcfg['puren']['enable'])) {
2312
		$wlcmd[] = "puren";
2313
	} else {
2314
		$wlcmd[] = "-puren";
2315
	}
2316

    
2317
	/* enable apbridge option */
2318
	if(isset($wlcfg['apbridge']['enable'])) {
2319
		$wlcmd[] = "apbridge";
2320
	} else {
2321
		$wlcmd[] = "-apbridge";
2322
	}
2323

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

    
2331
	/* handle txpower setting */
2332
	/* if($wlcfg['txpower'] <> "")
2333
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2334
	*/
2335
	/* handle wme option */
2336
	if(isset($wlcfg['wme']['enable'])) {
2337
		$wlcmd[] = "wme";
2338
	} else {
2339
		$wlcmd[] = "-wme";
2340
	}
2341

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

    
2368
	mwexec(kill_hostapd("{$if}"));
2369
	mwexec(kill_wpasupplicant("{$if}"));
2370

    
2371
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2372
	conf_mount_rw();
2373

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

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

    
2428
EOD;
2429

    
2430
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2431
	$wpa .= <<<EOD
2432
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2433
rsn_preauth=1
2434
rsn_preauth_interfaces={$if}
2435

    
2436
EOD;
2437

    
2438
}
2439
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2440
					$auth_server_port = "1812";
2441
					if($wlcfg['auth_server_port'])
2442
						$auth_server_port = $wlcfg['auth_server_port'];
2443
					$auth_server_port2 = "1812";
2444
					if($wlcfg['auth_server_port2'])
2445
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2446
					$wpa .= <<<EOD
2447

    
2448
ieee8021x=1
2449
auth_server_addr={$wlcfg['auth_server_addr']}
2450
auth_server_port={$auth_server_port}
2451
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2452
auth_server_addr={$wlcfg['auth_server_addr2']}
2453
auth_server_port={$auth_server_port2}
2454
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2455

    
2456
EOD;
2457
				} else {
2458
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2459
				}
2460

    
2461
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2462
				fwrite($fd, "{$wpa}");
2463
				fclose($fd);
2464

    
2465
			}
2466
			break;
2467
	}
2468

    
2469
	/*
2470
	 *    all variables are set, lets start up everything
2471
	 */
2472

    
2473
	$baseif = interface_get_wireless_base($if);
2474
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2475
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2476

    
2477
	/* set sysctls for the wireless interface */
2478
	if (!empty($wl_sysctl)) {
2479
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2480
		foreach ($wl_sysctl as $wl_sysctl_line) {
2481
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2482
		}
2483
	}
2484

    
2485
	/* set ack timers according to users preference (if he/she has any) */
2486
	if($distance) {
2487
		fwrite($fd_set, "# Enable ATH distance settings\n");
2488
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2489
	}
2490

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

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

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

    
2519
	fclose($fd_set);
2520
	conf_mount_ro();
2521

    
2522
	/* Making sure regulatory settings have actually changed
2523
	 * before applying, because changing them requires bringing
2524
	 * down all wireless networks on the interface. */
2525
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2526
	$ifconfig_str = implode($output);
2527
	unset($output);
2528
	$reg_changing = false;
2529

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

    
2542
	if ($reg_changing) {
2543
		/* set regulatory domain */
2544
		if($wlcfg['regdomain'])
2545
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2546

    
2547
		/* set country */
2548
		if($wlcfg['regcountry'])
2549
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2550

    
2551
		/* set location */
2552
		if($wlcfg['reglocation'])
2553
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2554

    
2555
		$wlregcmd_args = implode(" ", $wlregcmd);
2556

    
2557
		/* build a complete list of the wireless clones for this interface */
2558
		$clone_list = array();
2559
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2560
			$clone_list[] = interface_get_wireless_clone($baseif);
2561
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2562
			foreach ($config['wireless']['clone'] as $clone) {
2563
				if ($clone['if'] == $baseif)
2564
					$clone_list[] = $clone['cloneif'];
2565
			}
2566
		}
2567

    
2568
		/* find which clones are up and bring them down */
2569
		$clones_up = array();
2570
		foreach ($clone_list as $clone_if) {
2571
			$clone_status = pfSense_get_interface_addresses($clone_if);
2572
			if ($clone_status['status'] == 'up') {
2573
				$clones_up[] = $clone_if;
2574
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2575
			}
2576
		}
2577

    
2578
		/* apply the regulatory settings */
2579
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2580

    
2581
		/* bring the clones back up that were previously up */
2582
		foreach ($clones_up as $clone_if) {
2583
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2584

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

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

    
2605
	/* configure wireless */
2606
	$wlcmd_args = implode(" ", $wlcmd);
2607
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2608

    
2609

    
2610
	sleep(1);
2611
	/* execute hostapd and wpa_supplicant if required in shell */
2612
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2613

    
2614
	return 0;
2615

    
2616
}
2617

    
2618
function kill_hostapd($interface) {
2619
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2620
}
2621

    
2622
function kill_wpasupplicant($interface) {
2623
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2624
}
2625

    
2626
function find_dhclient_process($interface) {
2627
	if ($interface)
2628
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2629
	else
2630
		$pid = 0;
2631

    
2632
	return intval($pid);
2633
}
2634

    
2635
function find_dhcp6c_process($interface) {
2636
	if ($interface)
2637
		$pid = `/bin/ps auxw|grep "[d]hcp6c" |grep "{$interface}"|awk '{print $2}'`;
2638
	else
2639
		return(false);
2640

    
2641
	return intval($pid);
2642
}
2643

    
2644
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2645
	global $config, $g;
2646
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2647
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2648

    
2649
	$wancfg = $config['interfaces'][$interface];
2650

    
2651
	$realif = get_real_interface($interface);
2652
	$realhwif_array = get_parent_interface($interface);
2653
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2654
	$realhwif = $realhwif_array[0];
2655

    
2656
	/* Disable Accepting router advertisements unless specifically requested */
2657
	log_error("Deny router advertisements for interface {$interface}");
2658
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2659

    
2660
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2661
		/* remove all IPv4 and IPv6 addresses */
2662
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2663
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2664

    
2665
		/* only bring down the interface when both v4 and v6 are set to NONE */
2666
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2667
			interface_bring_down($interface);
2668
		}
2669
	}
2670

    
2671
	/* wireless configuration? */
2672
	if (is_array($wancfg['wireless']))
2673
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2674

    
2675
	$mac = get_interface_mac($realhwif);
2676
	/*
2677
	 * Don't try to reapply the spoofed MAC if it's already applied.
2678
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2679
	 * the interface config again, which attempts to spoof the MAC again,
2680
	 * which cycles the link again...
2681
	 */
2682
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2683
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2684
			" link " . escapeshellarg($wancfg['spoofmac']));
2685

    
2686
		/*
2687
		 * All vlans need to spoof their parent mac address, too.  see
2688
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2689
		 */
2690
		if (is_array($config['vlans']['vlan'])) {
2691
			foreach ($config['vlans']['vlan'] as $vlan) {
2692
				if ($vlan['if'] == $realhwif)
2693
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2694
					" link " . escapeshellarg($wancfg['spoofmac']));
2695
			}
2696
		}
2697
	}  else {
2698

    
2699
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2700
			/*   this is not a valid mac address.  generate a
2701
			 *   temporary mac address so the machine can get online.
2702
			 */
2703
			echo gettext("Generating new MAC address.");
2704
			$random_mac = generate_random_mac_address();
2705
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2706
				" link " . escapeshellarg($random_mac));
2707
			$wancfg['spoofmac'] = $random_mac;
2708
			write_config();
2709
			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");
2710
		}
2711
	}
2712

    
2713
	/* media */
2714
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2715
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2716
		if ($wancfg['media'])
2717
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2718
		if ($wancfg['mediaopt'])
2719
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2720
		mwexec($cmd);
2721
	}
2722
	if (!empty($wancfg['mtu']))
2723
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2724
	else {
2725
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2726
		if ($mtu != get_interface_mtu($realhwif))
2727
			pfSense_interface_mtu($realhwif, $mtu);
2728
	}
2729

    
2730
	$options = pfSense_get_interface_addresses($realhwif);
2731
	if (is_array($options) && isset($options['caps']['polling'])) {
2732
		if (isset($config['system']['polling']))
2733
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2734
		else
2735
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2736
	}
2737

    
2738
	/* skip vlans for checksumming and polling */
2739
	if (!stristr($realhwif, "vlan") && is_array($options)) {
2740
		$flags = 0;
2741
		if(isset($config['system']['disablechecksumoffloading'])) {
2742
			if (isset($options['encaps']['txcsum']))
2743
				$flags |= IFCAP_TXCSUM;
2744
			if (isset($options['encaps']['rxcsum']))
2745
				$flags |= IFCAP_RXCSUM;
2746
		} else {
2747
			if (!isset($options['caps']['txcsum']))
2748
				$flags |= IFCAP_TXCSUM;
2749
			if (!isset($options['caps']['rxcsum']))
2750
				$flags |= IFCAP_RXCSUM;
2751
		}
2752

    
2753
		if(isset($config['system']['disablesegmentationoffloading'])) {
2754
			if (isset($options['encaps']['tso4']))
2755
				$flags |= IFCAP_TSO;
2756
			if (isset($options['encaps']['tso6']))
2757
				$flags |= IFCAP_TSO;
2758
		} else {
2759
			if (!isset($options['caps']['tso4']))
2760
				$flags |= IFCAP_TSO;
2761
			if (!isset($options['caps']['tso6']))
2762
				$flags |= IFCAP_TSO;
2763
		}
2764

    
2765
		if(isset($config['system']['disablelargereceiveoffloading'])) {
2766
			if (isset($options['encaps']['lro']))
2767
				$flags |= IFCAP_LRO;
2768
		} else {
2769
			if (!isset($options['caps']['lro']))
2770
				$flags |= IFCAP_LRO;
2771
		}
2772

    
2773
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2774
		if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2775
			$flags |= IFCAP_POLLING;
2776
		}
2777
		pfSense_interface_capabilities($realhwif, -$flags);
2778
	}
2779

    
2780
	/* invalidate interface/ip/sn cache */
2781
	get_interface_arr(true);
2782
	unset($interface_ip_arr_cache[$realif]);
2783
	unset($interface_sn_arr_cache[$realif]);
2784
	unset($interface_ipv6_arr_cache[$realif]);
2785
	unset($interface_snv6_arr_cache[$realif]);
2786

    
2787
	switch ($wancfg['ipaddr']) {
2788
		case 'dhcp':
2789
			interface_dhcp_configure($interface);
2790
			break;
2791
		case 'pppoe':
2792
		case 'l2tp':
2793
		case 'pptp':
2794
		case 'ppp':
2795
			interface_ppps_configure($interface);
2796
			break;
2797
		default:
2798
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2799
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2800
			} else if (substr($realif, 0, 3) == "gre") {
2801
				if (is_array($config['gres']['gre'])) {
2802
					foreach ($config['gres']['gre'] as $gre)
2803
						if ($gre['greif'] == $realif)
2804
							interface_gre_configure($gre);
2805
				}
2806
			} else if (substr($realif, 0, 3) == "gif") {
2807
				if (is_array($config['gifs']['gif'])) {
2808
					foreach ($config['gifs']['gif'] as $gif)
2809
						if($gif['gifif'] == $realif)
2810
							interface_gif_configure($gif);
2811
				}
2812
			} else if (substr($realif, 0, 4) == "ovpn") {
2813
				/* XXX: Should be done anything?! */
2814
			}
2815
			break;
2816
	}
2817

    
2818
	switch ($wancfg['ipaddrv6']) {
2819
		case 'slaac':
2820
		case 'dhcp6':
2821
			interface_dhcpv6_configure($interface);
2822
			break;
2823
		case '6rd':
2824
			interface_6rd_configure($interface);
2825
			break;
2826
		case '6to4':
2827
			interface_6to4_configure($interface);
2828
			break;
2829
		case 'track6':
2830
			interface_track6_configure($interface);
2831
			break;
2832
		default:
2833
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2834
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2835
				// FIXME: Add IPv6 Support to the pfSense module
2836
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2837
			}
2838
			break;
2839
	}
2840

    
2841
	if(does_interface_exist($wancfg['if']))
2842
		interfaces_bring_up($wancfg['if']);
2843

    
2844
	interface_netgraph_needed($interface);
2845

    
2846
	if (!$g['booting']) {
2847
		link_interface_to_vips($interface, "update");
2848

    
2849
		unset($gre);
2850
		$gre = link_interface_to_gre($interface);
2851
		if (!empty($gre))
2852
			array_walk($gre, 'interface_gre_configure');
2853

    
2854
		unset($gif);
2855
		$gif = link_interface_to_gif($interface);
2856
		if (!empty($gif))
2857
			array_walk($gif, 'interface_gif_configure');
2858

    
2859
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2860
			unset($bridgetmp);
2861
			$bridgetmp = link_interface_to_bridge($interface);
2862
			if (!empty($bridgetmp))
2863
				interface_bridge_add_member($bridgetmp, $realif);
2864
		}
2865

    
2866
		$grouptmp = link_interface_to_group($interface);
2867
		if (!empty($grouptmp))
2868
			array_walk($grouptmp, 'interface_group_add_member');
2869

    
2870
		if ($interface == "lan")
2871
			/* make new hosts file */
2872
			system_hosts_generate();
2873

    
2874
		if ($reloadall == true) {
2875

    
2876
			/* reconfigure static routes (kernel may have deleted them) */
2877
			system_routing_configure($interface);
2878

    
2879
			/* reload ipsec tunnels */
2880
			vpn_ipsec_configure();
2881

    
2882
			/* restart dnsmasq */
2883
			services_dnsmasq_configure();
2884

    
2885
			/* update dyndns */
2886
			send_event("service reload dyndns {$interface}");
2887

    
2888
			/* reload captive portal */
2889
			captiveportal_init_rules();
2890
		}
2891
	}
2892

    
2893
	return 0;
2894
}
2895

    
2896
function interface_track6_configure($interface = "lan") {
2897
	global $config, $g;
2898
	$iflist = get_configured_interface_with_descr(false, true);
2899

    
2900
	$wancfg = $config['interfaces'][$interface];
2901
	$wanif = $wancfg['if'];
2902
	if (empty($wancfg))
2903
		$wancfg = array();
2904

    
2905
	$wanif = get_real_interface($interface);
2906

    
2907
	/* If the interface is not configured via another, exit */
2908
	if(!$wancfg['track6-interface'] <> "") {
2909
		return(false);
2910
	}
2911

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

    
2916
	$type = $config['interfaces'][$wancfg['track6-interface']]['ipaddrv6'];
2917
	switch($type) {
2918
		case "6to4":
2919
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2920
			interface_track6_6to4_configure($interface);
2921
			break;
2922
		case "6rd":
2923
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2924
			interface_track6_6rd_configure($interface);
2925
			break;
2926
		case "dhcp6":
2927
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2928
			interface_track6_dhcp6_configure($interface);
2929
			break;
2930
		default:
2931
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']} but unknown type {$type}");
2932
			break;
2933
	}
2934
	return 0;
2935
}
2936

    
2937

    
2938
function interface_track6_6rd_configure($interface = "lan") {
2939
	global $config, $g;
2940
	$iflist = get_configured_interface_with_descr(false, true);
2941

    
2942
	$lancfg = $config['interfaces'][$interface];
2943
	$lanif = $lancfg['if'];
2944
	if (empty($lancfg))
2945
		$lancfg = array();
2946

    
2947
	$lanif = get_real_interface($interface);
2948

    
2949
	/* If the interface is not configured via another, exit */
2950
	if(!$lancfg['track6-interface'] <> "") {
2951
		return(false);
2952
	}
2953
	if(!is_numeric($lancfg['track6-prefix-id']))
2954
		$lancfg['track6-prefix-id'] = 0;
2955

    
2956
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2957
	$wanif = $wancfg['if'];
2958
	if (empty($wancfg))
2959
		$wancfg = array();
2960

    
2961
	$ip4address = find_interface_ip($wanif);
2962
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
2963
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
2964
		return false;
2965
	}
2966
	$hexwanv4 = return_hex_ipv4($ip4address);
2967

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

    
2973
	/* binary presentation of the prefix for all 128 bits. */
2974
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
2975

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

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

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

    
2992
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
2993
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
2994
	return 0;
2995
}
2996

    
2997
function interface_track6_6to4_configure($interface = "lan") {
2998
	global $config, $g;
2999
	$iflist = get_configured_interface_with_descr(false, true);
3000

    
3001
	$lancfg = $config['interfaces'][$interface];
3002
	$lanif = $lancfg['if'];
3003
	if (empty($lancfg))
3004
		$lancfg = array();
3005

    
3006
	$lanif = get_real_interface($interface);
3007

    
3008
	/* If the interface is not configured via another, exit */
3009
	if(!$lancfg['track6-interface'] <> "") {
3010
		return(false);
3011
	}
3012
	if(!is_numeric($lancfg['track6-prefix-id']))
3013
		$lancfg['track6-prefix-id'] = 0;
3014

    
3015
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3016
	$wanif = $wancfg['if'];
3017
	if (empty($wancfg))
3018
		$wancfg = array();
3019

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

    
3027
	/* create the long prefix notation for math, save the prefix length */
3028
	$sixto4prefix = "2002::";
3029
	$sixto4prefixlen = 16;
3030
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3031

    
3032
	/* binary presentation of the prefix for all 128 bits. */
3033
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3034

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

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

    
3047
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3048
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3049
	return 0;
3050
}
3051

    
3052
function interface_track6_dhcp6_configure($interface = "lan") {
3053
	global $config, $g;
3054
	$iflist = get_configured_interface_with_descr(false, true);
3055

    
3056
	$lancfg = $config['interfaces'][$interface];
3057
	$lanif = $lancfg['if'];
3058
	if (empty($lancfg))
3059
		$lancfg = array();
3060

    
3061
	$lanif = get_real_interface($interface);
3062

    
3063
	/* If the interface is not configured via another, exit */
3064
	if(!$lancfg['track6-interface'] <> "") {
3065
		return(false);
3066
	}
3067
	if(!is_numeric($lancfg['track6-prefix-id']))
3068
		$lancfg['track6-prefix-id'] = 0;
3069

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

    
3075

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

    
3090
function interface_6rd_configure($interface = "wan") {
3091
	global $config, $g;
3092
	$iflist = get_configured_interface_with_descr(false, true);
3093

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

    
3097
	$wancfg = $config['interfaces'][$interface];
3098
	$wanif = $wancfg['if'];
3099
	if (empty($wancfg))
3100
		$wancfg = array();
3101

    
3102
	$wanif = get_real_interface($interface);
3103

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

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

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

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

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

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

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

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

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

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

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

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

    
3159
	/* configure dependent interfaces */
3160
	foreach($iflist as $if => $ifname) {
3161
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3162
			interface_track6_configure($if);
3163
	}
3164

    
3165
	return 0;
3166
}
3167

    
3168
function interface_6to4_configure($interface = "wan"){
3169
	global $config, $g;
3170
	$iflist = get_configured_interface_with_descr(false, true);
3171

    
3172
	/* because this is a tunnel interface we can only function
3173
	 *	with a public IPv4 address on the interface */
3174

    
3175
	$wancfg = $config['interfaces'][$interface];
3176
	$wanif = $wancfg['if'];
3177
	if (empty($wancfg))
3178
		$wancfg = array();
3179

    
3180
	$wanif = get_real_interface($interface);
3181

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

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

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

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

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

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

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

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

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

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

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

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

    
3253
	if (is_ipaddrv4($ip4gateway)) {
3254
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3255
	}
3256

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

    
3263
	return 0;
3264
}
3265

    
3266
function interface_dhcpv6_configure($interface = "wan") {
3267
	global $config, $g;
3268
	$iflist = get_configured_interface_with_descr(false, true);
3269

    
3270
	$wancfg = $config['interfaces'][$interface];
3271
	$wanif = $wancfg['if'];
3272
	if (empty($wancfg))
3273
		$wancfg = array();
3274

    
3275
	$wanif = get_real_interface($interface);
3276

    
3277
	/* wide-dhcp6c works for now. */
3278
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
3279
	if (!$fd) {
3280
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3281
		return 1;
3282
	}
3283

    
3284
	$dhcp6cconf = "";
3285
	$dhcp6cconf .= "interface {$wanif} {\n";
3286

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

    
3296
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3297
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3298
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3299
		}
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

    
3304
		$dhcp6cconf .= "};\n";
3305
		$dhcp6cconf .= "id-assoc na 0 { };\n";
3306
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3307
			/* Setup the prefix delegation */
3308
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3309
			foreach($iflist as $friendly => $ifdescr) {
3310
				if($config['interfaces'][$friendly]['track6-interface'] != $interface)
3311
					continue;
3312
				if(is_numeric($config['interfaces'][$friendly]['track6-prefix-id'])) {
3313
					log_error("setting up $friendly - {$config['interfaces'][$friendly]['track6-prefix-id']}");
3314
					$realif = get_real_interface($friendly);
3315
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3316
					$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['track6-prefix-id']};\n";
3317
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3318
					$dhcp6cconf .= "	};\n";
3319
				}
3320
			}
3321
			$dhcp6cconf .= "};\n";
3322
		}
3323
	}
3324
	fwrite($fd, $dhcp6cconf);
3325
	fclose($fd);
3326

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

    
3337
	fwrite($fds, $dhcp6cscript);
3338
	fclose($fds);
3339
	chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3340

    
3341

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

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

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

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

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

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

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

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

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

    
3418
EOD;
3419

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

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

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

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

    
3443
	return 0;
3444
}
3445

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

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

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

    
3455
	return;
3456
}
3457

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

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

    
3470
	return;
3471
}
3472

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

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

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

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

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

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

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

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

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

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

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

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

    
3578
	return $ifdesc;
3579
}
3580

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

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

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

    
3591
	return $interface;
3592
}
3593

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

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

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

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

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

    
3651
	return $parents;
3652
}
3653

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

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

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

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

    
3681
	$wanif = NULL;
3682

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

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

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

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

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

    
3746
	return $wanif;
3747
}
3748

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3917

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

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

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

    
3950
	return $carp_ints;
3951
}
3952

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

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

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

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

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

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

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

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

    
4010
	$result = array();
4011

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

    
4019
	return $result;
4020
}
4021

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

    
4025
	$result = array();
4026

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

    
4033
	return $result;
4034
}
4035

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

    
4039
	$result = array();
4040

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

    
4047
	return $result;
4048
}
4049

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
4216
	return false;
4217
}
4218

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

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

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

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

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

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

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

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

    
4299
	return null;
4300
}
4301

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

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

    
4318
	return null;
4319
}
4320

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

    
4325
	$ints = array();
4326

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

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

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

    
4371
	return false;
4372
}
4373

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

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

    
4400
	return false;
4401
}
4402

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

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

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

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

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

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

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

    
4464
	$cloned_interface = get_real_interface($interface);
4465

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

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

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

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

    
4509
	$cloned_interface = get_real_interface($interface);
4510

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

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

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

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

    
4539
function get_interface_mac($interface) {
4540

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

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

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

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

    
4575
	return false;
4576
}
4577

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

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

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

    
4589
EOD;
4590

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

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

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

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

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

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

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

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

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

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

    
4651
			}
4652

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

    
4666
	return 0;
4667
}
4668

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

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

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

    
4693
?>
(25-25/67)