Project

General

Profile

Download (127 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

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

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

    
64
        /* If the cache doesn't exist, build it */
65
        if (!isset($interface_arr_cache) or $flush)
66
                $interface_arr_cache = explode(" ", trim(`/sbin/ifconfig -l`));
67

    
68
        return $interface_arr_cache;
69
}
70

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

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

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

    
98

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

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

    
125
	return false;
126
}
127

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

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

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

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

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

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

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

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

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

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

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

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

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

    
268
	interfaces_bring_up($vlanif);
269

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

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

    
276
	return $vlanif;
277
}
278

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

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

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

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

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

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

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

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

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

    
346
        return $vlanif;
347
}
348

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

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

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

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

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

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

    
389
        return $vlanif;
390
}
391

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

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

    
412
}
413

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

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

    
433
function interface_bridge_configure(&$bridge) {
434
	global $config, $g;
435

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

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

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

    
448
	$checklist = get_configured_interface_list();
449

    
450
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
451
		pfSense_interface_destroy($bridge['bridgeif']);
452
		pfSense_interface_create($bridge['bridgeif']);
453
		$bridgeif = $bridge['bridgeif'];
454
	} else
455
		$bridgeif = pfSense_interface_create("bridge");
456

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

    
487
	$flags = 0;
488
	if ($commonrx === false)
489
		$flags |= IFCAP_RXCSUM;
490
	if ($commontx === false)
491
		$flags |= IFCAP_TXCSUM;
492
	if ($commontso4 === false)
493
		$flags |= IFCAP_TSO4;
494
	if ($commontso6 === false)
495
		$flags |= IFCAP_TSO6;
496
	if ($commonlro === false)
497
		$flags |= IFCAP_LRO;
498
		
499
	/* Add interfaces to bridge */
500
	foreach ($members as $member) {
501
		if (!array_key_exists($member, $checklist))
502
			continue;
503
		$realif1 = get_real_interface($member);
504
		$realif =  escapeshellarg($realif1);
505
		if (!$realif) {
506
			log_error(gettext("realif not defined in interfaces bridge - up"));
507
			continue;
508
		}
509
		/* make sure the parent interface is up */
510
		pfSense_interface_mtu($realif1, $smallermtu);
511
		pfSense_interface_capabilities($realif1, -$flags);
512
		interfaces_bring_up($realif1);
513
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
514
	}
515

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

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

    
616
	if($bridgeif)
617
		interfaces_bring_up($bridgeif);	
618
	else 
619
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
620

    
621
	return $bridgeif;
622
}
623

    
624
function interface_bridge_add_member($bridgeif, $interface) {
625

    
626
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
627
		return;
628

    
629
	$mtu = get_interface_mtu($brigeif);
630
	$mtum = get_interface_mtu($interface);
631
	
632
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
633
		pfSense_interface_mtu($interface, $mtu);
634

    
635
	$options = pfSense_get_interface_addresses($bridgeif);
636
	$flags = 0;
637
	if (!isset($options['encaps']['txcsum']))
638
		$flags |= IFCAP_TXCSUM;
639

    
640
	if (!isset($options['encaps']['rxcsum']))
641
		$flags |= IFCAP_RXCSUM;
642

    
643
	pfSense_interface_capabilities($interface, -$flags);
644

    
645
	interfaces_bring_up($interface);
646
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
647
}
648

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

    
668
function interface_lagg_configure(&$lagg) {
669
        global $config, $g;
670

    
671
        if (!is_array($lagg))
672
		return -1;
673

    
674
	$members = explode(',', $lagg['members']);
675
	if (!count($members))
676
		return -1;
677
	
678
	$checklist = get_interface_list();
679

    
680
	if ($g['booting'] || !(empty($lagg['laggif']))) {
681
		pfSense_interface_destroy($lagg['laggif']);
682
		pfSense_interface_create($lagg['laggif']);
683
                $laggif = $lagg['laggif'];
684
        } else
685
		$laggif = pfSense_interface_create("lagg");
686

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

    
708
	/* Just in case anything is not working well */
709
        if ($smallermtu == 0)
710
                $smallermtu = 1500;
711

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

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

    
736
	interfaces_bring_up($laggif);
737

    
738
	return $laggif;
739
}
740

    
741
function interfaces_gre_configure($checkparent = 0) {
742
        global $config;
743

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

    
758
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
759
function interface_gre_configure(&$gre, $grekey = "") {
760
        global $config, $g;
761

    
762
	if (!is_array($gre))
763
		return -1;
764

    
765
	$realif = get_real_interface($gre['if']);
766
	$realifip = get_interface_ip($gre['if']);
767

    
768
	/* make sure the parent interface is up */
769
	interfaces_bring_up($realif);
770

    
771
	if ($g['booting'] || !(empty($gre['greif']))) {
772
		pfSense_interface_destroy($gre['greif']);
773
		pfSense_interface_create($gre['greif']);
774
		$greif = $gre['greif'];
775
	} else
776
		$greif = pfSense_interface_create("gre");
777

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

    
792
	if($greif)
793
		interfaces_bring_up($greif);
794
	else 
795
		log_error(gettext("Could not bring greif up -- variable not defined."));
796

    
797
	if (isset($gre['link1']) && $gre['link1'])
798
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
799
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
800
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
801
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
802
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
803

    
804
	return $greif;
805
}
806

    
807
function interfaces_gif_configure($checkparent = 0) {
808
	global $config;
809

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

    
824
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
825
function interface_gif_configure(&$gif, $gifkey = "") {
826
	global $config, $g;
827

    
828
	if (!is_array($gif))
829
		return -1;
830

    
831
	$realif = get_real_interface($gif['if']);
832
	$realifip = get_interface_ip($gif['if']);
833

    
834
	/* make sure the parent interface is up */
835
	if($realif)
836
		interfaces_bring_up($realif);
837
	else 
838
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
839

    
840
	if ($g['booting'] || !(empty($gif['gifif']))) {
841
		pfSense_interface_destroy($gif['gifif']);
842
		pfSense_interface_create($gif['gifif']);
843
		$gifif = $gif['gifif'];
844
	} else
845
		$gifif = pfSense_interface_create("gif");
846

    
847
	/* Do not change the order here for more see gif(4) NOTES section. */
848
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
849
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
850
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen /{$gif['tunnel-remote-net']} ");
851
	} else {
852
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
853
	}
854
	if (isset($gif['link0']) && $gif['link0'])
855
		pfSense_interface_flags($gifif, IFF_LINK0);
856
	if (isset($gif['link1']) && $gif['link1'])
857
		pfSense_interface_flags($gifif, IFF_LINK1);
858
	if($gifif)
859
		interfaces_bring_up($gifif);
860
	else
861
		log_error(gettext("could not bring gifif up -- variable not defined"));
862

    
863
	$iflist = get_configured_interface_list();
864
	foreach($iflist as $ifname) {
865
		if($config['interfaces'][$ifname]['if'] == $gifif) {
866
			if(get_interface_gateway($ifname)) {
867
				system_routing_configure($ifname);
868
				break;
869
			}
870
			if(get_interface_gateway_v6($ifname)) {
871
				system_routing_configure($ifname);
872
				break;
873
			}
874
		}
875
	}
876

    
877

    
878
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
879
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
880
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
881
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
882

    
883
	return $gifif;
884
}
885

    
886
function interfaces_configure() {
887
	global $config, $g;
888

    
889
	if ($g['platform'] == 'jail')
890
		return;
891

    
892
	/* Set up our loopback interface */
893
	interfaces_loopback_configure();
894

    
895
	/* set up LAGG virtual interfaces */
896
	interfaces_lagg_configure();
897

    
898
	/* set up VLAN virtual interfaces */
899
	interfaces_vlan_configure();
900

    
901
	interfaces_qinq_configure();
902

    
903
	$iflist = get_configured_interface_with_descr();
904
	$delayed_list = array();
905
	$bridge_list = array();
906
	
907
	/* This is needed to speedup interfaces on bootup. */
908
	$reload = false;
909
	if ($g['booting'])
910
		$reload = true;
911

    
912
	foreach($iflist as $if => $ifname) {
913
		$realif = $config['interfaces'][$if]['if'];
914
		if (strstr($realif, "bridge")) 
915
			$bridge_list[$if] = $ifname;
916
		else if (strstr($realif, "gre"))
917
			$delayed_list[$if] = $ifname;
918
		else if (strstr($realif, "gif"))
919
			$delayed_list[$if] = $ifname;
920
		else if (strstr($realif, "ovpn")) {
921
			//echo "Delaying OpenVPN interface configuration...done.\n";
922
			continue;
923
		} else {
924
			if ($g['booting'])
925
				printf(gettext("Configuring %s interface..."), $ifname);
926

    
927
			if($g['debug'])
928
				log_error(sprintf(gettext("Configuring %s"), $ifname));
929
			interface_configure($if, $reload);
930
			if ($g['booting']) 
931
				echo gettext( "done.") . "\n";
932
		}
933
	}
934

    
935
	/* create the unconfigured wireless clones */
936
	interfaces_create_wireless_clones();
937

    
938
	/*
939
	 * NOTE: The following function parameter consists of
940
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
941
	 *	2 - Do load gre/gif/bridge with parent/member as vip
942
	 */
943

    
944
	/* set up GRE virtual interfaces */
945
	interfaces_gre_configure(1);
946

    
947
	/* set up GIF virtual interfaces */
948
	interfaces_gif_configure(1);
949

    
950
	/* set up BRIDGe virtual interfaces */
951
	interfaces_bridge_configure(1);
952

    
953
	/* bring up vip interfaces */
954
	interfaces_vips_configure();
955

    
956
	/* set up GRE virtual interfaces */
957
	interfaces_gre_configure(2);
958

    
959
	/* set up GIF virtual interfaces */
960
	interfaces_gif_configure(2);
961

    
962
	foreach ($delayed_list as $if => $ifname) {
963
		if ($g['booting'])
964
			printf(gettext("Configuring %s interface..."), $ifname);
965
        	if ($g['debug'])
966
        		log_error(sprintf(gettext("Configuring %s"), $ifname));
967

    
968
		interface_configure($if, $reload);
969

    
970
		if ($g['booting'])
971
			echo gettext("done.") . "\n";
972
	}
973

    
974
	/* set up BRIDGe virtual interfaces */
975
	interfaces_bridge_configure(2);
976

    
977
	foreach ($bridge_list as $if => $ifname) {
978
		if ($g['booting'])
979
			printf(gettext("Configuring %s interface..."), $ifname);
980
		if($g['debug'])
981
			log_error(sprintf(gettext("Configuring %s"), $ifname));
982

    
983
		interface_configure($if, $reload);
984

    
985
		if ($g['booting'])
986
			echo gettext("done.") . "\n";
987
	}
988

    
989
	/* configure interface groups */
990
	interfaces_group_setup();
991

    
992
	if (!$g['booting']) {
993
		/* reconfigure static routes (kernel may have deleted them) */
994
		system_routing_configure();
995

    
996
		/* reload IPsec tunnels */
997
		vpn_ipsec_configure();
998

    
999
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1000
		services_dhcpd_configure();
1001

    
1002
		/* restart dnsmasq */
1003
		services_dnsmasq_configure();
1004

    
1005
		/* reload captive portal */
1006
		captiveportal_init_rules();
1007
	}
1008

    
1009
	return 0;
1010
}
1011

    
1012
function interface_reconfigure($interface = "wan", $reloadall = false) {
1013
	interface_bring_down($interface);
1014
	interface_configure($interface, $reloadall);
1015
}
1016

    
1017
function interface_vip_bring_down($vip) {
1018
	global $g;
1019

    
1020
	switch ($vip['mode']) {
1021
	case "proxyarp":
1022
		$vipif = get_real_interface($vip['interface']);
1023
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1024
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1025
		break;
1026
	case "ipalias":
1027
		$vipif = get_real_interface($vip['interface']);
1028
		if(does_interface_exist($vipif))
1029
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1030
		break;
1031
	case "carp":
1032
		$vipif = "vip" . $vip['vhid'];
1033
		if(does_interface_exist($vipif)) 
1034
			pfSense_interface_destroy($vipif);
1035
		break;
1036
	case "carpdev-dhcp":
1037
		$vipif = "vip" . $vip['vhid'];
1038
		if(does_interface_exist($vipif)) 
1039
			pfSense_interface_destroy($vipif);
1040
		break;
1041
	}
1042
}
1043

    
1044
function interface_bring_down($interface = "wan", $destroy = false) {
1045
	global $config, $g;
1046

    
1047
	if (!isset($config['interfaces'][$interface]))
1048
		return; 
1049

    
1050
	log_error("Calling interface down for interface {$interface}, destroy is {$destroy}");
1051

    
1052
	$ifcfg = $config['interfaces'][$interface];
1053

    
1054
	$realif = get_real_interface($interface);
1055

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

    
1106
	switch ($ifcfg['ipaddrv6']) {
1107
	case "dhcp6":
1108
		$pidv6 = find_dhcp6c_process($realif);
1109
		if($pidv6)
1110
			mwexec("/bin/kill {$pidv6}");
1111
		sleep(1);
1112
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1113
		if(does_interface_exist("$realif")) {
1114
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1115
			if ($destroy == true)
1116
				pfSense_interface_flags($realif, -IFF_UP);
1117
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1118
		}
1119
		break;
1120
	default:
1121
		if(does_interface_exist("$realif")) {
1122
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1123
			if ($destroy == true)
1124
				pfSense_interface_flags($realif, -IFF_UP);
1125
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1126
		}
1127
		break;
1128
	}
1129

    
1130

    
1131
	/* remove interface up file if it exists */
1132
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1133
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1134
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1135
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1136
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1137
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1138
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1139
	
1140
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1141
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1142
	if (is_array($ifcfg['wireless'])) {
1143
		mwexec(kill_hostapd($realif));
1144
		mwexec(kill_wpasupplicant($realif));
1145
	}
1146

    
1147
	if ($destroy == true) {
1148
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1149
			pfSense_interface_destroy($realif);
1150
	}	
1151

    
1152
	return;
1153
}
1154

    
1155
function interfaces_ptpid_used($ptpid) {
1156
	global $config;
1157

    
1158
	if (is_array($config['ppps']['ppp']))
1159
		foreach ($config['ppps']['ppp'] as & $settings)
1160
			if ($ptpid == $settings['ptpid'])
1161
				return true;
1162

    
1163
	return false;
1164
}
1165

    
1166
function interfaces_ptpid_next() {
1167

    
1168
	$ptpid = 0;
1169
	while(interfaces_ptpid_used($ptpid))
1170
		$ptpid++;
1171

    
1172
	return $ptpid;
1173
}
1174

    
1175
function getMPDCRONSettings($pppif_) {
1176
	global $config;
1177
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1178
	if (is_array($config['cron']['item'])) {
1179
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1180
			$item = $config['cron']['item'][$i];
1181
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1182
				return array("ID" => $i, "ITEM" => $item);
1183
			}
1184
		}
1185
	}
1186
	return NULL;
1187
}
1188

    
1189
function handle_pppoe_reset($post_array) {
1190
	global $config, $g;
1191

    
1192
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1193

    
1194
	$pppif = $post_array['type'].$post_array['ptpid'];
1195
	if (!is_array($config['cron']['item'])) 
1196
		$config['cron']['item'] = array(); 
1197
	$itemhash = getMPDCRONSettings($pppif);
1198
	$item = $itemhash['ITEM'];
1199
	
1200
	// reset cron items if necessary and return
1201
	if (empty($post_array['pppoe-reset-type'])) {
1202
		if (isset($item))
1203
			unset($config['cron']['item'][$itemhash['ID']]);
1204
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1205
		return;
1206
	}
1207

    
1208
	if (empty($item)) 
1209
		$item = array();
1210
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1211
		$item['minute'] = $post_array['pppoe_resetminute'];
1212
		$item['hour'] = $post_array['pppoe_resethour'];
1213
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1214
			$date = explode("/", $post_array['pppoe_resetdate']);
1215
			$item['mday'] = $date[1];
1216
			$item['month'] = $date[0];
1217
		} else {
1218
			$item['mday'] = "*";
1219
			$item['month'] = "*";
1220
		}
1221
		$item['wday'] = "*";
1222
		$item['who'] = "root";
1223
		$item['command'] = $cron_cmd_file.$pppif;
1224
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1225
		switch ($post_array['pppoe_pr_preset_val']) {
1226
			case "monthly":
1227
				$item['minute'] = "0";
1228
				$item['hour'] = "0";
1229
				$item['mday'] = "1";
1230
				$item['month'] = "*";
1231
				$item['wday'] = "*";
1232
				$item['who'] = "root";
1233
				$item['command'] = $cron_cmd_file.$pppif;
1234
				break;
1235
	        case "weekly":
1236
				$item['minute'] = "0";
1237
				$item['hour'] = "0";
1238
				$item['mday'] = "*";
1239
				$item['month'] = "*";
1240
				$item['wday'] = "0";
1241
				$item['who'] = "root";
1242
				$item['command'] = $cron_cmd_file.$pppif;
1243
				break;
1244
			case "daily":
1245
				$item['minute'] = "0";
1246
				$item['hour'] = "0";
1247
				$item['mday'] = "*";
1248
				$item['month'] = "*";
1249
				$item['wday'] = "*";
1250
				$item['who'] = "root";
1251
				$item['command'] = $cron_cmd_file.$pppif;
1252
				break;
1253
			case "hourly":
1254
				$item['minute'] = "0";
1255
				$item['hour'] = "*";
1256
				$item['mday'] = "*";
1257
				$item['month'] = "*";
1258
				$item['wday'] = "*";
1259
				$item['who'] = "root";
1260
				$item['command'] = $cron_cmd_file.$pppif;
1261
				break;
1262
		} // end switch
1263
	} else {
1264
		/* test whether a cron item exists and unset() it if necessary */
1265
		$itemhash = getMPDCRONSettings($pppif);
1266
		$item = $itemhash['ITEM'];
1267
		if (isset($item))
1268
			unset($config['cron']['item'][$itemhash['ID']]); 
1269
	}// end if
1270
	if (isset($itemhash['ID'])) 
1271
		$config['cron']['item'][$itemhash['ID']] = $item;
1272
	else 
1273
		$config['cron']['item'][] = $item;
1274
}
1275

    
1276
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1277
*	It writes the mpd config file to /var/etc every time the link is opened.
1278
*/
1279

    
1280
function interface_ppps_configure($interface) {
1281
	global $config, $g;
1282

    
1283
	/* Return for unassigned interfaces. This is a minimum requirement. */
1284
	if (empty($config['interfaces'][$interface]))
1285
		return 0;
1286
	$ifcfg = $config['interfaces'][$interface];
1287
	if (!isset($ifcfg['enable']))
1288
		return 0;
1289

    
1290
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1291
	if(!is_dir("/var/spool/lock")) {
1292
		exec("/bin/mkdir -p /var/spool/lock");
1293
		exec("/bin/chmod a+rw /var/spool/lock/.");
1294
	}
1295
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1296
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1297
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1298

    
1299
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1300
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1301
			if ($ifcfg['if'] == $ppp['if'])
1302
				break;
1303
		}
1304
	}
1305
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1306
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1307
		return 0;
1308
	}
1309
	$pppif = $ifcfg['if'];
1310
	if ($ppp['type'] == "ppp")
1311
		$type = "modem";
1312
	else
1313
		$type = $ppp['type'];
1314
	$upper_type = strtoupper($ppp['type']);	
1315

    
1316
	if($g['booting']) {
1317
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1318
		echo "starting {$pppif} link...";
1319
		// Do not re-configure the interface if we are booting and it's already been started
1320
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1321
			return 0;
1322
	}
1323

    
1324
	$ports = explode(',',$ppp['ports']);
1325
	if ($type != "modem") {
1326
		foreach ($ports as $pid => $port)
1327
			$ports[$pid] = get_real_interface($port);
1328
	}
1329
	$localips = explode(',',$ppp['localip']);
1330
	$gateways = explode(',',$ppp['gateway']);
1331
	$subnets = explode(',',$ppp['subnet']);
1332

    
1333
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1334
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1335
	 */
1336
	foreach($ports as $pid => $port){
1337
		switch ($ppp['type']) {
1338
			case "pppoe": 
1339
				/* Bring the parent interface up */
1340
				interfaces_bring_up($port);
1341
				pfSense_ngctl_attach(".", $port);
1342
				break;
1343
			case "pptp":
1344
			case "l2tp":
1345
				/* configure interface */
1346
				if(is_ipaddr($localips[$pid])){
1347
					// Manually configure interface IP/subnet
1348
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1349
					interfaces_bring_up($port);
1350
				} else if (empty($localips[$pid]))
1351
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1352
				
1353
				if(!is_ipaddr($localips[$pid])){
1354
					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!");
1355
					$localips[$pid] = "0.0.0.0";
1356
				}
1357
				/* XXX: This needs to go away soon! [It's commented out!] */
1358
				/* Configure the gateway (remote IP ) */
1359
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1360
					/* XXX: Fix later 
1361
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1362
					if(!is_ipaddr($gateways[$pid])) {
1363
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1364
						return 0;
1365
					}
1366
					*/
1367
				}
1368
				if(!is_ipaddr($gateways[$pid])){
1369
					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));
1370
					return 0;
1371
				}
1372
				pfSense_ngctl_attach(".", $port);
1373
				break;
1374
			case "ppp":
1375
				if (!file_exists("{$port}")) {
1376
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1377
					return 0;
1378
				}
1379
				break;
1380
			default:
1381
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1382
				break;
1383
		}
1384
	}
1385
	
1386
	if (is_array($ports) && count($ports) > 1)
1387
		$multilink = "enable";
1388
	else
1389
		$multilink = "disable";
1390
	
1391
	if ($type == "modem"){
1392
		if (is_ipaddr($ppp['localip']))
1393
			$localip = $ppp['localip'];
1394
		else
1395
			$localip = '0.0.0.0';
1396

    
1397
		if (is_ipaddr($ppp['gateway']))
1398
			$gateway = $ppp['gateway'];
1399
		else
1400
			$gateway = "10.64.64.{$pppid}";
1401
		$ranges = "{$localip}/0 {$gateway}/0";
1402
		
1403
		if (empty($ppp['apnum']))	
1404
			$ppp['apnum'] = 1;
1405
	} else
1406
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1407

    
1408
	if (isset($ppp['ondemand'])) 
1409
		$ondemand = "enable";
1410
	else
1411
		$ondemand = "disable";
1412
	if (!isset($ppp['idletimeout']))
1413
		$ppp['idletimeout'] = 0;
1414

    
1415
	if (empty($ppp['username']) && $type == "modem"){
1416
		$ppp['username'] = "user";
1417
		$ppp['password'] = "none";
1418
	}
1419
	if (empty($ppp['password']) && $type == "modem")
1420
		$passwd = "none";
1421
	else
1422
		$passwd = base64_decode($ppp['password']);
1423

    
1424
	$bandwidths = explode(',',$ppp['bandwidth']);
1425
	$mtus = explode(',',$ppp['mtu']);
1426
	$mrus = explode(',',$ppp['mru']);
1427

    
1428
	if (isset($ppp['mrru']))
1429
		$mrrus = explode(',',$ppp['mrru']);
1430

    
1431
	// Construct the mpd.conf file
1432
	$mpdconf = <<<EOD
1433
startup:
1434
	# configure the console
1435
	set console close
1436
	# configure the web server
1437
	set web close
1438

    
1439
default:
1440
{$ppp['type']}client:
1441
	create bundle static {$interface}
1442
	set bundle enable ipv6cp
1443
	set iface name {$pppif}
1444

    
1445
EOD;
1446
	$setdefaultgw = false;
1447
	$founddefaultgw = false;
1448
	if (is_array($config['gateways']['gateway_item'])) {
1449
		foreach($config['gateways']['gateway_item'] as $gateway) {
1450
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1451
				$setdefaultgw = true;
1452
				break;
1453
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1454
				$founddefaultgw = true;
1455
				break;
1456
			}
1457
		}
1458
	}
1459
	
1460
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1461
		$setdefaultgw = true;
1462
		$mpdconf .= <<<EOD
1463
	set iface route default
1464

    
1465
EOD;
1466
	}
1467
	$mpdconf .= <<<EOD
1468
	set iface {$ondemand} on-demand
1469
	set iface idle {$ppp['idletimeout']}
1470

    
1471
EOD;
1472

    
1473
	if (isset($ppp['ondemand']))
1474
		$mpdconf .= <<<EOD
1475
	set iface addrs 10.10.1.1 10.10.1.2
1476

    
1477
EOD;
1478
	
1479
	if (isset($ppp['tcpmssfix']))
1480
		$tcpmss = "disable";
1481
	else
1482
		$tcpmss = "enable";
1483
		$mpdconf .= <<<EOD
1484
	set iface {$tcpmss} tcpmssfix
1485

    
1486
EOD;
1487

    
1488
	$mpdconf .= <<<EOD
1489
	set iface up-script /usr/local/sbin/ppp-linkup
1490
	set iface down-script /usr/local/sbin/ppp-linkdown
1491
	set ipcp ranges {$ranges}
1492

    
1493
EOD;
1494
	if (isset($ppp['vjcomp']))
1495
		$mpdconf .= <<<EOD
1496
	set ipcp no vjcomp
1497

    
1498
EOD;
1499

    
1500
	if (isset($config['system']['dnsallowoverride']))
1501
		$mpdconf .= <<<EOD
1502
	set ipcp enable req-pri-dns
1503
	set ipcp enable req-sec-dns
1504

    
1505
EOD;
1506
	if (!isset($ppp['verbose_log']))
1507
		$mpdconf .= <<<EOD
1508
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1509

    
1510
EOD;
1511
	foreach($ports as $pid => $port){
1512
		$port = get_real_interface($port);
1513
		$mpdconf .= <<<EOD
1514

    
1515
	create link static {$interface}_link{$pid} {$type}
1516
	set link action bundle {$interface}
1517
	set link {$multilink} multilink
1518
	set link keep-alive 10 60
1519
	set link max-redial 0
1520

    
1521
EOD;
1522
		if (isset($ppp['shortseq']))
1523
			$mpdconf .= <<<EOD
1524
	set link no shortseq
1525

    
1526
EOD;
1527

    
1528
		if (isset($ppp['acfcomp']))
1529
			$mpdconf .= <<<EOD
1530
	set link no acfcomp
1531

    
1532
EOD;
1533

    
1534
		if (isset($ppp['protocomp']))
1535
			$mpdconf .= <<<EOD
1536
	set link no protocomp
1537

    
1538
EOD;
1539

    
1540
		$mpdconf .= <<<EOD
1541
	set link disable chap pap
1542
	set link accept chap pap eap
1543
	set link disable incoming
1544

    
1545
EOD;
1546

    
1547

    
1548
		if (!empty($bandwidths[$pid]))
1549
			$mpdconf .= <<<EOD
1550
	set link bandwidth {$bandwidths[$pid]}
1551

    
1552
EOD;
1553

    
1554
		if (empty($mtus[$pid]))
1555
			$mtus[$pid] = "1492";
1556
			$mpdconf .= <<<EOD
1557
	set link mtu {$mtus[$pid]}
1558

    
1559
EOD;
1560

    
1561
		if (!empty($mrus[$pid]))
1562
			$mpdconf .= <<<EOD
1563
	set link mru {$mrus[$pid]}
1564

    
1565
EOD;
1566

    
1567
		if (!empty($mrrus[$pid]))
1568
			$mpdconf .= <<<EOD
1569
	set link mrru {$mrrus[$pid]}
1570

    
1571
EOD;
1572

    
1573
		$mpdconf .= <<<EOD
1574
	set auth authname "{$ppp['username']}"
1575
	set auth password {$passwd}
1576

    
1577
EOD;
1578
		if ($type == "modem") {
1579
			$mpdconf .= <<<EOD
1580
	set modem device {$ppp['ports']}
1581
	set modem script DialPeer
1582
	set modem idle-script Ringback
1583
	set modem watch -cd
1584
	set modem var \$DialPrefix "DT"
1585
	set modem var \$Telephone "{$ppp['phone']}"
1586

    
1587
EOD;
1588
		}
1589
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1590
			$mpdconf .= <<<EOD
1591
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1592

    
1593
EOD;
1594
		}
1595
		if (isset($ppp['initstr']) && $type == "modem") {
1596
			$initstr = base64_decode($ppp['initstr']);
1597
			$mpdconf .= <<<EOD
1598
	set modem var \$InitString "{$initstr}"
1599

    
1600
EOD;
1601
		}
1602
		if (isset($ppp['simpin']) && $type == "modem") {
1603
			$mpdconf .= <<<EOD
1604
	set modem var \$SimPin "{$ppp['simpin']}"
1605
	set modem var \$PinWait "{$ppp['pin-wait']}"
1606

    
1607
EOD;
1608
		}
1609
		if (isset($ppp['apn']) && $type == "modem") {
1610
			$mpdconf .= <<<EOD
1611
	set modem var \$APN "{$ppp['apn']}"
1612
	set modem var \$APNum "{$ppp['apnum']}"
1613

    
1614
EOD;
1615
		}
1616
		if ($type == "pppoe") {
1617
			// Send a null service name if none is set.
1618
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1619
			$mpdconf .= <<<EOD
1620
	set pppoe service "{$provider}"
1621

    
1622
EOD;
1623
		}
1624
		if ($type == "pppoe")
1625
			$mpdconf .= <<<EOD
1626
	set pppoe iface {$port}
1627

    
1628
EOD;
1629

    
1630
		if ($type == "pptp" || $type == "l2tp") {
1631
			$mpdconf .= <<<EOD
1632
	set {$type} self {$localips[$pid]}
1633
	set {$type} peer {$gateways[$pid]}
1634

    
1635
EOD;
1636
		}
1637
		
1638
		$mpdconf .= "\topen\r\n";
1639
	} //end foreach($port)
1640

    
1641

    
1642
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1643
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1644
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1645
	else {
1646
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1647
		if (!$fd) {
1648
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1649
			return 0;
1650
		}
1651
		// Write out mpd_ppp.conf
1652
		fwrite($fd, $mpdconf);
1653
		fclose($fd);
1654
	}
1655

    
1656
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1657
	if (isset($ppp['uptime'])) {
1658
		if (!file_exists("/conf/{$pppif}.log")) {
1659
			conf_mount_rw();
1660
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1661
			conf_mount_ro();
1662
		}
1663
	} else {
1664
		if (file_exists("/conf/{$pppif}.log")) {
1665
			conf_mount_rw();
1666
			mwexec("rm -f /conf/{$pppif}.log");
1667
			conf_mount_ro();
1668
		}
1669
	}
1670

    
1671
	/* fire up mpd */
1672
	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");
1673

    
1674
	// Check for PPPoE periodic reset request 
1675
	if ($type == "pppoe") {
1676
		if (isset($ppp['pppoe-reset-type']))
1677
			setup_pppoe_reset_file($ppp['if'], $interface);
1678
		else
1679
			setup_pppoe_reset_file($ppp['if']);
1680
	}
1681
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1682
	$i = 0;
1683
	while($i < 10) {
1684
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1685
		if($ret == 0)
1686
			break;
1687
		sleep(1);
1688
		$i++;
1689
	}
1690

    
1691
	return 1;
1692
}
1693

    
1694
function interfaces_carp_setup() {
1695
	global $g, $config;
1696

    
1697
	$balanacing = "";
1698
	$pfsyncinterface = "";
1699
	$pfsyncenabled = "";
1700
	if(isset($config['system']['developerspew'])) {
1701
		$mt = microtime();
1702
		echo "interfaces_carp_setup() being called $mt\n";
1703
	}
1704

    
1705
	// Prepare CmdCHAIN that will be used to execute commands.
1706
	$cmdchain = new CmdCHAIN();	
1707

    
1708
	if ($g['booting']) {
1709
		echo gettext("Configuring CARP settings...");
1710
		mute_kernel_msgs();
1711
	}
1712

    
1713
	/* suck in configuration items */
1714
	if($config['installedpackages']['carpsettings']) {
1715
		if($config['installedpackages']['carpsettings']['config']) {
1716
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1717
				$pfsyncenabled = $carp['pfsyncenabled'];
1718
				$balanacing = $carp['balancing'];
1719
				$pfsyncinterface = $carp['pfsyncinterface'];
1720
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1721
			}
1722
		}
1723
	} else {
1724
		unset($pfsyncinterface);
1725
		unset($balanacing);
1726
		unset($pfsyncenabled);
1727
	}
1728

    
1729
	if($balanacing) {
1730
		$cmdchain->add(gettext("Enable CARP ARP-balancing"), "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1731
		$cmdchain->add(gettext("Disallow CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=0", true);
1732
	} else
1733
		$cmdchain->add(gettext("Enable CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=1", true);		
1734

    
1735
	$cmdchain->add(gettext("Enable CARP logging"), "/sbin/sysctl net.inet.carp.log=1", true);
1736
	if (!empty($pfsyncinterface))
1737
		$carp_sync_int = get_real_interface($pfsyncinterface);
1738

    
1739
	if($g['booting']) {
1740
		/*    install rules to alllow pfsync to sync up during boot
1741
		 *    carp interfaces will remain down until the bootup sequence finishes
1742
		 */
1743
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1744
		if ($fd) {
1745
			fwrite($fd, "block quick proto carp \n");
1746
			fwrite($fd, "block quick proto pfsync \n");
1747
			fwrite($fd, "pass out quick from any to any keep state\n");
1748
			fclose($fd);
1749
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1750
		} else
1751
			log_error(gettext("Could not create rules.boot file!"));
1752
	}
1753

    
1754
	/* setup pfsync interface */
1755
	if($carp_sync_int and $pfsyncenabled) {
1756
		if (is_ipaddr($pfsyncpeerip))
1757
			$cmdchain->add(gettext("Bring up pfsync0 syncpeer"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1758
		else
1759
			$cmdchain->add(gettext("Bring up pfsync0 syncdev"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1760
	} else
1761
		$cmdchain->add(gettext("Bring up pfsync0"), "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1762

    
1763
	sleep(1);
1764

    
1765
	/* 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
1766
	 * for exiting sessions.
1767
	 */
1768
	$i = 0;
1769
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1770
		$i++;
1771
		sleep(1);
1772
	}
1773

    
1774
	if($config['virtualip']['vip'])
1775
		$cmdchain->add(gettext("Allow CARP."), "/sbin/sysctl net.inet.carp.allow=1", true);				
1776
	else
1777
		$cmdchain->add(gettext("Disallow CARP."), "/sbin/sysctl net.inet.carp.allow=0", true);		
1778
	
1779
	if($g['debug'])
1780
		$cmdchain->setdebug(); // optional for verbose logging
1781

    
1782
	$cmdchain->execute();
1783
	$cmdchain->clear();
1784

    
1785
	if ($g['booting']) {
1786
		unmute_kernel_msgs();
1787
		echo gettext("done.") . "\n";
1788
	}
1789
}
1790

    
1791
function interface_proxyarp_configure($interface = "") {
1792
	global $config, $g;
1793
	if(isset($config['system']['developerspew'])) {
1794
		$mt = microtime();
1795
		echo "interface_proxyarp_configure() being called $mt\n";
1796
	}
1797

    
1798
	/* kill any running choparp */
1799
	if (empty($interface))
1800
		killbyname("choparp");
1801
	else {
1802
		$vipif = get_real_interface($interface);
1803
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1804
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1805
	}
1806

    
1807
	$paa = array();
1808
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1809

    
1810
		/* group by interface */
1811
		foreach ($config['virtualip']['vip'] as $vipent) {
1812
			if ($vipent['mode'] === "proxyarp") {
1813
				if ($vipent['interface'])
1814
					$proxyif = $vipent['interface'];
1815
				else
1816
					$proxyif = "wan";
1817
				
1818
				if (!empty($interface) && $interface != $proxyif)
1819
					continue;
1820

    
1821
				if (!is_array($paa[$proxyif]))
1822
					$paa[$proxyif] = array();
1823

    
1824
				$paa[$proxyif][] = $vipent;
1825
			}
1826
		}
1827
	}
1828

    
1829
	if (!empty($interface)) {
1830
		if (is_array($paa[$interface])) {
1831
			$paaifip = get_interface_ip($interface);
1832
                        if (!is_ipaddr($paaifip))
1833
                                return;
1834
                        $args = get_real_interface($interface) . " auto";
1835
                        foreach ($paa[$interface] as $paent) {
1836
                                if (isset($paent['subnet']))
1837
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1838
                                else if (isset($paent['range']))
1839
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1840
                        }
1841
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1842
		}
1843
	} else if (count($paa) > 0) {
1844
		foreach ($paa as $paif => $paents)  {
1845
			$paaifip = get_interface_ip($paif);
1846
			if (!is_ipaddr($paaifip))
1847
				continue;
1848
			$args = get_real_interface($paif) . " auto";
1849
			foreach ($paents as $paent) {
1850
				if (isset($paent['subnet']))
1851
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1852
				else if (isset($paent['range']))
1853
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1854
			}
1855
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1856
		}
1857
	}
1858
}
1859

    
1860
function interfaces_vips_configure($interface = "") {
1861
	global $g, $config;
1862
	if(isset($config['system']['developerspew'])) {
1863
		$mt = microtime();
1864
		echo "interfaces_vips_configure() being called $mt\n";
1865
	}
1866
	$paa = array();
1867
	if(is_array($config['virtualip']['vip'])) {
1868
		$carp_setuped = false;
1869
		$anyproxyarp = false;
1870
		foreach ($config['virtualip']['vip'] as $vip) {
1871
			switch ($vip['mode']) {
1872
			case "proxyarp":
1873
				/* nothing it is handled on interface_proxyarp_configure() */
1874
				if ($interface <> "" && $vip['interface'] <> $interface)
1875
					continue;
1876
				$anyproxyarp = true;
1877
				break;
1878
			case "ipalias":
1879
				if ($interface <> "" && $vip['interface'] <> $interface)
1880
					continue;
1881
				interface_ipalias_configure(&$vip);
1882
				break;
1883
			case "carp":
1884
				if ($interface <> "" && $vip['interface'] <> $interface)
1885
					continue;
1886
				if ($carp_setuped == false)
1887
					$carp_setuped = true;
1888
				interface_carp_configure($vip);
1889
				break;
1890
			case "carpdev-dhcp":
1891
				if ($interface <> "" && $vip['interface'] <> $interface)
1892
					continue;
1893
				interface_carpdev_configure($vip);
1894
				break;
1895
			}
1896
		}
1897
		if ($carp_setuped == true)
1898
			interfaces_carp_setup();
1899
		if ($anyproxyarp == true)
1900
			interface_proxyarp_configure();
1901
	}
1902
}
1903

    
1904
function interface_ipalias_configure(&$vip) {
1905

    
1906
	if ($vip['mode'] == "ipalias") {
1907
		$if = get_real_interface($vip['interface']);
1908
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1909
	}
1910
}
1911

    
1912
function interface_reload_carps($cif) {
1913
	global $config;
1914

    
1915
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1916
	if (empty($carpifs))
1917
		return;
1918

    
1919
	$carps = explode(" ", $carpifs);
1920
	if(is_array($config['virtualip']['vip'])) {
1921
		$viparr = &$config['virtualip']['vip'];
1922
		foreach ($viparr as $vip) {
1923
			if (in_array($vip['carpif'], $carps)) {
1924
				switch ($vip['mode']) {
1925
				case "carp":
1926
					interface_vip_bring_down($vip);
1927
					sleep(1);
1928
					interface_carp_configure($vip);
1929
					break;
1930
				case "carpdev-dhcp":
1931
					interface_vip_bring_down($vip);
1932
					sleep(1);
1933
					interface_carpdev_configure($vip);
1934
					break;
1935
				case "ipalias":
1936
					interface_vip_bring_down($vip);
1937
					sleep(1);
1938
					interface_ipalias_configure($vip);
1939
					break;
1940
				}
1941
			}
1942
		}
1943
	}
1944
}
1945

    
1946
function interface_carp_configure(&$vip) {
1947
	global $config, $g;
1948
	if(isset($config['system']['developerspew'])) {
1949
		$mt = microtime();
1950
		echo "interface_carp_configure() being called $mt\n";
1951
	}
1952

    
1953
	if ($vip['mode'] != "carp")
1954
		return;
1955

    
1956
	$vip_password = $vip['password'];
1957
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1958
	if ($vip['password'] != "")
1959
		$password = " pass {$vip_password}";
1960

    
1961
	// set the vip interface to the vhid
1962
	$vipif = "vip{$vip['vhid']}";
1963

    
1964
	/*
1965
	 * ensure the interface containing the VIP really exists
1966
 	 * prevents a panic if the interface is missing or invalid
1967
	 */
1968
	$realif = get_real_interface($vip['interface']);
1969
	if (!does_interface_exist($realif)) {
1970
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
1971
		return;
1972
	}
1973

    
1974
	if(is_ipaddrv4($vip['subnet'])) {
1975
		/* Ensure CARP IP really exists prior to loading up. */
1976
		$ww_subnet_ip = find_interface_ip($realif);
1977
		$ww_subnet_bits = find_interface_subnet($realif);
1978
		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'])) {
1979
			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", "");
1980
			return;
1981
		}
1982
	}
1983
	if(is_ipaddrv6($vip['subnet'])) {
1984
		/* Ensure CARP IP really exists prior to loading up. */
1985
		$ww_subnet_ip = find_interface_ipv6($realif);
1986
		$ww_subnet_bits = find_interface_subnetv6($realif);
1987
		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'])) {
1988
			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", "");
1989
			return;
1990
		}
1991
	}
1992

    
1993
	/* create the carp interface and setup */
1994
	if (does_interface_exist($vipif)) {
1995
		pfSense_interface_flags($vipif, -IFF_UP);
1996
	} else {
1997
		$carpif = pfSense_interface_create("carp");
1998
		pfSense_interface_rename($carpif, $vipif);
1999
		pfSense_ngctl_name("{$carpif}:", $vipif);
2000
	}
2001

    
2002
	/* invalidate interface cache */
2003
	get_interface_arr(true);
2004

    
2005

    
2006
	$advbase = "";
2007
	if (!empty($vip['advbase']))
2008
		$advbase = "advbase {$vip['advbase']}";
2009

    
2010
	if(is_ipaddrv4($vip['subnet'])) {
2011
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2012
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2013
	}
2014
	if(is_ipaddrv6($vip['subnet'])) {
2015
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2016
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2017
	}
2018

    
2019
	interfaces_bring_up($vipif);
2020
	
2021
	return $vipif;
2022
}
2023

    
2024
function interface_carpdev_configure(&$vip) {
2025
	global $g;
2026

    
2027
	if ($vip['mode'] != "carpdev-dhcp")
2028
		return;
2029

    
2030
	$vip_password = $vip['password'];
2031
	$vip_password = str_replace(" ", "", $vip_password);
2032
	if($vip['password'] != "")
2033
		$password = " pass \"" . $vip_password . "\"";
2034

    
2035
	if (empty($vip['interface']))
2036
		return;
2037

    
2038
	$vipif = "vip" . $vip['vhid'];
2039
	$realif = get_real_interface($vip['interface']);
2040
	interfaces_bring_up($realif);
2041
	/*
2042
	 * ensure the interface containing the VIP really exists
2043
	 * prevents a panic if the interface is missing or invalid
2044
	 */
2045
	if (!does_interface_exist($realif)) {
2046
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2047
		return;
2048
	}
2049

    
2050
	if (does_interface_exist($vipif)) {
2051
		interface_bring_down($vipif);
2052
	} else {
2053
		$carpdevif = exec("/sbin/ifconfig carp create");
2054
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
2055
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
2056
	}
2057

    
2058
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
2059
	interfaces_bring_up($vipif);
2060

    
2061
	/*
2062
	 * XXX: BIG HACK but carpdev needs ip services active
2063
	 *      before even starting something as dhclient.
2064
	 *      I do not know if this is a feature or a bug
2065
	 *      but better than track it make it work ;) .
2066
	 */
2067
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
2068
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
2069

    
2070
	/* generate dhclient_wan.conf */
2071
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
2072
	if ($fd) {
2073
		$dhclientconf = "";
2074

    
2075
		$dhclientconf .= <<<EOD
2076
interface "{$vipif}" {
2077
timeout 60;
2078
retry 1;
2079
select-timeout 0;
2080
initial-interval 1;
2081
script "/sbin/dhclient-script";
2082
}
2083

    
2084
EOD;
2085

    
2086
		fwrite($fd, $dhclientconf);
2087
		fclose($fd);
2088

    
2089
		/* fire up dhclient */
2090
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
2091
	} else {
2092
		log_error(sprintf(gettext("Error: cannot open dhclient_%s.conf in interfaces_carpdev_configure() for writing.%s"), $vipif, "\n"));
2093
		mwexec("/sbin/dhclient -b {$vipif}");
2094
	}
2095

    
2096
	return $vipif;
2097
}
2098

    
2099
function interface_wireless_clone($realif, $wlcfg) {
2100
	global $config, $g;
2101
	/*   Check to see if interface has been cloned as of yet.  
2102
	 *   If it has not been cloned then go ahead and clone it.
2103
	 */
2104
	$needs_clone = false;
2105
	if(is_array($wlcfg['wireless']))
2106
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2107
	else
2108
		$wlcfg_mode = $wlcfg['mode'];
2109
	switch($wlcfg_mode) {
2110
		 case "hostap":
2111
			$mode = "wlanmode hostap";
2112
			break;
2113
		 case "adhoc":
2114
			$mode = "wlanmode adhoc";
2115
			break;
2116
		 default:
2117
			$mode = "";
2118
			break;
2119
	}
2120
	$baseif = interface_get_wireless_base($wlcfg['if']);
2121
	if(does_interface_exist($realif)) {
2122
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2123
		$ifconfig_str = implode($output);
2124
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2125
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2126
			$needs_clone = true;
2127
		}
2128
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2129
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2130
			$needs_clone = true;
2131
		}
2132
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2133
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2134
			$needs_clone = true;
2135
		}
2136
	} else {
2137
		$needs_clone = true;
2138
	}
2139

    
2140
	if($needs_clone == true) {
2141
		/* remove previous instance if it exists */
2142
		if(does_interface_exist($realif))
2143
			pfSense_interface_destroy($realif);
2144

    
2145
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2146
		// Create the new wlan interface. FreeBSD returns the new interface name.
2147
		// example:  wlan2
2148
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2149
		if($ret <> 0) {
2150
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2151
			return false;
2152
		}
2153
		$newif = trim($out[0]);
2154
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2155
		pfSense_interface_rename($newif, $realif);
2156
		// FIXME: not sure what ngctl is for. Doesn't work.
2157
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2158
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2159
	}
2160
	return true;
2161
}
2162

    
2163
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2164
	global $config, $g;
2165

    
2166
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2167
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2168
	                         'regdomain', 'regcountry', 'reglocation');
2169

    
2170
	if(!is_interface_wireless($ifcfg['if']))
2171
		return;
2172

    
2173
	$baseif = interface_get_wireless_base($ifcfg['if']);
2174

    
2175
	// Sync shared settings for assigned clones
2176
	$iflist = get_configured_interface_list(false, true);
2177
	foreach ($iflist as $if) {
2178
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2179
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2180
				foreach ($shared_settings as $setting) {
2181
					if ($sync_changes) {
2182
						if (isset($ifcfg['wireless'][$setting]))
2183
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2184
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2185
							unset($config['interfaces'][$if]['wireless'][$setting]);
2186
					} else {
2187
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2188
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2189
						else if (isset($ifcfg['wireless'][$setting]))
2190
							unset($ifcfg['wireless'][$setting]);
2191
					}
2192
				}
2193
				if (!$sync_changes)
2194
					break;
2195
			}
2196
		}
2197
	}
2198

    
2199
	// Read or write settings at shared area
2200
	if (isset($config['wireless']['interfaces'][$baseif])) {
2201
		foreach ($shared_settings as $setting) {
2202
			if ($sync_changes) {
2203
				if (isset($ifcfg['wireless'][$setting]))
2204
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2205
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2206
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2207
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2208
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2209
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2210
				else if (isset($ifcfg['wireless'][$setting]))
2211
					unset($ifcfg['wireless'][$setting]);
2212
			}
2213
		}
2214
	}
2215

    
2216
	// Sync the mode on the clone creation page with the configured mode on the interface
2217
	if (interface_is_wireless_clone($ifcfg['if'])) {
2218
		foreach ($config['wireless']['clone'] as &$clone) {
2219
			if ($clone['cloneif'] == $ifcfg['if']) {
2220
				if ($sync_changes) {
2221
					$clone['mode'] = $ifcfg['wireless']['mode'];
2222
				} else {
2223
					$ifcfg['wireless']['mode'] = $clone['mode'];
2224
				}
2225
				break;
2226
			}
2227
		}
2228
		unset($clone);
2229
	}
2230
}
2231

    
2232
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2233
	global $config, $g;
2234

    
2235
	/*    open up a shell script that will be used to output the commands.
2236
	 *    since wireless is changing a lot, these series of commands are fragile
2237
     *    and will sometimes need to be verified by a operator by executing the command
2238
     *    and returning the output of the command to the developers for inspection.  please
2239
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2240
	 */
2241

    
2242
	// Remove script file
2243
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2244

    
2245
	// Clone wireless nic if needed.
2246
	interface_wireless_clone($if, $wl);
2247

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

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

    
2255
	/* set values for /path/program */
2256
	$hostapd = "/usr/sbin/hostapd";
2257
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2258
	$ifconfig = "/sbin/ifconfig";
2259
	$sysctl = "/sbin/sysctl";
2260
	$killall = "/usr/bin/killall";
2261

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

    
2264
	$wlcmd = array();
2265
	$wl_sysctl = array();
2266
	/* Make sure it's up */
2267
	$wlcmd[] = "up";
2268
	/* Set a/b/g standard */
2269
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2270
	$wlcmd[] = "mode " . escapeshellarg($standard);
2271

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

    
2277
	/* Set ssid */
2278
	if($wlcfg['ssid'])
2279
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2280

    
2281
	/* Set 802.11g protection mode */
2282
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2283

    
2284
	/* set wireless channel value */
2285
	if(isset($wlcfg['channel'])) {
2286
		if($wlcfg['channel'] == "0") {
2287
			$wlcmd[] = "channel any";
2288
		} else {
2289
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2290
		}
2291
	}
2292

    
2293
	/* Set antenna diversity value */
2294
	if(isset($wlcfg['diversity']))
2295
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2296

    
2297
	/* Set txantenna value */
2298
	if(isset($wlcfg['txantenna']))
2299
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2300

    
2301
	/* Set rxantenna value */
2302
	if(isset($wlcfg['rxantenna']))
2303
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2304

    
2305
	/* set Distance value */
2306
	if($wlcfg['distance'])
2307
		$distance = escapeshellarg($wlcfg['distance']);
2308

    
2309
	/* Set wireless hostap mode */
2310
	if ($wlcfg['mode'] == "hostap") {
2311
		$wlcmd[] = "mediaopt hostap";
2312
	} else {
2313
		$wlcmd[] = "-mediaopt hostap";
2314
	}
2315

    
2316
	/* Set wireless adhoc mode */
2317
	if ($wlcfg['mode'] == "adhoc") {
2318
		$wlcmd[] = "mediaopt adhoc";
2319
	} else {
2320
		$wlcmd[] = "-mediaopt adhoc";
2321
	}
2322

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

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

    
2332
	/* handle pureg (802.11g) only option */
2333
	if(isset($wlcfg['pureg']['enable'])) {
2334
		$wlcmd[] = "mode 11g pureg";
2335
	} else {
2336
		$wlcmd[] = "-pureg";
2337
	}
2338

    
2339
	/* handle puren (802.11n) only option */
2340
	if(isset($wlcfg['puren']['enable'])) {
2341
		$wlcmd[] = "puren";
2342
	} else {
2343
		$wlcmd[] = "-puren";
2344
	}
2345

    
2346
	/* enable apbridge option */
2347
	if(isset($wlcfg['apbridge']['enable'])) {
2348
		$wlcmd[] = "apbridge";
2349
	} else {
2350
		$wlcmd[] = "-apbridge";
2351
	}
2352

    
2353
	/* handle turbo option */
2354
	if(isset($wlcfg['turbo']['enable'])) {
2355
		$wlcmd[] = "mediaopt turbo";
2356
	} else {
2357
		$wlcmd[] = "-mediaopt turbo";
2358
	}
2359

    
2360
	/* handle txpower setting */
2361
	/* if($wlcfg['txpower'] <> "")
2362
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2363
	*/
2364
	/* handle wme option */
2365
	if(isset($wlcfg['wme']['enable'])) {
2366
		$wlcmd[] = "wme";
2367
	} else {
2368
		$wlcmd[] = "-wme";
2369
	}
2370

    
2371
	/* set up wep if enabled */
2372
	$wepset = "";
2373
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2374
		switch($wlcfg['wpa']['auth_algs']) {
2375
			case "1":
2376
				$wepset .= "authmode open wepmode on ";
2377
				break;
2378
			case "2":
2379
				$wepset .= "authmode shared wepmode on ";
2380
				break;
2381
			case "3":
2382
				$wepset .= "authmode mixed wepmode on ";
2383
		}
2384
		$i = 1;
2385
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2386
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2387
			if (isset($wepkey['txkey'])) {
2388
				$wlcmd[] = "weptxkey {$i} ";
2389
			}
2390
			$i++;
2391
		}
2392
		$wlcmd[] = $wepset;
2393
	} else {
2394
		$wlcmd[] = "authmode open wepmode off ";
2395
	}
2396

    
2397
	mwexec(kill_hostapd("{$if}"));
2398
	mwexec(kill_wpasupplicant("{$if}"));
2399

    
2400
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2401
	conf_mount_rw();
2402

    
2403
	switch ($wlcfg['mode']) {
2404
		case 'bss':
2405
			if (isset($wlcfg['wpa']['enable'])) {
2406
				$wpa .= <<<EOD
2407
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2408
ctrl_interface_group=0
2409
ap_scan=1
2410
#fast_reauth=1
2411
network={
2412
ssid="{$wlcfg['ssid']}"
2413
scan_ssid=1
2414
priority=5
2415
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2416
psk="{$wlcfg['wpa']['passphrase']}"
2417
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2418
group={$wlcfg['wpa']['wpa_pairwise']}
2419
}
2420
EOD;
2421

    
2422
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2423
				fwrite($fd, "{$wpa}");
2424
				fclose($fd);
2425
			}
2426
			break;
2427
		case 'hostap':
2428
			if($wlcfg['wpa']['passphrase']) 
2429
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2430
			else 
2431
				$wpa_passphrase = "";
2432
			if (isset($wlcfg['wpa']['enable'])) {
2433
				$wpa .= <<<EOD
2434
interface={$if}
2435
driver=bsd
2436
logger_syslog=-1
2437
logger_syslog_level=0
2438
logger_stdout=-1
2439
logger_stdout_level=0
2440
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2441
ctrl_interface={$g['varrun_path']}/hostapd
2442
ctrl_interface_group=wheel
2443
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2444
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2445
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2446
ssid={$wlcfg['ssid']}
2447
debug={$wlcfg['wpa']['debug_mode']}
2448
auth_algs={$wlcfg['wpa']['auth_algs']}
2449
wpa={$wlcfg['wpa']['wpa_mode']}
2450
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2451
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2452
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2453
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2454
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2455
{$wpa_passphrase}
2456

    
2457
EOD;
2458

    
2459
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2460
	$wpa .= <<<EOD
2461
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2462
rsn_preauth=1
2463
rsn_preauth_interfaces={$if}
2464

    
2465
EOD;
2466

    
2467
}
2468
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2469
					$auth_server_port = "1812";
2470
					if($wlcfg['auth_server_port']) 
2471
						$auth_server_port = $wlcfg['auth_server_port'];
2472
					$auth_server_port2 = "1812";
2473
					if($wlcfg['auth_server_port2']) 
2474
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2475
					$wpa .= <<<EOD
2476

    
2477
ieee8021x=1
2478
auth_server_addr={$wlcfg['auth_server_addr']}
2479
auth_server_port={$auth_server_port}
2480
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2481
auth_server_addr={$wlcfg['auth_server_addr2']}
2482
auth_server_port={$auth_server_port2}
2483
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2484

    
2485
EOD;
2486
				} else {
2487
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2488
				}
2489

    
2490
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2491
				fwrite($fd, "{$wpa}");
2492
				fclose($fd);
2493

    
2494
			}
2495
			break;
2496
	}
2497

    
2498
	/*
2499
	 *    all variables are set, lets start up everything
2500
	 */
2501

    
2502
	$baseif = interface_get_wireless_base($if);
2503
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2504
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2505

    
2506
	/* set sysctls for the wireless interface */
2507
	if (!empty($wl_sysctl)) {
2508
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2509
		foreach ($wl_sysctl as $wl_sysctl_line) {
2510
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2511
		}
2512
	}
2513

    
2514
	/* set ack timers according to users preference (if he/she has any) */
2515
	if($distance) {
2516
		fwrite($fd_set, "# Enable ATH distance settings\n");
2517
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2518
	}
2519

    
2520
	if (isset($wlcfg['wpa']['enable'])) {
2521
		if ($wlcfg['mode'] == "bss") {
2522
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2523
		}
2524
		if ($wlcfg['mode'] == "hostap") {
2525
			/* add line to script to restore old mac to make hostapd happy */
2526
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2527
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2528
				if (is_macaddr($if_oldmac))
2529
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2530
						" link " . escapeshellarg($if_oldmac) . "\n");
2531
			}
2532

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

    
2535
			/* add line to script to restore spoofed mac after running hostapd */
2536
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2537
				if ($wl['spoofmac'])
2538
					$if_curmac = $wl['spoofmac'];
2539
				else
2540
					$if_curmac = get_interface_mac($if);
2541
				if (is_macaddr($if_curmac))
2542
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2543
						" link " . escapeshellarg($if_curmac) . "\n");
2544
			}
2545
		}
2546
	}
2547

    
2548
	fclose($fd_set);
2549
	conf_mount_ro();
2550

    
2551
	/* Making sure regulatory settings have actually changed
2552
	 * before applying, because changing them requires bringing
2553
	 * down all wireless networks on the interface. */
2554
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2555
	$ifconfig_str = implode($output);
2556
	unset($output);
2557
	$reg_changing = false;
2558

    
2559
	/* special case for the debug country code */
2560
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2561
		$reg_changing = true;
2562
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2563
		$reg_changing = true;
2564
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2565
		$reg_changing = true;
2566
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2567
		$reg_changing = true;
2568
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2569
		$reg_changing = true;
2570

    
2571
	if ($reg_changing) {
2572
		/* set regulatory domain */
2573
		if($wlcfg['regdomain'])
2574
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2575

    
2576
		/* set country */
2577
		if($wlcfg['regcountry'])
2578
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2579

    
2580
		/* set location */
2581
		if($wlcfg['reglocation'])
2582
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2583

    
2584
		$wlregcmd_args = implode(" ", $wlregcmd);
2585

    
2586
		/* build a complete list of the wireless clones for this interface */
2587
		$clone_list = array();
2588
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2589
			$clone_list[] = interface_get_wireless_clone($baseif);
2590
		if (is_array($config['wireless']['clone'])) {
2591
			foreach ($config['wireless']['clone'] as $clone) {
2592
				if ($clone['if'] == $baseif)
2593
					$clone_list[] = $clone['cloneif'];
2594
			}
2595
		}
2596

    
2597
		/* find which clones are up and bring them down */
2598
		$clones_up = array();
2599
		foreach ($clone_list as $clone_if) {
2600
			$clone_status = pfSense_get_interface_addresses($clone_if);
2601
			if ($clone_status['status'] == 'up') {
2602
				$clones_up[] = $clone_if;
2603
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2604
			}
2605
		}
2606

    
2607
		/* apply the regulatory settings */
2608
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2609

    
2610
		/* bring the clones back up that were previously up */
2611
		foreach ($clones_up as $clone_if) {
2612
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2613

    
2614
			/*
2615
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2616
			 * is in infrastructure mode, and WPA is enabled.
2617
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2618
			 */
2619
			if ($clone_if != $if) {
2620
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2621
				if ( !empty($friendly_if)
2622
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2623
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2624
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2625
				}
2626
			}
2627
		}
2628
	}
2629

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

    
2634
	/* configure wireless */
2635
	$wlcmd_args = implode(" ", $wlcmd);
2636
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2637

    
2638
	
2639
	sleep(1);
2640
	/* execute hostapd and wpa_supplicant if required in shell */
2641
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2642

    
2643
	return 0;
2644

    
2645
}
2646

    
2647
function kill_hostapd($interface) {
2648
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2649
}
2650

    
2651
function kill_wpasupplicant($interface) {
2652
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2653
}
2654

    
2655
function find_dhclient_process($interface) {
2656
	if ($interface)
2657
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2658
	else
2659
		$pid = 0;
2660

    
2661
	return intval($pid);
2662
}
2663

    
2664
function find_dhcp6c_process($interface) {
2665
	if ($interface)
2666
		$pid = `/bin/ps auxw|grep "dhcp6c" |grep "{$interface}"|awk '{print $2}'`;
2667
	else
2668
		$pid = 0;
2669

    
2670
	return intval($pid);
2671
}
2672

    
2673
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2674
	global $config, $g;
2675
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2676
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2677

    
2678
	$wancfg = $config['interfaces'][$interface];
2679

    
2680
	$realif = get_real_interface($interface);
2681
	$realhwif_array = get_parent_interface($interface);
2682
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2683
	$realhwif = $realhwif_array[0];
2684

    
2685
	/* Disable Accepting router advertisements unless specifically requested */
2686
	log_error("Deny router advertisements for interface {$interface}");
2687
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2688
			
2689
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2690
		/* remove all IPv4 and IPv6 addresses */
2691
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2692
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2693

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

    
2697

    
2698

    
2699

    
2700

    
2701

    
2702

    
2703

    
2704
			interface_bring_down($interface);
2705

    
2706
		}
2707
	}
2708

    
2709
	/* wireless configuration? */
2710
	if (is_array($wancfg['wireless']))
2711
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2712

    
2713
	$mac = get_interface_mac($realhwif);
2714
	/*	Don't try to reapply the spoofed MAC if it's already applied.
2715
		When ifconfig link is used, it cycles the interface down/up, which triggers 
2716
		the interface config again, which attempts to spoof the MAC again, 
2717
		which cycles the link again... */
2718
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2719
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2720
			" link " . escapeshellarg($wancfg['spoofmac']));
2721

    
2722
                /*
2723
                 * All vlans need to spoof their parent mac address, too.  see
2724
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2725
                 */
2726
                if (is_array($config['vlans']['vlan'])) {
2727
                        foreach ($config['vlans']['vlan'] as $vlan) {
2728
                                if ($vlan['if'] == $realhwif)
2729
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2730
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2731
                        }
2732
                }
2733
	}  else {
2734

    
2735
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2736
			/*   this is not a valid mac address.  generate a
2737
			 *   temporary mac address so the machine can get online.
2738
			 */
2739
			echo gettext("Generating new MAC address.");
2740
			$random_mac = generate_random_mac_address();
2741
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2742
				" link " . escapeshellarg($random_mac));
2743
			$wancfg['spoofmac'] = $random_mac;
2744
			write_config();
2745
			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");
2746
		}
2747
	}
2748

    
2749
	/* media */
2750
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2751
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2752
		if ($wancfg['media'])
2753
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2754
		if ($wancfg['mediaopt'])
2755
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2756
		mwexec($cmd);
2757
	}
2758
	if (!empty($wancfg['mtu']))
2759
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2760
	else {
2761
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2762
		if ($mtu != get_interface_mtu($realhwif))
2763
			pfSense_interface_mtu($realhwif, $mtu);
2764
	}
2765

    
2766
	$options = pfSense_get_interface_addresses($realhwif);
2767
	if (is_array($options) && isset($options['caps']['polling'])) {
2768
		if (isset($config['system']['polling']))
2769
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2770
		else
2771
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2772
	}
2773

    
2774
	/* skip vlans for checksumming and polling */
2775
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2776
		$flags = 0;
2777
		if(isset($config['system']['disablechecksumoffloading'])) {
2778
			if (isset($options['encaps']['txcsum']))
2779
				$flags |= IFCAP_TXCSUM;
2780
			if (isset($options['encaps']['rxcsum']))
2781
				$flags |= IFCAP_RXCSUM;
2782
        	} else {
2783
 			if (!isset($options['caps']['txcsum']))
2784
				$flags |= IFCAP_TXCSUM;
2785
			if (!isset($options['caps']['rxcsum']))
2786
				$flags |= IFCAP_RXCSUM;
2787
        	}
2788

    
2789
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2790
                	if (isset($options['encaps']['tso4']))
2791
				$flags |= IFCAP_TSO;
2792
                	if (isset($options['encaps']['tso6']))
2793
				$flags |= IFCAP_TSO;
2794
        	} else {
2795
                	if (!isset($options['caps']['tso4']))
2796
				$flags |= IFCAP_TSO;
2797
                	if (!isset($options['caps']['tso6']))
2798
				$flags |= IFCAP_TSO;
2799
        	}
2800

    
2801
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2802
                	if (isset($options['encaps']['lro']))
2803
				$flags |= IFCAP_LRO;
2804
        	} else {
2805
                	if (!isset($options['caps']['lro']))
2806
				$flags |= IFCAP_LRO;
2807
        	}
2808

    
2809
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2810
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2811
			$flags |= IFCAP_POLLING;
2812
		}
2813
               	pfSense_interface_capabilities($realhwif, -$flags);
2814
	}
2815

    
2816
	/* invalidate interface/ip/sn cache */
2817
	get_interface_arr(true);
2818
	unset($interface_ip_arr_cache[$realif]);
2819
	unset($interface_sn_arr_cache[$realif]);
2820
	unset($interface_ipv6_arr_cache[$realif]);
2821
	unset($interface_snv6_arr_cache[$realif]);
2822

    
2823
	switch ($wancfg['ipaddr']) {
2824
		case 'carpdev-dhcp':
2825
			interface_carpdev_dhcp_configure($interface);
2826
			break;
2827
		case 'dhcp':
2828
			interface_dhcp_configure($interface);
2829
			break;
2830
		case 'pppoe':
2831
		case 'l2tp':
2832
		case 'pptp':
2833
		case 'ppp':
2834
			interface_ppps_configure($interface);
2835
			break;
2836
		default:
2837
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2838
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2839
			} else if (substr($realif, 0, 3) == "gre") {
2840
				if (is_array($config['gres']['gre'])) {
2841
					foreach ($config['gres']['gre'] as $gre)
2842
						if ($gre['greif'] == $realif)
2843
							interface_gre_configure($gre);
2844
				}
2845
			} else if (substr($realif, 0, 3) == "gif") {
2846
				 if (is_array($config['gifs']['gif'])) {
2847
					foreach ($config['gifs']['gif'] as $gif)
2848
						if($gif['gifif'] == $realif)
2849
							interface_gif_configure($gif);
2850
				}
2851
			} else if (substr($realif, 0, 4) == "ovpn") {
2852
				/* XXX: Should be done anything?! */
2853
			}
2854
			break;
2855
	}
2856

    
2857
	switch ($wancfg['ipaddrv6']) {
2858
		case 'dhcp6':
2859
			interface_dhcpv6_configure($interface);
2860
			break;
2861
		default:
2862
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2863
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2864
				// FIXME: Add IPv6 Support to the pfSense module
2865
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2866
			}
2867
			break;
2868
	}
2869

    
2870
	if(does_interface_exist($wancfg['if']))
2871
		interfaces_bring_up($wancfg['if']);
2872

    
2873
	interface_netgraph_needed($interface);
2874
 	
2875
	if (!$g['booting']) {
2876
		link_interface_to_vips($interface, "update");
2877

    
2878
		unset($gre);
2879
		$gre = link_interface_to_gre($interface);
2880
		if (!empty($gre))
2881
			array_walk($gre, 'interface_gre_configure');
2882

    
2883
		unset($gif);
2884
		$gif = link_interface_to_gif($interface);
2885
		if (!empty($gif))
2886
			array_walk($gif, 'interface_gif_configure');
2887

    
2888
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2889
			unset($bridgetmp);
2890
			$bridgetmp = link_interface_to_bridge($interface);
2891
			if (!empty($bridgetmp))
2892
				interface_bridge_add_member($bridgetmp, $realif);
2893
		}
2894

    
2895
		$grouptmp = link_interface_to_group($interface);
2896
		if (!empty($grouptmp))
2897
			array_walk($grouptmp, 'interface_group_add_member');
2898

    
2899
		if ($interface == "lan")
2900
			/* make new hosts file */
2901
			system_hosts_generate();
2902

    
2903
		if ($reloadall == true) {
2904

    
2905
			/* reconfigure static routes (kernel may have deleted them) */
2906
			system_routing_configure($interface);
2907

    
2908
			/* reload ipsec tunnels */
2909
			vpn_ipsec_configure();
2910

    
2911
			/* restart dnsmasq */
2912
			services_dnsmasq_configure();
2913

    
2914
			/* update dyndns */
2915
			send_event("service reload dyndns {$interface}");
2916

    
2917
			/* reload captive portal */
2918
			captiveportal_init_rules();
2919
		}
2920
	}
2921

    
2922
	return 0;
2923
}
2924

    
2925
function interface_carpdev_dhcp_configure($interface = "wan") {
2926
	global $config, $g;
2927

    
2928
	$wancfg = $config['interfaces'][$interface];
2929
	$wanif = $wancfg['if'];
2930
	/* bring wan interface up before starting dhclient */
2931
	if($wanif)
2932
		interfaces_bring_up($wanif);
2933
	else 
2934
		log_error(gettext("Could not bring wanif up in terface_carpdev_dhcp_configure()"));
2935

    
2936
	return 0;
2937
}
2938

    
2939
function interface_6rd_configure($interface = "wan"){
2940
	global $config, $g;
2941
	$iflist = get_configured_interface_with_descr(false, true);
2942

    
2943
	/* because this is a tunnel interface we can only function 
2944
	 *	with a public IPv4 address on the interface */
2945

    
2946
	$wancfg = $config['interfaces'][$interface];
2947
	$wanif = $wancfg['if'];
2948
	if (empty($wancfg))
2949
		$wancfg = array();
2950

    
2951
	$wanif = get_real_interface($interface);
2952
	
2953
	$ip4address = find_interface_ip($wanif);
2954
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
2955
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
2956
		return false;
2957
	}
2958
	
2959
	if(!is_numeric($wancfg['prefixlenv4-6rd']))
2960
		$v4prefixlen = 0;
2961
	else
2962
		$v4prefixlen = $wancfg['prefixlenv4-6rd'];	
2963

    
2964
	/* create the long prefix notation for math, save the prefix length */
2965
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
2966
	$rd6prefixlen = $rd6prefix[1];
2967
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
2968
	$rd6arr = explode(":", $rd6prefix);
2969
	// echo "6RD prefix {$wancfg['prefix-6rd']} length {$rd6prefixlen}\n";
2970

    
2971
	/* we need the hex form of the interface IPv4 address */
2972
	// $ip4address = "178.196.136.54";
2973
	$ip4arr = explode(".", $ip4address);
2974
	$hexwanv4 = "";
2975
	foreach($ip4arr as $octet)
2976
		$hexwanv4 .= sprintf("%02x", $octet);
2977

    
2978
	/* we need the hex form of the broker IPv4 address */
2979
	$ip4arr = explode(".", $wancfg['gateway-6rd']);
2980
	$hexbrv4 = "";
2981
	foreach($ip4arr as $octet)
2982
		$hexbrv4 .= sprintf("%02x", $octet);
2983
	
2984
	/* binary presentation of the prefix for all 128 bits. */
2985
	$rd6prefixbin = "";
2986
	foreach($rd6arr as $element) {
2987
		$rd6prefixbin .= sprintf("%016b", hexdec($element));
2988
	}
2989
	/* just save the left prefix length bits */
2990
	$rd6prefixstartbin = substr($rd6prefixbin, 0, $rd6prefixlen);
2991

    
2992
	// echo "$rd6prefixstartbin\n";
2993
	
2994
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
2995
	$rd6brokerbin = substr(sprintf("%032b", hexdec($hexbrv4)), $v4prefixlen, 32);
2996
	// echo "$rd6prefixstartbin . $rd6brokerbin\n";
2997
	$rd6brokerbin = str_pad($rd6prefixstartbin . $rd6brokerbin, 128, "0", STR_PAD_RIGHT);;
2998

    
2999
	/* for the local subnet too. */
3000
	$rd6lanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3001
	// echo "$rd6prefixstartbin . $rd6lanbin\n";
3002
	$rd6lanbin = str_pad($rd6prefixstartbin . $rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3003

    
3004
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3005
	$rd6brarr = array();
3006
	$rd6brbinarr = array();
3007
	$rd6brbinarr = str_split($rd6brokerbin, 16);
3008
	foreach($rd6brbinarr as $bin)
3009
		$rd6brarr[] = dechex(bindec($bin));
3010
	$rd6brarr[7] = 1;
3011
	$rd6brgw = Net_IPv6::compress(implode(":", $rd6brarr));
3012
	// echo "6RD stf gateway $rd6brgw length {$rd6prefixlen}\n";
3013

    
3014
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3015
	$rd6lanarr = array();
3016
	$rd6lanbinarr = array();
3017
	$rd6lanbinarr = str_split($rd6lanbin, 16);
3018
	foreach($rd6lanbinarr as $bin)
3019
		$rd6lanarr[] = dechex(bindec($bin));
3020
	$rd6lanpr = Net_IPv6::compress(implode(":", $rd6lanarr));
3021
	$rd6lanarr[7] = 1;
3022
	$rd6lan = Net_IPv6::compress(implode(":", $rd6lanarr));
3023
	// echo "6RD LAN prefix $rd6lan length 64\n";
3024

    
3025

    
3026
	/* setup the stf interface */
3027
	mwexec("/sbin/ifconfig stf0 destroy");
3028
	mwexec("/sbin/ifconfig stf0 create");
3029
	mwexec("/sbin/ifconfig stf0 inet6 {$rd6lanpr}/{$rd6prefixlen}");
3030

    
3031
	/* Example 6RD setup steps
3032
		# ifconfig fxp0 inet6 2001:db8:c000:0202::1/64
3033
		# ifconfig fxp1 inet 192.0.2.2/24
3034
		# ifconfig stf0 create
3035
		# ifconfig stf0 inet6 2001:db8:c000:0202::/32
3036
		# route add -inet6 default 2001:db8:c000:0201::1
3037
	*/
3038

    
3039
	
3040
	log_error("would have run: route add -inet6 default {$rd6brgw}");
3041

    
3042
	return 0;
3043

    
3044
}
3045

    
3046

    
3047
function interface_dhcpv6_configure($interface = "wan") {
3048
	global $config, $g;
3049
	$iflist = get_configured_interface_with_descr(false, true);
3050

    
3051
	$wancfg = $config['interfaces'][$interface];
3052
	$wanif = $wancfg['if'];
3053
	if (empty($wancfg))
3054
		$wancfg = array();
3055

    
3056
	$wanif = get_real_interface($interface);
3057

    
3058
	/* Add ISC IPv6 dhclient here, only wide-dhcp6c works for now. */
3059
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
3060
	if (!$fd) {
3061
		printf("Error: cannot open dhcp6c_{$interface}.conf in interfaces_wan_dhcpv6_configure() for writing.\n");
3062
		return 1;
3063
	}
3064

    
3065
	$dhcp6cconf = "";
3066
 	$dhcp6cconf .= "interface {$wanif} {\n";
3067
	$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3068
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3069
		$dhcp6cconf .= " 	send ia-pd 0;	# request prefix delegation\n";
3070
	}
3071
	$dhcp6cconf .= "request domain-name-servers;\n";
3072
	$dhcp6cconf .= "request domain-name;\n";
3073
	$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3074

    
3075
	$dhcp6cconf .= "};\n";
3076
	$dhcp6cconf .= "id-assoc na 0 { };\n";
3077
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3078
		/* Setup the prefix delegation */
3079
		$dhcp6cconf .= "	id-assoc pd 0 {\n";
3080
		foreach($iflist as $friendly => $pdinterface) {
3081
			// log_error("setting up $friendly - $pdinterface - {$pdinterface['dhcp6-pd-sla-id']}");
3082
			if(is_numeric($config['interfaces'][$friendly]['dhcp6-pd-sla-id'])) {
3083
				$realif = get_real_interface($friendly);
3084
				$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3085
				$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['dhcp6-pd-sla-id']};\n";
3086
				$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3087
				$dhcp6cconf .= "	};\n";
3088
			}
3089
		}
3090
		$dhcp6cconf .= "};\n";
3091
	}
3092

    
3093
	fwrite($fd, $dhcp6cconf);
3094
	fclose($fd);
3095

    
3096
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3097
	$fds = fopen("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", "w");
3098
	if (!$fds) {
3099
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interfaces_wan_dhcpv6_configure() for writing.\n");
3100
		return 1;
3101
	}
3102
	$dhcp6cscript = "#!/bin/sh\n";
3103
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3104
	$dhcp6cscript .= "/etc/rc.newwanipv6 $interface \n";
3105

    
3106
	fwrite($fds, $dhcp6cscript);
3107
	fclose($fds);
3108
	chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3109

    
3110

    
3111
	/* accept router advertisements for this interface */
3112
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3113
	log_error("Accept router advertisements on interface {$wanif} ");
3114
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3115
	mwexec("/sbin/ifconfig {$wanif} inet6 defroute_rtadv");
3116

    
3117
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3118
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
3119
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3120
	if(!empty($out)) {
3121
		foreach($out as $line) {
3122
			if(stristr($line, "received")) {
3123
				$parts = explode(" ", $line);
3124
				if(is_ipaddrv6($parts[3])) {
3125
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3126
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3127
				}
3128
			}
3129
		}
3130
	}
3131
	/* sleep a few seconds before returning to give the client some time
3132
	 * to configure a lan interface with a prefix */
3133
	sleep(5);
3134
	return 0;
3135
}
3136

    
3137
function interface_dhcp_configure($interface = "wan") {
3138
	global $config, $g;
3139

    
3140
	$wancfg = $config['interfaces'][$interface];
3141
	$wanif = $wancfg['if'];
3142
	if (empty($wancfg))
3143
		$wancfg = array();
3144

    
3145
	/* generate dhclient_wan.conf */
3146
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3147
	if (!$fd) {
3148
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interfaces_wan_dhcp_configure() for writing.%s"), $interface, "\n"));
3149
		return 1;
3150
	}
3151

    
3152
	if ($wancfg['dhcphostname']) {
3153
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3154
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3155
	} else {
3156
		$dhclientconf_hostname = "";
3157
	}
3158

    
3159
	$wanif = get_real_interface($interface);
3160
	if (empty($wanif)) {
3161
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3162
		return 0;
3163
	}
3164
 	$dhclientconf = "";
3165
	
3166
	$dhclientconf .= <<<EOD
3167
interface "{$wanif}" {
3168
timeout 60;
3169
retry 1;
3170
select-timeout 0;
3171
initial-interval 1;
3172
	{$dhclientconf_hostname}
3173
	script "/sbin/dhclient-script";
3174
}
3175

    
3176
EOD;
3177

    
3178
if(is_ipaddr($wancfg['alias-address'])) {
3179
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3180
	$dhclientconf .= <<<EOD
3181
alias {
3182
	interface  "{$wanif}";
3183
	fixed-address {$wancfg['alias-address']};
3184
	option subnet-mask {$subnetmask};
3185
}
3186

    
3187
EOD;
3188
}
3189
	fwrite($fd, $dhclientconf);
3190
	fclose($fd);
3191

    
3192
	/* bring wan interface up before starting dhclient */
3193
	if($wanif)
3194
		interfaces_bring_up($wanif);
3195
	else 
3196
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3197

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

    
3201
	return 0;
3202
}
3203

    
3204
function interfaces_group_setup() {
3205
	global $config;
3206

    
3207
	if (!is_array($config['ifgroups']['ifgroupentry']))
3208
		return;
3209

    
3210
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3211
		interface_group_setup($groupar);
3212

    
3213
	return;
3214
}
3215

    
3216
function interface_group_setup(&$groupname /* The parameter is an array */) {
3217
	global $config;
3218

    
3219
	if (!is_array($groupname))
3220
		return;
3221
	$members = explode(" ", $groupname['members']);
3222
	foreach($members as $ifs) {
3223
		$realif = get_real_interface($ifs);
3224
		if ($realif)
3225
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3226
	}
3227

    
3228
	return;
3229
}
3230

    
3231
function interface_group_add_member($interface, $groupname) {
3232
	$interface = get_real_interface($interface);
3233
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3234
}
3235
 
3236
/* COMPAT Function */
3237
function convert_friendly_interface_to_real_interface_name($interface) {
3238
	return get_real_interface($interface);
3239
}
3240

    
3241
/* COMPAT Function */
3242
function get_real_wan_interface($interface = "wan") {
3243
	return get_real_interface($interface);
3244
}
3245

    
3246
/* COMPAT Function */
3247
function get_current_wan_address($interface = "wan") {
3248
	return get_interface_ip($interface);
3249
}
3250

    
3251
/*
3252
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3253
 */
3254
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3255
        global $config;
3256

    
3257
	if (stristr($interface, "vip")) {
3258
                $index = intval(substr($interface, 3));
3259
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3260
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3261
                                if ($index == $vip['vhid'])
3262
                                        return $vip['interface'];
3263
                        }
3264
                }
3265
        }
3266

    
3267
        /* XXX: For speed reasons reference directly the interface array */
3268
	$ifdescrs = &$config['interfaces'];
3269
        //$ifdescrs = get_configured_interface_list(false, true);
3270

    
3271
        foreach ($ifdescrs as $if => $ifname) {
3272
                if ($config['interfaces'][$if]['if'] == $interface)
3273
                        return $if;
3274

    
3275
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3276
                        return $if;
3277

    
3278
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3279
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3280
		/*
3281
                $int = get_parent_interface($if);
3282
                if ($int[0] == $interface)
3283
                        return $ifname;
3284
		*/
3285
        }
3286
        return NULL;
3287
}
3288

    
3289
/* attempt to resolve interface to friendly descr */
3290
function convert_friendly_interface_to_friendly_descr($interface) {
3291
        global $config;
3292

    
3293
        switch ($interface) {
3294
        case "l2tp":
3295
        	$ifdesc = "L2TP";
3296
                break;
3297
	case "pptp":
3298
		$ifdesc = "PPTP";
3299
		break;
3300
	case "pppoe":
3301
		$ifdesc = "PPPoE";
3302
		break;
3303
	case "openvpn":
3304
		$ifdesc = "OpenVPN";
3305
		break;
3306
	case "enc0":
3307
	case "ipsec":
3308
		$ifdesc = "IPsec";
3309
		break;
3310
        default:
3311
                if (isset($config['interfaces'][$interface])) {
3312
                        if (empty($config['interfaces'][$interface]['descr']))
3313
                                $ifdesc = strtoupper($interface);
3314
                        else
3315
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3316
			break;
3317
		} else if (substr($interface, 0, 3) == "vip") {
3318
			if (is_array($config['virtualip']['vip'])) {
3319
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3320
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3321
						if ($interface == "vip{$vip['vhid']}")
3322
							return "{$vip['subnet']} - {$vip['descr']}";
3323
					}
3324
				}
3325
                        }
3326
                } else {
3327
			/* if list */
3328
			$ifdescrs = get_configured_interface_with_descr(false, true);
3329
			foreach ($ifdescrs as $if => $ifname) {
3330
					if ($if == $interface || $ifname == $interface)
3331
						return $ifname;
3332
			}
3333
		}
3334
                break;
3335
        }
3336

    
3337
        return $ifdesc;
3338
}
3339

    
3340
function convert_real_interface_to_friendly_descr($interface) {
3341
        global $config;
3342

    
3343
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3344

    
3345
        if ($ifdesc) {
3346
                $iflist = get_configured_interface_with_descr(false, true);
3347
                return $iflist[$ifdesc];
3348
        }
3349

    
3350
        return $interface;
3351
}
3352

    
3353
/*
3354
 *  get_parent_interface($interface):
3355
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3356
 *				or virtual interface (i.e. vlan)
3357
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3358
 *			-- returns $interface passed in if $interface parent is not found
3359
 *			-- returns empty array if an invalid interface is passed
3360
 *	(Only handles ppps and vlans now.)
3361
 */
3362
function get_parent_interface($interface) {
3363
	global $config;
3364

    
3365
	$parents = array();
3366
	//Check that we got a valid interface passed
3367
	$realif = get_real_interface($interface);
3368
	if ($realif == NULL)
3369
		return $parents;
3370

    
3371
	// If we got a real interface, find it's friendly assigned name
3372
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3373
		
3374
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3375
		$ifcfg = $config['interfaces'][$interface];
3376
		switch ($ifcfg['ipaddr']) {
3377
			case "ppp":
3378
			case "pppoe":
3379
			case "pptp":
3380
			case "l2tp":
3381
				if (empty($parents))
3382
					if (is_array($config['ppps']['ppp']))
3383
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3384
							if ($ppp_if == $ppp['if']) {
3385
								$ports = explode(',', $ppp['ports']);
3386
								foreach ($ports as $pid => $parent_if) 
3387
									$parents[$pid] = get_real_interface($parent_if);
3388
								break;
3389
							}
3390
						}
3391
				break;
3392
			case "dhcp":
3393
			case "static":
3394
			default:
3395
				// Handle _vlans
3396
				if (strstr($realif,"_vlan"))
3397
					if (is_array($config['vlans']['vlan'])) 
3398
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3399
							if ($ifcfg['if'] == $vlan['vlanif']){
3400
								$parents[0] = $vlan['if'];
3401
								break;
3402
							}
3403
				break;
3404
		}
3405
	}
3406
	
3407
	if (empty($parents))
3408
		$parents[0] = $realif;
3409
	
3410
	return $parents;
3411
}
3412

    
3413
function interface_is_wireless_clone($wlif) {
3414
	if(!stristr($wlif, "_wlan")) {
3415
		return false;
3416
	} else {
3417
		return true;
3418
	}
3419
}
3420

    
3421
function interface_get_wireless_base($wlif) {
3422
	if(!stristr($wlif, "_wlan")) {
3423
		return $wlif;
3424
	} else {
3425
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3426
	}
3427
}
3428

    
3429
function interface_get_wireless_clone($wlif) {
3430
	if(!stristr($wlif, "_wlan")) {
3431
		return $wlif . "_wlan0";
3432
	} else {
3433
		return $wlif;
3434
	}
3435
}
3436

    
3437
function get_real_interface($interface = "wan") {
3438
    global $config;
3439

    
3440
	$wanif = NULL;
3441

    
3442
	switch ($interface) {
3443
	case "l2tp":
3444
		$wanif = "l2tp";
3445
		break;
3446
	case "pptp":
3447
		$wanif = "pptp";
3448
		break;
3449
	case "pppoe":
3450
		$wanif = "pppoe";
3451
		break;
3452
	case "openvpn":
3453
		$wanif = "openvpn";
3454
		break;
3455
	case "ipsec":
3456
	case "enc0":
3457
		$wanif = "enc0";
3458
		break;
3459
	case "ppp":
3460
		$wanif = "ppp";
3461
		break;
3462
	default:
3463
		// If a real interface was alread passed simply
3464
		// pass the real interface back.  This encourages
3465
		// the usage of this function in more cases so that
3466
		// we can combine logic for more flexibility.
3467
		if(does_interface_exist($interface)) {
3468
			$wanif = $interface;
3469
			break;
3470
		}
3471
		if (empty($config['interfaces'][$interface]))
3472
			break;
3473

    
3474
		$cfg = &$config['interfaces'][$interface];
3475

    
3476
		// Wireless cloned NIC support (FreeBSD 8+)
3477
		// interface name format: $parentnic_wlanparentnic#
3478
		// example: ath0_wlan0
3479
		if (is_interface_wireless($cfg['if'])) {
3480
			$wanif = interface_get_wireless_clone($cfg['if']);
3481
			break;
3482
		}
3483
		/*
3484
		if (empty($cfg['if'])) {
3485
			$wancfg = $cfg['if'];
3486
			break;
3487
		}
3488
		*/
3489

    
3490
		switch ($cfg['ipaddr']) {
3491
			case "carpdev-dhcp":
3492
				$viparr = &$config['virtualip']['vip'];
3493
				if(is_array($viparr))
3494
				foreach ($viparr as $counter => $vip) {
3495
					if ($vip['mode'] == "carpdev-dhcp") {
3496
						if($vip['interface'] == $interface) {
3497
							$wanif = "carp{$counter}";
3498
							break;
3499
						}
3500
					}
3501
				}
3502
				break;
3503
			case "pppoe": 
3504
			case "pptp": 
3505
			case "l2tp": 
3506
			case "ppp":
3507
				$wanif = $cfg['if'];
3508
				break;
3509
			default:
3510
				$wanif = $cfg['if'];
3511
				break;
3512
		}
3513
		break;
3514
	}
3515

    
3516
    return $wanif;
3517
}
3518

    
3519
/* Guess the physical interface by providing a IP address */
3520
function guess_interface_from_ip($ipaddress) {
3521
	if(! is_ipaddr($ipaddress)) {
3522
		return false;
3523
	}
3524
	if(is_ipaddrv4($ipaddress)) {
3525
		/* create a route table we can search */
3526
		exec("netstat -rnWf inet", $output, $ret);
3527
		foreach($output as $line) {
3528
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3529
				$fields = preg_split("/[ ]+/", $line);
3530
				if(ip_in_subnet($ipaddress, $fields[0])) {
3531
					return $fields[6];
3532
				}
3533
			}
3534
		}
3535
	}
3536
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3537
	if(is_ipaddrv6($ipaddress)) {
3538
		/* create a route table we can search */
3539
		exec("netstat -rnWf inet6", $output, $ret);
3540
		foreach($output as $line) {
3541
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3542
				$fields = preg_split("/[ ]+/", $line);
3543
				if(ip_in_subnet($ipaddress, $fields[0])) {
3544
					return $fields[6];
3545
				}
3546
			}
3547
		}
3548
	}
3549
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3550
	if(empty($ret)) {
3551
        	return false;
3552
	}
3553
	return $ret;
3554
}
3555

    
3556
/*
3557
 * find_ip_interface($ip): return the interface where an ip is defined
3558
 */
3559
function find_ip_interface($ip)
3560
{
3561
        /* if list */
3562
        $ifdescrs = get_configured_interface_list();
3563

    
3564
        foreach ($ifdescrs as $ifdescr => $ifname) {
3565
		if ($ip == get_interface_ip($ifname)) {
3566
                	$int = get_real_interface($ifname);
3567
			return $int;
3568
		}
3569
        }
3570
        return false;
3571
}
3572

    
3573
/*
3574
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3575
 */
3576
function find_number_of_created_carp_interfaces() {
3577
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3578
}
3579

    
3580
function get_all_carp_interfaces() {
3581
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3582
	$ints = explode(" ", $ints);
3583
	return $ints;
3584
}
3585

    
3586
/*
3587
 * find_carp_interface($ip): return the carp interface where an ip is defined
3588
 */
3589
function find_carp_interface($ip) {
3590
	global $config;
3591
	if (is_array($config['virtualip']['vip'])) {
3592
		foreach ($config['virtualip']['vip'] as $vip) {
3593
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3594
				if(is_ipaddrv4($ip)) {
3595
					$carp_ip = get_interface_ip($vip['interface']);
3596
				}
3597
				if(is_ipaddrv6($ip)) {
3598
					$carp_ip = get_interface_ipv6($vip['interface']);
3599
				}
3600
				exec("/sbin/ifconfig", $output, $return);
3601
				foreach($output as $line) {
3602
					$elements = preg_split("/[ ]+/i", $line);
3603
					if(strstr($elements[0], "vip"))
3604
						$curif = str_replace(":", "", $elements[0]);
3605
					if(stristr($line, $ip)) {
3606
						$if = $curif;
3607
						continue;
3608
					}
3609
				}
3610

    
3611
				if ($if)
3612
					return $if;
3613
			}
3614
		}
3615
	}
3616
}
3617

    
3618
function link_carp_interface_to_parent($interface) {
3619
        global $config;
3620

    
3621
        if ($interface == "")
3622
                return;
3623

    
3624
        $carp_ip = get_interface_ip($interface);
3625
        if (!is_ipaddr($carp_ip))
3626
                return;
3627

    
3628
        /* if list */
3629
        $ifdescrs = get_configured_interface_list();
3630
        foreach ($ifdescrs as $ifdescr => $ifname) {
3631
                $interfaceip = get_interface_ip($ifname);
3632
                $subnet_bits = get_interface_subnet($ifname);
3633
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3634
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3635
                        return $ifname;
3636
        }
3637

    
3638
        return "";
3639
}
3640

    
3641
/****f* interfaces/link_ip_to_carp_interface
3642
 * NAME
3643
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3644
 * INPUTS
3645
 *   $ip
3646
 * RESULT
3647
 *   $carp_ints
3648
 ******/
3649
function link_ip_to_carp_interface($ip) {
3650
        global $config;
3651

    
3652
        if (!is_ipaddr($ip))
3653
                return;
3654

    
3655
        $carp_ints = "";
3656
        if (is_array($config['virtualip']['vip'])) {
3657
		$first = 0;
3658
		$carp_int = array();
3659
                foreach ($config['virtualip']['vip'] as $vip) {
3660
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3661
                                $carp_ip = $vip['subnet'];
3662
                                $carp_sn = $vip['subnet_bits'];
3663
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3664
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3665
					$carp_int[] = "vip{$vip['vhid']}";
3666
                        }
3667
                }
3668
		if (!empty($carp_int))
3669
			$carp_ints = implode(" ", array_unique($carp_int));
3670
        }
3671

    
3672
        return $carp_ints;
3673
}
3674

    
3675
function link_interface_to_vlans($int, $action = "") {
3676
	global $config;
3677

    
3678
	if (empty($int))
3679
		return;
3680

    
3681
	if (is_array($config['vlans']['vlan'])) {
3682
                foreach ($config['vlans']['vlan'] as $vlan) {
3683
			if ($int == $vlan['if']) {
3684
				if ($action == "update") {
3685
					interfaces_bring_up($int);
3686
				} else if ($action == "")
3687
					return $vlan;
3688
			}
3689
		}
3690
	}
3691
}
3692

    
3693
function link_interface_to_vips($int, $action = "") {
3694
        global $config;
3695

    
3696
        if (is_array($config['virtualip']['vip'])) {
3697
		foreach ($config['virtualip']['vip'] as $vip) {
3698
			if ($int == $vip['interface']) {
3699
				if ($action == "update") {
3700
					if ($vip['mode'] == "carp" && !does_interface_exist("vip{$vip['vhid']}"))
3701
						interfaces_vips_configure($int);
3702
					else {
3703
						interface_vip_bring_down($vip);
3704
						interfaces_vips_configure($int);
3705
					}
3706
				} else
3707
					return $vip;
3708
			}
3709
		}
3710
	}
3711
}
3712

    
3713
/****f* interfaces/link_interface_to_bridge
3714
 * NAME
3715
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3716
 * INPUTS
3717
 *   $ip
3718
 * RESULT
3719
 *   bridge[0-99]
3720
 ******/
3721
function link_interface_to_bridge($int) {
3722
        global $config;
3723

    
3724
        if (is_array($config['bridges']['bridged'])) {
3725
                foreach ($config['bridges']['bridged'] as $bridge) {
3726
			if (in_array($int, explode(',', $bridge['members'])))
3727
                                return "{$bridge['bridgeif']}";
3728
		}
3729
	}
3730
}
3731

    
3732
function link_interface_to_group($int) {
3733
        global $config;
3734

    
3735
	$result = array();
3736

    
3737
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3738
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3739
			if (in_array($int, explode(" ", $group['members'])))
3740
				$result[$group['ifname']] = $int;
3741
		}
3742
	}
3743

    
3744
	return $result;
3745
}
3746

    
3747
function link_interface_to_gre($interface) {
3748
        global $config;
3749

    
3750
	$result = array();
3751

    
3752
        if (is_array($config['gres']['gre'])) {
3753
                foreach ($config['gres']['gre'] as $gre)
3754
                        if($gre['if'] == $interface)
3755
				$result[] = $gre;
3756
	}
3757

    
3758
	return $result;
3759
}
3760

    
3761
function link_interface_to_gif($interface) {
3762
        global $config;
3763

    
3764
	$result = array();
3765

    
3766
        if (is_array($config['gifs']['gif'])) {
3767
                foreach ($config['gifs']['gif'] as $gif)
3768
                        if($gif['if'] == $interface)
3769
                                $result[] = $gif;
3770
	}
3771

    
3772
	return $result;
3773
}
3774

    
3775
/*
3776
 * find_interface_ip($interface): return the interface ip (first found)
3777
 */
3778
function find_interface_ip($interface, $flush = false)
3779
{
3780
	global $interface_ip_arr_cache;
3781
	global $interface_sn_arr_cache;
3782

    
3783
	$interface = str_replace("\n", "", $interface);
3784
	
3785
	if (!does_interface_exist($interface))
3786
		return;
3787

    
3788
	/* Setup IP cache */
3789
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3790
		$ifinfo = pfSense_get_interface_addresses($interface);
3791
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3792
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3793
	}
3794

    
3795
	return $interface_ip_arr_cache[$interface];
3796
}
3797

    
3798
/*
3799
 * find_interface_ipv6($interface): return the interface ip (first found)
3800
 */
3801
function find_interface_ipv6($interface, $flush = false)
3802
{
3803
	global $interface_ipv6_arr_cache;
3804
	global $interface_snv6_arr_cache;
3805
	global $config;
3806
	
3807
	$interface = str_replace("\n", "", $interface);
3808
	
3809
	if (!does_interface_exist($interface))
3810
		return;
3811

    
3812
	/* Setup IP cache */
3813
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3814
		$ifinfo = pfSense_get_interface_addresses($interface);
3815
		// FIXME: Add IPv6 support to the pfSense module
3816
		exec("/sbin/ifconfig {$interface} inet6", $output);
3817
		foreach($output as $line) {
3818
			if(preg_match("/inet6/", $line)) {
3819
				$parts = explode(" ", $line);
3820
				if(! preg_match("/fe80::/", $parts[1])) {
3821
					$ifinfo['ipaddrv6'] = $parts[1];
3822
					if($parts[2] == "-->") {
3823
						$parts[5] = "126";
3824
						$ifinfo['subnetbitsv6'] = $parts[5];
3825
					} else {
3826
						$ifinfo['subnetbitsv6'] = $parts[3];
3827
					}
3828
				}
3829
			}
3830
		}
3831
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3832
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3833
	}
3834

    
3835
	return $interface_ipv6_arr_cache[$interface];
3836
}
3837

    
3838
/*
3839
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
3840
 */
3841
function find_interface_ipv6_ll($interface, $flush = false)
3842
{
3843
	global $interface_llv6_arr_cache;
3844
	global $config;
3845
	
3846
	$interface = str_replace("\n", "", $interface);
3847
	
3848
	if (!does_interface_exist($interface))
3849
		return;
3850

    
3851
	/* Setup IP cache */
3852
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
3853
		$ifinfo = pfSense_get_interface_addresses($interface);
3854
		// FIXME: Add IPv6 support to the pfSense module
3855
		exec("/sbin/ifconfig {$interface} inet6", $output);
3856
		foreach($output as $line) {
3857
			if(preg_match("/inet6/", $line)) {
3858
				$parts = explode(" ", $line);
3859
				if(preg_match("/fe80::/", $parts[1])) {
3860
					$partsaddress = explode("%", $parts[1]);
3861
					$ifinfo['linklocal'] = $partsaddress[0];
3862
				}
3863
			}
3864
		}
3865
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
3866
	}
3867
	return $interface_llv6_arr_cache[$interface];
3868
}
3869

    
3870
function find_interface_subnet($interface, $flush = false)
3871
{
3872
	global $interface_sn_arr_cache;
3873
	global $interface_ip_arr_cache;
3874

    
3875
	$interface = str_replace("\n", "", $interface);
3876
	if (does_interface_exist($interface) == false)
3877
		return;
3878

    
3879
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3880
		$ifinfo = pfSense_get_interface_addresses($interface);
3881
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3882
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3883
        }
3884

    
3885
	return $interface_sn_arr_cache[$interface];
3886
}
3887

    
3888
function find_interface_subnetv6($interface, $flush = false)
3889
{
3890
	global $interface_snv6_arr_cache;
3891
	global $interface_ipv6_arr_cache;
3892

    
3893
	$interface = str_replace("\n", "", $interface);
3894
	if (does_interface_exist($interface) == false)
3895
		return;
3896

    
3897
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3898
		$ifinfo = pfSense_get_interface_addresses($interface);
3899
		// FIXME: Add IPv6 support to the pfSense module
3900
		exec("/sbin/ifconfig {$interface} inet6", $output);
3901
		foreach($output as $line) {
3902
			if(preg_match("/inet6/", $line)) {
3903
				$parts = explode(" ", $line);
3904
				if(! preg_match("/fe80::/", $parts[1])) {
3905
					$ifinfo['ipaddrv6'] = $parts[1];
3906
					if($parts[2] == "-->") {
3907
						$parts[5] = "126";
3908
						$ifinfo['subnetbitsv6'] = $parts[5];
3909
					} else {
3910
						$ifinfo['subnetbitsv6'] = $parts[3];
3911
					}
3912
				}
3913
			}
3914
		}
3915
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3916
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3917
        }
3918

    
3919
	return $interface_snv6_arr_cache[$interface];
3920
}
3921

    
3922
function ip_in_interface_alias_subnet($interface, $ipalias) {
3923
	global $config;
3924

    
3925
	if (empty($interface) || !is_ipaddr($ipalias))
3926
		return false;
3927
	if (is_array($config['virtualip']['vip'])) {
3928
                foreach ($config['virtualip']['vip'] as $vip) {
3929
                        switch ($vip['mode']) {
3930
                        case "ipalias":
3931
                                if ($vip['interface'] <> $interface)
3932
                                        break;
3933
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3934
					return true;
3935
                                break;
3936
                        }
3937
                }
3938
	}
3939

    
3940
	return false;
3941
}
3942

    
3943
function get_interface_ip($interface = "wan")
3944
{
3945
	$realif = get_real_interface($interface);
3946
	if (!$realif) {
3947
		if (preg_match("/^carp/i", $interface))
3948
			$realif = $interface;
3949
		else if (preg_match("/^vip/i", $interface))
3950
			$realif = $interface;
3951
		else
3952
			return null;
3953
	}
3954

    
3955
	$curip = find_interface_ip($realif);
3956
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3957
		return $curip;
3958
	else
3959
		return null;
3960
}
3961

    
3962
function get_interface_ipv6($interface = "wan")
3963
{
3964
	$realif = get_real_interface($interface);
3965
	if (!$realif) {
3966
		if (preg_match("/^carp/i", $interface))
3967
			$realif = $interface;
3968
		else if (preg_match("/^vip/i", $interface))
3969
			$realif = $interface;
3970
		else
3971
			return null;
3972
	}
3973

    
3974
	$curip = find_interface_ipv6($realif);
3975
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3976
		return $curip;
3977
	else
3978
		return null;
3979
}
3980

    
3981
function get_interface_linklocal($interface = "wan")
3982
{
3983
	$realif = get_real_interface($interface);
3984
	if (!$realif) {
3985
		if (preg_match("/^carp/i", $interface))
3986
			$realif = $interface;
3987
		else if (preg_match("/^vip/i", $interface))
3988
			$realif = $interface;
3989
		else
3990
			return null;
3991
	}
3992

    
3993
	$curip = find_interface_ipv6_ll($realif);
3994
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3995
		return $curip;
3996
	else
3997
		return null;
3998
}
3999

    
4000
function get_interface_subnet($interface = "wan")
4001
{
4002
	$realif = get_real_interface($interface);
4003
	if (!$realif) {
4004
                if (preg_match("/^carp/i", $interface))
4005
                        $realif = $interface;
4006
                else if (preg_match("/^vip/i", $interface))
4007
                        $realif = $interface;
4008
                else
4009
                        return null;
4010
        }
4011

    
4012
	$cursn = find_interface_subnet($realif);
4013
	if (!empty($cursn))
4014
		return $cursn;
4015

    
4016
	return null;
4017
}
4018

    
4019
function get_interface_subnetv6($interface = "wan")
4020
{
4021
	$realif = get_real_interface($interface);
4022
	if (!$realif) {
4023
                if (preg_match("/^carp/i", $interface))
4024
                        $realif = $interface;
4025
                else if (preg_match("/^vip/i", $interface))
4026
                        $realif = $interface;
4027
                else
4028
                        return null;
4029
        }
4030

    
4031
	$cursn = find_interface_subnetv6($realif);
4032
	if (!empty($cursn))
4033
		return $cursn;
4034

    
4035
	return null;
4036
}
4037

    
4038
/* return outside interfaces with a gateway */
4039
function get_interfaces_with_gateway() {
4040
	global $config;
4041

    
4042
	$ints = array();
4043

    
4044
	/* loop interfaces, check config for outbound */
4045
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4046
		switch ($ifname['ipaddr']) {
4047
			case "dhcp":
4048
			case "carpdev-dhcp":
4049
			case "ppp";
4050
			case "pppoe":
4051
			case "pptp":
4052
			case "l2tp":
4053
			case "ppp";
4054
				$ints[$ifdescr] = $ifdescr;
4055
			break;
4056
			default:
4057
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
4058
				    !empty($ifname['gateway']))
4059
					$ints[$ifdescr] = $ifdescr;
4060
			break;
4061
		}
4062
	}
4063
	return $ints;
4064
}
4065

    
4066
/* return true if interface has a gateway */
4067
function interface_has_gateway($friendly) {
4068
	global $config;
4069

    
4070
	if (!empty($config['interfaces'][$friendly])) {
4071
		$ifname = &$config['interfaces'][$friendly];
4072
		switch ($ifname['ipaddr']) {
4073
			case "dhcp":
4074
			case "carpdev-dhcp":
4075
			case "pppoe":
4076
			case "pptp":
4077
			case "l2tp":
4078
			case "ppp";
4079
				return true;
4080
			break;
4081
			default:
4082
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
4083
					return true;
4084
				if (!empty($ifname['gateway']))
4085
					return true;
4086
			break;
4087
		}
4088
	}
4089

    
4090
	return false;
4091
}
4092

    
4093
/* return true if interface has a gateway */
4094
function interface_has_gatewayv6($friendly) {
4095
	global $config;
4096

    
4097
	if (!empty($config['interfaces'][$friendly])) {
4098
		$ifname = &$config['interfaces'][$friendly];
4099
		switch ($ifname['ipaddrv6']) {
4100
			case "dhcp6":
4101
				return true;
4102
			break;
4103
			default:
4104
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
4105
					return true;
4106
				if (!empty($ifname['gatewayv6']))
4107
					return true;
4108
			break;
4109
		}
4110
	}
4111

    
4112
	return false;
4113
}
4114

    
4115
/****f* interfaces/is_altq_capable
4116
 * NAME
4117
 *   is_altq_capable - Test if interface is capable of using ALTQ
4118
 * INPUTS
4119
 *   $int            - string containing interface name
4120
 * RESULT
4121
 *   boolean         - true or false
4122
 ******/
4123

    
4124
function is_altq_capable($int) {
4125
        /* Per:
4126
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
4127
         * Only the following drivers have ALTQ support
4128
         */
4129
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
4130
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
4131
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
4132
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
4133
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
4134
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
4135
			"l2tp", "ppp");
4136

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

    
4139
        if (in_array($int_family[0], $capable))
4140
                return true;
4141
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4142
		return true;
4143
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4144
		return true;
4145
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4146
		return true;
4147
        else
4148
                return false;
4149
}
4150

    
4151
/****f* interfaces/is_interface_wireless
4152
 * NAME
4153
 *   is_interface_wireless - Returns if an interface is wireless
4154
 * RESULT
4155
 *   $tmp       - Returns if an interface is wireless
4156
 ******/
4157
function is_interface_wireless($interface) {
4158
        global $config, $g;
4159

    
4160
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
4161
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
4162
                if (preg_match($g['wireless_regex'], $interface)) {
4163
                        if (isset($config['interfaces'][$friendly]))
4164
                                $config['interfaces'][$friendly]['wireless'] = array();
4165
                        return true;
4166
                }
4167
                return false;
4168
        } else
4169
                return true;
4170
}
4171

    
4172
function get_wireless_modes($interface) {
4173
	/* return wireless modes and channels */
4174
	$wireless_modes = array();
4175

    
4176
	$cloned_interface = get_real_interface($interface);
4177

    
4178
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4179
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4180
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4181
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4182

    
4183
		$interface_channels = "";
4184
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4185
		$interface_channel_count = count($interface_channels);
4186

    
4187
		$c = 0;
4188
		while ($c < $interface_channel_count)
4189
		{
4190
			$channel_line = explode(",", $interface_channels["$c"]);
4191
			$wireless_mode = trim($channel_line[0]);
4192
			$wireless_channel = trim($channel_line[1]);
4193
			if(trim($wireless_mode) != "") {
4194
				/* if we only have 11g also set 11b channels */
4195
				if($wireless_mode == "11g") {
4196
					if(!isset($wireless_modes["11b"]))
4197
						$wireless_modes["11b"] = array();
4198
				} else if($wireless_mode == "11g ht") {
4199
					if(!isset($wireless_modes["11b"]))
4200
						$wireless_modes["11b"] = array();
4201
					if(!isset($wireless_modes["11g"]))
4202
						$wireless_modes["11g"] = array();
4203
					$wireless_mode = "11ng";
4204
				} else if($wireless_mode == "11a ht") {
4205
					if(!isset($wireless_modes["11a"]))
4206
						$wireless_modes["11a"] = array();
4207
					$wireless_mode = "11na";
4208
				}
4209
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4210
			}
4211
			$c++;
4212
		}
4213
	}
4214
	return($wireless_modes);
4215
}
4216

    
4217
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4218
function get_wireless_channel_info($interface) {
4219
	$wireless_channels = array();
4220

    
4221
	$cloned_interface = get_real_interface($interface);
4222

    
4223
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4224
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4225
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4226
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4227

    
4228
		$interface_channels = "";
4229
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4230

    
4231
		foreach ($interface_channels as $channel_line) {
4232
			$channel_line = explode(",", $channel_line);
4233
			if(!isset($wireless_channels[$channel_line[0]]))
4234
				$wireless_channels[$channel_line[0]] = $channel_line;
4235
		}
4236
	}
4237
	return($wireless_channels);
4238
}
4239

    
4240
/****f* interfaces/get_interface_mtu
4241
 * NAME
4242
 *   get_interface_mtu - Return the mtu of an interface
4243
 * RESULT
4244
 *   $tmp       - Returns the mtu of an interface
4245
 ******/
4246
function get_interface_mtu($interface) {
4247
        $mtu = pfSense_get_interface_addresses($interface);
4248
        return $mtu['mtu'];
4249
}
4250

    
4251
function get_interface_mac($interface) {
4252

    
4253
	$macinfo = pfSense_get_interface_addresses($interface);
4254
	return $macinfo["macaddr"];
4255
}
4256

    
4257
/****f* pfsense-utils/generate_random_mac_address
4258
 * NAME
4259
 *   generate_random_mac - generates a random mac address
4260
 * INPUTS
4261
 *   none
4262
 * RESULT
4263
 *   $mac - a random mac address
4264
 ******/
4265
function generate_random_mac_address() {
4266
        $mac = "02";
4267
        for($x=0; $x<5; $x++)
4268
                $mac .= ":" . dechex(rand(16, 255));
4269
        return $mac;
4270
}
4271

    
4272
/****f* interfaces/is_jumbo_capable
4273
 * NAME
4274
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4275
 * INPUTS
4276
 *   $int             - string containing interface name
4277
 * RESULT
4278
 *   boolean          - true or false
4279
 ******/
4280
function is_jumbo_capable($iface) {
4281

    
4282

    
4283
	$iface = trim($iface);
4284
	$capable = pfSense_get_interface_addresses($iface);
4285
	if (isset($capable['caps']['vlanmtu']))
4286
                return true;
4287

    
4288

    
4289

    
4290

    
4291

    
4292
	return false;
4293
}
4294

    
4295
function setup_pppoe_reset_file($pppif, $iface="") {
4296
	global $g;
4297
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4298

    
4299
	if(!empty($iface) && !empty($pppif)){
4300
		$cron_cmd = <<<EOD
4301
#!/bin/sh
4302
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4303
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
4304

    
4305
EOD;
4306

    
4307
		file_put_contents($cron_file, $cron_cmd);
4308
		chmod($cron_file, 0700);
4309
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4310
	} else
4311
		unlink_if_exists($cron_file);
4312
}
4313

    
4314
function get_interface_default_mtu($type = "ethernet") {
4315
	switch ($type) {
4316
	case "gre":
4317
		return 1476;
4318
		break;
4319
	case "gif":
4320
		return 1280;
4321
		break;
4322
	case "tun":
4323
	case "vlan":
4324
	case "tap":
4325
	case "ethernet":
4326
	default:
4327
		return 1500;
4328
		break;
4329
	}
4330

    
4331
	/* Never reached */
4332
	return 1500;
4333
}
4334

    
4335
function get_vip_descr($ipaddress) {
4336
	global $config;
4337

    
4338
	foreach ($config['virtualip']['vip'] as $vip) {
4339
		if ($vip['subnet'] == $ipaddress) {
4340
			return ($vip['descr']);
4341
		}
4342
	}
4343
	return "";
4344
}
4345

    
4346
function interfaces_staticarp_configure($if) {
4347
	global $config, $g;
4348
	if(isset($config['system']['developerspew'])) {
4349
		$mt = microtime();
4350
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4351
	}
4352

    
4353
	$ifcfg = $config['interfaces'][$if];
4354

    
4355
	if (empty($if) || empty($ifcfg['if']))
4356
		return 0;
4357

    
4358
	/* Enable staticarp, if enabled */
4359
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4360
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4361
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4362
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4363

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

    
4367
			}
4368

    
4369
		}
4370
	} else {
4371
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4372
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4373
	}
4374

    
4375
	return 0;
4376
}
4377

    
4378
?>
(26-26/64)