Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
68
	return $interface_arr_cache;
69
}
70

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

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

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

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

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

    
98

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

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

    
124
	return false;
125
}
126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
267
	interfaces_bring_up($vlanif);
268

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

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

    
275
	return $vlanif;
276
}
277

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

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

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

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

    
298
	$vlanif = interface_vlan_configure($vlan);
299

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

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

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

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

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

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

    
351
	return $vlanif;
352
}
353

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

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

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

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

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

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

    
394
	return $vlanif;
395
}
396

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

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

    
403
	$iflist = get_configured_interface_list();
404

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

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

    
424
}
425

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

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

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

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

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

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

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

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

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

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

    
515
	$checklist = get_configured_interface_list();
516

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
736
	$checklist = get_interface_list();
737

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

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

    
750
	interfaces_bring_up($laggif);
751

    
752
	return $laggif;
753
}
754

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

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

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

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

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

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

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

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

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

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

    
818
	return $greif;
819
}
820

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

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

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

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

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

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

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

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

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

    
904

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

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

    
917
	return $gifif;
918
}
919

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

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

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

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

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

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

    
938
	interfaces_qinq_configure();
939

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

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

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

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

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

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

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

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

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

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

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

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

    
1004
		interface_configure($if, $reload);
1005

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

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

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

    
1019
		interface_configure($if, $reload);
1020

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

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

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

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

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

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

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

    
1046
	return 0;
1047
}
1048

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

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

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

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

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

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

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

    
1097
	$realif = get_real_interface($interface);
1098

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

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

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

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

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

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

    
1215
	return;
1216
}
1217

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

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

    
1226
	return false;
1227
}
1228

    
1229
function interfaces_ptpid_next() {
1230

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

    
1235
	return $ptpid;
1236
}
1237

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

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

    
1249
	return NULL;
1250
}
1251

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

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

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

    
1261
	$itemhash = getMPDCRONSettings($pppif);
1262

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1533
EOD;
1534

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

    
1539
EOD;
1540

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

    
1548
EOD;
1549

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

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

    
1560
EOD;
1561

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

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

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

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

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

    
1588
EOD;
1589

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

    
1594
EOD;
1595

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

    
1600
EOD;
1601

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

    
1607
EOD;
1608

    
1609

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

    
1614
EOD;
1615

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

    
1621
EOD;
1622

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

    
1627
EOD;
1628

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

    
1633
EOD;
1634

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

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

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

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

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

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

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

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

    
1692
EOD;
1693

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

    
1699
EOD;
1700
		}
1701

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

    
1705

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

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

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

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

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

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

    
1780
	return 1;
1781
}
1782

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

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

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

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

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

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

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

    
1827
		sleep(1);
1828

    
1829
		/* XXX: Handle an issue with pfsync(4) and carp(4). In a cluster carp will come up before pfsync(4) has updated and so will cause issues
1830
		 * for existing sessions.
1831
		 */
1832
		log_error("waiting for pfsync...");
1833
		$i = 0;
1834
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1835
			$i++;
1836
			sleep(1);
1837
		}
1838
		log_error("pfsync done in $i seconds.");
1839
		log_error("Configuring CARP settings finalize...");
1840
	}
1841

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2020
	if(is_ipaddrv4($vip['subnet'])) {
2021
		/* Ensure CARP IP really exists prior to loading up. */
2022
		$ww_subnet_ip = find_interface_ip($realif);
2023
		$ww_subnet_bits = find_interface_subnet($realif);
2024
		if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
2025
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IP address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
2026
			return;
2027
		}
2028
	}
2029
	if(is_ipaddrv6($vip['subnet'])) {
2030
		/* Ensure CARP IP really exists prior to loading up. */
2031
		$ww_subnet_ip = find_interface_ipv6($realif);
2032
		$ww_subnet_bits = find_interface_subnetv6($realif);
2033
		if (!ip_in_subnet($vip['subnet'], gen_subnetv6($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
2034
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IPv6 address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
2035
			return;
2036
		}
2037
	}
2038

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

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

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

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

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

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

    
2073
	interfaces_bring_up($vipif);
2074

    
2075
	return $vipif;
2076
}
2077

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2436
EOD;
2437

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

    
2444
EOD;
2445

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

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

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

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

    
2473
			}
2474
			break;
2475
	}
2476

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2617

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

    
2622
	return 0;
2623

    
2624
}
2625

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

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

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

    
2640
	return intval($pid);
2641
}
2642

    
2643
function find_dhcp6c_process($interface) {
2644
	global $g;
2645

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

    
2652
	return intval($pid);
2653
}
2654

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

    
2660
	$wancfg = $config['interfaces'][$interface];
2661

    
2662
	if (!isset($wancfg['enable']))
2663
		return;
2664

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2855
	if(does_interface_exist($wancfg['if']))
2856
		interfaces_bring_up($wancfg['if']);
2857

    
2858
	interface_netgraph_needed($interface);
2859

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

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

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

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

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

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

    
2888
		if ($reloadall == true) {
2889

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

    
2893
			/* reload ipsec tunnels */
2894
			vpn_ipsec_configure();
2895

    
2896
			/* restart dnsmasq */
2897
			services_dnsmasq_configure();
2898

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

    
2902
			/* reload captive portal */
2903
			captiveportal_init_rules();
2904
		}
2905
	}
2906

    
2907
	return 0;
2908
}
2909

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

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

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

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

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

    
2944
	return 0;
2945
}
2946

    
2947

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

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

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

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

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

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

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

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

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

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

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

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

    
3002
	return 0;
3003
}
3004

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

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

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

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

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

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

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

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

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

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

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

    
3057
	return 0;
3058
}
3059

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

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

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

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

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

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

    
3092
	return 0;
3093
}
3094

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3175
	return 0;
3176
}
3177

    
3178
function interface_6to4_configure($interface = "wan"){
3179
	global $config, $g;
3180

    
3181
	/* because this is a tunnel interface we can only function
3182
	 *	with a public IPv4 address on the interface */
3183

    
3184
	$wancfg = $config['interfaces'][$interface];
3185
	$wanif = $wancfg['if'];
3186
	if (empty($wancfg))
3187
		$wancfg = array();
3188

    
3189
	$wanif = get_real_interface($interface);
3190

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

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

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

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

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

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

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

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

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

    
3250
	/* setup the stf interface */
3251
	$stfiface = "{$interface}_stf";
3252
	pfSense_interface_destroy($stfiface);
3253
	$tmpstfiface = pfSense_interface_create("stf");
3254
	pfSense_interface_rename($tmpstfiface, $stfiface);
3255
	pfSense_interface_flags($stfiface, IFF_LINK2);
3256
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3257

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

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

    
3265
	if (is_ipaddrv4($ip4gateway)) {
3266
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3267
	}
3268

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

    
3279
	return 0;
3280
}
3281

    
3282
function interface_dhcpv6_configure($interface = "wan") {
3283
	global $config, $g;
3284

    
3285
	$wancfg = $config['interfaces'][$interface];
3286
	if (empty($config['interfaces'][$interface]))
3287
		return;
3288

    
3289
	$wanif = get_real_interface($interface);
3290

    
3291
	$dhcp6cconf = "";
3292
	$dhcp6cconf .= "interface {$wanif} {\n";
3293

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

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

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

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

    
3352

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

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

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

    
3393
	return 0;
3394
}
3395

    
3396
function interface_dhcp_configure($interface = "wan") {
3397
	global $config, $g;
3398

    
3399
	$wancfg = $config['interfaces'][$interface];
3400
	$wanif = $wancfg['if'];
3401
	if (empty($wancfg))
3402
		$wancfg = array();
3403

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

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

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

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

    
3435
EOD;
3436

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

    
3446
EOD;
3447
}
3448
	fwrite($fd, $dhclientconf);
3449
	fclose($fd);
3450

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

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

    
3460
	return 0;
3461
}
3462

    
3463
function interfaces_group_setup() {
3464
	global $config;
3465

    
3466
	if (!is_array($config['ifgroups']['ifgroupentry']))
3467
		return;
3468

    
3469
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3470
		interface_group_setup($groupar);
3471

    
3472
	return;
3473
}
3474

    
3475
function interface_group_setup(&$groupname /* The parameter is an array */) {
3476
	global $config;
3477

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

    
3487
	return;
3488
}
3489

    
3490
function interface_group_add_member($interface, $groupname) {
3491
	$interface = get_real_interface($interface);
3492
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3493
}
3494

    
3495
/* COMPAT Function */
3496
function convert_friendly_interface_to_real_interface_name($interface) {
3497
	return get_real_interface($interface);
3498
}
3499

    
3500
/* COMPAT Function */
3501
function get_real_wan_interface($interface = "wan") {
3502
	return get_real_interface($interface);
3503
}
3504

    
3505
/* COMPAT Function */
3506
function get_current_wan_address($interface = "wan") {
3507
	return get_interface_ip($interface);
3508
}
3509

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

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

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

    
3529
	foreach ($ifdescrs as $if => $ifname) {
3530
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3531
			return $if;
3532

    
3533
		if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3534
			return $if;
3535

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

    
3547
/* attempt to resolve interface to friendly descr */
3548
function convert_friendly_interface_to_friendly_descr($interface) {
3549
	global $config;
3550

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

    
3595
	return $ifdesc;
3596
}
3597

    
3598
function convert_real_interface_to_friendly_descr($interface) {
3599
	global $config;
3600

    
3601
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3602

    
3603
	if ($ifdesc) {
3604
		$iflist = get_configured_interface_with_descr(false, true);
3605
		return $iflist[$ifdesc];
3606
	}
3607

    
3608
	return $interface;
3609
}
3610

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

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

    
3629
	// If we got a real interface, find it's friendly assigned name
3630
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3631

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

    
3665
	if (empty($parents))
3666
		$parents[0] = $realif;
3667

    
3668
	return $parents;
3669
}
3670

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

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

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

    
3695
function get_real_interface($interface = "wan") {
3696
	global $config;
3697

    
3698
	$wanif = NULL;
3699

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

    
3730
		if (empty($config['interfaces'][$interface]))
3731
			break;
3732

    
3733
		$cfg = &$config['interfaces'][$interface];
3734

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

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

    
3763
	return $wanif;
3764
}
3765

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

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

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

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

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

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

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

    
3893
				if ($if)
3894
					return $if;
3895
			}
3896
		}
3897
	}
3898
}
3899

    
3900
function link_carp_interface_to_parent($interface) {
3901
	global $config;
3902

    
3903
	if ($interface == "")
3904
		return;
3905

    
3906
	$carp_ip = get_interface_ip($interface);
3907
	$carp_ipv6 = get_interface_ipv6($interface);
3908

    
3909
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
3910
		return;
3911

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

    
3934

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

    
3946
	if (!is_ipaddr($ip))
3947
		return;
3948

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

    
3967
	return $carp_ints;
3968
}
3969

    
3970
function link_interface_to_vlans($int, $action = "") {
3971
	global $config;
3972

    
3973
	if (empty($int))
3974
		return;
3975

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

    
3988
function link_interface_to_vips($int, $action = "") {
3989
	global $config;
3990

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

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

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

    
4024
function link_interface_to_group($int) {
4025
	global $config;
4026

    
4027
	$result = array();
4028

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

    
4036
	return $result;
4037
}
4038

    
4039
function link_interface_to_gre($interface) {
4040
	global $config;
4041

    
4042
	$result = array();
4043

    
4044
	if (is_array($config['gres']['gre'])) {
4045
		foreach ($config['gres']['gre'] as $gre)
4046
			if($gre['if'] == $interface)
4047
				$result[] = $gre;
4048
	}
4049

    
4050
	return $result;
4051
}
4052

    
4053
function link_interface_to_gif($interface) {
4054
	global $config;
4055

    
4056
	$result = array();
4057

    
4058
	if (is_array($config['gifs']['gif'])) {
4059
		foreach ($config['gifs']['gif'] as $gif)
4060
			if($gif['if'] == $interface)
4061
				$result[] = $gif;
4062
	}
4063

    
4064
	return $result;
4065
}
4066

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

    
4075
	$interface = str_replace("\n", "", $interface);
4076

    
4077
	if (!does_interface_exist($interface))
4078
		return;
4079

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

    
4087
	return $interface_ip_arr_cache[$interface];
4088
}
4089

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

    
4099
	$interface = trim($interface);
4100
	$interface = get_real_interface($interface);
4101

    
4102
	if (!does_interface_exist($interface))
4103
		return;
4104

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

    
4128
	return $interface_ipv6_arr_cache[$interface];
4129
}
4130

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

    
4139
	$interface = str_replace("\n", "", $interface);
4140

    
4141
	if (!does_interface_exist($interface))
4142
		return;
4143

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

    
4163
function find_interface_subnet($interface, $flush = false)
4164
{
4165
	global $interface_sn_arr_cache;
4166
	global $interface_ip_arr_cache;
4167

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

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

    
4178
	return $interface_sn_arr_cache[$interface];
4179
}
4180

    
4181
function find_interface_subnetv6($interface, $flush = false)
4182
{
4183
	global $interface_snv6_arr_cache;
4184
	global $interface_ipv6_arr_cache;
4185

    
4186
	$interface = str_replace("\n", "", $interface);
4187
	if (does_interface_exist($interface) == false)
4188
		return;
4189

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

    
4212
	return $interface_snv6_arr_cache[$interface];
4213
}
4214

    
4215
function ip_in_interface_alias_subnet($interface, $ipalias) {
4216
	global $config;
4217

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

    
4233
	return false;
4234
}
4235

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

    
4248
	$curip = find_interface_ip($realif);
4249
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4250
		return $curip;
4251
	else
4252
		return null;
4253
}
4254

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

    
4274
	$curip = find_interface_ipv6($realif);
4275
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4276
		return $curip;
4277
	else
4278
		return null;
4279
}
4280

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

    
4293
	$curip = find_interface_ipv6_ll($realif);
4294
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4295
		return $curip;
4296
	else
4297
		return null;
4298
}
4299

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

    
4312
	$cursn = find_interface_subnet($realif);
4313
	if (!empty($cursn))
4314
		return $cursn;
4315

    
4316
	return null;
4317
}
4318

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

    
4331
	$cursn = find_interface_subnetv6($realif);
4332
	if (!empty($cursn))
4333
		return $cursn;
4334

    
4335
	return null;
4336
}
4337

    
4338
/* return outside interfaces with a gateway */
4339
function get_interfaces_with_gateway() {
4340
	global $config;
4341

    
4342
	$ints = array();
4343

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

    
4365
/* return true if interface has a gateway */
4366
function interface_has_gateway($friendly) {
4367
	global $config;
4368

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

    
4388
	return false;
4389
}
4390

    
4391
/* return true if interface has a gateway */
4392
function interface_has_gatewayv6($friendly) {
4393
	global $config;
4394

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

    
4417
	return false;
4418
}
4419

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

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

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

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

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

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

    
4477
function get_wireless_modes($interface) {
4478
	/* return wireless modes and channels */
4479
	$wireless_modes = array();
4480

    
4481
	$cloned_interface = get_real_interface($interface);
4482

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

    
4488
		$interface_channels = "";
4489
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4490
		$interface_channel_count = count($interface_channels);
4491

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

    
4522
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4523
function get_wireless_channel_info($interface) {
4524
	$wireless_channels = array();
4525

    
4526
	$cloned_interface = get_real_interface($interface);
4527

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

    
4533
		$interface_channels = "";
4534
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4535

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

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

    
4556
function get_interface_mac($interface) {
4557

    
4558
	$macinfo = pfSense_get_interface_addresses($interface);
4559
	return $macinfo["macaddr"];
4560
}
4561

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

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

    
4589
	if (isset($capable['caps']['vlanmtu']))
4590
		return true;
4591

    
4592
	return false;
4593
}
4594

    
4595
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4596
	global $g;
4597

    
4598
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4599

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

    
4606
EOD;
4607

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

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

    
4632
	/* Never reached */
4633
	return 1500;
4634
}
4635

    
4636
function get_vip_descr($ipaddress) {
4637
	global $config;
4638

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

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

    
4654
	$ifcfg = $config['interfaces'][$if];
4655

    
4656
	if (empty($if) || empty($ifcfg['if']))
4657
		return 0;
4658

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

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

    
4668
			}
4669

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

    
4683
	return 0;
4684
}
4685

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

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

    
4703
		return $wanif;
4704
	}
4705
	/* fall through to get_real_interface */
4706
	$wanif = get_real_interface($interface);
4707
	return $wanif;
4708
}
4709

    
4710
?>
(25-25/67)