Project

General

Profile

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

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

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

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

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

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

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

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

    
43
*/
44

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

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

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

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

    
69
        return $interface_arr_cache;
70
}
71

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

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

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

    
99

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

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

    
126
	return false;
127
}
128

    
129
function interface_netgraph_needed($interface = "wan") {
130
	global $config;
131

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

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

    
172
				if ($realif == $ppp['if']) {
173
					$found = true;
174
					break;
175
				}
176
*/			
177
				$ports = explode(',',$ppp['ports']);
178
				foreach($ports as $pid => $port){
179
					$port = get_real_interface($port);
180
					if ($realif == $port) {
181
						$found = true;
182
						break;
183
					}
184
					/* Find the parent interfaces of the vlans in the MLPPP configs 
185
					* there should be only one element in the array here 
186
					* -- this could be better . . . */
187
					$parent_if = get_parent_interface($port);
188
					if ($realif == $parent_if[0]) {
189
						$found = true;
190
						break;
191
					}
192
				}
193
			}
194
		}
195
	}
196
	
197
	if ($found == false) {
198
		$realif = get_real_interface($interface);
199
		pfSense_ngctl_detach("{$realif}:", $realif);
200
	}
201
	/* NOTE: We make sure for this on interface_ppps_configure()
202
	 *	no need to do it here agan.
203
	 *	else
204
	 *		pfSense_ngctl_attach(".", $realif);
205
	 */
206
}
207

    
208
function interfaces_loopback_configure() {
209
	global $g;
210

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

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

    
238
function interface_vlan_configure(&$vlan) {
239
        global $config, $g;
240

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

    
249
	if (empty($if)) {
250
		log_error(gettext("interface_vlan_confgure called with if undefined."));
251
		return;
252
	}
253

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

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

    
267
	pfSense_vlan_create($vlanif, $if, $tag);
268

    
269
	interfaces_bring_up($vlanif);
270

    
271
	/* invalidate interface cache */
272
	get_interface_arr(true);
273

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

    
277
	return $vlanif;
278
}
279

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

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

    
288
        $qinqif = $vlan['if'];
289
        $tag = $vlan['tag'];
290
        if(empty($qinqif)) {
291
                log_error(sprintf(gettext("interface_qinq_confgure called with if undefined.%s"), "\n"));
292
                return;
293
        }
294
	$vlanif = interface_vlan_configure($vlan);
295

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

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

    
319
        /* invalidate interface cache */
320
        get_interface_arr(true);
321

    
322
        if (!stristr($qinqif, "vlan"))
323
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
324

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

    
340
        interfaces_bring_up($qinqif);
341
        if (!empty($vlan['members'])) {
342
                $members = explode(" ", $vlan['members']);
343
                foreach ($members as $qif)
344
                        interfaces_bring_up("{$vlanif}_{$qif}");
345
        }
346

    
347
        return $vlanif;
348
}
349

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

    
364
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
365
        global $config, $g;
366

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

    
372
        $if = $qinq['if'];
373
        $tag = $qinq['tag'];
374
        $vlanif = "{$if}_{$tag}";
375
        if(empty($if)) {
376
                log_error(sprintf(gettext("interface_qinq_confgure called with if undefined.%s"), "\n"));
377
                return;
378
        }
379

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

    
387
        /* invalidate interface cache */
388
        get_interface_arr(true);
389

    
390
        return $vlanif;
391
}
392

    
393
function interfaces_create_wireless_clones() {
394
	global $config;
395

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

    
413
}
414

    
415
function interfaces_bridge_configure($checkmember = 0) {
416
        global $config;
417

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

    
430
function interface_bridge_configure(&$bridge, $checkmember = 0) {
431
	global $config, $g;
432

    
433
	if (!is_array($bridge))
434
	        return -1;
435

    
436
	if (empty($bridge['members'])) {
437
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
438
		return -1;
439
	}
440

    
441
	$members = explode(',', $bridge['members']);
442
	if (!count($members))
443
		return -1;
444

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

    
479
	/* Just in case anything is not working well */
480
	if ($smallermtu == 0)
481
		$smallermtu = 1500; 
482

    
483
	$flags = 0;
484
	if ($commonrx === false)
485
		$flags |= IFCAP_RXCSUM;
486
	if ($commontx === false)
487
		$flags |= IFCAP_TXCSUM;
488
	if ($commontso4 === false)
489
		$flags |= IFCAP_TSO4;
490
	if ($commontso6 === false)
491
		$flags |= IFCAP_TSO6;
492
	if ($commonlro === false)
493
		$flags |= IFCAP_LRO;
494

    
495
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
496
		pfSense_interface_destroy($bridge['bridgeif']);
497
		pfSense_interface_create($bridge['bridgeif']);
498
		$bridgeif = $bridge['bridgeif'];
499
	} else
500
		$bridgeif = pfSense_interface_create("bridge");
501

    
502
	$checklist = get_configured_interface_list();
503

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

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

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

    
621
	if($bridgeif)
622
		interfaces_bring_up($bridgeif);	
623
	else 
624
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
625

    
626
	return $bridgeif;
627
}
628

    
629
function interface_bridge_add_member($bridgeif, $interface) {
630

    
631
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
632
		return;
633

    
634
	$mtu = get_interface_mtu($bridgeif);
635
	$mtum = get_interface_mtu($interface);
636
	
637
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
638
		pfSense_interface_mtu($interface, $mtu);
639

    
640
	$options = pfSense_get_interface_addresses($bridgeif);
641
	$flags = 0;
642
	if (!isset($options['encaps']['txcsum']))
643
		$flags |= IFCAP_TXCSUM;
644

    
645
	if (!isset($options['encaps']['rxcsum']))
646
		$flags |= IFCAP_RXCSUM;
647

    
648
	pfSense_interface_capabilities($interface, -$flags);
649

    
650
	interfaces_bring_up($interface);
651
	pfSense_bridge_add_member($bridgeif, $interface);
652
}
653

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

    
673
function interface_lagg_configure(&$lagg) {
674
        global $config, $g;
675

    
676
        if (!is_array($lagg))
677
		return -1;
678

    
679
	$members = explode(',', $lagg['members']);
680
	if (!count($members))
681
		return -1;
682
	
683
	if ($g['booting'] || !(empty($lagg['laggif']))) {
684
		pfSense_interface_destroy($lagg['laggif']);
685
		pfSense_interface_create($lagg['laggif']);
686
                $laggif = $lagg['laggif'];
687
        } else
688
		$laggif = pfSense_interface_create("lagg");
689

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

    
711
	/* Just in case anything is not working well */
712
        if ($smallermtu == 0)
713
                $smallermtu = 1500;
714

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

    
727
	$checklist = get_interface_list();
728

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

    
741
	interfaces_bring_up($laggif);
742

    
743
	return $laggif;
744
}
745

    
746
function interfaces_gre_configure($checkparent = 0) {
747
        global $config;
748

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

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

    
767
	if (!is_array($gre))
768
		return -1;
769

    
770
	$realif = get_real_interface($gre['if']);
771
	$realifip = get_interface_ip($gre['if']);
772

    
773
	/* make sure the parent interface is up */
774
	interfaces_bring_up($realif);
775

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

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

    
797
	if($greif)
798
		interfaces_bring_up($greif);
799
	else 
800
		log_error(gettext("Could not bring greif up -- variable not defined."));
801

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

    
809
	return $greif;
810
}
811

    
812
function interfaces_gif_configure($checkparent = 0) {
813
	global $config;
814

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

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

    
833
	if (!is_array($gif))
834
		return -1;
835

    
836
	$realif = get_real_interface($gif['if']);
837

    
838
	if(is_ipaddrv4($gif['remote-addr'])) {
839
		$realifip = get_interface_ip($gif['if']);
840
		$realifgw = get_interface_gateway($gif['if']);
841
	}
842
	if(is_ipaddrv6($gif['remote-addr'])) {
843
		$realifip = get_interface_ipv6($gif['if']);
844
		$realifgw = get_interface_gatewayv6($gif['if']);
845
	}
846
	/* make sure the parent interface is up */
847
	if($realif)
848
		interfaces_bring_up($realif);
849
	else 
850
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
851

    
852
	if ($g['booting'] || !(empty($gif['gifif']))) {
853
		pfSense_interface_destroy($gif['gifif']);
854
		pfSense_interface_create($gif['gifif']);
855
		$gifif = $gif['gifif'];
856
	} else
857
		$gifif = pfSense_interface_create("gif");
858

    
859
	/* Do not change the order here for more see gif(4) NOTES section. */
860
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
861
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
862
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen /{$gif['tunnel-remote-net']} ");
863
	} else {
864
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
865
	}
866
	if (isset($gif['link0']) && $gif['link0'])
867
		pfSense_interface_flags($gifif, IFF_LINK0);
868
	if (isset($gif['link1']) && $gif['link1'])
869
		pfSense_interface_flags($gifif, IFF_LINK1);
870
	if($gifif)
871
		interfaces_bring_up($gifif);
872
	else
873
		log_error(gettext("could not bring gifif up -- variable not defined"));
874

    
875
	$iflist = get_configured_interface_list();
876
	foreach($iflist as $ifname) {
877
		if($config['interfaces'][$ifname]['if'] == $gifif) {
878
			if(get_interface_gateway($ifname)) {
879
				system_routing_configure($ifname);
880
				break;
881
			}
882
			if(get_interface_gateway_v6($ifname)) {
883
				system_routing_configure($ifname);
884
				break;
885
			}
886
		}
887
	}
888

    
889

    
890
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
891
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
892
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
893
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
894

    
895
        if (is_ipaddrv4($realifgw)) {
896
                mwexec("route change -host {$gif['remote-addr']} {$realifgw}");
897
        }
898
        if (is_ipaddrv6($realifgw)) {
899
                mwexec("route change -host -inet6 {$gif['remote-addr']} {$realifgw}");
900
        }
901

    
902
	return $gifif;
903
}
904

    
905
function interfaces_configure() {
906
	global $config, $g;
907

    
908
	if ($g['platform'] == 'jail')
909
		return;
910

    
911
	/* Set up our loopback interface */
912
	interfaces_loopback_configure();
913

    
914
	/* set up LAGG virtual interfaces */
915
	interfaces_lagg_configure();
916

    
917
	/* set up VLAN virtual interfaces */
918
	interfaces_vlan_configure();
919

    
920
	interfaces_qinq_configure();
921

    
922
	$iflist = get_configured_interface_with_descr();
923
	$delayed_list = array();
924
	$bridge_list = array();
925
	
926
	/* This is needed to speedup interfaces on bootup. */
927
	$reload = false;
928
	if ($g['booting'])
929
		$reload = true;
930

    
931
	foreach($iflist as $if => $ifname) {
932
		$realif = $config['interfaces'][$if]['if'];
933
		if (strstr($realif, "bridge")) 
934
			$bridge_list[$if] = $ifname;
935
		else if (strstr($realif, "gre"))
936
			$delayed_list[$if] = $ifname;
937
		else if (strstr($realif, "gif"))
938
			$delayed_list[$if] = $ifname;
939
		else if (strstr($realif, "ovpn")) {
940
			//echo "Delaying OpenVPN interface configuration...done.\n";
941
			continue;
942
		} else {
943
			if ($g['booting'])
944
				printf(gettext("Configuring %s interface..."), $ifname);
945

    
946
			if($g['debug'])
947
				log_error(sprintf(gettext("Configuring %s"), $ifname));
948
			interface_configure($if, $reload);
949
			if ($g['booting']) 
950
				echo gettext( "done.") . "\n";
951
		}
952
	}
953

    
954
	/* create the unconfigured wireless clones */
955
	interfaces_create_wireless_clones();
956

    
957
	/*
958
	 * NOTE: The following function parameter consists of
959
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
960
	 *	2 - Do load gre/gif/bridge with parent/member as vip
961
	 */
962

    
963
	/* set up GRE virtual interfaces */
964
	interfaces_gre_configure(1);
965

    
966
	/* set up GIF virtual interfaces */
967
	interfaces_gif_configure(1);
968

    
969
	/* set up BRIDGe virtual interfaces */
970
	interfaces_bridge_configure(1);
971

    
972
	/* bring up vip interfaces */
973
	interfaces_vips_configure();
974

    
975
	/* set up GRE virtual interfaces */
976
	interfaces_gre_configure(2);
977

    
978
	/* set up GIF virtual interfaces */
979
	interfaces_gif_configure(2);
980

    
981
	foreach ($delayed_list as $if => $ifname) {
982
		if ($g['booting'])
983
			printf(gettext("Configuring %s interface..."), $ifname);
984
        	if ($g['debug'])
985
        		log_error(sprintf(gettext("Configuring %s"), $ifname));
986

    
987
		interface_configure($if, $reload);
988

    
989
		if ($g['booting'])
990
			echo gettext("done.") . "\n";
991
	}
992

    
993
	/* set up BRIDGe virtual interfaces */
994
	interfaces_bridge_configure(2);
995

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

    
1002
		interface_configure($if, $reload);
1003

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

    
1008
	/* configure interface groups */
1009
	interfaces_group_setup();
1010

    
1011
	if (!$g['booting']) {
1012
		/* reconfigure static routes (kernel may have deleted them) */
1013
		system_routing_configure();
1014

    
1015
		/* reload IPsec tunnels */
1016
		vpn_ipsec_configure();
1017

    
1018
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1019
		services_dhcpd_configure();
1020

    
1021
		/* restart dnsmasq */
1022
		services_dnsmasq_configure();
1023

    
1024
		/* reload captive portal */
1025
		captiveportal_init_rules();
1026
	}
1027

    
1028
	return 0;
1029
}
1030

    
1031
function interface_reconfigure($interface = "wan", $reloadall = false) {
1032
	interface_bring_down($interface);
1033
	interface_configure($interface, $reloadall);
1034
}
1035

    
1036
function interface_vip_bring_down($vip) {
1037
	global $g;
1038

    
1039
	switch ($vip['mode']) {
1040
	case "proxyarp":
1041
		$vipif = get_real_interface($vip['interface']);
1042
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1043
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1044
		break;
1045
	case "ipalias":
1046
		$vipif = get_real_interface($vip['interface']);
1047
		if(does_interface_exist($vipif))
1048
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1049
		break;
1050
	case "carp":
1051
	case "carpdev-dhcp":
1052
		$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
1053
		if (does_interface_exist($vipif)) 
1054
			pfSense_interface_destroy($vipif);
1055
		break;
1056
	}
1057
}
1058

    
1059
function interface_bring_down($interface = "wan", $destroy = false) {
1060
	global $config, $g;
1061

    
1062
	if (!isset($config['interfaces'][$interface]))
1063
		return; 
1064

    
1065
	log_error("Calling interface down for interface {$interface}, destroy is {$destroy}");
1066

    
1067
	$ifcfg = $config['interfaces'][$interface];
1068

    
1069
	$realif = get_real_interface($interface);
1070

    
1071
	switch ($ifcfg['ipaddr']) {
1072
	case "ppp":
1073
	case "pppoe":
1074
	case "pptp":
1075
	case "l2tp":
1076
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1077
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1078
				if ($realif == $ppp['if']) {
1079
					if (isset($ppp['ondemand']) && !$destroy){
1080
						send_event("interface reconfigure {$interface}");
1081
						break;
1082
					}
1083
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1084
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1085
						sleep(2);
1086
					}
1087
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1088
					break;
1089
				}
1090
			}
1091
		}
1092
		break;
1093
	case "carpdev-dhcp":
1094
		/* 
1095
		 * NB: When carpdev gets enabled it would be better to be handled as all
1096
		 *	   other interfaces! 
1097
		 */
1098
	case "dhcp":
1099
		$pid = find_dhclient_process($realif);
1100
		if($pid)
1101
			mwexec("/bin/kill {$pid}");
1102
		sleep(1);
1103
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1104
		if(does_interface_exist("$realif")) {
1105
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1106
			if ($destroy == true)
1107
				pfSense_interface_flags($realif, -IFF_UP);
1108
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1109
		}
1110
		break;
1111
	default:
1112
		if(does_interface_exist("$realif")) {
1113
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1114
			if ($destroy == true)
1115
				pfSense_interface_flags($realif, -IFF_UP);
1116
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1117
		}
1118
		break;
1119
	}
1120

    
1121
	switch ($ifcfg['ipaddrv6']) {
1122
	case "slaac":
1123
	case "dhcp6":
1124
		$pidv6 = find_dhcp6c_process($realif);
1125
		if($pidv6)
1126
			mwexec("/bin/kill {$pidv6}");
1127
		sleep(3);
1128
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1129
		if(does_interface_exist("$realif")) {
1130
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1131
			if ($destroy == true)
1132
				pfSense_interface_flags($realif, -IFF_UP);
1133
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1134
		}
1135
		break;
1136
	case "6rd":
1137
		$realif = "srd0";
1138
		if(does_interface_exist("$realif")) {
1139
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1140
			if ($destroy == true)
1141
				pfSense_interface_flags($realif, -IFF_UP);
1142
		}		
1143
		break;
1144
	case "6to4":
1145
		$realif = "stf0";
1146
		if(does_interface_exist("$realif")) {
1147
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1148
			if ($destroy == true)
1149
				pfSense_interface_flags($realif, -IFF_UP);
1150
		}		
1151
		break;
1152
	default:
1153
		if(does_interface_exist("$realif")) {
1154
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1155
			if ($destroy == true)
1156
				pfSense_interface_flags($realif, -IFF_UP);
1157
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1158
		}
1159
		break;
1160
	}
1161

    
1162

    
1163
	/* remove interface up file if it exists */
1164
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1165
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1166
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1167
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1168
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1169
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1170
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1171
	
1172
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1173
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1174
	if (is_array($ifcfg['wireless'])) {
1175
		mwexec(kill_hostapd($realif));
1176
		mwexec(kill_wpasupplicant($realif));
1177
	}
1178

    
1179
	if ($destroy == true) {
1180
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|^stf|^srd/i", $realif))
1181
			pfSense_interface_destroy($realif);
1182
	}	
1183

    
1184
	return;
1185
}
1186

    
1187
function interfaces_ptpid_used($ptpid) {
1188
	global $config;
1189

    
1190
	if (is_array($config['ppps']['ppp']))
1191
		foreach ($config['ppps']['ppp'] as & $settings)
1192
			if ($ptpid == $settings['ptpid'])
1193
				return true;
1194

    
1195
	return false;
1196
}
1197

    
1198
function interfaces_ptpid_next() {
1199

    
1200
	$ptpid = 0;
1201
	while(interfaces_ptpid_used($ptpid))
1202
		$ptpid++;
1203

    
1204
	return $ptpid;
1205
}
1206

    
1207
function getMPDCRONSettings($pppif_) {
1208
	global $config;
1209
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1210
	if (is_array($config['cron']['item'])) {
1211
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1212
			$item = $config['cron']['item'][$i];
1213
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1214
				return array("ID" => $i, "ITEM" => $item);
1215
			}
1216
		}
1217
	}
1218
	return NULL;
1219
}
1220

    
1221
function handle_pppoe_reset($post_array) {
1222
	global $config, $g;
1223

    
1224
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1225

    
1226
	$pppif = $post_array['type'].$post_array['ptpid'];
1227
	if (!is_array($config['cron']['item'])) 
1228
		$config['cron']['item'] = array(); 
1229
	$itemhash = getMPDCRONSettings($pppif);
1230
	$item = $itemhash['ITEM'];
1231
	
1232
	// reset cron items if necessary and return
1233
	if (empty($post_array['pppoe-reset-type'])) {
1234
		if (isset($item))
1235
			unset($config['cron']['item'][$itemhash['ID']]);
1236
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1237
		return;
1238
	}
1239

    
1240
	if (empty($item)) 
1241
		$item = array();
1242
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1243
		$item['minute'] = $post_array['pppoe_resetminute'];
1244
		$item['hour'] = $post_array['pppoe_resethour'];
1245
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1246
			$date = explode("/", $post_array['pppoe_resetdate']);
1247
			$item['mday'] = $date[1];
1248
			$item['month'] = $date[0];
1249
		} else {
1250
			$item['mday'] = "*";
1251
			$item['month'] = "*";
1252
		}
1253
		$item['wday'] = "*";
1254
		$item['who'] = "root";
1255
		$item['command'] = $cron_cmd_file.$pppif;
1256
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1257
		switch ($post_array['pppoe_pr_preset_val']) {
1258
			case "monthly":
1259
				$item['minute'] = "0";
1260
				$item['hour'] = "0";
1261
				$item['mday'] = "1";
1262
				$item['month'] = "*";
1263
				$item['wday'] = "*";
1264
				$item['who'] = "root";
1265
				$item['command'] = $cron_cmd_file.$pppif;
1266
				break;
1267
	        case "weekly":
1268
				$item['minute'] = "0";
1269
				$item['hour'] = "0";
1270
				$item['mday'] = "*";
1271
				$item['month'] = "*";
1272
				$item['wday'] = "0";
1273
				$item['who'] = "root";
1274
				$item['command'] = $cron_cmd_file.$pppif;
1275
				break;
1276
			case "daily":
1277
				$item['minute'] = "0";
1278
				$item['hour'] = "0";
1279
				$item['mday'] = "*";
1280
				$item['month'] = "*";
1281
				$item['wday'] = "*";
1282
				$item['who'] = "root";
1283
				$item['command'] = $cron_cmd_file.$pppif;
1284
				break;
1285
			case "hourly":
1286
				$item['minute'] = "0";
1287
				$item['hour'] = "*";
1288
				$item['mday'] = "*";
1289
				$item['month'] = "*";
1290
				$item['wday'] = "*";
1291
				$item['who'] = "root";
1292
				$item['command'] = $cron_cmd_file.$pppif;
1293
				break;
1294
		} // end switch
1295
	} else {
1296
		/* test whether a cron item exists and unset() it if necessary */
1297
		$itemhash = getMPDCRONSettings($pppif);
1298
		$item = $itemhash['ITEM'];
1299
		if (isset($item))
1300
			unset($config['cron']['item'][$itemhash['ID']]); 
1301
	}// end if
1302
	if (isset($itemhash['ID'])) 
1303
		$config['cron']['item'][$itemhash['ID']] = $item;
1304
	else 
1305
		$config['cron']['item'][] = $item;
1306
}
1307

    
1308
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1309
*	It writes the mpd config file to /var/etc every time the link is opened.
1310
*/
1311

    
1312
function interface_ppps_configure($interface) {
1313
	global $config, $g;
1314

    
1315
	/* Return for unassigned interfaces. This is a minimum requirement. */
1316
	if (empty($config['interfaces'][$interface]))
1317
		return 0;
1318
	$ifcfg = $config['interfaces'][$interface];
1319
	if (!isset($ifcfg['enable']))
1320
		return 0;
1321

    
1322
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1323
	if(!is_dir("/var/spool/lock")) {
1324
		exec("/bin/mkdir -p /var/spool/lock");
1325
		exec("/bin/chmod a+rw /var/spool/lock/.");
1326
	}
1327
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1328
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1329
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1330

    
1331
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1332
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1333
			if ($ifcfg['if'] == $ppp['if'])
1334
				break;
1335
		}
1336
	}
1337
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1338
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1339
		return 0;
1340
	}
1341
	$pppif = $ifcfg['if'];
1342
	if ($ppp['type'] == "ppp")
1343
		$type = "modem";
1344
	else
1345
		$type = $ppp['type'];
1346
	$upper_type = strtoupper($ppp['type']);	
1347

    
1348
	if($g['booting']) {
1349
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1350
		echo "starting {$pppif} link...";
1351
		// Do not re-configure the interface if we are booting and it's already been started
1352
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1353
			return 0;
1354
	}
1355

    
1356
	$ports = explode(',',$ppp['ports']);
1357
	if ($type != "modem") {
1358
		foreach ($ports as $pid => $port)
1359
			$ports[$pid] = get_real_interface($port);
1360
	}
1361
	$localips = explode(',',$ppp['localip']);
1362
	$gateways = explode(',',$ppp['gateway']);
1363
	$subnets = explode(',',$ppp['subnet']);
1364

    
1365
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1366
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1367
	 */
1368
	foreach($ports as $pid => $port){
1369
		switch ($ppp['type']) {
1370
			case "pppoe": 
1371
				/* Bring the parent interface up */
1372
				interfaces_bring_up($port);
1373
				pfSense_ngctl_attach(".", $port);
1374
				break;
1375
			case "pptp":
1376
			case "l2tp":
1377
				/* configure interface */
1378
				if(is_ipaddr($localips[$pid])){
1379
					// Manually configure interface IP/subnet
1380
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1381
					interfaces_bring_up($port);
1382
				} else if (empty($localips[$pid]))
1383
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1384
				
1385
				if(!is_ipaddr($localips[$pid])){
1386
					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!");
1387
					$localips[$pid] = "0.0.0.0";
1388
				}
1389
				/* XXX: This needs to go away soon! [It's commented out!] */
1390
				/* Configure the gateway (remote IP ) */
1391
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1392
					/* XXX: Fix later 
1393
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1394
					if(!is_ipaddr($gateways[$pid])) {
1395
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1396
						return 0;
1397
					}
1398
					*/
1399
				}
1400
				if(!is_ipaddr($gateways[$pid])){
1401
					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));
1402
					return 0;
1403
				}
1404
				pfSense_ngctl_attach(".", $port);
1405
				break;
1406
			case "ppp":
1407
				if (!file_exists("{$port}")) {
1408
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1409
					return 0;
1410
				}
1411
				break;
1412
			default:
1413
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1414
				break;
1415
		}
1416
	}
1417
	
1418
	if (is_array($ports) && count($ports) > 1)
1419
		$multilink = "enable";
1420
	else
1421
		$multilink = "disable";
1422
	
1423
	if ($type == "modem"){
1424
		if (is_ipaddr($ppp['localip']))
1425
			$localip = $ppp['localip'];
1426
		else
1427
			$localip = '0.0.0.0';
1428

    
1429
		if (is_ipaddr($ppp['gateway']))
1430
			$gateway = $ppp['gateway'];
1431
		else
1432
			$gateway = "10.64.64.{$pppid}";
1433
		$ranges = "{$localip}/0 {$gateway}/0";
1434
		
1435
		if (empty($ppp['apnum']))	
1436
			$ppp['apnum'] = 1;
1437
	} else
1438
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1439

    
1440
	if (isset($ppp['ondemand'])) 
1441
		$ondemand = "enable";
1442
	else
1443
		$ondemand = "disable";
1444
	if (!isset($ppp['idletimeout']))
1445
		$ppp['idletimeout'] = 0;
1446

    
1447
	if (empty($ppp['username']) && $type == "modem"){
1448
		$ppp['username'] = "user";
1449
		$ppp['password'] = "none";
1450
	}
1451
	if (empty($ppp['password']) && $type == "modem")
1452
		$passwd = "none";
1453
	else
1454
		$passwd = base64_decode($ppp['password']);
1455

    
1456
	$bandwidths = explode(',',$ppp['bandwidth']);
1457
	$mtus = explode(',',$ppp['mtu']);
1458
	$mrus = explode(',',$ppp['mru']);
1459

    
1460
	if (isset($ppp['mrru']))
1461
		$mrrus = explode(',',$ppp['mrru']);
1462

    
1463
	// Construct the mpd.conf file
1464
	$mpdconf = <<<EOD
1465
startup:
1466
	# configure the console
1467
	set console close
1468
	# configure the web server
1469
	set web close
1470

    
1471
default:
1472
{$ppp['type']}client:
1473
	create bundle static {$interface}
1474
	set bundle enable ipv6cp
1475
	set iface name {$pppif}
1476

    
1477
EOD;
1478
	$setdefaultgw = false;
1479
	$founddefaultgw = false;
1480
	if (is_array($config['gateways']['gateway_item'])) {
1481
		foreach($config['gateways']['gateway_item'] as $gateway) {
1482
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1483
				$setdefaultgw = true;
1484
				break;
1485
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1486
				$founddefaultgw = true;
1487
				break;
1488
			}
1489
		}
1490
	}
1491
	
1492
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1493
		$setdefaultgw = true;
1494
		$mpdconf .= <<<EOD
1495
	set iface route default
1496

    
1497
EOD;
1498
	}
1499
	$mpdconf .= <<<EOD
1500
	set iface {$ondemand} on-demand
1501
	set iface idle {$ppp['idletimeout']}
1502

    
1503
EOD;
1504

    
1505
	if (isset($ppp['ondemand']))
1506
		$mpdconf .= <<<EOD
1507
	set iface addrs 10.10.1.1 10.10.1.2
1508

    
1509
EOD;
1510
	
1511
	if (isset($ppp['tcpmssfix']))
1512
		$tcpmss = "disable";
1513
	else
1514
		$tcpmss = "enable";
1515
		$mpdconf .= <<<EOD
1516
	set iface {$tcpmss} tcpmssfix
1517

    
1518
EOD;
1519

    
1520
	$mpdconf .= <<<EOD
1521
	set iface up-script /usr/local/sbin/ppp-linkup
1522
	set iface down-script /usr/local/sbin/ppp-linkdown
1523
	set ipcp ranges {$ranges}
1524

    
1525
EOD;
1526
	if (isset($ppp['vjcomp']))
1527
		$mpdconf .= <<<EOD
1528
	set ipcp no vjcomp
1529

    
1530
EOD;
1531

    
1532
	if (isset($config['system']['dnsallowoverride']))
1533
		$mpdconf .= <<<EOD
1534
	set ipcp enable req-pri-dns
1535
	set ipcp enable req-sec-dns
1536

    
1537
EOD;
1538
	if (!isset($ppp['verbose_log']))
1539
		$mpdconf .= <<<EOD
1540
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1541

    
1542
EOD;
1543
	foreach($ports as $pid => $port){
1544
		$port = get_real_interface($port);
1545
		$mpdconf .= <<<EOD
1546

    
1547
	create link static {$interface}_link{$pid} {$type}
1548
	set link action bundle {$interface}
1549
	set link {$multilink} multilink
1550
	set link keep-alive 10 60
1551
	set link max-redial 0
1552

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

    
1558
EOD;
1559

    
1560
		if (isset($ppp['acfcomp']))
1561
			$mpdconf .= <<<EOD
1562
	set link no acfcomp
1563

    
1564
EOD;
1565

    
1566
		if (isset($ppp['protocomp']))
1567
			$mpdconf .= <<<EOD
1568
	set link no protocomp
1569

    
1570
EOD;
1571

    
1572
		$mpdconf .= <<<EOD
1573
	set link disable chap pap
1574
	set link accept chap pap eap
1575
	set link disable incoming
1576

    
1577
EOD;
1578

    
1579

    
1580
		if (!empty($bandwidths[$pid]))
1581
			$mpdconf .= <<<EOD
1582
	set link bandwidth {$bandwidths[$pid]}
1583

    
1584
EOD;
1585

    
1586
		if (empty($mtus[$pid]))
1587
			$mtus[$pid] = "1492";
1588
			$mpdconf .= <<<EOD
1589
	set link mtu {$mtus[$pid]}
1590

    
1591
EOD;
1592

    
1593
		if (!empty($mrus[$pid]))
1594
			$mpdconf .= <<<EOD
1595
	set link mru {$mrus[$pid]}
1596

    
1597
EOD;
1598

    
1599
		if (!empty($mrrus[$pid]))
1600
			$mpdconf .= <<<EOD
1601
	set link mrru {$mrrus[$pid]}
1602

    
1603
EOD;
1604

    
1605
		$mpdconf .= <<<EOD
1606
	set auth authname "{$ppp['username']}"
1607
	set auth password {$passwd}
1608

    
1609
EOD;
1610
		if ($type == "modem") {
1611
			$mpdconf .= <<<EOD
1612
	set modem device {$ppp['ports']}
1613
	set modem script DialPeer
1614
	set modem idle-script Ringback
1615
	set modem watch -cd
1616
	set modem var \$DialPrefix "DT"
1617
	set modem var \$Telephone "{$ppp['phone']}"
1618

    
1619
EOD;
1620
		}
1621
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1622
			$mpdconf .= <<<EOD
1623
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1624

    
1625
EOD;
1626
		}
1627
		if (isset($ppp['initstr']) && $type == "modem") {
1628
			$initstr = base64_decode($ppp['initstr']);
1629
			$mpdconf .= <<<EOD
1630
	set modem var \$InitString "{$initstr}"
1631

    
1632
EOD;
1633
		}
1634
		if (isset($ppp['simpin']) && $type == "modem") {
1635
			$mpdconf .= <<<EOD
1636
	set modem var \$SimPin "{$ppp['simpin']}"
1637
	set modem var \$PinWait "{$ppp['pin-wait']}"
1638

    
1639
EOD;
1640
		}
1641
		if (isset($ppp['apn']) && $type == "modem") {
1642
			$mpdconf .= <<<EOD
1643
	set modem var \$APN "{$ppp['apn']}"
1644
	set modem var \$APNum "{$ppp['apnum']}"
1645

    
1646
EOD;
1647
		}
1648
		if ($type == "pppoe") {
1649
			// Send a null service name if none is set.
1650
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1651
			$mpdconf .= <<<EOD
1652
	set pppoe service "{$provider}"
1653

    
1654
EOD;
1655
		}
1656
		if ($type == "pppoe")
1657
			$mpdconf .= <<<EOD
1658
	set pppoe iface {$port}
1659

    
1660
EOD;
1661

    
1662
		if ($type == "pptp" || $type == "l2tp") {
1663
			$mpdconf .= <<<EOD
1664
	set {$type} self {$localips[$pid]}
1665
	set {$type} peer {$gateways[$pid]}
1666

    
1667
EOD;
1668
		}
1669
		
1670
		$mpdconf .= "\topen\r\n";
1671
	} //end foreach($port)
1672

    
1673

    
1674
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1675
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1676
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1677
	else {
1678
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1679
		if (!$fd) {
1680
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1681
			return 0;
1682
		}
1683
		// Write out mpd_ppp.conf
1684
		fwrite($fd, $mpdconf);
1685
		fclose($fd);
1686
	}
1687

    
1688
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1689
	if (isset($ppp['uptime'])) {
1690
		if (!file_exists("/conf/{$pppif}.log")) {
1691
			conf_mount_rw();
1692
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1693
			conf_mount_ro();
1694
		}
1695
	} else {
1696
		if (file_exists("/conf/{$pppif}.log")) {
1697
			conf_mount_rw();
1698
			mwexec("rm -f /conf/{$pppif}.log");
1699
			conf_mount_ro();
1700
		}
1701
	}
1702

    
1703
	/* fire up mpd */
1704
	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");
1705

    
1706
	// Check for PPPoE periodic reset request 
1707
	if ($type == "pppoe") {
1708
		if (isset($ppp['pppoe-reset-type']))
1709
			setup_pppoe_reset_file($ppp['if'], $interface);
1710
		else
1711
			setup_pppoe_reset_file($ppp['if']);
1712
	}
1713
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1714
	$i = 0;
1715
	while($i < 10) {
1716
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1717
		if($ret == 0)
1718
			break;
1719
		sleep(1);
1720
		$i++;
1721
	}
1722

    
1723
	return 1;
1724
}
1725

    
1726
function interfaces_carp_setup() {
1727
	global $g, $config;
1728

    
1729
	$balanacing = "";
1730
	$pfsyncinterface = "";
1731
	$pfsyncenabled = "";
1732
	if(isset($config['system']['developerspew'])) {
1733
		$mt = microtime();
1734
		echo "interfaces_carp_setup() being called $mt\n";
1735
	}
1736

    
1737
	// Prepare CmdCHAIN that will be used to execute commands.
1738
	$cmdchain = new CmdCHAIN();	
1739

    
1740
	if ($g['booting']) {
1741
		echo gettext("Configuring CARP settings...");
1742
		mute_kernel_msgs();
1743
	}
1744

    
1745
	/* suck in configuration items */
1746
	if($config['hasync']) {
1747
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1748
		$balanacing = $config['hasync']['balancing'];
1749
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1750
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1751
	} else {
1752
		unset($pfsyncinterface);
1753
		unset($balanacing);
1754
		unset($pfsyncenabled);
1755
	}
1756

    
1757
	if($balanacing) {
1758
		$cmdchain->add(gettext("Enable CARP ARP-balancing"), "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1759
		$cmdchain->add(gettext("Disallow CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=0", true);
1760
	} else
1761
		$cmdchain->add(gettext("Enable CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=1", true);		
1762

    
1763
	$cmdchain->add(gettext("Enable CARP logging"), "/sbin/sysctl net.inet.carp.log=1", true);
1764
	if (!empty($pfsyncinterface))
1765
		$carp_sync_int = get_real_interface($pfsyncinterface);
1766

    
1767
	if($g['booting']) {
1768
		/*    install rules to alllow pfsync to sync up during boot
1769
		 *    carp interfaces will remain down until the bootup sequence finishes
1770
		 */
1771
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1772
		if ($fd) {
1773
			fwrite($fd, "block quick proto carp \n");
1774
			fwrite($fd, "block quick proto pfsync \n");
1775
			fwrite($fd, "pass out quick from any to any keep state\n");
1776
			fclose($fd);
1777
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1778
		} else
1779
			log_error(gettext("Could not create rules.boot file!"));
1780
	}
1781

    
1782
	/* setup pfsync interface */
1783
	if($carp_sync_int and $pfsyncenabled) {
1784
		if (is_ipaddr($pfsyncpeerip))
1785
			$cmdchain->add(gettext("Bring up pfsync0 syncpeer"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1786
		else
1787
			$cmdchain->add(gettext("Bring up pfsync0 syncdev"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1788
	} else
1789
		$cmdchain->add(gettext("Bring up pfsync0"), "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1790

    
1791
	sleep(1);
1792

    
1793
	/* 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 issuese
1794
	 * for exiting sessions.
1795
	 */
1796
	$i = 0;
1797
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1798
		$i++;
1799
		sleep(1);
1800
	}
1801

    
1802
	if($config['virtualip']['vip'])
1803
		$cmdchain->add(gettext("Allow CARP."), "/sbin/sysctl net.inet.carp.allow=1", true);				
1804
	else
1805
		$cmdchain->add(gettext("Disallow CARP."), "/sbin/sysctl net.inet.carp.allow=0", true);		
1806
	
1807
	if($g['debug'])
1808
		$cmdchain->setdebug(); // optional for verbose logging
1809

    
1810
	$cmdchain->execute();
1811
	$cmdchain->clear();
1812

    
1813
	if ($g['booting']) {
1814
		unmute_kernel_msgs();
1815
		echo gettext("done.") . "\n";
1816
	}
1817
}
1818

    
1819
function interface_proxyarp_configure($interface = "") {
1820
	global $config, $g;
1821
	if(isset($config['system']['developerspew'])) {
1822
		$mt = microtime();
1823
		echo "interface_proxyarp_configure() being called $mt\n";
1824
	}
1825

    
1826
	/* kill any running choparp */
1827
	if (empty($interface))
1828
		killbyname("choparp");
1829
	else {
1830
		$vipif = get_real_interface($interface);
1831
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1832
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1833
	}
1834

    
1835
	$paa = array();
1836
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1837

    
1838
		/* group by interface */
1839
		foreach ($config['virtualip']['vip'] as $vipent) {
1840
			if ($vipent['mode'] === "proxyarp") {
1841
				if ($vipent['interface'])
1842
					$proxyif = $vipent['interface'];
1843
				else
1844
					$proxyif = "wan";
1845
				
1846
				if (!empty($interface) && $interface != $proxyif)
1847
					continue;
1848

    
1849
				if (!is_array($paa[$proxyif]))
1850
					$paa[$proxyif] = array();
1851

    
1852
				$paa[$proxyif][] = $vipent;
1853
			}
1854
		}
1855
	}
1856

    
1857
	if (!empty($interface)) {
1858
		if (is_array($paa[$interface])) {
1859
			$paaifip = get_interface_ip($interface);
1860
                        if (!is_ipaddr($paaifip))
1861
                                return;
1862
                        $args = get_real_interface($interface) . " auto";
1863
                        foreach ($paa[$interface] as $paent) {
1864
                                if (isset($paent['subnet']))
1865
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1866
                                else if (isset($paent['range']))
1867
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1868
                        }
1869
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1870
		}
1871
	} else if (count($paa) > 0) {
1872
		foreach ($paa as $paif => $paents)  {
1873
			$paaifip = get_interface_ip($paif);
1874
			if (!is_ipaddr($paaifip))
1875
				continue;
1876
			$args = get_real_interface($paif) . " auto";
1877
			foreach ($paents as $paent) {
1878
				if (isset($paent['subnet']))
1879
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1880
				else if (isset($paent['range']))
1881
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1882
			}
1883
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1884
		}
1885
	}
1886
}
1887

    
1888
function interfaces_vips_configure($interface = "") {
1889
	global $g, $config;
1890
	if(isset($config['system']['developerspew'])) {
1891
		$mt = microtime();
1892
		echo "interfaces_vips_configure() being called $mt\n";
1893
	}
1894
	$paa = array();
1895
	if(is_array($config['virtualip']['vip'])) {
1896
		$carp_setuped = false;
1897
		$anyproxyarp = false;
1898
		foreach ($config['virtualip']['vip'] as $vip) {
1899
			switch ($vip['mode']) {
1900
			case "proxyarp":
1901
				/* nothing it is handled on interface_proxyarp_configure() */
1902
				if ($interface <> "" && $vip['interface'] <> $interface)
1903
					continue;
1904
				$anyproxyarp = true;
1905
				break;
1906
			case "ipalias":
1907
				if ($interface <> "" && $vip['interface'] <> $interface)
1908
					continue;
1909
				interface_ipalias_configure(&$vip);
1910
				break;
1911
			case "carp":
1912
				if ($interface <> "" && $vip['interface'] <> $interface)
1913
					continue;
1914
				if ($carp_setuped == false)
1915
					$carp_setuped = true;
1916
				interface_carp_configure($vip);
1917
				break;
1918
			case "carpdev-dhcp":
1919
				if ($interface <> "" && $vip['interface'] <> $interface)
1920
					continue;
1921
				interface_carpdev_configure($vip);
1922
				break;
1923
			}
1924
		}
1925
		if ($carp_setuped == true)
1926
			interfaces_carp_setup();
1927
		if ($anyproxyarp == true)
1928
			interface_proxyarp_configure();
1929
	}
1930
}
1931

    
1932
function interface_ipalias_configure(&$vip) {
1933

    
1934
	if ($vip['mode'] == "ipalias") {
1935
		$if = get_real_interface($vip['interface']);
1936
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1937
	}
1938
}
1939

    
1940
function interface_reload_carps($cif) {
1941
	global $config;
1942

    
1943
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1944
	if (empty($carpifs))
1945
		return;
1946

    
1947
	$carps = explode(" ", $carpifs);
1948
	if(is_array($config['virtualip']['vip'])) {
1949
		$viparr = &$config['virtualip']['vip'];
1950
		foreach ($viparr as $vip) {
1951
			if (in_array($vip['carpif'], $carps)) {
1952
				switch ($vip['mode']) {
1953
				case "carp":
1954
					interface_vip_bring_down($vip);
1955
					sleep(1);
1956
					interface_carp_configure($vip);
1957
					break;
1958
				case "carpdev-dhcp":
1959
					interface_vip_bring_down($vip);
1960
					sleep(1);
1961
					interface_carpdev_configure($vip);
1962
					break;
1963
				case "ipalias":
1964
					interface_vip_bring_down($vip);
1965
					sleep(1);
1966
					interface_ipalias_configure($vip);
1967
					break;
1968
				}
1969
			}
1970
		}
1971
	}
1972
}
1973

    
1974
function interface_carp_configure(&$vip) {
1975
	global $config, $g;
1976
	if(isset($config['system']['developerspew'])) {
1977
		$mt = microtime();
1978
		echo "interface_carp_configure() being called $mt\n";
1979
	}
1980

    
1981
	if ($vip['mode'] != "carp")
1982
		return;
1983

    
1984
	/*
1985
	 * ensure the interface containing the VIP really exists
1986
 	 * prevents a panic if the interface is missing or invalid
1987
	 */
1988
	$realif = get_real_interface($vip['interface']);
1989
	if (!does_interface_exist($realif)) {
1990
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
1991
		return;
1992
	}
1993

    
1994
	if(is_ipaddrv4($vip['subnet'])) {
1995
		/* Ensure CARP IP really exists prior to loading up. */
1996
		$ww_subnet_ip = find_interface_ip($realif);
1997
		$ww_subnet_bits = find_interface_subnet($realif);
1998
		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'])) {
1999
			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", "");
2000
			return;
2001
		}
2002
	}
2003
	if(is_ipaddrv6($vip['subnet'])) {
2004
		/* Ensure CARP IP really exists prior to loading up. */
2005
		$ww_subnet_ip = find_interface_ipv6($realif);
2006
		$ww_subnet_bits = find_interface_subnetv6($realif);
2007
		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'])) {
2008
			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", "");
2009
			return;
2010
		}
2011
	}
2012

    
2013
	// set the vip interface to the vhid
2014
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2015

    
2016
	/* create the carp interface and setup */
2017
	if (does_interface_exist($vipif)) {
2018
		pfSense_interface_flags($vipif, -IFF_UP);
2019
	} else {
2020
		$carpif = pfSense_interface_create("carp");
2021
		pfSense_interface_rename($carpif, $vipif);
2022
		pfSense_ngctl_name("{$carpif}:", $vipif);
2023
	}
2024

    
2025
	/* invalidate interface cache */
2026
	get_interface_arr(true);
2027

    
2028
	$vip_password = $vip['password'];
2029
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2030
	if ($vip['password'] != "")
2031
		$password = " pass {$vip_password}";
2032

    
2033
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2034
	$advbase = "";
2035
	if (!empty($vip['advbase']))
2036
		$advbase = "advbase {$vip['advbase']}";
2037

    
2038
	if(is_ipaddrv4($vip['subnet'])) {
2039
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2040
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2041
	}
2042
	if(is_ipaddrv6($vip['subnet'])) {
2043
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2044
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2045
		/* make sure to add a link local address too */
2046
		mwexec("/sbin/ifconfig {$vipif} inet6 fe80::5:{$vip['vhid']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2047
	}
2048

    
2049
	interfaces_bring_up($vipif);
2050

    
2051
	return $vipif;
2052
}
2053

    
2054
function interface_carpdev_configure(&$vip) {
2055
	global $g;
2056

    
2057
	if ($vip['mode'] != "carpdev-dhcp")
2058
		return;
2059

    
2060
	if (empty($vip['interface']))
2061
		return;
2062

    
2063
	$realif = get_real_interface($vip['interface']);
2064
	interfaces_bring_up($realif);
2065

    
2066
	/*
2067
	 * ensure the interface containing the VIP really exists
2068
	 * prevents a panic if the interface is missing or invalid
2069
	 */
2070
	if (!does_interface_exist($realif)) {
2071
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2072
		return;
2073
	}
2074

    
2075
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2076
	if (does_interface_exist($vipif)) {
2077
		interface_bring_down($vipif);
2078
	} else {
2079
		$carpdevif = exec("/sbin/ifconfig carp create");
2080
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
2081
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
2082
	}
2083

    
2084
	$vip_password = $vip['password'];
2085
	$vip_password = str_replace(" ", "", $vip_password);
2086
	if ($vip['password'] != "")
2087
		$password = " pass \"" . $vip_password . "\"";
2088

    
2089

    
2090
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
2091
	interfaces_bring_up($vipif);
2092

    
2093
	/*
2094
	 * XXX: BIG HACK but carpdev needs ip services active
2095
	 *      before even starting something as dhclient.
2096
	 *      I do not know if this is a feature or a bug
2097
	 *      but better than track it make it work ;) .
2098
	 */
2099
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
2100
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
2101

    
2102
	/* generate dhclient_wan.conf */
2103
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
2104
	if ($fd) {
2105
		$dhclientconf = "";
2106

    
2107
		$dhclientconf .= <<<EOD
2108
interface "{$vipif}" {
2109
timeout 60;
2110
retry 1;
2111
select-timeout 0;
2112
initial-interval 1;
2113
script "/sbin/dhclient-script";
2114
}
2115

    
2116
EOD;
2117

    
2118
		fwrite($fd, $dhclientconf);
2119
		fclose($fd);
2120

    
2121
		/* fire up dhclient */
2122
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
2123
	} else {
2124
		log_error(sprintf(gettext("Error: cannot open dhclient_%s.conf in interfaces_carpdev_configure() for writing.%s"), $vipif, "\n"));
2125
		mwexec("/sbin/dhclient -b {$vipif}");
2126
	}
2127

    
2128
	return $vipif;
2129
}
2130

    
2131
function interface_wireless_clone($realif, $wlcfg) {
2132
	global $config, $g;
2133
	/*   Check to see if interface has been cloned as of yet.  
2134
	 *   If it has not been cloned then go ahead and clone it.
2135
	 */
2136
	$needs_clone = false;
2137
	if(is_array($wlcfg['wireless']))
2138
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2139
	else
2140
		$wlcfg_mode = $wlcfg['mode'];
2141
	switch($wlcfg_mode) {
2142
		 case "hostap":
2143
			$mode = "wlanmode hostap";
2144
			break;
2145
		 case "adhoc":
2146
			$mode = "wlanmode adhoc";
2147
			break;
2148
		 default:
2149
			$mode = "";
2150
			break;
2151
	}
2152
	$baseif = interface_get_wireless_base($wlcfg['if']);
2153
	if(does_interface_exist($realif)) {
2154
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2155
		$ifconfig_str = implode($output);
2156
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2157
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2158
			$needs_clone = true;
2159
		}
2160
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2161
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2162
			$needs_clone = true;
2163
		}
2164
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2165
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2166
			$needs_clone = true;
2167
		}
2168
	} else {
2169
		$needs_clone = true;
2170
	}
2171

    
2172
	if($needs_clone == true) {
2173
		/* remove previous instance if it exists */
2174
		if(does_interface_exist($realif))
2175
			pfSense_interface_destroy($realif);
2176

    
2177
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2178
		// Create the new wlan interface. FreeBSD returns the new interface name.
2179
		// example:  wlan2
2180
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2181
		if($ret <> 0) {
2182
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2183
			return false;
2184
		}
2185
		$newif = trim($out[0]);
2186
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2187
		pfSense_interface_rename($newif, $realif);
2188
		// FIXME: not sure what ngctl is for. Doesn't work.
2189
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2190
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2191
	}
2192
	return true;
2193
}
2194

    
2195
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2196
	global $config, $g;
2197

    
2198
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2199
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2200
	                         'regdomain', 'regcountry', 'reglocation');
2201

    
2202
	if(!is_interface_wireless($ifcfg['if']))
2203
		return;
2204

    
2205
	$baseif = interface_get_wireless_base($ifcfg['if']);
2206

    
2207
	// Sync shared settings for assigned clones
2208
	$iflist = get_configured_interface_list(false, true);
2209
	foreach ($iflist as $if) {
2210
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2211
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2212
				foreach ($shared_settings as $setting) {
2213
					if ($sync_changes) {
2214
						if (isset($ifcfg['wireless'][$setting]))
2215
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2216
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2217
							unset($config['interfaces'][$if]['wireless'][$setting]);
2218
					} else {
2219
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2220
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2221
						else if (isset($ifcfg['wireless'][$setting]))
2222
							unset($ifcfg['wireless'][$setting]);
2223
					}
2224
				}
2225
				if (!$sync_changes)
2226
					break;
2227
			}
2228
		}
2229
	}
2230

    
2231
	// Read or write settings at shared area
2232
	if (isset($config['wireless']['interfaces'][$baseif])) {
2233
		foreach ($shared_settings as $setting) {
2234
			if ($sync_changes) {
2235
				if (isset($ifcfg['wireless'][$setting]))
2236
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2237
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2238
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2239
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2240
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2241
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2242
				else if (isset($ifcfg['wireless'][$setting]))
2243
					unset($ifcfg['wireless'][$setting]);
2244
			}
2245
		}
2246
	}
2247

    
2248
	// Sync the mode on the clone creation page with the configured mode on the interface
2249
	if (interface_is_wireless_clone($ifcfg['if'])) {
2250
		foreach ($config['wireless']['clone'] as &$clone) {
2251
			if ($clone['cloneif'] == $ifcfg['if']) {
2252
				if ($sync_changes) {
2253
					$clone['mode'] = $ifcfg['wireless']['mode'];
2254
				} else {
2255
					$ifcfg['wireless']['mode'] = $clone['mode'];
2256
				}
2257
				break;
2258
			}
2259
		}
2260
		unset($clone);
2261
	}
2262
}
2263

    
2264
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2265
	global $config, $g;
2266

    
2267
	/*    open up a shell script that will be used to output the commands.
2268
	 *    since wireless is changing a lot, these series of commands are fragile
2269
     *    and will sometimes need to be verified by a operator by executing the command
2270
     *    and returning the output of the command to the developers for inspection.  please
2271
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2272
	 */
2273

    
2274
	// Remove script file
2275
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2276

    
2277
	// Clone wireless nic if needed.
2278
	interface_wireless_clone($if, $wl);
2279

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

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

    
2287
	/* set values for /path/program */
2288
	$hostapd = "/usr/sbin/hostapd";
2289
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2290
	$ifconfig = "/sbin/ifconfig";
2291
	$sysctl = "/sbin/sysctl";
2292
	$killall = "/usr/bin/killall";
2293

    
2294
	/* Set all wireless ifconfig variables (splitt up to get rid of needed checking) */
2295

    
2296
	$wlcmd = array();
2297
	$wl_sysctl = array();
2298
	/* Make sure it's up */
2299
	$wlcmd[] = "up";
2300
	/* Set a/b/g standard */
2301
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2302
	$wlcmd[] = "mode " . escapeshellarg($standard);
2303

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

    
2309
	/* Set ssid */
2310
	if($wlcfg['ssid'])
2311
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2312

    
2313
	/* Set 802.11g protection mode */
2314
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2315

    
2316
	/* set wireless channel value */
2317
	if(isset($wlcfg['channel'])) {
2318
		if($wlcfg['channel'] == "0") {
2319
			$wlcmd[] = "channel any";
2320
		} else {
2321
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2322
		}
2323
	}
2324

    
2325
	/* Set antenna diversity value */
2326
	if(isset($wlcfg['diversity']))
2327
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2328

    
2329
	/* Set txantenna value */
2330
	if(isset($wlcfg['txantenna']))
2331
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2332

    
2333
	/* Set rxantenna value */
2334
	if(isset($wlcfg['rxantenna']))
2335
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2336

    
2337
	/* set Distance value */
2338
	if($wlcfg['distance'])
2339
		$distance = escapeshellarg($wlcfg['distance']);
2340

    
2341
	/* Set wireless hostap mode */
2342
	if ($wlcfg['mode'] == "hostap") {
2343
		$wlcmd[] = "mediaopt hostap";
2344
	} else {
2345
		$wlcmd[] = "-mediaopt hostap";
2346
	}
2347

    
2348
	/* Set wireless adhoc mode */
2349
	if ($wlcfg['mode'] == "adhoc") {
2350
		$wlcmd[] = "mediaopt adhoc";
2351
	} else {
2352
		$wlcmd[] = "-mediaopt adhoc";
2353
	}
2354

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

    
2357
	/* handle hide ssid option */
2358
	if(isset($wlcfg['hidessid']['enable'])) {
2359
		$wlcmd[] = "hidessid";
2360
	} else {
2361
		$wlcmd[] = "-hidessid";
2362
	}
2363

    
2364
	/* handle pureg (802.11g) only option */
2365
	if(isset($wlcfg['pureg']['enable'])) {
2366
		$wlcmd[] = "mode 11g pureg";
2367
	} else {
2368
		$wlcmd[] = "-pureg";
2369
	}
2370

    
2371
	/* handle puren (802.11n) only option */
2372
	if(isset($wlcfg['puren']['enable'])) {
2373
		$wlcmd[] = "puren";
2374
	} else {
2375
		$wlcmd[] = "-puren";
2376
	}
2377

    
2378
	/* enable apbridge option */
2379
	if(isset($wlcfg['apbridge']['enable'])) {
2380
		$wlcmd[] = "apbridge";
2381
	} else {
2382
		$wlcmd[] = "-apbridge";
2383
	}
2384

    
2385
	/* handle turbo option */
2386
	if(isset($wlcfg['turbo']['enable'])) {
2387
		$wlcmd[] = "mediaopt turbo";
2388
	} else {
2389
		$wlcmd[] = "-mediaopt turbo";
2390
	}
2391

    
2392
	/* handle txpower setting */
2393
	/* if($wlcfg['txpower'] <> "")
2394
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2395
	*/
2396
	/* handle wme option */
2397
	if(isset($wlcfg['wme']['enable'])) {
2398
		$wlcmd[] = "wme";
2399
	} else {
2400
		$wlcmd[] = "-wme";
2401
	}
2402

    
2403
	/* set up wep if enabled */
2404
	$wepset = "";
2405
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2406
		switch($wlcfg['wpa']['auth_algs']) {
2407
			case "1":
2408
				$wepset .= "authmode open wepmode on ";
2409
				break;
2410
			case "2":
2411
				$wepset .= "authmode shared wepmode on ";
2412
				break;
2413
			case "3":
2414
				$wepset .= "authmode mixed wepmode on ";
2415
		}
2416
		$i = 1;
2417
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2418
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2419
			if (isset($wepkey['txkey'])) {
2420
				$wlcmd[] = "weptxkey {$i} ";
2421
			}
2422
			$i++;
2423
		}
2424
		$wlcmd[] = $wepset;
2425
	} else {
2426
		$wlcmd[] = "authmode open wepmode off ";
2427
	}
2428

    
2429
	mwexec(kill_hostapd("{$if}"));
2430
	mwexec(kill_wpasupplicant("{$if}"));
2431

    
2432
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2433
	conf_mount_rw();
2434

    
2435
	switch ($wlcfg['mode']) {
2436
		case 'bss':
2437
			if (isset($wlcfg['wpa']['enable'])) {
2438
				$wpa .= <<<EOD
2439
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2440
ctrl_interface_group=0
2441
ap_scan=1
2442
#fast_reauth=1
2443
network={
2444
ssid="{$wlcfg['ssid']}"
2445
scan_ssid=1
2446
priority=5
2447
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2448
psk="{$wlcfg['wpa']['passphrase']}"
2449
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2450
group={$wlcfg['wpa']['wpa_pairwise']}
2451
}
2452
EOD;
2453

    
2454
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2455
				fwrite($fd, "{$wpa}");
2456
				fclose($fd);
2457
			}
2458
			break;
2459
		case 'hostap':
2460
			if($wlcfg['wpa']['passphrase']) 
2461
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2462
			else 
2463
				$wpa_passphrase = "";
2464
			if (isset($wlcfg['wpa']['enable'])) {
2465
				$wpa .= <<<EOD
2466
interface={$if}
2467
driver=bsd
2468
logger_syslog=-1
2469
logger_syslog_level=0
2470
logger_stdout=-1
2471
logger_stdout_level=0
2472
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2473
ctrl_interface={$g['varrun_path']}/hostapd
2474
ctrl_interface_group=wheel
2475
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2476
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2477
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2478
ssid={$wlcfg['ssid']}
2479
debug={$wlcfg['wpa']['debug_mode']}
2480
auth_algs={$wlcfg['wpa']['auth_algs']}
2481
wpa={$wlcfg['wpa']['wpa_mode']}
2482
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2483
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2484
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2485
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2486
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2487
{$wpa_passphrase}
2488

    
2489
EOD;
2490

    
2491
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2492
	$wpa .= <<<EOD
2493
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2494
rsn_preauth=1
2495
rsn_preauth_interfaces={$if}
2496

    
2497
EOD;
2498

    
2499
}
2500
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2501
					$auth_server_port = "1812";
2502
					if($wlcfg['auth_server_port']) 
2503
						$auth_server_port = $wlcfg['auth_server_port'];
2504
					$auth_server_port2 = "1812";
2505
					if($wlcfg['auth_server_port2']) 
2506
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2507
					$wpa .= <<<EOD
2508

    
2509
ieee8021x=1
2510
auth_server_addr={$wlcfg['auth_server_addr']}
2511
auth_server_port={$auth_server_port}
2512
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2513
auth_server_addr={$wlcfg['auth_server_addr2']}
2514
auth_server_port={$auth_server_port2}
2515
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2516

    
2517
EOD;
2518
				} else {
2519
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2520
				}
2521

    
2522
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2523
				fwrite($fd, "{$wpa}");
2524
				fclose($fd);
2525

    
2526
			}
2527
			break;
2528
	}
2529

    
2530
	/*
2531
	 *    all variables are set, lets start up everything
2532
	 */
2533

    
2534
	$baseif = interface_get_wireless_base($if);
2535
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2536
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2537

    
2538
	/* set sysctls for the wireless interface */
2539
	if (!empty($wl_sysctl)) {
2540
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2541
		foreach ($wl_sysctl as $wl_sysctl_line) {
2542
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2543
		}
2544
	}
2545

    
2546
	/* set ack timers according to users preference (if he/she has any) */
2547
	if($distance) {
2548
		fwrite($fd_set, "# Enable ATH distance settings\n");
2549
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2550
	}
2551

    
2552
	if (isset($wlcfg['wpa']['enable'])) {
2553
		if ($wlcfg['mode'] == "bss") {
2554
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2555
		}
2556
		if ($wlcfg['mode'] == "hostap") {
2557
			/* add line to script to restore old mac to make hostapd happy */
2558
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2559
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2560
				if (is_macaddr($if_oldmac))
2561
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2562
						" link " . escapeshellarg($if_oldmac) . "\n");
2563
			}
2564

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

    
2567
			/* add line to script to restore spoofed mac after running hostapd */
2568
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2569
				if ($wl['spoofmac'])
2570
					$if_curmac = $wl['spoofmac'];
2571
				else
2572
					$if_curmac = get_interface_mac($if);
2573
				if (is_macaddr($if_curmac))
2574
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2575
						" link " . escapeshellarg($if_curmac) . "\n");
2576
			}
2577
		}
2578
	}
2579

    
2580
	fclose($fd_set);
2581
	conf_mount_ro();
2582

    
2583
	/* Making sure regulatory settings have actually changed
2584
	 * before applying, because changing them requires bringing
2585
	 * down all wireless networks on the interface. */
2586
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2587
	$ifconfig_str = implode($output);
2588
	unset($output);
2589
	$reg_changing = false;
2590

    
2591
	/* special case for the debug country code */
2592
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2593
		$reg_changing = true;
2594
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2595
		$reg_changing = true;
2596
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2597
		$reg_changing = true;
2598
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2599
		$reg_changing = true;
2600
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2601
		$reg_changing = true;
2602

    
2603
	if ($reg_changing) {
2604
		/* set regulatory domain */
2605
		if($wlcfg['regdomain'])
2606
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2607

    
2608
		/* set country */
2609
		if($wlcfg['regcountry'])
2610
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2611

    
2612
		/* set location */
2613
		if($wlcfg['reglocation'])
2614
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2615

    
2616
		$wlregcmd_args = implode(" ", $wlregcmd);
2617

    
2618
		/* build a complete list of the wireless clones for this interface */
2619
		$clone_list = array();
2620
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2621
			$clone_list[] = interface_get_wireless_clone($baseif);
2622
		if (is_array($config['wireless']['clone'])) {
2623
			foreach ($config['wireless']['clone'] as $clone) {
2624
				if ($clone['if'] == $baseif)
2625
					$clone_list[] = $clone['cloneif'];
2626
			}
2627
		}
2628

    
2629
		/* find which clones are up and bring them down */
2630
		$clones_up = array();
2631
		foreach ($clone_list as $clone_if) {
2632
			$clone_status = pfSense_get_interface_addresses($clone_if);
2633
			if ($clone_status['status'] == 'up') {
2634
				$clones_up[] = $clone_if;
2635
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2636
			}
2637
		}
2638

    
2639
		/* apply the regulatory settings */
2640
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2641

    
2642
		/* bring the clones back up that were previously up */
2643
		foreach ($clones_up as $clone_if) {
2644
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2645

    
2646
			/*
2647
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2648
			 * is in infrastructure mode, and WPA is enabled.
2649
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2650
			 */
2651
			if ($clone_if != $if) {
2652
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2653
				if ( !empty($friendly_if)
2654
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2655
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2656
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2657
				}
2658
			}
2659
		}
2660
	}
2661

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

    
2666
	/* configure wireless */
2667
	$wlcmd_args = implode(" ", $wlcmd);
2668
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2669

    
2670
	
2671
	sleep(1);
2672
	/* execute hostapd and wpa_supplicant if required in shell */
2673
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2674

    
2675
	return 0;
2676

    
2677
}
2678

    
2679
function kill_hostapd($interface) {
2680
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2681
}
2682

    
2683
function kill_wpasupplicant($interface) {
2684
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2685
}
2686

    
2687
function find_dhclient_process($interface) {
2688
	if ($interface)
2689
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2690
	else
2691
		$pid = 0;
2692

    
2693
	return intval($pid);
2694
}
2695

    
2696
function find_dhcp6c_process($interface) {
2697
	if ($interface)
2698
		$pid = `/bin/ps auxw|grep "[d]hcp6c" |grep "{$interface}"|awk '{print $2}'`;
2699
	else
2700
		return(false);
2701

    
2702
	return intval($pid);
2703
}
2704

    
2705
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2706
	global $config, $g;
2707
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2708
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2709

    
2710
	$wancfg = $config['interfaces'][$interface];
2711

    
2712
	$realif = get_real_interface($interface);
2713
	$realhwif_array = get_parent_interface($interface);
2714
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2715
	$realhwif = $realhwif_array[0];
2716

    
2717
	/* Disable Accepting router advertisements unless specifically requested */
2718
	log_error("Deny router advertisements for interface {$interface}");
2719
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2720
			
2721
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2722
		/* remove all IPv4 and IPv6 addresses */
2723
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2724
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2725

    
2726
		/* only bring down the interface when both v4 and v6 are set to NONE */
2727
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2728

    
2729

    
2730

    
2731

    
2732

    
2733

    
2734

    
2735

    
2736
			interface_bring_down($interface);
2737

    
2738
		}
2739
	}
2740

    
2741
	/* wireless configuration? */
2742
	if (is_array($wancfg['wireless']))
2743
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2744

    
2745
	$mac = get_interface_mac($realhwif);
2746
	/*	Don't try to reapply the spoofed MAC if it's already applied.
2747
		When ifconfig link is used, it cycles the interface down/up, which triggers 
2748
		the interface config again, which attempts to spoof the MAC again, 
2749
		which cycles the link again... */
2750
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2751
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2752
			" link " . escapeshellarg($wancfg['spoofmac']));
2753

    
2754
                /*
2755
                 * All vlans need to spoof their parent mac address, too.  see
2756
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2757
                 */
2758
                if (is_array($config['vlans']['vlan'])) {
2759
                        foreach ($config['vlans']['vlan'] as $vlan) {
2760
                                if ($vlan['if'] == $realhwif)
2761
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2762
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2763
                        }
2764
                }
2765
	}  else {
2766

    
2767
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2768
			/*   this is not a valid mac address.  generate a
2769
			 *   temporary mac address so the machine can get online.
2770
			 */
2771
			echo gettext("Generating new MAC address.");
2772
			$random_mac = generate_random_mac_address();
2773
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2774
				" link " . escapeshellarg($random_mac));
2775
			$wancfg['spoofmac'] = $random_mac;
2776
			write_config();
2777
			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");
2778
		}
2779
	}
2780

    
2781
	/* media */
2782
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2783
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2784
		if ($wancfg['media'])
2785
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2786
		if ($wancfg['mediaopt'])
2787
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2788
		mwexec($cmd);
2789
	}
2790
	if (!empty($wancfg['mtu']))
2791
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2792
	else {
2793
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2794
		if ($mtu != get_interface_mtu($realhwif))
2795
			pfSense_interface_mtu($realhwif, $mtu);
2796
	}
2797

    
2798
	$options = pfSense_get_interface_addresses($realhwif);
2799
	if (is_array($options) && isset($options['caps']['polling'])) {
2800
		if (isset($config['system']['polling']))
2801
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2802
		else
2803
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2804
	}
2805

    
2806
	/* skip vlans for checksumming and polling */
2807
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2808
		$flags = 0;
2809
		if(isset($config['system']['disablechecksumoffloading'])) {
2810
			if (isset($options['encaps']['txcsum']))
2811
				$flags |= IFCAP_TXCSUM;
2812
			if (isset($options['encaps']['rxcsum']))
2813
				$flags |= IFCAP_RXCSUM;
2814
        	} else {
2815
 			if (!isset($options['caps']['txcsum']))
2816
				$flags |= IFCAP_TXCSUM;
2817
			if (!isset($options['caps']['rxcsum']))
2818
				$flags |= IFCAP_RXCSUM;
2819
        	}
2820

    
2821
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2822
                	if (isset($options['encaps']['tso4']))
2823
				$flags |= IFCAP_TSO;
2824
                	if (isset($options['encaps']['tso6']))
2825
				$flags |= IFCAP_TSO;
2826
        	} else {
2827
                	if (!isset($options['caps']['tso4']))
2828
				$flags |= IFCAP_TSO;
2829
                	if (!isset($options['caps']['tso6']))
2830
				$flags |= IFCAP_TSO;
2831
        	}
2832

    
2833
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2834
                	if (isset($options['encaps']['lro']))
2835
				$flags |= IFCAP_LRO;
2836
        	} else {
2837
                	if (!isset($options['caps']['lro']))
2838
				$flags |= IFCAP_LRO;
2839
        	}
2840

    
2841
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2842
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2843
			$flags |= IFCAP_POLLING;
2844
		}
2845
               	pfSense_interface_capabilities($realhwif, -$flags);
2846
	}
2847

    
2848
	/* invalidate interface/ip/sn cache */
2849
	get_interface_arr(true);
2850
	unset($interface_ip_arr_cache[$realif]);
2851
	unset($interface_sn_arr_cache[$realif]);
2852
	unset($interface_ipv6_arr_cache[$realif]);
2853
	unset($interface_snv6_arr_cache[$realif]);
2854

    
2855
	switch ($wancfg['ipaddr']) {
2856
		case 'carpdev-dhcp':
2857
			interface_carpdev_dhcp_configure($interface);
2858
			break;
2859
		case 'dhcp':
2860
			interface_dhcp_configure($interface);
2861
			break;
2862
		case 'pppoe':
2863
		case 'l2tp':
2864
		case 'pptp':
2865
		case 'ppp':
2866
			interface_ppps_configure($interface);
2867
			break;
2868
		default:
2869
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2870
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2871
			} else if (substr($realif, 0, 3) == "gre") {
2872
				if (is_array($config['gres']['gre'])) {
2873
					foreach ($config['gres']['gre'] as $gre)
2874
						if ($gre['greif'] == $realif)
2875
							interface_gre_configure($gre);
2876
				}
2877
			} else if (substr($realif, 0, 3) == "gif") {
2878
				 if (is_array($config['gifs']['gif'])) {
2879
					foreach ($config['gifs']['gif'] as $gif)
2880
						if($gif['gifif'] == $realif)
2881
							interface_gif_configure($gif);
2882
				}
2883
			} else if (substr($realif, 0, 4) == "ovpn") {
2884
				/* XXX: Should be done anything?! */
2885
			}
2886
			break;
2887
	}
2888

    
2889
	switch ($wancfg['ipaddrv6']) {
2890
		case 'slaac':
2891
		case 'dhcp6':
2892
			interface_dhcpv6_configure($interface);
2893
			break;
2894
		case '6rd':
2895
			interface_6rd_configure($interface);
2896
			break;
2897
		case '6to4':
2898
			interface_6to4_configure($interface);
2899
			break;
2900
		case 'track6':
2901
			interface_track6_configure($interface);
2902
			break;
2903
		default:
2904
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2905
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2906
				// FIXME: Add IPv6 Support to the pfSense module
2907
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2908
			}
2909
			break;
2910
	}
2911

    
2912
	if(does_interface_exist($wancfg['if']))
2913
		interfaces_bring_up($wancfg['if']);
2914

    
2915
	interface_netgraph_needed($interface);
2916
 	
2917
	if (!$g['booting']) {
2918
		link_interface_to_vips($interface, "update");
2919

    
2920
		unset($gre);
2921
		$gre = link_interface_to_gre($interface);
2922
		if (!empty($gre))
2923
			array_walk($gre, 'interface_gre_configure');
2924

    
2925
		unset($gif);
2926
		$gif = link_interface_to_gif($interface);
2927
		if (!empty($gif))
2928
			array_walk($gif, 'interface_gif_configure');
2929

    
2930
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2931
			unset($bridgetmp);
2932
			$bridgetmp = link_interface_to_bridge($interface);
2933
			if (!empty($bridgetmp))
2934
				interface_bridge_add_member($bridgetmp, $realif);
2935
		}
2936

    
2937
		$grouptmp = link_interface_to_group($interface);
2938
		if (!empty($grouptmp))
2939
			array_walk($grouptmp, 'interface_group_add_member');
2940

    
2941
		if ($interface == "lan")
2942
			/* make new hosts file */
2943
			system_hosts_generate();
2944

    
2945
		if ($reloadall == true) {
2946

    
2947
			/* reconfigure static routes (kernel may have deleted them) */
2948
			system_routing_configure($interface);
2949

    
2950
			/* reload ipsec tunnels */
2951
			vpn_ipsec_configure();
2952

    
2953
			/* restart dnsmasq */
2954
			services_dnsmasq_configure();
2955

    
2956
			/* update dyndns */
2957
			send_event("service reload dyndns {$interface}");
2958

    
2959
			/* reload captive portal */
2960
			captiveportal_init_rules();
2961
		}
2962
	}
2963

    
2964
	return 0;
2965
}
2966

    
2967
function interface_carpdev_dhcp_configure($interface = "wan") {
2968
	global $config, $g;
2969

    
2970
	$wancfg = $config['interfaces'][$interface];
2971
	$wanif = $wancfg['if'];
2972
	/* bring wan interface up before starting dhclient */
2973
	if($wanif)
2974
		interfaces_bring_up($wanif);
2975
	else 
2976
		log_error(gettext("Could not bring wanif up in terface_carpdev_dhcp_configure()"));
2977

    
2978
	return 0;
2979
}
2980

    
2981
function interface_track6_configure($interface = "lan") {
2982
	global $config, $g;
2983
	$iflist = get_configured_interface_with_descr(false, true);
2984

    
2985
	$wancfg = $config['interfaces'][$interface];
2986
	$wanif = $wancfg['if'];
2987
	if (empty($wancfg))
2988
		$wancfg = array();
2989

    
2990
	$wanif = get_real_interface($interface);
2991
	
2992
	/* If the interface is not configured via another, exit */
2993
	if(!$wancfg['track6-interface'] <> "") {
2994
		return(false);
2995
	}
2996

    
2997
	$type = $config['interfaces'][$wancfg['track6-interface']]['ipaddrv6'];
2998
	switch($type) {
2999
		case "6to4":
3000
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3001
			interface_track6_6to4_configure($interface);
3002
			break;
3003
		case "6rd":
3004
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3005
			interface_track6_6rd_configure($interface);
3006
			break;
3007
		case "dhcp6":
3008
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3009
			interface_track6_dhcp6_configure($interface);
3010
			break;
3011
		default:
3012
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']} but unknown type {$type}");
3013
			break;
3014
	}
3015
	return 0;
3016
}
3017

    
3018

    
3019
function interface_track6_6rd_configure($interface = "lan") {
3020
	global $config, $g;
3021
	$iflist = get_configured_interface_with_descr(false, true);
3022

    
3023
	$lancfg = $config['interfaces'][$interface];
3024
	$lanif = $lancfg['if'];
3025
	if (empty($lancfg))
3026
		$lancfg = array();
3027

    
3028
	$lanif = get_real_interface($interface);
3029
	
3030
	/* If the interface is not configured via another, exit */
3031
	if(!$lancfg['track6-interface'] <> "") {
3032
		return(false);
3033
	}
3034
	if(!is_numeric($lancfg['track6-prefix-id']))
3035
		$lancfg['track6-prefix-id'] = 0;
3036
	
3037
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3038
	$wanif = $wancfg['if'];
3039
	if (empty($wancfg))
3040
		$wancfg = array();
3041
	
3042
	$ip4address = find_interface_ip($wanif);
3043
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3044
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3045
		return false;
3046
	}
3047
	$hexwanv4 = return_hex_ipv4($ip4address);
3048
	
3049
	/* create the long prefix notation for math, save the prefix length */
3050
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3051
	$rd6prefixlen = $rd6prefix[1];
3052
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3053

    
3054
	/* binary presentation of the prefix for all 128 bits. */
3055
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3056
	
3057
	/* just save the left prefix length bits */
3058
	$rd6lanbin = substr($rd6lanbin, 0, $rd6prefixlen);
3059
	/* add the v4 address, offset n bits from the left */
3060
	$rd6lanbin .= substr(sprintf("%032b", hexdec($hexwanv4)), (0 + $wancfg['prefix-6rd-v4plen']), 32);
3061

    
3062
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3063
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3064
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3065
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3066
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3067
	/* fill the rest out with zeros */
3068
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3069

    
3070
	/* convert the 128 bits for the lan address back into a valid IPv6 address */ 
3071
	$rd6lan = convert_128bit_to_ipv6($rd6lanbin) ."1";
3072
	
3073
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3074
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3075
	return 0;
3076
}
3077

    
3078
function interface_track6_6to4_configure($interface = "lan") {
3079
	global $config, $g;
3080
	$iflist = get_configured_interface_with_descr(false, true);
3081

    
3082
	$lancfg = $config['interfaces'][$interface];
3083
	$lanif = $lancfg['if'];
3084
	if (empty($lancfg))
3085
		$lancfg = array();
3086

    
3087
	$lanif = get_real_interface($interface);
3088
	
3089
	/* If the interface is not configured via another, exit */
3090
	if(!$lancfg['track6-interface'] <> "") {
3091
		return(false);
3092
	}
3093
	if(!is_numeric($lancfg['track6-prefix-id']))
3094
		$lancfg['track6-prefix-id'] = 0;
3095
	
3096
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3097
	$wanif = $wancfg['if'];
3098
	if (empty($wancfg))
3099
		$wancfg = array();
3100
	
3101
	$ip4address = find_interface_ip($wanif);
3102
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3103
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3104
		return false;
3105
	}
3106
	$hexwanv4 = return_hex_ipv4($ip4address);
3107
	
3108
	/* create the long prefix notation for math, save the prefix length */
3109
	$sixto4prefix = "2002::";
3110
	$sixto4prefixlen = 16;
3111
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3112

    
3113
	/* binary presentation of the prefix for all 128 bits. */
3114
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3115
	
3116
	/* just save the left prefix length bits */
3117
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3118
	/* add the v4 address */
3119
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3120
	/* add the custom prefix id */
3121
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3122
	/* fill the rest out with zeros */
3123
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3124
	
3125
	/* convert the 128 bits for the lan address back into a valid IPv6 address */ 
3126
	$sixto4lan = convert_128bit_to_ipv6($sixto4lanbin) ."1";
3127
	
3128
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3129
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3130
	return 0;
3131
}
3132

    
3133
function interface_track6_dhcp6_configure($interface = "lan") {
3134
	global $config, $g;
3135
	$iflist = get_configured_interface_with_descr(false, true);
3136

    
3137
	$lancfg = $config['interfaces'][$interface];
3138
	$lanif = $lancfg['if'];
3139
	if (empty($lancfg))
3140
		$lancfg = array();
3141

    
3142
	$lanif = get_real_interface($interface);
3143
	
3144
	/* If the interface is not configured via another, exit */
3145
	if(!$lancfg['track6-interface'] <> "") {
3146
		return(false);
3147
	}
3148
	if(!is_numeric($lancfg['track6-prefix-id']))
3149
		$lancfg['track6-prefix-id'] = 0;
3150
	
3151
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3152
	$wanif = $wancfg['if'];
3153
	if (empty($wancfg))
3154
		$wancfg = array();
3155
	
3156
	
3157
	$ifcfgipv6 = find_interface_ipv6($lanif);
3158
	if(is_ipaddrv6($ifcfgipv6)) {
3159
		$dhcp6lanarr = explode(":", Net_IPv6::uncompress($ifcfgipv6));
3160
		$dhcp6lanarr[4] = 0;
3161
		$dhcp6lanarr[5] = 0;
3162
		$dhcp6lanarr[6] = 0;
3163
		$dhcp6lanarr[7] = 1;
3164
		$dhcp6lan =  Net_IPv6::compress(implode(":", $dhcp6lanarr));
3165
		log_error("dhcp6 {$interface} with ipv6 address {$dhcp6lan} based on {$lancfg['track6-interface']}");
3166
		mwexec("/sbin/ifconfig {$lanif} inet6 {$dhcp6lan} prefixlen 64");
3167
	}
3168
	return 0;
3169
}
3170

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

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

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

    
3183
	$wanif = get_real_interface($interface);
3184
	
3185
	$ip4address = find_interface_ip($wanif);
3186
	$ip4gateway = get_interface_gateway($wanif);
3187
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3188
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3189
		return false;
3190
	}
3191
	$hexwanv4 = return_hex_ipv4($ip4address);
3192
	
3193
	if(!is_numeric($wancfg['prefix-6rd-v4plen']))
3194
		$wancfg['prefix-6rd-v4plen'] = 0;
3195

    
3196
	/* create the long prefix notation for math, save the prefix length */
3197
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3198
	$rd6prefixlen = $rd6prefix[1];
3199
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3200

    
3201
	/* we need the hex form of the broker IPv4 address */
3202
	$hexbrv4 = return_hex_ipv4($wancfg['gateway-6rd']);
3203
	
3204
	/* binary presentation of the prefix for all 128 bits. */
3205
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3206
		
3207
	/* just save the left prefix length bits */
3208
	$rd6brprefixbin = substr($rd6prefixbin, 0, $rd6prefixlen);
3209
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3210
	$rd6brprefixbin .= substr(sprintf("%032b", hexdec($hexbrv4)), $wancfg['prefix-6rd-v4plen'], 32);
3211
	/* fill out the rest with 0's */
3212
	$rd6brprefixbin = str_pad($rd6brprefixbin, 128, "0", STR_PAD_RIGHT);;
3213

    
3214
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3215
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3216

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

    
3224
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3225
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3226

    
3227
	/* setup the stf interface */
3228
	/* use the srd device
3229
	mwexec("/sbin/ifconfig srd0 destroy");
3230
	mwexec("/sbin/ifconfig srd0 create");
3231
	mwexec("/sbin/ifconfig srd0 v4plen {$wancfg['prefix-6rd-v4plen']} pfix {$rd6prefix} plen {$rd6prefixlen} braddr {$wancfg['gateway-6rd']}");
3232
	log_error("Created 6rd interface srd0 v4plen {$wancfg['prefix-6rd-v4plen']} pfix {$rd6prefix} plen {$rd6prefixlen} braddr {$wancfg['gateway-6rd']}");
3233
	*/
3234
	/* stf approach only works when embedding the entire 32 bits of the v4 */
3235
	mwexec("/sbin/ifconfig stf0 destroy");
3236
	mwexec("/sbin/ifconfig stf0 create");
3237
	mwexec("/sbin/ifconfig stf0 inet6 {$rd6prefix}/{$rd6prefixlen}");
3238
	log_error("Created 6rd interface stf0 {$rd6prefix}/{$rd6prefixlen}");
3239

    
3240
	/* write out a default router file */
3241
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3242
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3243

    
3244
	if (is_ipaddrv4($ip4gateway)) {
3245
		mwexec("route change -host " . $wancfg['gateway-6rd'] . " {$ip4gateway}");
3246
	}
3247

    
3248
	/* configure dependent interfaces */
3249
	foreach($iflist as $if => $ifname) {
3250
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3251
			interface_track6_configure($if);
3252
	}
3253
	
3254
	return 0;
3255
}
3256

    
3257
function interface_6to4_configure($interface = "wan"){
3258
	global $config, $g;
3259
	$iflist = get_configured_interface_with_descr(false, true);
3260

    
3261
	/* because this is a tunnel interface we can only function 
3262
	 *	with a public IPv4 address on the interface */
3263

    
3264
	$wancfg = $config['interfaces'][$interface];
3265
	$wanif = $wancfg['if'];
3266
	if (empty($wancfg))
3267
		$wancfg = array();
3268

    
3269
	$wanif = get_real_interface($interface);
3270
	
3271
	$ip4address = find_interface_ip($wanif);
3272
	$ip4gateway = get_interface_gateway($wanif);
3273
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3274
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3275
		return false;
3276
	}
3277
	
3278
	/* create the long prefix notation for math, save the prefix length */
3279
	$stfprefixlen = 16;
3280
	$stfprefix = Net_IPv6::uncompress("2002::");
3281
	$stfarr = explode(":", $stfprefix);
3282
	$v4prefixlen = "0";
3283
	
3284
	/* we need the hex form of the interface IPv4 address */
3285
	$ip4arr = explode(".", $ip4address);
3286
	$hexwanv4 = "";
3287
	foreach($ip4arr as $octet)
3288
		$hexwanv4 .= sprintf("%02x", $octet);
3289

    
3290
	/* we need the hex form of the broker IPv4 address */
3291
	$ip4arr = explode(".", "192.88.99.1");
3292
	$hexbrv4 = "";
3293
	foreach($ip4arr as $octet)
3294
		$hexbrv4 .= sprintf("%02x", $octet);
3295
	
3296
	/* binary presentation of the prefix for all 128 bits. */
3297
	$stfprefixbin = "";
3298
	foreach($stfarr as $element) {
3299
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3300
	}
3301
	/* just save the left prefix length bits */
3302
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3303

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

    
3308
	/* for the local subnet too. */
3309
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3310
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3311

    
3312
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3313
	$stfbrarr = array();
3314
	$stfbrbinarr = array();
3315
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3316
	foreach($stfbrbinarr as $bin)
3317
		$stfbrarr[] = dechex(bindec($bin));
3318
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3319

    
3320
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3321
	$stflanarr = array();
3322
	$stflanbinarr = array();
3323
	$stflanbinarr = str_split($stflanbin, 16);
3324
	foreach($stflanbinarr as $bin)
3325
		$stflanarr[] = dechex(bindec($bin));
3326
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3327
	$stflanarr[7] = 1;
3328
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3329

    
3330
	/* setup the stf interface */
3331
	mwexec("/sbin/ifconfig stf0 destroy");
3332
	mwexec("/sbin/ifconfig stf0 create");
3333
	mwexec("/sbin/ifconfig stf0 inet6 {$stflanpr} prefixlen 16");
3334

    
3335
	log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for stf0, route {$stfbrgw}");
3336
	
3337
	/* write out a default router file */
3338
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3339
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3340

    
3341
	if (is_ipaddrv4($ip4gateway)) {
3342
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3343
	}
3344

    
3345
	/* configure dependent interfaces */
3346
	foreach($iflist as $if => $ifname) {
3347
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3348
			interface_track6_configure($if);
3349
	}
3350
	
3351
	return 0;
3352
}
3353

    
3354
function interface_dhcpv6_configure($interface = "wan") {
3355
	global $config, $g;
3356
	$iflist = get_configured_interface_with_descr(false, true);
3357

    
3358
	$wancfg = $config['interfaces'][$interface];
3359
	$wanif = $wancfg['if'];
3360
	if (empty($wancfg))
3361
		$wancfg = array();
3362

    
3363
	$wanif = get_real_interface($interface);
3364

    
3365
	/* Add ISC IPv6 dhclient here, only wide-dhcp6c works for now. */
3366
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
3367
	if (!$fd) {
3368
		printf("Error: cannot open dhcp6c_{$interface}.conf in interfaces_wan_dhcpv6_configure() for writing.\n");
3369
		return 1;
3370
	}
3371

    
3372
	$dhcp6cconf = "";
3373
	$dhcp6cconf .= "interface {$wanif} {\n";
3374

    
3375
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3376
	if($wancfg['ipaddrv6'] == "slaac") {
3377
		$dhcp6cconf .= "	information-only;\n";
3378
		$dhcp6cconf .= "	request domain-name-servers;\n";
3379
		$dhcp6cconf .= "	request domain-name;\n";
3380
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3381
		$dhcp6cconf .= "};\n";
3382
	} else {
3383
	
3384
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3385
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3386
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3387
		}
3388
		$dhcp6cconf .= "request domain-name-servers;\n";
3389
		$dhcp6cconf .= "request domain-name;\n";
3390
		$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3391

    
3392
		$dhcp6cconf .= "};\n";
3393
		$dhcp6cconf .= "id-assoc na 0 { };\n";
3394
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3395
			/* Setup the prefix delegation */
3396
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3397
			foreach($iflist as $friendly => $ifdescr) {
3398
				if($config['interfaces'][$friendly]['track6-interface'] != $interface)
3399
					continue;
3400
				if(is_numeric($config['interfaces'][$friendly]['track6-prefix-id'])) {
3401
					log_error("setting up $friendly - {$config['interfaces'][$friendly]['track6-prefix-id']}");
3402
					$realif = get_real_interface($friendly);
3403
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3404
					$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['track6-prefix-id']};\n";
3405
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3406
					$dhcp6cconf .= "	};\n";
3407
				}
3408
			}
3409
			$dhcp6cconf .= "};\n";
3410
		}
3411
	}
3412
	fwrite($fd, $dhcp6cconf);
3413
	fclose($fd);
3414

    
3415
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3416
	$fds = fopen("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", "w");
3417
	if (!$fds) {
3418
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interfaces_wan_dhcpv6_configure() for writing.\n");
3419
		return 1;
3420
	}
3421
	$dhcp6cscript = "#!/bin/sh\n";
3422
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3423
	$dhcp6cscript .= "/etc/rc.newwanipv6 $interface \n";
3424

    
3425
	fwrite($fds, $dhcp6cscript);
3426
	fclose($fds);
3427
	chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3428

    
3429

    
3430
	/* accept router advertisements for this interface */
3431
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3432
	log_error("Accept router advertisements on interface {$wanif} ");
3433
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3434
	mwexec("/sbin/ifconfig {$wanif} inet6 defroute_rtadv");
3435

    
3436
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3437
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
3438
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3439
	if(!empty($out)) {
3440
		foreach($out as $line) {
3441
			if(stristr($line, "received")) {
3442
				$parts = explode(" ", $line);
3443
				if(is_ipaddrv6($parts[3])) {
3444
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3445
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3446
					file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$parts[3]}\n");
3447
					break;
3448
				}
3449
			}
3450
		}
3451
	}
3452
	/* sleep a few seconds before returning to give the client some time
3453
	 * to configure a lan interface with a prefix */
3454
	sleep(5);
3455

    
3456
	if($wancfg['ippaddrv6'] != "slaac") {
3457
		/* configure dependent interfaces */
3458
		foreach($iflist as $if => $ifname) {
3459
			if($config['interfaces'][$if]['track6-interface'] == $interface)
3460
				interface_track6_configure($if);
3461
		}
3462
	}
3463
	return 0;
3464
}
3465

    
3466
function interface_dhcp_configure($interface = "wan") {
3467
	global $config, $g;
3468

    
3469
	$wancfg = $config['interfaces'][$interface];
3470
	$wanif = $wancfg['if'];
3471
	if (empty($wancfg))
3472
		$wancfg = array();
3473

    
3474
	/* generate dhclient_wan.conf */
3475
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3476
	if (!$fd) {
3477
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interfaces_wan_dhcp_configure() for writing.%s"), $interface, "\n"));
3478
		return 1;
3479
	}
3480

    
3481
	if ($wancfg['dhcphostname']) {
3482
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3483
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3484
	} else {
3485
		$dhclientconf_hostname = "";
3486
	}
3487

    
3488
	$wanif = get_real_interface($interface);
3489
	if (empty($wanif)) {
3490
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3491
		return 0;
3492
	}
3493
 	$dhclientconf = "";
3494
	
3495
	$dhclientconf .= <<<EOD
3496
interface "{$wanif}" {
3497
timeout 60;
3498
retry 1;
3499
select-timeout 0;
3500
initial-interval 1;
3501
	{$dhclientconf_hostname}
3502
	script "/sbin/dhclient-script";
3503
}
3504

    
3505
EOD;
3506

    
3507
if(is_ipaddr($wancfg['alias-address'])) {
3508
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3509
	$dhclientconf .= <<<EOD
3510
alias {
3511
	interface  "{$wanif}";
3512
	fixed-address {$wancfg['alias-address']};
3513
	option subnet-mask {$subnetmask};
3514
}
3515

    
3516
EOD;
3517
}
3518
	fwrite($fd, $dhclientconf);
3519
	fclose($fd);
3520

    
3521
	/* bring wan interface up before starting dhclient */
3522
	if($wanif)
3523
		interfaces_bring_up($wanif);
3524
	else 
3525
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3526

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

    
3530
	return 0;
3531
}
3532

    
3533
function interfaces_group_setup() {
3534
	global $config;
3535

    
3536
	if (!is_array($config['ifgroups']['ifgroupentry']))
3537
		return;
3538

    
3539
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3540
		interface_group_setup($groupar);
3541

    
3542
	return;
3543
}
3544

    
3545
function interface_group_setup(&$groupname /* The parameter is an array */) {
3546
	global $config;
3547

    
3548
	if (!is_array($groupname))
3549
		return;
3550
	$members = explode(" ", $groupname['members']);
3551
	foreach($members as $ifs) {
3552
		$realif = get_real_interface($ifs);
3553
		if ($realif)
3554
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3555
	}
3556

    
3557
	return;
3558
}
3559

    
3560
function interface_group_add_member($interface, $groupname) {
3561
	$interface = get_real_interface($interface);
3562
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3563
}
3564
 
3565
/* COMPAT Function */
3566
function convert_friendly_interface_to_real_interface_name($interface) {
3567
	return get_real_interface($interface);
3568
}
3569

    
3570
/* COMPAT Function */
3571
function get_real_wan_interface($interface = "wan") {
3572
	return get_real_interface($interface);
3573
}
3574

    
3575
/* COMPAT Function */
3576
function get_current_wan_address($interface = "wan") {
3577
	return get_interface_ip($interface);
3578
}
3579

    
3580
/*
3581
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3582
 */
3583
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3584
        global $config;
3585

    
3586
	if (stristr($interface, "_vip")) {
3587
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3588
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3589
                                if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3590
                                        return $vip['interface'];
3591
                        }
3592
                }
3593
        }
3594

    
3595
        /* XXX: For speed reasons reference directly the interface array */
3596
	$ifdescrs = &$config['interfaces'];
3597
        //$ifdescrs = get_configured_interface_list(false, true);
3598

    
3599
        foreach ($ifdescrs as $if => $ifname) {
3600
                if ($config['interfaces'][$if]['if'] == $interface)
3601
                        return $if;
3602

    
3603
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3604
                        return $if;
3605

    
3606
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3607
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3608
		/*
3609
                $int = get_parent_interface($if);
3610
                if ($int[0] == $interface)
3611
                        return $ifname;
3612
		*/
3613
        }
3614
        return NULL;
3615
}
3616

    
3617
/* attempt to resolve interface to friendly descr */
3618
function convert_friendly_interface_to_friendly_descr($interface) {
3619
        global $config;
3620

    
3621
        switch ($interface) {
3622
        case "l2tp":
3623
        	$ifdesc = "L2TP";
3624
                break;
3625
	case "pptp":
3626
		$ifdesc = "PPTP";
3627
		break;
3628
	case "pppoe":
3629
		$ifdesc = "PPPoE";
3630
		break;
3631
	case "openvpn":
3632
		$ifdesc = "OpenVPN";
3633
		break;
3634
	case "enc0":
3635
	case "ipsec":
3636
		$ifdesc = "IPsec";
3637
		break;
3638
        default:
3639
                if (isset($config['interfaces'][$interface])) {
3640
                        if (empty($config['interfaces'][$interface]['descr']))
3641
                                $ifdesc = strtoupper($interface);
3642
                        else
3643
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3644
			break;
3645
		} else if (stristr($interface, "_vip")) {
3646
			if (is_array($config['virtualip']['vip'])) {
3647
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3648
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3649
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3650
							return "{$vip['subnet']} - {$vip['descr']}";
3651
					}
3652
				}
3653
                        }
3654
                } else {
3655
			/* if list */
3656
			$ifdescrs = get_configured_interface_with_descr(false, true);
3657
			foreach ($ifdescrs as $if => $ifname) {
3658
				if ($if == $interface || $ifname == $interface)
3659
					return $ifname;
3660
			}
3661
		}
3662
                break;
3663
        }
3664

    
3665
        return $ifdesc;
3666
}
3667

    
3668
function convert_real_interface_to_friendly_descr($interface) {
3669
        global $config;
3670

    
3671
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3672

    
3673
        if ($ifdesc) {
3674
                $iflist = get_configured_interface_with_descr(false, true);
3675
                return $iflist[$ifdesc];
3676
        }
3677

    
3678
        return $interface;
3679
}
3680

    
3681
/*
3682
 *  get_parent_interface($interface):
3683
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3684
 *				or virtual interface (i.e. vlan)
3685
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3686
 *			-- returns $interface passed in if $interface parent is not found
3687
 *			-- returns empty array if an invalid interface is passed
3688
 *	(Only handles ppps and vlans now.)
3689
 */
3690
function get_parent_interface($interface) {
3691
	global $config;
3692

    
3693
	$parents = array();
3694
	//Check that we got a valid interface passed
3695
	$realif = get_real_interface($interface);
3696
	if ($realif == NULL)
3697
		return $parents;
3698

    
3699
	// If we got a real interface, find it's friendly assigned name
3700
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3701
		
3702
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3703
		$ifcfg = $config['interfaces'][$interface];
3704
		switch ($ifcfg['ipaddr']) {
3705
			case "ppp":
3706
			case "pppoe":
3707
			case "pptp":
3708
			case "l2tp":
3709
				if (empty($parents))
3710
					if (is_array($config['ppps']['ppp']))
3711
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3712
							if ($ppp_if == $ppp['if']) {
3713
								$ports = explode(',', $ppp['ports']);
3714
								foreach ($ports as $pid => $parent_if) 
3715
									$parents[$pid] = get_real_interface($parent_if);
3716
								break;
3717
							}
3718
						}
3719
				break;
3720
			case "dhcp":
3721
			case "static":
3722
			default:
3723
				// Handle _vlans
3724
				if (strstr($realif,"_vlan"))
3725
					if (is_array($config['vlans']['vlan'])) 
3726
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3727
							if ($ifcfg['if'] == $vlan['vlanif']){
3728
								$parents[0] = $vlan['if'];
3729
								break;
3730
							}
3731
				break;
3732
		}
3733
	}
3734
	
3735
	if (empty($parents))
3736
		$parents[0] = $realif;
3737
	
3738
	return $parents;
3739
}
3740

    
3741
function interface_is_wireless_clone($wlif) {
3742
	if(!stristr($wlif, "_wlan")) {
3743
		return false;
3744
	} else {
3745
		return true;
3746
	}
3747
}
3748

    
3749
function interface_get_wireless_base($wlif) {
3750
	if(!stristr($wlif, "_wlan")) {
3751
		return $wlif;
3752
	} else {
3753
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3754
	}
3755
}
3756

    
3757
function interface_get_wireless_clone($wlif) {
3758
	if(!stristr($wlif, "_wlan")) {
3759
		return $wlif . "_wlan0";
3760
	} else {
3761
		return $wlif;
3762
	}
3763
}
3764

    
3765
function get_real_interface($interface = "wan") {
3766
    global $config;
3767

    
3768
	$wanif = NULL;
3769

    
3770
	switch ($interface) {
3771
	case "l2tp":
3772
		$wanif = "l2tp";
3773
		break;
3774
	case "pptp":
3775
		$wanif = "pptp";
3776
		break;
3777
	case "pppoe":
3778
		$wanif = "pppoe";
3779
		break;
3780
	case "openvpn":
3781
		$wanif = "openvpn";
3782
		break;
3783
	case "ipsec":
3784
	case "enc0":
3785
		$wanif = "enc0";
3786
		break;
3787
	case "ppp":
3788
		$wanif = "ppp";
3789
		break;
3790
	default:
3791
		// If a real interface was alread passed simply
3792
		// pass the real interface back.  This encourages
3793
		// the usage of this function in more cases so that
3794
		// we can combine logic for more flexibility.
3795
		if(does_interface_exist($interface)) {
3796
			$wanif = $interface;
3797
			break;
3798
		}
3799
		if (empty($config['interfaces'][$interface]))
3800
			break;
3801

    
3802
		$cfg = &$config['interfaces'][$interface];
3803

    
3804
		// Wireless cloned NIC support (FreeBSD 8+)
3805
		// interface name format: $parentnic_wlanparentnic#
3806
		// example: ath0_wlan0
3807
		if (is_interface_wireless($cfg['if'])) {
3808
			$wanif = interface_get_wireless_clone($cfg['if']);
3809
			break;
3810
		}
3811
		/*
3812
		if (empty($cfg['if'])) {
3813
			$wancfg = $cfg['if'];
3814
			break;
3815
		}
3816
		*/
3817

    
3818
		switch ($cfg['ipaddr']) {
3819
			case "carpdev-dhcp":
3820
				$viparr = &$config['virtualip']['vip'];
3821
				if(is_array($viparr))
3822
				foreach ($viparr as $counter => $vip) {
3823
					if ($vip['mode'] == "carpdev-dhcp") {
3824
						if($vip['interface'] == $interface) {
3825
							$wanif = "carp{$counter}";
3826
							break;
3827
						}
3828
					}
3829
				}
3830
				break;
3831
			case "pppoe": 
3832
			case "pptp": 
3833
			case "l2tp": 
3834
			case "ppp":
3835
				$wanif = $cfg['if'];
3836
				break;
3837
			default:
3838
				$wanif = $cfg['if'];
3839
				break;
3840
		}
3841
		break;
3842
	}
3843

    
3844
    return $wanif;
3845
}
3846

    
3847
/* Guess the physical interface by providing a IP address */
3848
function guess_interface_from_ip($ipaddress) {
3849
	if(! is_ipaddr($ipaddress)) {
3850
		return false;
3851
	}
3852
	if(is_ipaddrv4($ipaddress)) {
3853
		/* create a route table we can search */
3854
		exec("netstat -rnWf inet", $output, $ret);
3855
		foreach($output as $line) {
3856
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3857
				$fields = preg_split("/[ ]+/", $line);
3858
				if(ip_in_subnet($ipaddress, $fields[0])) {
3859
					return $fields[6];
3860
				}
3861
			}
3862
		}
3863
	}
3864
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3865
	if(is_ipaddrv6($ipaddress)) {
3866
		/* create a route table we can search */
3867
		exec("netstat -rnWf inet6", $output, $ret);
3868
		foreach($output as $line) {
3869
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3870
				$fields = preg_split("/[ ]+/", $line);
3871
				if(ip_in_subnet($ipaddress, $fields[0])) {
3872
					return $fields[6];
3873
				}
3874
			}
3875
		}
3876
	}
3877
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3878
	if(empty($ret)) {
3879
        	return false;
3880
	}
3881
	return $ret;
3882
}
3883

    
3884
/*
3885
 * find_ip_interface($ip): return the interface where an ip is defined
3886
 *   (or if $bits is specified, where an IP within the subnet is defined)
3887
 */
3888
function find_ip_interface($ip, $bits = null)
3889
{
3890
	/* if list */
3891
	$ifdescrs = get_configured_interface_list();
3892
		
3893
	foreach ($ifdescrs as $ifdescr => $ifname) {
3894
		if ($bits === null) {
3895
			if ($ip == get_interface_ip($ifname)) {
3896
				$int = get_real_interface($ifname);
3897
				return $int;
3898
			}
3899
		}
3900
		else {
3901
			if (ip_in_subnet(get_interface_ip($ifname), $ip . "/" . $bits)) {
3902
				$int = get_real_interface($ifname);
3903
				return $int;
3904
			}
3905
		}
3906
	}
3907
	return false;
3908
}
3909

    
3910
/*
3911
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
3912
 *   (or if $bits is specified, where an IP within the subnet is found)
3913
 */
3914
function find_virtual_ip_alias($ip, $bits = null) {
3915
	global $config;
3916
	if (!is_array($config['virtualip']['vip'])) {
3917
		return false;
3918
	}
3919
	foreach ($config['virtualip']['vip'] as $vip) {
3920
		if ($vip['mode'] === "ipalias") {
3921
			if ($bits === null) {
3922
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
3923
					return $vip;
3924
				}
3925
			}
3926
			else {
3927
				if (check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits'])) {
3928
					return $vip;
3929
				}
3930
			}
3931
		}
3932
	}
3933
	return false;
3934
}
3935

    
3936
/*
3937
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3938
 */
3939
function find_number_of_created_carp_interfaces() {
3940
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3941
}
3942

    
3943
function get_all_carp_interfaces() {
3944
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3945
	$ints = explode(" ", $ints);
3946
	return $ints;
3947
}
3948

    
3949
/*
3950
 * find_carp_interface($ip): return the carp interface where an ip is defined
3951
 */
3952
function find_carp_interface($ip) {
3953
	global $config;
3954
	if (is_array($config['virtualip']['vip'])) {
3955
		foreach ($config['virtualip']['vip'] as $vip) {
3956
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3957
				if(is_ipaddrv4($ip)) {
3958
					$carp_ip = get_interface_ip($vip['interface']);
3959
				}
3960
				if(is_ipaddrv6($ip)) {
3961
					$carp_ip = get_interface_ipv6($vip['interface']);
3962
				}
3963
				exec("/sbin/ifconfig", $output, $return);
3964
				foreach($output as $line) {
3965
					$elements = preg_split("/[ ]+/i", $line);
3966
					if(strstr($elements[0], "vip"))
3967
						$curif = str_replace(":", "", $elements[0]);
3968
					if(stristr($line, $ip)) {
3969
						$if = $curif;
3970
						continue;
3971
					}
3972
				}
3973

    
3974
				if ($if)
3975
					return $if;
3976
			}
3977
		}
3978
	}
3979
}
3980

    
3981
function link_carp_interface_to_parent($interface) {
3982
        global $config;
3983

    
3984
        if ($interface == "")
3985
                return;
3986

    
3987
        $carp_ip = get_interface_ip($interface);
3988
        if (!is_ipaddr($carp_ip))
3989
                return;
3990

    
3991
        /* if list */
3992
        $ifdescrs = get_configured_interface_list();
3993
        foreach ($ifdescrs as $ifdescr => $ifname) {
3994
                $interfaceip = get_interface_ip($ifname);
3995
                $subnet_bits = get_interface_subnet($ifname);
3996
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3997
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3998
                        return $ifname;
3999
        }
4000

    
4001
        return "";
4002
}
4003

    
4004
/****f* interfaces/link_ip_to_carp_interface
4005
 * NAME
4006
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4007
 * INPUTS
4008
 *   $ip
4009
 * RESULT
4010
 *   $carp_ints
4011
 ******/
4012
function link_ip_to_carp_interface($ip) {
4013
        global $config;
4014

    
4015
        if (!is_ipaddr($ip))
4016
                return;
4017

    
4018
        $carp_ints = "";
4019
        if (is_array($config['virtualip']['vip'])) {
4020
		$first = 0;
4021
		$carp_int = array();
4022
                foreach ($config['virtualip']['vip'] as $vip) {
4023
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
4024
                                $carp_ip = $vip['subnet'];
4025
                                $carp_sn = $vip['subnet_bits'];
4026
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
4027
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4028
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
4029
				}
4030
                        }
4031
                }
4032
		if (!empty($carp_int))
4033
			$carp_ints = implode(" ", array_unique($carp_int));
4034
        }
4035

    
4036
        return $carp_ints;
4037
}
4038

    
4039
function link_interface_to_vlans($int, $action = "") {
4040
	global $config;
4041

    
4042
	if (empty($int))
4043
		return;
4044

    
4045
	if (is_array($config['vlans']['vlan'])) {
4046
                foreach ($config['vlans']['vlan'] as $vlan) {
4047
			if ($int == $vlan['if']) {
4048
				if ($action == "update") {
4049
					interfaces_bring_up($int);
4050
				} else if ($action == "")
4051
					return $vlan;
4052
			}
4053
		}
4054
	}
4055
}
4056

    
4057
function link_interface_to_vips($int, $action = "") {
4058
        global $config;
4059

    
4060
        if (is_array($config['virtualip']['vip'])) {
4061
		foreach ($config['virtualip']['vip'] as $vip) {
4062
			if ($int == $vip['interface']) {
4063
				if ($action == "update")
4064
					interfaces_vips_configure($int);
4065
				else
4066
					return $vip;
4067
			}
4068
		}
4069
	}
4070
}
4071

    
4072
/****f* interfaces/link_interface_to_bridge
4073
 * NAME
4074
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4075
 * INPUTS
4076
 *   $ip
4077
 * RESULT
4078
 *   bridge[0-99]
4079
 ******/
4080
function link_interface_to_bridge($int) {
4081
        global $config;
4082

    
4083
        if (is_array($config['bridges']['bridged'])) {
4084
                foreach ($config['bridges']['bridged'] as $bridge) {
4085
			if (in_array($int, explode(',', $bridge['members'])))
4086
                                return "{$bridge['bridgeif']}";
4087
		}
4088
	}
4089
}
4090

    
4091
function link_interface_to_group($int) {
4092
        global $config;
4093

    
4094
	$result = array();
4095

    
4096
        if (is_array($config['ifgroups']['ifgroupentry'])) {
4097
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4098
			if (in_array($int, explode(" ", $group['members'])))
4099
				$result[$group['ifname']] = $int;
4100
		}
4101
	}
4102

    
4103
	return $result;
4104
}
4105

    
4106
function link_interface_to_gre($interface) {
4107
        global $config;
4108

    
4109
	$result = array();
4110

    
4111
        if (is_array($config['gres']['gre'])) {
4112
                foreach ($config['gres']['gre'] as $gre)
4113
                        if($gre['if'] == $interface)
4114
				$result[] = $gre;
4115
	}
4116

    
4117
	return $result;
4118
}
4119

    
4120
function link_interface_to_gif($interface) {
4121
        global $config;
4122

    
4123
	$result = array();
4124

    
4125
        if (is_array($config['gifs']['gif'])) {
4126
                foreach ($config['gifs']['gif'] as $gif)
4127
                        if($gif['if'] == $interface)
4128
                                $result[] = $gif;
4129
	}
4130

    
4131
	return $result;
4132
}
4133

    
4134
/*
4135
 * find_interface_ip($interface): return the interface ip (first found)
4136
 */
4137
function find_interface_ip($interface, $flush = false)
4138
{
4139
	global $interface_ip_arr_cache;
4140
	global $interface_sn_arr_cache;
4141

    
4142
	$interface = str_replace("\n", "", $interface);
4143
	
4144
	if (!does_interface_exist($interface))
4145
		return;
4146

    
4147
	/* Setup IP cache */
4148
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4149
		$ifinfo = pfSense_get_interface_addresses($interface);
4150
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4151
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4152
	}
4153

    
4154
	return $interface_ip_arr_cache[$interface];
4155
}
4156

    
4157
/*
4158
 * find_interface_ipv6($interface): return the interface ip (first found)
4159
 */
4160
function find_interface_ipv6($interface, $flush = false)
4161
{
4162
	global $interface_ipv6_arr_cache;
4163
	global $interface_snv6_arr_cache;
4164
	global $config;
4165
	
4166
	$interface = str_replace("\n", "", $interface);
4167
	
4168
	if (!does_interface_exist($interface))
4169
		return;
4170

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

    
4194
	return $interface_ipv6_arr_cache[$interface];
4195
}
4196

    
4197
/*
4198
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4199
 */
4200
function find_interface_ipv6_ll($interface, $flush = false)
4201
{
4202
	global $interface_llv6_arr_cache;
4203
	global $config;
4204
	
4205
	$interface = str_replace("\n", "", $interface);
4206
	
4207
	if (!does_interface_exist($interface))
4208
		return;
4209

    
4210
	/* Setup IP cache */
4211
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4212
		$ifinfo = pfSense_get_interface_addresses($interface);
4213
		// FIXME: Add IPv6 support to the pfSense module
4214
		exec("/sbin/ifconfig {$interface} inet6", $output);
4215
		foreach($output as $line) {
4216
			if(preg_match("/inet6/", $line)) {
4217
				$parts = explode(" ", $line);
4218
				if(preg_match("/fe80::/", $parts[1])) {
4219
					$partsaddress = explode("%", $parts[1]);
4220
					$ifinfo['linklocal'] = $partsaddress[0];
4221
				}
4222
			}
4223
		}
4224
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4225
	}
4226
	return $interface_llv6_arr_cache[$interface];
4227
}
4228

    
4229
function find_interface_subnet($interface, $flush = false)
4230
{
4231
	global $interface_sn_arr_cache;
4232
	global $interface_ip_arr_cache;
4233

    
4234
	$interface = str_replace("\n", "", $interface);
4235
	if (does_interface_exist($interface) == false)
4236
		return;
4237

    
4238
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4239
		$ifinfo = pfSense_get_interface_addresses($interface);
4240
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4241
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4242
        }
4243

    
4244
	return $interface_sn_arr_cache[$interface];
4245
}
4246

    
4247
function find_interface_subnetv6($interface, $flush = false)
4248
{
4249
	global $interface_snv6_arr_cache;
4250
	global $interface_ipv6_arr_cache;
4251

    
4252
	$interface = str_replace("\n", "", $interface);
4253
	if (does_interface_exist($interface) == false)
4254
		return;
4255

    
4256
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4257
		$ifinfo = pfSense_get_interface_addresses($interface);
4258
		// FIXME: Add IPv6 support to the pfSense module
4259
		exec("/sbin/ifconfig {$interface} inet6", $output);
4260
		foreach($output as $line) {
4261
			if(preg_match("/inet6/", $line)) {
4262
				$parts = explode(" ", $line);
4263
				if(! preg_match("/fe80::/", $parts[1])) {
4264
					$ifinfo['ipaddrv6'] = $parts[1];
4265
					if($parts[2] == "-->") {
4266
						$parts[5] = "126";
4267
						$ifinfo['subnetbitsv6'] = $parts[5];
4268
					} else {
4269
						$ifinfo['subnetbitsv6'] = $parts[3];
4270
					}
4271
				}
4272
			}
4273
		}
4274
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4275
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4276
        }
4277

    
4278
	return $interface_snv6_arr_cache[$interface];
4279
}
4280

    
4281
function ip_in_interface_alias_subnet($interface, $ipalias) {
4282
	global $config;
4283

    
4284
	if (empty($interface) || !is_ipaddr($ipalias))
4285
		return false;
4286
	if (is_array($config['virtualip']['vip'])) {
4287
                foreach ($config['virtualip']['vip'] as $vip) {
4288
                        switch ($vip['mode']) {
4289
                        case "ipalias":
4290
                                if ($vip['interface'] <> $interface)
4291
                                        break;
4292
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4293
					return true;
4294
                                break;
4295
                        }
4296
                }
4297
	}
4298

    
4299
	return false;
4300
}
4301

    
4302
function get_interface_ip($interface = "wan")
4303
{
4304
	$realif = get_real_interface($interface);
4305
	if (!$realif) {
4306
		if (preg_match("/^carp/i", $interface))
4307
			$realif = $interface;
4308
		else if (preg_match("/^vip/i", $interface))
4309
			$realif = $interface;
4310
		else
4311
			return null;
4312
	}
4313

    
4314
	$curip = find_interface_ip($realif);
4315
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4316
		return $curip;
4317
	else
4318
		return null;
4319
}
4320

    
4321
function get_interface_ipv6($interface = "wan")
4322
{
4323
	global $config;
4324
	$realif = get_real_interface($interface);
4325
	switch($config['interfaces'][$interface]['ipaddrv6']) {
4326
		case "6rd":
4327
		case "6to4":
4328
			$realif = "stf0";
4329
			break;
4330
	}
4331
	if (!$realif) {
4332
		if (preg_match("/^carp/i", $interface))
4333
			$realif = $interface;
4334
		else if (preg_match("/^vip/i", $interface))
4335
			$realif = $interface;
4336
		else
4337
			return null;
4338
	}
4339

    
4340
	$curip = find_interface_ipv6($realif);
4341
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4342
		return $curip;
4343
	else
4344
		return null;
4345
}
4346

    
4347
function get_interface_linklocal($interface = "wan")
4348
{
4349
	$realif = get_real_interface($interface);
4350
	if (!$realif) {
4351
		if (preg_match("/^carp/i", $interface))
4352
			$realif = $interface;
4353
		else if (preg_match("/^vip/i", $interface))
4354
			$realif = $interface;
4355
		else
4356
			return null;
4357
	}
4358

    
4359
	$curip = find_interface_ipv6_ll($realif);
4360
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4361
		return $curip;
4362
	else
4363
		return null;
4364
}
4365

    
4366
function get_interface_subnet($interface = "wan")
4367
{
4368
	$realif = get_real_interface($interface);
4369
	if (!$realif) {
4370
                if (preg_match("/^carp/i", $interface))
4371
                        $realif = $interface;
4372
                else if (preg_match("/^vip/i", $interface))
4373
                        $realif = $interface;
4374
                else
4375
                        return null;
4376
        }
4377

    
4378
	$cursn = find_interface_subnet($realif);
4379
	if (!empty($cursn))
4380
		return $cursn;
4381

    
4382
	return null;
4383
}
4384

    
4385
function get_interface_subnetv6($interface = "wan")
4386
{
4387
	$realif = get_real_interface($interface);
4388
	if (!$realif) {
4389
                if (preg_match("/^carp/i", $interface))
4390
                        $realif = $interface;
4391
                else if (preg_match("/^vip/i", $interface))
4392
                        $realif = $interface;
4393
                else
4394
                        return null;
4395
        }
4396

    
4397
	$cursn = find_interface_subnetv6($realif);
4398
	if (!empty($cursn))
4399
		return $cursn;
4400

    
4401
	return null;
4402
}
4403

    
4404
/* return outside interfaces with a gateway */
4405
function get_interfaces_with_gateway() {
4406
	global $config;
4407

    
4408
	$ints = array();
4409

    
4410
	/* loop interfaces, check config for outbound */
4411
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4412
		switch ($ifname['ipaddr']) {
4413
			case "dhcp":
4414
			case "carpdev-dhcp":
4415
			case "ppp";
4416
			case "pppoe":
4417
			case "pptp":
4418
			case "l2tp":
4419
			case "ppp";
4420
				$ints[$ifdescr] = $ifdescr;
4421
			break;
4422
			default:
4423
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
4424
				    !empty($ifname['gateway']))
4425
					$ints[$ifdescr] = $ifdescr;
4426
			break;
4427
		}
4428
	}
4429
	return $ints;
4430
}
4431

    
4432
/* return true if interface has a gateway */
4433
function interface_has_gateway($friendly) {
4434
	global $config;
4435

    
4436
	if (!empty($config['interfaces'][$friendly])) {
4437
		$ifname = &$config['interfaces'][$friendly];
4438
		switch ($ifname['ipaddr']) {
4439
			case "dhcp":
4440
			case "carpdev-dhcp":
4441
			case "pppoe":
4442
			case "pptp":
4443
			case "l2tp":
4444
			case "ppp";
4445
				return true;
4446
			break;
4447
			default:
4448
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
4449
					return true;
4450
				if (!empty($ifname['gateway']))
4451
					return true;
4452
			break;
4453
		}
4454
	}
4455

    
4456
	return false;
4457
}
4458

    
4459
/* return true if interface has a gateway */
4460
function interface_has_gatewayv6($friendly) {
4461
	global $config;
4462

    
4463
	if (!empty($config['interfaces'][$friendly])) {
4464
		$ifname = &$config['interfaces'][$friendly];
4465
		switch ($ifname['ipaddrv6']) {
4466
			case "slaac":
4467
			case "dhcp6":
4468
				return true;
4469
				break;
4470
			case "6to4":
4471
				return true;
4472
				break;
4473
			case "6rd":
4474
				return true;
4475
				break;
4476
			default:
4477
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
4478
					return true;
4479
				if (!empty($ifname['gatewayv6']))
4480
					return true;
4481
				break;
4482
		}
4483
	}
4484

    
4485
	return false;
4486
}
4487

    
4488
/****f* interfaces/is_altq_capable
4489
 * NAME
4490
 *   is_altq_capable - Test if interface is capable of using ALTQ
4491
 * INPUTS
4492
 *   $int            - string containing interface name
4493
 * RESULT
4494
 *   boolean         - true or false
4495
 ******/
4496

    
4497
function is_altq_capable($int) {
4498
        /* Per:
4499
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
4500
         * Only the following drivers have ALTQ support
4501
         */
4502
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
4503
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
4504
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
4505
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
4506
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
4507
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
4508
			"l2tp", "ppp");
4509

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

    
4512
        if (in_array($int_family[0], $capable))
4513
                return true;
4514
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4515
		return true;
4516
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4517
		return true;
4518
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4519
		return true;
4520
        else
4521
                return false;
4522
}
4523

    
4524
/****f* interfaces/is_interface_wireless
4525
 * NAME
4526
 *   is_interface_wireless - Returns if an interface is wireless
4527
 * RESULT
4528
 *   $tmp       - Returns if an interface is wireless
4529
 ******/
4530
function is_interface_wireless($interface) {
4531
        global $config, $g;
4532

    
4533
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
4534
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
4535
                if (preg_match($g['wireless_regex'], $interface)) {
4536
                        if (isset($config['interfaces'][$friendly]))
4537
                                $config['interfaces'][$friendly]['wireless'] = array();
4538
                        return true;
4539
                }
4540
                return false;
4541
        } else
4542
                return true;
4543
}
4544

    
4545
function get_wireless_modes($interface) {
4546
	/* return wireless modes and channels */
4547
	$wireless_modes = array();
4548

    
4549
	$cloned_interface = get_real_interface($interface);
4550

    
4551
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4552
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4553
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4554
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4555

    
4556
		$interface_channels = "";
4557
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4558
		$interface_channel_count = count($interface_channels);
4559

    
4560
		$c = 0;
4561
		while ($c < $interface_channel_count)
4562
		{
4563
			$channel_line = explode(",", $interface_channels["$c"]);
4564
			$wireless_mode = trim($channel_line[0]);
4565
			$wireless_channel = trim($channel_line[1]);
4566
			if(trim($wireless_mode) != "") {
4567
				/* if we only have 11g also set 11b channels */
4568
				if($wireless_mode == "11g") {
4569
					if(!isset($wireless_modes["11b"]))
4570
						$wireless_modes["11b"] = array();
4571
				} else if($wireless_mode == "11g ht") {
4572
					if(!isset($wireless_modes["11b"]))
4573
						$wireless_modes["11b"] = array();
4574
					if(!isset($wireless_modes["11g"]))
4575
						$wireless_modes["11g"] = array();
4576
					$wireless_mode = "11ng";
4577
				} else if($wireless_mode == "11a ht") {
4578
					if(!isset($wireless_modes["11a"]))
4579
						$wireless_modes["11a"] = array();
4580
					$wireless_mode = "11na";
4581
				}
4582
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4583
			}
4584
			$c++;
4585
		}
4586
	}
4587
	return($wireless_modes);
4588
}
4589

    
4590
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4591
function get_wireless_channel_info($interface) {
4592
	$wireless_channels = array();
4593

    
4594
	$cloned_interface = get_real_interface($interface);
4595

    
4596
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4597
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4598
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4599
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4600

    
4601
		$interface_channels = "";
4602
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4603

    
4604
		foreach ($interface_channels as $channel_line) {
4605
			$channel_line = explode(",", $channel_line);
4606
			if(!isset($wireless_channels[$channel_line[0]]))
4607
				$wireless_channels[$channel_line[0]] = $channel_line;
4608
		}
4609
	}
4610
	return($wireless_channels);
4611
}
4612

    
4613
/****f* interfaces/get_interface_mtu
4614
 * NAME
4615
 *   get_interface_mtu - Return the mtu of an interface
4616
 * RESULT
4617
 *   $tmp       - Returns the mtu of an interface
4618
 ******/
4619
function get_interface_mtu($interface) {
4620
        $mtu = pfSense_get_interface_addresses($interface);
4621
        return $mtu['mtu'];
4622
}
4623

    
4624
function get_interface_mac($interface) {
4625

    
4626
	$macinfo = pfSense_get_interface_addresses($interface);
4627
	return $macinfo["macaddr"];
4628
}
4629

    
4630
/****f* pfsense-utils/generate_random_mac_address
4631
 * NAME
4632
 *   generate_random_mac - generates a random mac address
4633
 * INPUTS
4634
 *   none
4635
 * RESULT
4636
 *   $mac - a random mac address
4637
 ******/
4638
function generate_random_mac_address() {
4639
        $mac = "02";
4640
        for($x=0; $x<5; $x++)
4641
                $mac .= ":" . dechex(rand(16, 255));
4642
        return $mac;
4643
}
4644

    
4645
/****f* interfaces/is_jumbo_capable
4646
 * NAME
4647
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4648
 * INPUTS
4649
 *   $int             - string containing interface name
4650
 * RESULT
4651
 *   boolean          - true or false
4652
 ******/
4653
function is_jumbo_capable($iface) {
4654

    
4655

    
4656
	$iface = trim($iface);
4657
	$capable = pfSense_get_interface_addresses($iface);
4658
	if (isset($capable['caps']['vlanmtu']))
4659
                return true;
4660

    
4661

    
4662

    
4663

    
4664

    
4665
	return false;
4666
}
4667

    
4668
function setup_pppoe_reset_file($pppif, $iface="") {
4669
	global $g;
4670
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4671

    
4672
	if(!empty($iface) && !empty($pppif)){
4673
		$cron_cmd = <<<EOD
4674
#!/bin/sh
4675
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4676
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
4677

    
4678
EOD;
4679

    
4680
		file_put_contents($cron_file, $cron_cmd);
4681
		chmod($cron_file, 0700);
4682
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4683
	} else
4684
		unlink_if_exists($cron_file);
4685
}
4686

    
4687
function get_interface_default_mtu($type = "ethernet") {
4688
	switch ($type) {
4689
	case "gre":
4690
		return 1476;
4691
		break;
4692
	case "gif":
4693
		return 1280;
4694
		break;
4695
	case "tun":
4696
	case "vlan":
4697
	case "tap":
4698
	case "ethernet":
4699
	default:
4700
		return 1500;
4701
		break;
4702
	}
4703

    
4704
	/* Never reached */
4705
	return 1500;
4706
}
4707

    
4708
function get_vip_descr($ipaddress) {
4709
	global $config;
4710

    
4711
	foreach ($config['virtualip']['vip'] as $vip) {
4712
		if ($vip['subnet'] == $ipaddress) {
4713
			return ($vip['descr']);
4714
		}
4715
	}
4716
	return "";
4717
}
4718

    
4719
function interfaces_staticarp_configure($if) {
4720
	global $config, $g;
4721
	if(isset($config['system']['developerspew'])) {
4722
		$mt = microtime();
4723
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4724
	}
4725

    
4726
	$ifcfg = $config['interfaces'][$if];
4727

    
4728
	if (empty($if) || empty($ifcfg['if']))
4729
		return 0;
4730

    
4731
	/* Enable staticarp, if enabled */
4732
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4733
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4734
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4735
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4736

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

    
4740
			}
4741

    
4742
		}
4743
	} else {
4744
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4745
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4746
	}
4747

    
4748
	return 0;
4749
}
4750

    
4751
?>
(26-26/65)