Project

General

Profile

Download (112 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_MODULE:	interfaces
41

    
42
*/
43

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

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

    
87
function interface_netgraph_needed($interface = "wan") {
88
	global $config;
89

    
90
	$found = false;
91
	if (!empty($config['pptpd']) &&
92
		$config['pptpd']['mode'] == "server")
93
		$found = true;
94
	if ($found == false && !empty($config['l2tp']) &&
95
		$config['l2tp']['mode'] == "server")
96
		$found = true;
97
	if ($found == false && is_array($config['pppoes']['pppoe'])) {
98
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
99
			if ($pppoe['mode'] != "server")
100
				continue;
101
			if ($pppoe['interface'] == $interface)
102
				$found = true;
103
				break;
104
		}
105
	}
106
	if ($found == false) {
107
		if (!empty($config['interfaces'][$interface])) {
108
			switch ($config['interfaces'][$interface]['ipaddr']) {
109
			case "ppp":
110
			case "pppoe":
111
			case "l2tp":
112
			case "pptp":
113
				$found = true;
114
				break;
115
			default:
116
				$found = false;
117
				break;
118
			}
119
		}
120
	}
121
	if ($found == false) {
122
		$realif = get_real_interface($interface);
123
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
124
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
125

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

    
130
				if ($realif == $ppp['if']) {
131
					$found = true;
132
					break;
133
				}
134
*/			
135
				$ports = explode(',',$ppp['ports']);
136
				foreach($ports as $pid => $port){
137
					$port = get_real_interface($port);
138
					if ($realif == $port) {
139
						$found = true;
140
						break;
141
					}
142
					/* Find the parent interfaces of the vlans in the MLPPP configs 
143
					* there should be only one element in the array here 
144
					* -- this could be better . . . */
145
					$parent_if = get_parent_interface($port);
146
					if ($realif == $parent_if[0]) {
147
						$found = true;
148
						break;
149
					}
150
				}
151
			}
152
		}
153
	}
154
	
155
	if ($found == false) {
156
		$realif = get_real_interface($interface);
157
		pfSense_ngctl_detach("{$realif}:", $realif);
158
	}
159
	/* NOTE: We make sure for this on interface_ppps_configure()
160
	 *	no need to do it here agan.
161
	 *	else
162
	 *		pfSense_ngctl_attach(".", $realif);
163
	 */
164
}
165

    
166
function interfaces_loopback_configure() {
167
	if($g['booting'])
168
		echo "Configuring loopback interface...";
169
	pfSense_interface_setaddress("lo0", "127.0.0.1");
170
	interfaces_bring_up("lo0");
171
	if($g['booting'])
172
		echo "done.\n";
173
	return 0;
174
}
175

    
176
function interfaces_vlan_configure() {
177
	global $config, $g;
178
	if($g['booting'])
179
		echo "Configuring VLAN interfaces...";
180
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
181
		foreach ($config['vlans']['vlan'] as $vlan) {
182
			if(empty($vlan['vlanif']))
183
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
184
			/* XXX: Maybe we should report any errors?! */
185
			interface_vlan_configure($vlan);
186
		}
187
	}
188
	if($g['booting'])
189
		echo "done.\n";
190
}
191

    
192
function interface_vlan_configure(&$vlan) {
193
        global $config, $g;
194

    
195
	if (!is_array($vlan)) {
196
		log_error("VLAN: called with wrong options. Problems with config!");
197
		return;
198
	}
199
	$if = $vlan['if'];
200
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
201
	$tag = $vlan['tag'];
202

    
203
	if (empty($if)) {
204
		log_error("interface_vlan_confgure called with if undefined.");
205
		return;
206
	}
207

    
208
	/* make sure the parent interface is up */
209
	interfaces_bring_up($if);
210
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
211
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
212

    
213
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
214
		interface_bring_down($vlanif, true);
215
	} else {
216
		$tmpvlanif = pfSense_interface_create("vlan");
217
		pfSense_interface_rename($tmpvlanif, $vlanif);
218
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
219
	}
220

    
221
	pfSense_vlan_create($vlanif, $if, $tag);
222

    
223
	interfaces_bring_up($vlanif);
224

    
225
	/* invalidate interface cache */
226
	get_interface_arr(true);
227

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

    
231
	return $vlanif;
232
}
233

    
234
function interface_qinq_configure(&$vlan, $fd = NULL) {
235
        global $config, $g;
236

    
237
        if (!is_array($vlan)) {
238
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
239
                return;
240
        }
241

    
242
        $qinqif = $vlan['if'];
243
        $tag = $vlan['tag'];
244
        if(empty($qinqif)) {
245
                log_error("interface_qinq_confgure called with if undefined.\n");
246
                return;
247
        }
248
	$vlanif = interface_vlan_configure($vlan);
249

    
250
        if ($fd == NULL) {
251
                $exec = true;
252
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
253
        } else
254
                $exec = false;
255
        /* make sure the parent is converted to ng_vlan(4) and is up */
256
        interfaces_bring_up($qinqif);
257

    
258
	pfSense_ngctl_attach(".", $qinqif);
259
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
260
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
261
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
262
                if (empty($result)) {
263
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
264
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
265
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
266
                }
267
        } else {
268
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
269
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
270
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
271
        }
272

    
273
        /* invalidate interface cache */
274
        get_interface_arr(true);
275

    
276
        if (!stristr($qinqif, "vlan"))
277
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
278

    
279
        $macaddr = get_interface_mac($qinqif);
280
        if (!empty($vlan['members'])) {
281
                $members = explode(" ", $vlan['members']);
282
                foreach ($members as $qtag) {
283
                        $qinq = array();
284
                        $qinq['tag'] = $qtag;
285
                        $qinq['if'] = $vlanif;
286
                        interface_qinq2_configure($qinq, $fd, $macaddr);
287
                }
288
        }
289
        if ($exec == true) {
290
                fclose($fd);
291
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
292
        }
293

    
294
        interfaces_bring_up($qinqif);
295
        if (!empty($vlan['members'])) {
296
                $members = explode(" ", $vlan['members']);
297
                foreach ($members as $qif)
298
                        interfaces_bring_up("{$vlanif}_{$qif}");
299
        }
300

    
301
        return $vlanif;
302
}
303

    
304
function interfaces_qinq_configure() {
305
	global $config, $g;
306
	if($g['booting'])
307
		echo "Configuring QinQ interfaces...";
308
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
309
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
310
			/* XXX: Maybe we should report any errors?! */
311
			interface_qinq_configure($qinq);
312
		}
313
	}
314
	if($g['booting'])
315
		echo "done.\n";
316
}
317

    
318
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
319
        global $config, $g;
320

    
321
        if (!is_array($qinq)) {
322
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
323
                return;
324
        }
325

    
326
        $if = $qinq['if'];
327
        $tag = $qinq['tag'];
328
        $vlanif = "{$if}_{$tag}";
329
        if(empty($if)) {
330
                log_error("interface_qinq_confgure called with if undefined.\n");
331
                return;
332
        }
333

    
334
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
335
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
336
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
337
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
338
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
339
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
340

    
341
        /* invalidate interface cache */
342
        get_interface_arr(true);
343

    
344
        return $vlanif;
345
}
346

    
347
function interfaces_create_wireless_clones() {
348
	global $config;
349

    
350
	if($g['booting'])
351
		echo "Creating other wireless clone interfaces...";
352
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
353
		foreach ($config['wireless']['clone'] as $clone) {
354
			if(empty($clone['cloneif']))
355
				continue;
356
			if(does_interface_exist($clone['cloneif']))
357
				continue;
358
			/* XXX: Maybe we should report any errors?! */
359
			if(interface_wireless_clone($clone['cloneif'], $clone))
360
				if($g['booting'])
361
					echo " " . $clone['cloneif'];
362
		}
363
	}
364
	if($g['booting'])
365
		echo " done.\n";
366
}
367

    
368
function interfaces_bridge_configure($checkmember = 0) {
369
        global $config;
370

    
371
        $i = 0;
372
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
373
                foreach ($config['bridges']['bridged'] as $bridge) {
374
                        if(empty($bridge['bridgeif']))
375
                                $bridge['bridgeif'] = "bridge{$i}";
376
			if ($checkmember == 1 && (strstr($bridge['members'], "gif") || strstr($bridge['members'], "gre")))
377
				continue;
378
			if ($checkmember == 2 && !strstr($bridge['members'], "gif") && !strstr($bridge['members'], "gre"))
379
				continue;
380
                        /* XXX: Maybe we should report any errors?! */
381
                        interface_bridge_configure($bridge);
382
                        $i++;
383
                }
384
        }
385
}
386

    
387
function interface_bridge_configure(&$bridge) {
388
	global $config, $g;
389

    
390
	if (!is_array($bridge))
391
	        return -1;
392

    
393
	if (empty($bridge['members'])) {
394
		log_error("No members found on {$bridge['bridgeif']}");
395
		return -1;
396
	}
397

    
398
	$members = explode(',', $bridge['members']);
399
	if (!count($members))
400
		return -1;
401

    
402
	$checklist = get_configured_interface_list();
403

    
404
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
405
		pfSense_interface_destroy($bridge['bridgeif']);
406
		pfSense_interface_create($bridge['bridgeif']);
407
		$bridgeif = $bridge['bridgeif'];
408
	} else
409
		$bridgeif = pfSense_interface_create("bridge");
410

    
411
	/* Calculate smaller mtu and enforce it */
412
	$smallermtu = 0;
413
	$commonrx = true;
414
	$commontx = true;
415
	foreach ($members as $member) {
416
		$realif = get_real_interface($member);
417
		$opts = pfSense_get_interface_addresses($realif);
418
		$mtu = $opts['mtu'];
419
		if (!isset($opts['encaps']['txcsum']))
420
			$commontx = false;
421
		if (!isset($opts['encaps']['rxcsum']))
422
			$commonrx = false;
423
		if (!isset($opts['encaps']['tso4']))
424
			$commontso4 = false;
425
		if (!isset($opts['encaps']['tso6']))
426
			$commontso6 = false;
427
		if (!isset($opts['encaps']['lro']))
428
			$commonlro = false;
429
		if ($smallermtu == 0 && !empty($mtu))
430
			$smallermtu = $mtu;
431
		else if (!empty($mtu) && $mtu < $smallermtu)
432
			$smallermtu = $mtu;
433
	}
434
	 
435
	/* Just in case anything is not working well */
436
	if ($smallermtu == 0)
437
		$smallermtu = 1500; 
438

    
439
	$flags = 0;
440
	if ($commonrx === false)
441
		$flags |= IFCAP_RXCSUM;
442
	if ($commontx === false)
443
		$flags |= IFCAP_TXCSUM;
444
	if ($commontso4 === false)
445
		$flags |= IFCAP_TSO4;
446
	if ($commontso6 === false)
447
		$flags |= IFCAP_TSO6;
448
	if ($commonlro === false)
449
		$flags |= IFCAP_LRO;
450
		
451
	/* Add interfaces to bridge */
452
	foreach ($members as $member) {
453
		if (!array_key_exists($member, $checklist))
454
			continue;
455
		$realif1 = get_real_interface($member);
456
		$realif =  escapeshellarg($realif1);
457
		if (!$realif) {
458
			log_error("realif not defined in interfaces bridge - up");
459
			continue;
460
		}
461
		/* make sure the parent interface is up */
462
		pfSense_interface_mtu($realif1, $smallermtu);
463
		pfSense_interface_capabilities($realif1, -$flags);
464
		interfaces_bring_up($realif1);
465
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
466
	}
467

    
468
	if (isset($bridge['enablestp'])) {
469
		/* Choose spanning tree proto */
470
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
471
		
472
		if (!empty($bridge['stp'])) {
473
			$stpifs = explode(',', $bridge['stp']);
474
			foreach ($stpifs as $stpif) {
475
				$realif = get_real_interface($stpif);
476
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
477
			}
478
		}
479
		if (!empty($bridge['maxage']))
480
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
481
		if (!empty($brige['fwdelay']))
482
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
483
		if (!empty($brige['hellotime']))
484
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
485
		if (!empty($brige['priority']))
486
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
487
		if (!empty($brige['holdcount']))
488
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
489
		if (!empty($bridge['ifpriority'])) {
490
			$pconfig = explode(",", $bridge['ifpriority']);
491
			$ifpriority = array();
492
			foreach ($pconfig as $cfg) {
493
				$embcfg = explode(":", $cfg);
494
				foreach ($embcfg as $key => $value)
495
					$ifpriority[$key] = $value;
496
			}
497
			foreach ($ifpriority as $key => $value) {
498
				$realif = get_real_interface($key);
499
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
500
			}
501
		}
502
		if (!empty($bridge['ifpathcost'])) {
503
			$pconfig = explode(",", $bridges['ifpathcost']);
504
			$ifpathcost = array();
505
			foreach ($pconfig as $cfg) {
506
				$embcfg = explode(":", $cfg);
507
				foreach ($embcfg as $key => $value)
508
					$ifpathcost[$key] = $value;
509
			}
510
			foreach ($ifpathcost as $key => $value) {
511
                        	$realif = get_real_interface($key);
512
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
513
                	}
514
		}
515
	}
516

    
517
	if ($bridge['maxaddr'] <> "")
518
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
519
        if ($bridge['timeout'] <> "")
520
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
521
        if ($bridge['span'] <> "") {
522
		$realif = get_real_interface($bridge['span']);
523
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
524
	}
525
	if (!empty($bridge['edge'])) {
526
        	$edgeifs = explode(',', $bridge['edge']);
527
        	foreach ($edgeifs as $edgeif) {
528
			$realif = get_real_interface($edgeif);
529
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
530
        	}
531
	}
532
	if (!empty($bridge['autoedge'])) {
533
        	$edgeifs = explode(',', $bridge['autoedge']);
534
        	foreach ($edgeifs as $edgeif) {
535
                	$realif = get_real_interface($edgeif);
536
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
537
        	}
538
	}
539
	if (!empty($bridge['ptp'])) {
540
        	$ptpifs = explode(',', $bridge['ptp']);
541
        	foreach ($ptpifs as $ptpif) {
542
                	$realif = get_real_interface($ptpif);
543
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
544
        	}
545
	}
546
	if (!empty($bridge['autoptp'])) {
547
        	$ptpifs = explode(',', $bridge['autoptp']);
548
        	foreach ($ptpifs as $ptpif) {
549
                	$realif = get_real_interface($ptpif);
550
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
551
        	}
552
	}
553
	if (!empty($bridge['static'])) {
554
        	$stickyifs = explode(',', $bridge['static']);
555
        	foreach ($stickyifs as $stickyif) {
556
                	$realif = get_real_interface($stickyif);
557
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
558
        	}
559
	}
560
	if (!empty($bridge['private'])) {
561
        	$privateifs = explode(',', $bridge['private']);
562
        	foreach ($privateifs as $privateif) {
563
                	$realif = get_real_interface($privateif);
564
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
565
        	}
566
	}
567

    
568
	if($bridgeif)
569
		interfaces_bring_up($bridgeif);	
570
	else 
571
		log_error("bridgeif not defined -- could not bring interface up");
572

    
573
	return $bridgeif;
574
}
575

    
576
function interface_bridge_add_member($bridgeif, $interface) {
577

    
578
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
579
		return;
580

    
581
	$mtu = get_interface_mtu($brigeif);
582
	$mtum = get_interface_mtu($interface);
583
	
584
	if ($mtu != $mtum)
585
		pfSense_interface_mtu($interface, $mtu);
586

    
587
	$options = pfSense_get_interface_addresses($bridgeif);
588
	$flags = 0;
589
	if (!isset($options['encaps']['txcsum']))
590
		$flags |= IFCAP_TXCSUM;
591

    
592
	if (!isset($options['encaps']['rxcsum']))
593
		$flags |= IFCAP_RXCSUM;
594

    
595
	pfSense_interface_capabilities($interface, -$flags);
596

    
597
	interfaces_bring_up($interface);
598
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
599
}
600

    
601
function interfaces_lagg_configure() 
602
{
603
        global $config, $g;
604
		if($g['booting']) 
605
			echo "Configuring LAGG interfaces...";
606
        $i = 0;
607
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
608
			foreach ($config['laggs']['lagg'] as $lagg) {
609
				if(empty($lagg['laggif']))
610
					$lagg['laggif'] = "lagg{$i}";
611
				/* XXX: Maybe we should report any errors?! */
612
				interface_lagg_configure($lagg);
613
				$i++;
614
			}
615
		}
616
		if($g['booting']) 
617
			echo "done.\n";
618
}
619

    
620
function interface_lagg_configure(&$lagg) {
621
        global $config, $g;
622

    
623
        if (!is_array($lagg))
624
		return -1;
625

    
626
	$members = explode(',', $lagg['members']);
627
	if (!count($members))
628
		return -1;
629
	
630
	$checklist = get_interface_list();
631

    
632
	if ($g['booting'] || !(empty($lagg['laggif']))) {
633
		pfSense_interface_destroy($lagg['laggif']);
634
		pfSense_interface_create($lagg['laggif']);
635
                $laggif = $lagg['laggif'];
636
        } else
637
		$laggif = pfSense_interface_create("lagg");
638

    
639
	/* Calculate smaller mtu and enforce it */
640
        $smallermtu = 0;
641
        foreach ($members as $member) {
642
		$opts = pfSense_get_interface_addresses($member);
643
                $mtu = $opts['mtu'];
644
		if (!isset($opts['encaps']['txcsum']))
645
                        $commontx = false;
646
                if (!isset($opts['encaps']['rxcsum']))
647
                        $commonrx = false;
648
		if (!isset($opts['encaps']['tso4']))
649
			$commontso4 = false;
650
		if (!isset($opts['encaps']['tso6']))
651
			$commontso6 = false;
652
		if (!isset($opts['encaps']['lro']))
653
			$commonlro = false;
654
		if ($smallermtu == 0 && !empty($mtu))
655
			$smallermtu = $mtu;
656
                else if (!empty($mtu) && $mtu < $smallermtu)
657
                        $smallermtu = $mtu;
658
        }
659

    
660
	/* Just in case anything is not working well */
661
        if ($smallermtu == 0)
662
                $smallermtu = 1500;
663

    
664
	$flags = 0;
665
        if ($commonrx === false)
666
                $flags |= IFCAP_RXCSUM;
667
        if ($commontx === false)
668
                $flags |= IFCAP_TXCSUM;
669
	if ($commontso4 === false)
670
                $flags |= IFCAP_TSO4;
671
        if ($commontso6 === false)
672
                $flags |= IFCAP_TSO6;
673
        if ($commonlro === false)
674
                $flags |= IFCAP_LRO;
675

    
676
	foreach ($members as $member) {
677
		if (!array_key_exists($member, $checklist))
678
			continue;
679
		/* make sure the parent interface is up */
680
		pfSense_interface_mtu($member, $smallermtu);
681
		pfSense_interface_capabilities($member, -$flags);
682
		interfaces_bring_up($member);
683
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
684
	}
685
	
686
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
687

    
688
	interfaces_bring_up($laggif);
689

    
690
	return $laggif;
691
}
692

    
693
function interfaces_gre_configure($checkparent = 0) {
694
        global $config;
695

    
696
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
697
                foreach ($config['gres']['gre'] as $i => $gre) {
698
                        if(empty($gre['greif']))
699
                                $gre['greif'] = "gre{$i}";
700
			if ($checkparent == 1 && strstr($gre['if'], "vip"))
701
				continue;
702
			if ($checkparent == 2 && !strstr($gre['if'], "vip"))
703
				continue;
704
                        /* XXX: Maybe we should report any errors?! */
705
                        interface_gre_configure($gre);
706
                }
707
        }
708
}
709

    
710
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
711
function interface_gre_configure(&$gre, $grekey = "") {
712
        global $config, $g;
713

    
714
	if (!is_array($gre))
715
		return -1;
716

    
717
	$realif = get_real_interface($gre['if']);
718
	$realifip = get_interface_ip($gre['if']);
719

    
720
	/* make sure the parent interface is up */
721
	interfaces_bring_up($realif);
722

    
723
	if ($g['booting'] || !(empty($gre['greif']))) {
724
		pfSense_interface_destroy($gre['greif']);
725
		pfSense_interface_create($gre['greif']);
726
		$greif = $gre['greif'];
727
	} else
728
		$greif = pfSense_interface_create("gre");
729

    
730
	/* Do not change the order here for more see gre(4) NOTES section. */
731
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
732
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
733
	if (isset($gre['link0']) && $gre['link0'])
734
		pfSense_interface_flags($greif, IFF_LINK0);
735
	if (isset($gre['link1']) && $gre['link1'])
736
		pfSense_interface_flags($greif, IFF_LINK1);
737
	if (isset($gre['link2']) && $gre['link2'])
738
		pfSense_interface_flags($greif, IFF_LINK2);
739

    
740
	if($greif)
741
		interfaces_bring_up($greif);
742
	else 
743
		log_error("Could not bring greif up -- variable not defined.");
744

    
745
	if (isset($gre['link1']) && $gre['link1'])
746
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
747
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
748
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
749
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
750
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
751

    
752
	return $greif;
753
}
754

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

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

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

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

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

    
782
	/* make sure the parent interface is up */
783
	if($realif)
784
		interfaces_bring_up($realif);
785
	else 
786
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
787

    
788
	if ($g['booting'] || !(empty($gif['gifif']))) {
789
		pfSense_interface_destroy($gif['gifif']);
790
		pfSense_interface_create($gif['gifif']);
791
		$gifif = $gif['gifif'];
792
	} else
793
		$gifif = pfSense_interface_create("gif");
794

    
795
	/* Do not change the order here for more see gif(4) NOTES section. */
796
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
797
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
798
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen {$gif['tunnel-remote-net']} ");
799
	} else {
800
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
801
	}
802
	if (isset($gif['link0']) && $gif['link0'])
803
		pfSense_interface_flags($gifif, IFF_LINK0);
804
	if (isset($gif['link1']) && $gif['link1'])
805
		pfSense_interface_flags($gifif, IFF_LINK1);
806
	if($gifif)
807
		interfaces_bring_up($gifif);
808
	else
809
		log_error("could not bring gifif up -- variable not defined");
810

    
811
	/* XXX: Needed?! Let them use the defined gateways instead */
812
	//mwexec("/sbin/route add {$gif['tunnel-remote-addr']}/{$gif['tunnel-remote-net']} -iface {$gifif}");
813

    
814
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
815
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
816
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
817
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
818

    
819
	return $gifif;
820
}
821

    
822
function interfaces_configure() {
823
	global $config, $g;
824

    
825
	/* Set up our loopback interface */
826
	interfaces_loopback_configure();
827

    
828
	/* set up LAGG virtual interfaces */
829
	interfaces_lagg_configure();
830

    
831
	/* set up VLAN virtual interfaces */
832
	interfaces_vlan_configure();
833

    
834
	interfaces_qinq_configure();
835

    
836
	$iflist = get_configured_interface_with_descr();
837
	$delayed_list = array();
838
	$bridge_list = array();
839
	
840
	/* This is needed to speedup interfaces on bootup. */
841
	$reload = false;
842
	if ($g['booting'])
843
		$reload = true;
844

    
845
	foreach($iflist as $if => $ifname) {
846
		$realif = $config['interfaces'][$if]['if'];
847
		if (strstr($realif, "bridge")) 
848
			$bridge_list[$if] = $ifname;
849
		else if (strstr($realif, "gre"))
850
			$delayed_list[$if] = $ifname;
851
		else if (strstr($realif, "gif"))
852
			$delayed_list[$if] = $ifname;
853
		else if (strstr($realif, "ovpn")) {
854
			//echo "Delaying OpenVPN interface configuration...done.\n";
855
			continue;
856
		} else {
857
			if ($g['booting'])
858
				echo "Configuring {$ifname} interface...";
859
			if($g['debug'])
860
				log_error("Configuring {$ifname}");
861
			interface_configure($if, $reload);
862
			if ($g['booting']) 
863
				echo "done.\n";
864
		}
865
	}
866

    
867
	/* create the unconfigured wireless clones */
868
	interfaces_create_wireless_clones();
869

    
870
	/*
871
	 * NOTE: The following function parameter consists of
872
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
873
	 *	2 - Do load gre/gif/bridge with parent/member as vip
874
	 */
875

    
876
	/* set up GRE virtual interfaces */
877
	interfaces_gre_configure(1);
878

    
879
	/* set up GIF virtual interfaces */
880
	interfaces_gif_configure(1);
881

    
882
	/* set up BRIDGe virtual interfaces */
883
	interfaces_bridge_configure(1);
884

    
885
	/* bring up vip interfaces */
886
	interfaces_vips_configure();
887

    
888
	/* set up GRE virtual interfaces */
889
	interfaces_gre_configure(2);
890

    
891
	/* set up GIF virtual interfaces */
892
	interfaces_gif_configure(2);
893

    
894
	foreach ($delayed_list as $if => $ifname) {
895
		if ($g['booting'])
896
			echo "Configuring {$ifname} interface...";
897
        	if ($g['debug'])
898
        		log_error("Configuring {$ifname}");
899

    
900
		interface_configure($if, $reload);
901

    
902
		if ($g['booting'])
903
			echo "done.\n";
904
	}
905

    
906
	/* set up BRIDGe virtual interfaces */
907
	interfaces_bridge_configure(2);
908

    
909
	foreach ($bridge_list as $if => $ifname) {
910
		if ($g['booting'])
911
			echo "Configuring {$ifname} interface...";
912
		if($g['debug'])
913
			log_error("Configuring {$ifname}");
914

    
915
		interface_configure($if, $reload);
916

    
917
		if ($g['booting'])
918
			echo "done.\n";
919
	}
920

    
921
	/* configure interface groups */
922
	interfaces_group_setup();
923

    
924
	if (!$g['booting']) {
925
		/* reconfigure static routes (kernel may have deleted them) */
926
		system_routing_configure();
927

    
928
		/* reload IPsec tunnels */
929
		vpn_ipsec_configure();
930

    
931
		/* reload dhcpd (interface enabled/disabled status may have changed) */
932
		services_dhcpd_configure();
933

    
934
		/* restart dnsmasq */
935
		services_dnsmasq_configure();
936

    
937
		/* reload captive portal */
938
		captiveportal_init_rules();
939
	}
940

    
941
	return 0;
942
}
943

    
944
function interface_reconfigure($interface = "wan") {
945
	interface_bring_down($interface);
946
	interface_configure($interface, true);
947
}
948

    
949
function interface_vip_bring_down($vip) {
950
	global $g;
951

    
952
	switch ($vip['mode']) {
953
	case "proxyarp":
954
		$vipif = get_real_interface($vip['interface']);
955
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
956
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
957
		break;
958
	case "ipalias":
959
		$vipif = get_real_interface($vip['interface']);
960
		if(does_interface_exist($vipif))
961
			pfSense_interface_deladdress($vipif, $vip['subnet']);
962
		break;
963
	case "carp":
964
		$vipif = "vip" . $vip['vhid'];
965
		if(does_interface_exist($vipif)) 
966
			pfSense_interface_destroy($vipif);
967
		break;
968
	case "carpdev-dhcp":
969
		$vipif = "vip" . $vip['vhid'];
970
		if(does_interface_exist($vipif)) 
971
			pfSense_interface_destroy($vipif);
972
		break;
973
	}
974
}
975

    
976
function interface_bring_down($interface = "wan", $destroy = false) {
977
	global $config, $g;
978

    
979
	if (!isset($config['interfaces'][$interface]))
980
		return; 
981

    
982
	$ifcfg = $config['interfaces'][$interface];
983

    
984
	$realif = get_real_interface($interface);
985

    
986
	switch ($ifcfg['ipaddr']) {
987
	case "ppp":
988
	case "pppoe":
989
	case "pptp":
990
	case "l2tp":
991
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
992
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
993
				if ($realif == $ppp['if']) {
994
					if (isset($ppp['ondemand']) && !$destroy){
995
						send_event("interface reconfigure {$interface}");
996
						break;
997
					}
998
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
999
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1000
						sleep(2);
1001
					}
1002
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1003
					break;
1004
				}
1005
			}
1006
		}
1007
		break;
1008
	case "carpdev-dhcp":
1009
		/* 
1010
		 * NB: When carpdev gets enabled it would be better to be handled as all
1011
		 *	   other interfaces! 
1012
		 */
1013
	case "dhcp":
1014
		$pid = find_dhclient_process($realif);
1015
		if($pid)
1016
			mwexec("/bin/kill {$pid}");
1017
		sleep(1);
1018
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1019
		if(does_interface_exist("$realif")) {
1020
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1021
			if ($destroy == true)
1022
				pfSense_interface_flags($realif, -IFF_UP);
1023
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1024
		}
1025
		break;
1026
	default:
1027
		if(does_interface_exist("$realif")) {
1028
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1029
			if ($destroy == true)
1030
				pfSense_interface_flags($realif, -IFF_UP);
1031
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1032
		}
1033
		break;
1034
	}
1035

    
1036
	/* remove interface up file if it exists */
1037
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1038
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1039
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1040
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1041
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1042
	
1043
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1044
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1045
	if (is_array($ifcfg['wireless'])) {
1046
		mwexec(kill_hostapd($realif));
1047
		mwexec(kill_wpasupplicant($realif));
1048
	}
1049

    
1050
	if ($destroy == true) {
1051
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1052
			pfSense_interface_destroy($realif);
1053
	}	
1054

    
1055
	return;
1056
}
1057

    
1058
function interfaces_ptpid_used($ptpid) {
1059
	global $config;
1060

    
1061
	if (is_array($config['ppps']['ppp']))
1062
		foreach ($config['ppps']['ppp'] as & $settings)
1063
			if ($ptpid == $settings['ptpid'])
1064
				return true;
1065

    
1066
	return false;
1067
}
1068

    
1069
function interfaces_ptpid_next() {
1070

    
1071
	$ptpid = 0;
1072
	while(interfaces_ptpid_used($ptpid))
1073
		$ptpid++;
1074

    
1075
	return $ptpid;
1076
}
1077

    
1078
function getMPDCRONSettings($pppif_) {
1079
	global $config;
1080
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1081
	if (is_array($config['cron']['item'])) {
1082
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1083
			$item = $config['cron']['item'][$i];
1084
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1085
				return array("ID" => $i, "ITEM" => $item);
1086
			}
1087
		}
1088
	}
1089
	return NULL;
1090
}
1091

    
1092
function handle_pppoe_reset($post_array) {
1093
	global $config, $g;
1094

    
1095
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1096

    
1097
	$pppif = $post_array['type'].$post_array['ptpid'];
1098
	if (!is_array($config['cron']['item'])) 
1099
		$config['cron']['item'] = array(); 
1100
	$itemhash = getMPDCRONSettings($pppif);
1101
	$item = $itemhash['ITEM'];
1102
	
1103
	// reset cron items if necessary and return
1104
	if (empty($post_array['pppoe-reset-type'])) {
1105
		if (isset($item))
1106
			unset($config['cron']['item'][$itemhash['ID']]);
1107
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1108
		return;
1109
	}
1110

    
1111
	if (empty($item)) 
1112
		$item = array();
1113
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1114
		$item['minute'] = $post_array['pppoe_resetminute'];
1115
		$item['hour'] = $post_array['pppoe_resethour'];
1116
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1117
			$date = explode("/", $post_array['pppoe_resetdate']);
1118
			$item['mday'] = $date[1];
1119
			$item['month'] = $date[0];
1120
		} else {
1121
			$item['mday'] = "*";
1122
			$item['month'] = "*";
1123
		}
1124
		$item['wday'] = "*";
1125
		$item['who'] = "root";
1126
		$item['command'] = $cron_cmd_file.$pppif;
1127
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1128
		switch ($post_array['pppoe_pr_preset_val']) {
1129
			case "monthly":
1130
				$item['minute'] = "0";
1131
				$item['hour'] = "0";
1132
				$item['mday'] = "1";
1133
				$item['month'] = "*";
1134
				$item['wday'] = "*";
1135
				$item['who'] = "root";
1136
				$item['command'] = $cron_cmd_file.$pppif;
1137
				break;
1138
	        case "weekly":
1139
				$item['minute'] = "0";
1140
				$item['hour'] = "0";
1141
				$item['mday'] = "*";
1142
				$item['month'] = "*";
1143
				$item['wday'] = "0";
1144
				$item['who'] = "root";
1145
				$item['command'] = $cron_cmd_file.$pppif;
1146
				break;
1147
			case "daily":
1148
				$item['minute'] = "0";
1149
				$item['hour'] = "0";
1150
				$item['mday'] = "*";
1151
				$item['month'] = "*";
1152
				$item['wday'] = "*";
1153
				$item['who'] = "root";
1154
				$item['command'] = $cron_cmd_file.$pppif;
1155
				break;
1156
			case "hourly":
1157
				$item['minute'] = "0";
1158
				$item['hour'] = "*";
1159
				$item['mday'] = "*";
1160
				$item['month'] = "*";
1161
				$item['wday'] = "*";
1162
				$item['who'] = "root";
1163
				$item['command'] = $cron_cmd_file.$pppif;
1164
				break;
1165
		} // end switch
1166
	} else {
1167
		/* test whether a cron item exists and unset() it if necessary */
1168
		$itemhash = getMPDCRONSettings($pppif);
1169
		$item = $itemhash['ITEM'];
1170
		if (isset($item))
1171
			unset($config['cron']['item'][$itemhash['ID']]); 
1172
	}// end if
1173
	if (isset($itemhash['ID'])) 
1174
		$config['cron']['item'][$itemhash['ID']] = $item;
1175
	else 
1176
		$config['cron']['item'][] = $item;
1177
}
1178

    
1179
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1180
*	It writes the mpd config file to /var/etc every time the link is opened.
1181
*/
1182

    
1183
function interface_ppps_configure($interface) {
1184
	global $config, $g;
1185

    
1186
	/* Return for unassigned interfaces. This is a minimum requirement. */
1187
	if (empty($config['interfaces'][$interface]))
1188
		return 0;
1189
	$ifcfg = $config['interfaces'][$interface];
1190
	if (!isset($ifcfg['enable']))
1191
		return 0;
1192

    
1193
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1194
	if(!is_dir("/var/spool/lock")) {
1195
		exec("/bin/mkdir -p /var/spool/lock");
1196
		exec("/bin/chmod a+rw /var/spool/lock/.");
1197
	}
1198
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1199
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1200
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1201

    
1202
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1203
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1204
			if ($ifcfg['if'] == $ppp['if'])
1205
				break;
1206
		}
1207
	}
1208
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1209
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1210
		return 0;
1211
	}
1212
	$pppif = $ifcfg['if'];
1213
	if ($ppp['type'] == "ppp")
1214
		$type = "modem";
1215
	else
1216
		$type = $ppp['type'];
1217
	$upper_type = strtoupper($ppp['type']);	
1218

    
1219
	if($g['booting']) {
1220
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1221
		echo "starting {$pppif} link...";
1222
		// Do not re-configure the interface if we are booting and it's already been started
1223
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1224
			return 0;
1225
	}
1226

    
1227
	$ports = explode(',',$ppp['ports']);
1228
	if ($type != "modem") {
1229
		foreach ($ports as $pid => $port)
1230
			$ports[$pid] = get_real_interface($port);
1231
	}
1232
	$localips = explode(',',$ppp['localip']);
1233
	$gateways = explode(',',$ppp['gateway']);
1234
	$subnets = explode(',',$ppp['subnet']);
1235

    
1236
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1237
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1238
	 */
1239
	foreach($ports as $pid => $port){
1240
		switch ($ppp['type']) {
1241
			case "pppoe": 
1242
				/* Bring the parent interface up */
1243
				interfaces_bring_up($port);
1244
				pfSense_ngctl_attach(".", $port);
1245
				break;
1246
			case "pptp":
1247
			case "l2tp":
1248
				/* configure interface */
1249
				if(is_ipaddr($localips[$pid])){
1250
					// Manually configure interface IP/subnet
1251
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1252
					interfaces_bring_up($port);
1253
				} else if (empty($localips[$pid]))
1254
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1255
				
1256
				if(!is_ipaddr($localips[$pid])){
1257
					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!");
1258
					$localips[$pid] = "0.0.0.0";
1259
				}
1260
				/* XXX: This needs to go away soon! [It's commented out!] */
1261
				/* Configure the gateway (remote IP ) */
1262
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1263
					/* XXX: Fix later 
1264
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1265
					if(!is_ipaddr($gateways[$pid])) {
1266
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1267
						return 0;
1268
					}
1269
					*/
1270
				}
1271
				if(!is_ipaddr($gateways[$pid])){
1272
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1273
					return 0;
1274
				}
1275
				pfSense_ngctl_attach(".", $port);
1276
				break;
1277
			case "ppp":
1278
				if (!file_exists("{$port}")) {
1279
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1280
					return 0;
1281
				}
1282
				break;
1283
			default:
1284
				log_error("Unkown {$type} configured as ppp interface.");
1285
				break;
1286
		}
1287
	}
1288
	
1289
	if (is_array($ports) && count($ports) > 1)
1290
		$multilink = "enable";
1291
	else
1292
		$multilink = "disable";
1293
	
1294
	if ($type == "modem"){
1295
		if (is_ipaddr($ppp['localip']))
1296
			$localip = $ppp['localip'];
1297
		else
1298
			$localip = '0.0.0.0';
1299

    
1300
		if (is_ipaddr($ppp['gateway']))
1301
			$gateway = $ppp['gateway'];
1302
		else
1303
			$gateway = "10.64.64.{$pppid}";
1304
		$ranges = "{$localip}/0 {$gateway}/0";
1305
		
1306
		if (empty($ppp['apnum']))	
1307
			$ppp['apnum'] = 1;
1308
	} else
1309
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1310

    
1311
	if (isset($ppp['ondemand'])) 
1312
		$ondemand = "enable";
1313
	else
1314
		$ondemand = "disable";
1315
	if (!isset($ppp['idletimeout']))
1316
		$ppp['idletimeout'] = 0;
1317

    
1318
	if (empty($ppp['username']) && $type == "modem"){
1319
		$ppp['username'] = "user";
1320
		$ppp['password'] = "none";
1321
	}
1322
	if (empty($ppp['password']) && $type == "modem")
1323
		$passwd = "none";
1324
	else
1325
		$passwd = base64_decode($ppp['password']);
1326

    
1327
	$bandwidths = explode(',',$ppp['bandwidth']);
1328
	$mtus = explode(',',$ppp['mtu']);
1329
	$mrus = explode(',',$ppp['mru']);
1330

    
1331
	if (isset($ppp['mrru']))
1332
		$mrrus = explode(',',$ppp['mrru']);
1333

    
1334
	// Construct the mpd.conf file
1335
	$mpdconf = <<<EOD
1336
startup:
1337
	# configure the console
1338
	set console close
1339
	# configure the web server
1340
	set web close
1341

    
1342
default:
1343
{$ppp['type']}client:
1344
	create bundle static {$interface}
1345
	set bundle enable ipv6cp
1346
	set iface name {$pppif}
1347

    
1348
EOD;
1349
	$setdefaultgw = false;
1350
	$founddefaultgw = false;
1351
	if (is_array($config['gateways']['gateway_item'])) {
1352
		foreach($config['gateways']['gateway_item'] as $gateway) {
1353
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1354
				$setdefaultgw = true;
1355
				break;
1356
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1357
				$founddefaultgw = true;
1358
				break;
1359
			}
1360
		}
1361
	}
1362
	
1363
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1364
		$setdefaultgw = true;
1365
		$mpdconf .= <<<EOD
1366
	set iface route default
1367

    
1368
EOD;
1369
	}
1370
	$mpdconf .= <<<EOD
1371
	set iface {$ondemand} on-demand
1372
	set iface idle {$ppp['idletimeout']}
1373

    
1374
EOD;
1375

    
1376
	if (isset($ppp['ondemand']))
1377
		$mpdconf .= <<<EOD
1378
	set iface addrs 10.10.1.1 10.10.1.2
1379

    
1380
EOD;
1381
	
1382
	if (isset($ppp['tcpmssfix']))
1383
		$tcpmss = "disable";
1384
	else
1385
		$tcpmss = "enable";
1386
		$mpdconf .= <<<EOD
1387
	set iface {$tcpmss} tcpmssfix
1388

    
1389
EOD;
1390

    
1391
	$mpdconf .= <<<EOD
1392
	set iface up-script /usr/local/sbin/ppp-linkup
1393
	set iface down-script /usr/local/sbin/ppp-linkdown
1394
	set ipcp ranges {$ranges}
1395

    
1396
EOD;
1397
	if (isset($ppp['vjcomp']))
1398
		$mpdconf .= <<<EOD
1399
	set ipcp no vjcomp
1400

    
1401
EOD;
1402

    
1403
	if (isset($config['system']['dnsallowoverride']))
1404
		$mpdconf .= <<<EOD
1405
	set ipcp enable req-pri-dns
1406
	set ipcp enable req-sec-dns
1407

    
1408
EOD;
1409
	if (!isset($ppp['verbose_log']))
1410
		$mpdconf .= <<<EOD
1411
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1412

    
1413
EOD;
1414
	foreach($ports as $pid => $port){
1415
		$port = get_real_interface($port);
1416
		$mpdconf .= <<<EOD
1417

    
1418
	create link static {$interface}_link{$pid} {$type}
1419
	set link action bundle {$interface}
1420
	set link {$multilink} multilink
1421
	set link keep-alive 10 60
1422
	set link max-redial 0
1423

    
1424
EOD;
1425
		if (isset($ppp['shortseq']))
1426
			$mpdconf .= <<<EOD
1427
	set link no shortseq
1428

    
1429
EOD;
1430

    
1431
		if (isset($ppp['acfcomp']))
1432
			$mpdconf .= <<<EOD
1433
	set link no acfcomp
1434

    
1435
EOD;
1436

    
1437
		if (isset($ppp['protocomp']))
1438
			$mpdconf .= <<<EOD
1439
	set link no protocomp
1440

    
1441
EOD;
1442

    
1443
		$mpdconf .= <<<EOD
1444
	set link disable chap pap
1445
	set link accept chap pap eap
1446
	set link disable incoming
1447

    
1448
EOD;
1449

    
1450

    
1451
		if (!empty($bandwidths[$pid]))
1452
			$mpdconf .= <<<EOD
1453
	set link bandwidth {$bandwidths[$pid]}
1454

    
1455
EOD;
1456

    
1457
		if (empty($mtus[$pid]))
1458
			$mtus[$pid] = "1492";
1459
			$mpdconf .= <<<EOD
1460
	set link mtu {$mtus[$pid]}
1461

    
1462
EOD;
1463

    
1464
		if (!empty($mrus[$pid]))
1465
			$mpdconf .= <<<EOD
1466
	set link mru {$mrus[$pid]}
1467

    
1468
EOD;
1469

    
1470
		if (!empty($mrrus[$pid]))
1471
			$mpdconf .= <<<EOD
1472
	set link mrru {$mrrus[$pid]}
1473

    
1474
EOD;
1475

    
1476
		$mpdconf .= <<<EOD
1477
	set auth authname "{$ppp['username']}"
1478
	set auth password {$passwd}
1479

    
1480
EOD;
1481
		if ($type == "modem") {
1482
			$mpdconf .= <<<EOD
1483
	set modem device {$ppp['ports']}
1484
	set modem script DialPeer
1485
	set modem idle-script Ringback
1486
	set modem watch -cd
1487
	set modem var \$DialPrefix "DT"
1488
	set modem var \$Telephone "{$ppp['phone']}"
1489

    
1490
EOD;
1491
		}
1492
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1493
			$mpdconf .= <<<EOD
1494
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1495

    
1496
EOD;
1497
		}
1498
		if (isset($ppp['initstr']) && $type == "modem") {
1499
			$initstr = base64_decode($ppp['initstr']);
1500
			$mpdconf .= <<<EOD
1501
	set modem var \$InitString "{$initstr}"
1502

    
1503
EOD;
1504
		}
1505
		if (isset($ppp['simpin']) && $type == "modem") {
1506
			$mpdconf .= <<<EOD
1507
	set modem var \$SimPin "{$ppp['simpin']}"
1508
	set modem var \$PinWait "{$ppp['pin-wait']}"
1509

    
1510
EOD;
1511
		}
1512
		if (isset($ppp['apn']) && $type == "modem") {
1513
			$mpdconf .= <<<EOD
1514
	set modem var \$APN "{$ppp['apn']}"
1515
	set modem var \$APNum "{$ppp['apnum']}"
1516

    
1517
EOD;
1518
		}
1519
		if (isset($ppp['provider']) && $type == "pppoe") {
1520
			$mpdconf .= <<<EOD
1521
	set pppoe service "{$ppp['provider']}"
1522

    
1523
EOD;
1524
		}
1525
		if ($type == "pppoe")
1526
			$mpdconf .= <<<EOD
1527
	set pppoe iface {$port}
1528

    
1529
EOD;
1530

    
1531
		if ($type == "pptp" || $type == "l2tp") {
1532
			$mpdconf .= <<<EOD
1533
	set {$type} self {$localips[$pid]}
1534
	set {$type} peer {$gateways[$pid]}
1535

    
1536
EOD;
1537
		}
1538
		
1539
		$mpdconf .= "\topen\r\n";
1540
	} //end foreach($port)
1541

    
1542

    
1543
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1544
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1545
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1546
	else {
1547
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1548
		if (!$fd) {
1549
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1550
			return 0;
1551
		}
1552
		// Write out mpd_ppp.conf
1553
		fwrite($fd, $mpdconf);
1554
		fclose($fd);
1555
	}
1556

    
1557
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1558
	if (isset($ppp['uptime'])) {
1559
		if (!file_exists("/conf/{$pppif}.log")) {
1560
			conf_mount_rw();
1561
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1562
			conf_mount_ro();
1563
		}
1564
	} else {
1565
		if (file_exists("/conf/{$pppif}.log")) {
1566
			conf_mount_rw();
1567
			mwexec("rm -f /conf/{$pppif}.log");
1568
			conf_mount_ro();
1569
		}
1570
	}
1571

    
1572
	/* fire up mpd */
1573
	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");
1574

    
1575
	// Check for PPPoE periodic reset request 
1576
	if ($type == "pppoe") {
1577
		if (isset($ppp['pppoe-reset-type']))
1578
			setup_pppoe_reset_file($ppp['if'], $interface);
1579
		else
1580
			setup_pppoe_reset_file($ppp['if']);
1581
	}
1582

    
1583
	return 1;
1584
}
1585

    
1586
function interfaces_carp_setup() {
1587
	global $g, $config;
1588

    
1589
	$balanacing = "";
1590
	$pfsyncinterface = "";
1591
	$pfsyncenabled = "";
1592
	if(isset($config['system']['developerspew'])) {
1593
		$mt = microtime();
1594
		echo "interfaces_carp_setup() being called $mt\n";
1595
	}
1596

    
1597
	// Prepare CmdCHAIN that will be used to execute commands.
1598
	$cmdchain = new CmdCHAIN();	
1599

    
1600
	if ($g['booting']) {
1601
		echo "Configuring CARP settings...";
1602
		mute_kernel_msgs();
1603
	}
1604

    
1605
	/* suck in configuration items */
1606
	if($config['installedpackages']['carpsettings']) {
1607
		if($config['installedpackages']['carpsettings']['config']) {
1608
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1609
				$pfsyncenabled = $carp['pfsyncenabled'];
1610
				$balanacing = $carp['balancing'];
1611
				$pfsyncinterface = $carp['pfsyncinterface'];
1612
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1613
			}
1614
		}
1615
	} else {
1616
		unset($pfsyncinterface);
1617
		unset($balanacing);
1618
		unset($pfsyncenabled);
1619
	}
1620

    
1621
	if($balanacing) {
1622
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1623
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1624
	} else
1625
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1626

    
1627
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1628
	if (!empty($pfsyncinterface))
1629
		$carp_sync_int = get_real_interface($pfsyncinterface);
1630

    
1631
	if($g['booting']) {
1632
		/*    install rules to alllow pfsync to sync up during boot
1633
		 *    carp interfaces will remain down until the bootup sequence finishes
1634
		 */
1635
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1636
		if ($fd) {
1637
			fwrite($fd, "block quick proto carp \n");
1638
			fwrite($fd, "block quick proto pfsync \n");
1639
			fwrite($fd, "pass out quick from any to any keep state\n");
1640
			fclose($fd);
1641
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1642
		} else
1643
			log_error("Could not create rules.boot file!");
1644
	}
1645

    
1646
	/* setup pfsync interface */
1647
	if($carp_sync_int and $pfsyncenabled) {
1648
		if (is_ipaddr($pfsyncpeerip))
1649
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1650
		else
1651
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1652
	} else
1653
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1654

    
1655
	if($config['virtualip']['vip'])
1656
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1657
	else
1658
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1659
	
1660
	if($g['debug'])
1661
		$cmdchain->setdebug(); // optional for verbose logging
1662

    
1663
	$cmdchain->execute();
1664
	$cmdchain->clear();
1665

    
1666
	if ($g['booting']) {
1667
		unmute_kernel_msgs();
1668
		echo "done.\n";
1669
	}
1670
}
1671

    
1672
function interface_proxyarp_configure($interface = "") {
1673
	global $config, $g;
1674
	if(isset($config['system']['developerspew'])) {
1675
		$mt = microtime();
1676
		echo "interface_proxyarp_configure() being called $mt\n";
1677
	}
1678

    
1679
	/* kill any running choparp */
1680
	if (empty($interface))
1681
		killbyname("choparp");
1682
	else {
1683
		$vipif = get_real_interface($interface);
1684
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1685
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1686
	}
1687

    
1688
	$paa = array();
1689
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1690

    
1691
		/* group by interface */
1692
		foreach ($config['virtualip']['vip'] as $vipent) {
1693
			if ($vipent['mode'] === "proxyarp") {
1694
				if ($vipent['interface'])
1695
					$proxyif = $vipent['interface'];
1696
				else
1697
					$proxyif = "wan";
1698
				
1699
				if (!empty($interface) && $interface != $proxyif)
1700
					continue;
1701

    
1702
				if (!is_array($paa[$proxyif]))
1703
					$paa[$proxyif] = array();
1704

    
1705
				$paa[$proxyif][] = $vipent;
1706
			}
1707
		}
1708
	}
1709

    
1710
	if (!empty($interface)) {
1711
		if (is_array($paa[$interface])) {
1712
			$paaifip = get_interface_ip($interface);
1713
                        if (!is_ipaddr($paaifip))
1714
                                return;
1715
                        $args = get_real_interface($interface) . " auto";
1716
                        foreach ($paa[$interface] as $paent) {
1717
                                if (isset($paent['subnet']))
1718
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1719
                                else if (isset($paent['range']))
1720
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1721
                        }
1722
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1723
		}
1724
	} else if (count($paa) > 0) {
1725
		foreach ($paa as $paif => $paents)  {
1726
			$paaifip = get_interface_ip($paif);
1727
			if (!is_ipaddr($paaifip))
1728
				continue;
1729
			$args = get_real_interface($paif) . " auto";
1730
			foreach ($paents as $paent) {
1731
				if (isset($paent['subnet']))
1732
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1733
				else if (isset($paent['range']))
1734
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1735
			}
1736
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1737
		}
1738
	}
1739
}
1740

    
1741
function interfaces_vips_configure($interface = "") {
1742
	global $g, $config;
1743
	if(isset($config['system']['developerspew'])) {
1744
		$mt = microtime();
1745
		echo "interfaces_vips_configure() being called $mt\n";
1746
	}
1747
	$paa = array();
1748
	if(is_array($config['virtualip']['vip'])) {
1749
		$carp_setuped = false;
1750
		$anyproxyarp = false;
1751
		foreach ($config['virtualip']['vip'] as $vip) {
1752
			switch ($vip['mode']) {
1753
			case "proxyarp":
1754
				/* nothing it is handled on interface_proxyarp_configure() */
1755
				if ($interface <> "" && $vip['interface'] <> $interface)
1756
					continue;
1757
				$anyproxyarp = true;
1758
				break;
1759
			case "ipalias":
1760
				if ($interface <> "" && $vip['interface'] <> $interface)
1761
					continue;
1762
				interface_ipalias_configure(&$vip);
1763
				break;
1764
			case "carp":
1765
				if ($interface <> "" && $vip['interface'] <> $interface)
1766
					continue;
1767
				if ($carp_setuped == false)
1768
					$carp_setuped = true;
1769
				interface_carp_configure($vip);
1770
				break;
1771
			case "carpdev-dhcp":
1772
				if ($interface <> "" && $vip['interface'] <> $interface)
1773
					continue;
1774
				interface_carpdev_configure($vip);
1775
				break;
1776
			}
1777
		}
1778
		if ($carp_setuped == true)
1779
			interfaces_carp_setup();
1780
		if ($anyproxyarp == true)
1781
			interface_proxyarp_configure();
1782
	}
1783
}
1784

    
1785
function interface_ipalias_configure(&$vip) {
1786

    
1787
	if ($vip['mode'] == "ipalias") {
1788
		$if = get_real_interface($vip['interface']);
1789
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1790
	}
1791
}
1792

    
1793
function interface_reload_carps($cif) {
1794
	global $config;
1795

    
1796
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1797
	if (empty($carpifs))
1798
		return;
1799

    
1800
	$carps = explode(" ", $carpifs);
1801
	if(is_array($config['virtualip']['vip'])) {
1802
		$viparr = &$config['virtualip']['vip'];
1803
		foreach ($viparr as $vip) {
1804
			if (in_array($vip['carpif'], $carps)) {
1805
				switch ($vip['mode']) {
1806
				case "carp":
1807
					interface_vip_bring_down($vip);
1808
					sleep(1);
1809
					interface_carp_configure($vip);
1810
					break;
1811
				case "carpdev-dhcp":
1812
					interface_vip_bring_down($vip);
1813
					sleep(1);
1814
					interface_carpdev_configure($vip);
1815
					break;
1816
				case "ipalias":
1817
					interface_vip_bring_down($vip);
1818
					sleep(1);
1819
					interface_ipalias_configure($vip);
1820
					break;
1821
				}
1822
			}
1823
		}
1824
	}
1825
}
1826

    
1827
function interface_carp_configure(&$vip) {
1828
	global $config, $g;
1829
	if(isset($config['system']['developerspew'])) {
1830
		$mt = microtime();
1831
		echo "interface_carp_configure() being called $mt\n";
1832
	}
1833

    
1834
	if ($vip['mode'] != "carp")
1835
		return;
1836

    
1837
	$vip_password = $vip['password'];
1838
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1839
	if ($vip['password'] != "")
1840
		$password = " pass {$vip_password}";
1841

    
1842
	// set the vip interface to the vhid
1843
	$vipif = "vip{$vip['vhid']}";
1844

    
1845
	/*
1846
	 * ensure the interface containing the VIP really exists
1847
 	 * prevents a panic if the interface is missing or invalid
1848
	 */
1849
	$realif = get_real_interface($vip['interface']);
1850
	if (!does_interface_exist($realif)) {
1851
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1852
		return;
1853
	}
1854

    
1855
	if(is_ipaddrv4($vip['subnet'])) {
1856
		/* Ensure CARP IP really exists prior to loading up. */
1857
		$ww_subnet_ip = find_interface_ip($realif);
1858
		$ww_subnet_bits = find_interface_subnet($realif);
1859
		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'])) {
1860
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1861
			return;
1862
		}
1863
	}
1864
	if(is_ipaddrv6($vip['subnet'])) {
1865
		/* Ensure CARP IP really exists prior to loading up. */
1866
		$ww_subnet_ip = find_interface_ipv6($realif);
1867
		$ww_subnet_bits = find_interface_subnetv6($realif);
1868
		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'])) {
1869
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IPv6 address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1870
			return;
1871
		}
1872
	}
1873

    
1874
	/* create the carp interface and setup */
1875
	if (does_interface_exist($vipif)) {
1876
		pfSense_interface_flags($vipif, -IFF_UP);
1877
	} else {
1878
		$carpif = pfSense_interface_create("carp");
1879
		pfSense_interface_rename($carpif, $vipif);
1880
		pfSense_ngctl_name("{$carpif}:", $vipif);
1881
	}
1882

    
1883
	/* invalidate interface cache */
1884
	get_interface_arr(true);
1885

    
1886
	$advbase = "";
1887
	if (!empty($vip['advbase']))
1888
		$advbase = "advbase {$vip['advbase']}";
1889

    
1890
	if(is_ipaddrv4($vip['subnet'])) {
1891
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1892
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1893
	}
1894
	if(is_ipaddrv6($vip['subnet'])) {
1895
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1896
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1897
	}
1898

    
1899
	interfaces_bring_up($vipif);
1900
	
1901
	return $vipif;
1902
}
1903

    
1904
function interface_carpdev_configure(&$vip) {
1905
	global $g;
1906

    
1907
	if ($vip['mode'] != "carpdev-dhcp")
1908
		return;
1909

    
1910
	$vip_password = $vip['password'];
1911
	$vip_password = str_replace(" ", "", $vip_password);
1912
	if($vip['password'] != "")
1913
		$password = " pass \"" . $vip_password . "\"";
1914

    
1915
	if (empty($vip['interface']))
1916
		return;
1917

    
1918
	$vipif = "vip" . $vip['vhid'];
1919
	$realif = get_real_interface($vip['interface']);
1920
	interfaces_bring_up($realif);
1921
	/*
1922
	 * ensure the interface containing the VIP really exists
1923
	 * prevents a panic if the interface is missing or invalid
1924
	 */
1925
	if (!does_interface_exist($realif)) {
1926
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1927
		return;
1928
	}
1929

    
1930
	if (does_interface_exist($vipif)) {
1931
		interface_bring_down($vipif);
1932
	} else {
1933
		$carpdevif = exec("/sbin/ifconfig carp create");
1934
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1935
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1936
	}
1937

    
1938
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1939
	interfaces_bring_up($vipif);
1940

    
1941
	/*
1942
	 * XXX: BIG HACK but carpdev needs ip services active
1943
	 *      before even starting something as dhclient.
1944
	 *      I do not know if this is a feature or a bug
1945
	 *      but better than track it make it work ;) .
1946
	 */
1947
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1948
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1949

    
1950
	/* generate dhclient_wan.conf */
1951
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1952
	if ($fd) {
1953
		$dhclientconf = "";
1954

    
1955
		$dhclientconf .= <<<EOD
1956
interface "{$vipif}" {
1957
timeout 60;
1958
retry 1;
1959
select-timeout 0;
1960
initial-interval 1;
1961
script "/sbin/dhclient-script";
1962
}
1963

    
1964
EOD;
1965

    
1966
		fwrite($fd, $dhclientconf);
1967
		fclose($fd);
1968

    
1969
		/* fire up dhclient */
1970
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1971
	} else {
1972
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1973
		mwexec("/sbin/dhclient -b {$vipif}");
1974
	}
1975

    
1976
	return $vipif;
1977
}
1978

    
1979
function interface_wireless_clone($realif, $wlcfg) {
1980
	global $config, $g;
1981
	/*   Check to see if interface has been cloned as of yet.  
1982
	 *   If it has not been cloned then go ahead and clone it.
1983
	 */
1984
	$needs_clone = false;
1985
	if(is_array($wlcfg['wireless']))
1986
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1987
	else
1988
		$wlcfg_mode = $wlcfg['mode'];
1989
	switch($wlcfg_mode) {
1990
		 case "hostap":
1991
			$mode = "wlanmode hostap";
1992
			break;
1993
		 case "adhoc":
1994
			$mode = "wlanmode adhoc";
1995
			break;
1996
		 default:
1997
			$mode = "";
1998
			break;
1999
	}
2000
	$baseif = interface_get_wireless_base($wlcfg['if']);
2001
	if(does_interface_exist($realif)) {
2002
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2003
		$ifconfig_str = implode($output);
2004
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2005
			log_error("Interface {$realif} changed to hostap mode");
2006
			$needs_clone = true;
2007
		}
2008
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2009
			log_error("Interface {$realif} changed to adhoc mode");
2010
			$needs_clone = true;
2011
		}
2012
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2013
			log_error("Interface {$realif} changed to infrastructure mode");
2014
			$needs_clone = true;
2015
		}
2016
	} else {
2017
		$needs_clone = true;
2018
	}
2019

    
2020
	if($needs_clone == true) {
2021
		/* remove previous instance if it exists */
2022
		if(does_interface_exist($realif))
2023
			pfSense_interface_destroy($realif);
2024

    
2025
		log_error("Cloning new wireless interface {$realif}");
2026
		// Create the new wlan interface. FreeBSD returns the new interface name.
2027
		// example:  wlan2
2028
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2029
		if($ret <> 0) {
2030
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
2031
			return false;
2032
		}
2033
		$newif = trim($out[0]);
2034
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2035
		pfSense_interface_rename($newif, $realif);
2036
		// FIXME: not sure what ngctl is for. Doesn't work.
2037
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2038
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2039
	}
2040
	return true;
2041
}
2042

    
2043
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2044
	global $config, $g;
2045

    
2046
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2047
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2048
	                         'regdomain', 'regcountry', 'reglocation');
2049

    
2050
	if(!is_interface_wireless($ifcfg['if']))
2051
		return;
2052

    
2053
	$baseif = interface_get_wireless_base($ifcfg['if']);
2054

    
2055
	// Sync shared settings for assigned clones
2056
	$iflist = get_configured_interface_list(false, true);
2057
	foreach ($iflist as $if) {
2058
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2059
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2060
				foreach ($shared_settings as $setting) {
2061
					if ($sync_changes) {
2062
						if (isset($ifcfg['wireless'][$setting]))
2063
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2064
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2065
							unset($config['interfaces'][$if]['wireless'][$setting]);
2066
					} else {
2067
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2068
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2069
						else if (isset($ifcfg['wireless'][$setting]))
2070
							unset($ifcfg['wireless'][$setting]);
2071
					}
2072
				}
2073
				if (!$sync_changes)
2074
					break;
2075
			}
2076
		}
2077
	}
2078

    
2079
	// Read or write settings at shared area
2080
	if (isset($config['wireless']['interfaces'][$baseif])) {
2081
		foreach ($shared_settings as $setting) {
2082
			if ($sync_changes) {
2083
				if (isset($ifcfg['wireless'][$setting]))
2084
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2085
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2086
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2087
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2088
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2089
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2090
				else if (isset($ifcfg['wireless'][$setting]))
2091
					unset($ifcfg['wireless'][$setting]);
2092
			}
2093
		}
2094
	}
2095

    
2096
	// Sync the mode on the clone creation page with the configured mode on the interface
2097
	if (interface_is_wireless_clone($ifcfg['if'])) {
2098
		foreach ($config['wireless']['clone'] as &$clone) {
2099
			if ($clone['cloneif'] == $ifcfg['if']) {
2100
				if ($sync_changes) {
2101
					$clone['mode'] = $ifcfg['wireless']['mode'];
2102
				} else {
2103
					$ifcfg['wireless']['mode'] = $clone['mode'];
2104
				}
2105
				break;
2106
			}
2107
		}
2108
		unset($clone);
2109
	}
2110
}
2111

    
2112
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2113
	global $config, $g;
2114

    
2115
	/*    open up a shell script that will be used to output the commands.
2116
	 *    since wireless is changing a lot, these series of commands are fragile
2117
     *    and will sometimes need to be verified by a operator by executing the command
2118
     *    and returning the output of the command to the developers for inspection.  please
2119
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2120
	 */
2121

    
2122
	// Remove script file
2123
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2124

    
2125
	// Clone wireless nic if needed.
2126
	interface_wireless_clone($if, $wl);
2127

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

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

    
2135
	/* set values for /path/program */
2136
	$hostapd = "/usr/sbin/hostapd";
2137
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2138
	$ifconfig = "/sbin/ifconfig";
2139
	$sysctl = "/sbin/sysctl";
2140
	$killall = "/usr/bin/killall";
2141

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

    
2144
	$wlcmd = array();
2145
	$wl_sysctl = array();
2146
	/* Make sure it's up */
2147
	$wlcmd[] = "up";
2148
	/* Set a/b/g standard */
2149
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2150
	$wlcmd[] = "mode " . escapeshellarg($standard);
2151

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

    
2157
	/* Set ssid */
2158
	if($wlcfg['ssid'])
2159
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2160

    
2161
	/* Set 802.11g protection mode */
2162
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2163

    
2164
	/* set wireless channel value */
2165
	if(isset($wlcfg['channel'])) {
2166
		if($wlcfg['channel'] == "0") {
2167
			$wlcmd[] = "channel any";
2168
		} else {
2169
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2170
		}
2171
	}
2172

    
2173
	/* Set antenna diversity value */
2174
	if(isset($wlcfg['diversity']))
2175
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2176

    
2177
	/* Set txantenna value */
2178
	if(isset($wlcfg['txantenna']))
2179
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2180

    
2181
	/* Set rxantenna value */
2182
	if(isset($wlcfg['rxantenna']))
2183
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2184

    
2185
	/* set Distance value */
2186
	if($wlcfg['distance'])
2187
		$distance = escapeshellarg($wlcfg['distance']);
2188

    
2189
	/* Set wireless hostap mode */
2190
	if ($wlcfg['mode'] == "hostap") {
2191
		$wlcmd[] = "mediaopt hostap";
2192
	} else {
2193
		$wlcmd[] = "-mediaopt hostap";
2194
	}
2195

    
2196
	/* Set wireless adhoc mode */
2197
	if ($wlcfg['mode'] == "adhoc") {
2198
		$wlcmd[] = "mediaopt adhoc";
2199
	} else {
2200
		$wlcmd[] = "-mediaopt adhoc";
2201
	}
2202

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

    
2205
	/* handle hide ssid option */
2206
	if(isset($wlcfg['hidessid']['enable'])) {
2207
		$wlcmd[] = "hidessid";
2208
	} else {
2209
		$wlcmd[] = "-hidessid";
2210
	}
2211

    
2212
	/* handle pureg (802.11g) only option */
2213
	if(isset($wlcfg['pureg']['enable'])) {
2214
		$wlcmd[] = "mode 11g pureg";
2215
	} else {
2216
		$wlcmd[] = "-pureg";
2217
	}
2218

    
2219
	/* handle puren (802.11n) only option */
2220
	if(isset($wlcfg['puren']['enable'])) {
2221
		$wlcmd[] = "puren";
2222
	} else {
2223
		$wlcmd[] = "-puren";
2224
	}
2225

    
2226
	/* enable apbridge option */
2227
	if(isset($wlcfg['apbridge']['enable'])) {
2228
		$wlcmd[] = "apbridge";
2229
	} else {
2230
		$wlcmd[] = "-apbridge";
2231
	}
2232

    
2233
	/* handle turbo option */
2234
	if(isset($wlcfg['turbo']['enable'])) {
2235
		$wlcmd[] = "mediaopt turbo";
2236
	} else {
2237
		$wlcmd[] = "-mediaopt turbo";
2238
	}
2239

    
2240
	/* handle txpower setting */
2241
	/* if($wlcfg['txpower'] <> "")
2242
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2243
	*/
2244
	/* handle wme option */
2245
	if(isset($wlcfg['wme']['enable'])) {
2246
		$wlcmd[] = "wme";
2247
	} else {
2248
		$wlcmd[] = "-wme";
2249
	}
2250

    
2251
	/* set up wep if enabled */
2252
	$wepset = "";
2253
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2254
		switch($wlcfg['wpa']['auth_algs']) {
2255
			case "1":
2256
				$wepset .= "authmode open wepmode on ";
2257
				break;
2258
			case "2":
2259
				$wepset .= "authmode shared wepmode on ";
2260
				break;
2261
			case "3":
2262
				$wepset .= "authmode mixed wepmode on ";
2263
		}
2264
		$i = 1;
2265
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2266
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2267
			if (isset($wepkey['txkey'])) {
2268
				$wlcmd[] = "weptxkey {$i} ";
2269
			}
2270
			$i++;
2271
		}
2272
		$wlcmd[] = $wepset;
2273
	} else {
2274
		$wlcmd[] = "authmode open wepmode off ";
2275
	}
2276

    
2277
	mwexec(kill_hostapd("{$if}"));
2278
	mwexec(kill_wpasupplicant("{$if}"));
2279

    
2280
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2281
	conf_mount_rw();
2282

    
2283
	switch ($wlcfg['mode']) {
2284
		case 'bss':
2285
			if (isset($wlcfg['wpa']['enable'])) {
2286
				$wpa .= <<<EOD
2287
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2288
ctrl_interface_group=0
2289
ap_scan=1
2290
#fast_reauth=1
2291
network={
2292
ssid="{$wlcfg['ssid']}"
2293
scan_ssid=1
2294
priority=5
2295
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2296
psk="{$wlcfg['wpa']['passphrase']}"
2297
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2298
group={$wlcfg['wpa']['wpa_pairwise']}
2299
}
2300
EOD;
2301

    
2302
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2303
				fwrite($fd, "{$wpa}");
2304
				fclose($fd);
2305
			}
2306
			break;
2307
		case 'hostap':
2308
			if($wlcfg['wpa']['passphrase']) 
2309
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2310
			else 
2311
				$wpa_passphrase = "";
2312
			if (isset($wlcfg['wpa']['enable'])) {
2313
				$wpa .= <<<EOD
2314
interface={$if}
2315
driver=bsd
2316
logger_syslog=-1
2317
logger_syslog_level=0
2318
logger_stdout=-1
2319
logger_stdout_level=0
2320
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2321
ctrl_interface={$g['varrun_path']}/hostapd
2322
ctrl_interface_group=wheel
2323
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2324
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2325
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2326
ssid={$wlcfg['ssid']}
2327
debug={$wlcfg['wpa']['debug_mode']}
2328
auth_algs={$wlcfg['wpa']['auth_algs']}
2329
wpa={$wlcfg['wpa']['wpa_mode']}
2330
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2331
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2332
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2333
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2334
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2335
{$wpa_passphrase}
2336

    
2337
EOD;
2338

    
2339
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2340
	$wpa .= <<<EOD
2341
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2342
rsn_preauth=1
2343
rsn_preauth_interfaces={$if}
2344

    
2345
EOD;
2346

    
2347
}
2348
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2349
					$auth_server_port = "1812";
2350
					if($wlcfg['auth_server_port']) 
2351
						$auth_server_port = $wlcfg['auth_server_port'];
2352
					$wpa .= <<<EOD
2353

    
2354
ieee8021x=1
2355
auth_server_addr={$wlcfg['auth_server_addr']}
2356
auth_server_port={$auth_server_port}
2357
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2358

    
2359
EOD;
2360
				} else {
2361
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2362
				}
2363

    
2364
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2365
				fwrite($fd, "{$wpa}");
2366
				fclose($fd);
2367

    
2368
			}
2369
			break;
2370
	}
2371

    
2372
	/*
2373
	 *    all variables are set, lets start up everything
2374
	 */
2375

    
2376
	$baseif = interface_get_wireless_base($if);
2377
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2378
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2379

    
2380
	/* set sysctls for the wireless interface */
2381
	if (!empty($wl_sysctl)) {
2382
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2383
		foreach ($wl_sysctl as $wl_sysctl_line) {
2384
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2385
		}
2386
	}
2387

    
2388
	/* set ack timers according to users preference (if he/she has any) */
2389
	if($distance) {
2390
		fwrite($fd_set, "# Enable ATH distance settings\n");
2391
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2392
	}
2393

    
2394
	if (isset($wlcfg['wpa']['enable'])) {
2395
		if ($wlcfg['mode'] == "bss") {
2396
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2397
		}
2398
		if ($wlcfg['mode'] == "hostap") {
2399
			/* add line to script to restore old mac to make hostapd happy */
2400
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2401
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2402
				if (is_macaddr($if_oldmac))
2403
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2404
						" link " . escapeshellarg($if_oldmac) . "\n");
2405
			}
2406

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

    
2409
			/* add line to script to restore spoofed mac after running hostapd */
2410
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2411
				if ($wl['spoofmac'])
2412
					$if_curmac = $wl['spoofmac'];
2413
				else
2414
					$if_curmac = get_interface_mac($if);
2415
				if (is_macaddr($if_curmac))
2416
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2417
						" link " . escapeshellarg($if_curmac) . "\n");
2418
			}
2419
		}
2420
	}
2421

    
2422
	fclose($fd_set);
2423
	conf_mount_ro();
2424

    
2425
	/* Making sure regulatory settings have actually changed
2426
	 * before applying, because changing them requires bringing
2427
	 * down all wireless networks on the interface. */
2428
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2429
	$ifconfig_str = implode($output);
2430
	unset($output);
2431
	$reg_changing = false;
2432

    
2433
	/* special case for the debug country code */
2434
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2435
		$reg_changing = true;
2436
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2437
		$reg_changing = true;
2438
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2439
		$reg_changing = true;
2440
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2441
		$reg_changing = true;
2442
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2443
		$reg_changing = true;
2444

    
2445
	if ($reg_changing) {
2446
		/* set regulatory domain */
2447
		if($wlcfg['regdomain'])
2448
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2449

    
2450
		/* set country */
2451
		if($wlcfg['regcountry'])
2452
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2453

    
2454
		/* set location */
2455
		if($wlcfg['reglocation'])
2456
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2457

    
2458
		$wlregcmd_args = implode(" ", $wlregcmd);
2459

    
2460
		/* build a complete list of the wireless clones for this interface */
2461
		$clone_list = array();
2462
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2463
			$clone_list[] = interface_get_wireless_clone($baseif);
2464
		if (is_array($config['wireless']['clone'])) {
2465
			foreach ($config['wireless']['clone'] as $clone) {
2466
				if ($clone['if'] == $baseif)
2467
					$clone_list[] = $clone['cloneif'];
2468
			}
2469
		}
2470

    
2471
		/* find which clones are up and bring them down */
2472
		$clones_up = array();
2473
		foreach ($clone_list as $clone_if) {
2474
			$clone_status = pfSense_get_interface_addresses($clone_if);
2475
			if ($clone_status['status'] == 'up') {
2476
				$clones_up[] = $clone_if;
2477
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2478
			}
2479
		}
2480

    
2481
		/* apply the regulatory settings */
2482
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2483

    
2484
		/* bring the clones back up that were previously up */
2485
		foreach ($clones_up as $clone_if) {
2486
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2487

    
2488
			/*
2489
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2490
			 * is in infrastructure mode, and WPA is enabled.
2491
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2492
			 */
2493
			if ($clone_if != $if) {
2494
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2495
				if ( !empty($friendly_if)
2496
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2497
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2498
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2499
				}
2500
			}
2501
		}
2502
	}
2503

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

    
2508
	/* configure wireless */
2509
	$wlcmd_args = implode(" ", $wlcmd);
2510
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2511

    
2512
	
2513
	sleep(1);
2514
	/* execute hostapd and wpa_supplicant if required in shell */
2515
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2516

    
2517
	return 0;
2518

    
2519
}
2520

    
2521
function kill_hostapd($interface) {
2522
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2523
}
2524

    
2525
function kill_wpasupplicant($interface) {
2526
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2527
}
2528

    
2529
function find_dhclient_process($interface) {
2530
	if ($interface)
2531
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2532
	else
2533
		$pid = 0;
2534

    
2535
	return intval($pid);
2536
}
2537

    
2538
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2539
	global $config, $g;
2540
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2541
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2542

    
2543
	$wancfg = $config['interfaces'][$interface];
2544

    
2545
	$realif = get_real_interface($interface);
2546
	$realhwif_array = get_parent_interface($interface);
2547
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2548
	$realhwif = $realhwif_array[0];
2549

    
2550
			
2551
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2552
		/* remove all IPv4 addresses */
2553
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2554
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2555

    
2556
		switch ($wancfg['ipaddr']) {
2557
			case 'pppoe':
2558
			case 'l2tp':
2559
			case 'pptp':
2560
			case 'ppp':
2561
				break;
2562
			default:
2563
				interface_bring_down($interface);
2564
				break;
2565
		}
2566
	}
2567

    
2568
	/* wireless configuration? */
2569
	if (is_array($wancfg['wireless']))
2570
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2571

    
2572
	if ($wancfg['spoofmac']) {
2573
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2574
			" link " . escapeshellarg($wancfg['spoofmac']));
2575

    
2576
                /*
2577
                 * All vlans need to spoof their parent mac address, too.  see
2578
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2579
                 */
2580
                if (is_array($config['vlans']['vlan'])) {
2581
                        foreach ($config['vlans']['vlan'] as $vlan) {
2582
                                if ($vlan['if'] == $realhwif)
2583
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2584
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2585
                        }
2586
                }
2587
	}  else {
2588
		$mac = get_interface_mac($realhwif);
2589
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2590
			/*   this is not a valid mac address.  generate a
2591
			 *   temporary mac address so the machine can get online.
2592
			 */
2593
			echo "Generating new MAC address.";
2594
			$random_mac = generate_random_mac_address();
2595
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2596
				" link " . escapeshellarg($random_mac));
2597
			$wancfg['spoofmac'] = $random_mac;
2598
			write_config();
2599
			file_notice("MAC Address altered", "The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface {$realif} has been automatically replaced with {$random_mac}", "Interfaces");
2600
		}
2601
	}
2602

    
2603
	/* media */
2604
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2605
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2606
		if ($wancfg['media'])
2607
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2608
		if ($wancfg['mediaopt'])
2609
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2610
		mwexec($cmd);
2611
	}
2612
	if (!empty($wancfg['mtu']))
2613
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2614

    
2615
	$options = pfSense_get_interface_addresses($realhwif);
2616
	if (is_array($options) && isset($options['caps']['polling'])) {
2617
		if (isset($config['system']['polling']))
2618
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2619
		else
2620
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2621
	}
2622

    
2623
	/* skip vlans for checksumming and polling */
2624
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2625
		$flags = 0;
2626
		if(isset($config['system']['disablechecksumoffloading'])) {
2627
			if (isset($options['encaps']['txcsum']))
2628
				$flags |= IFCAP_TXCSUM;
2629
			if (isset($options['encaps']['rxcsum']))
2630
				$flags |= IFCAP_RXCSUM;
2631
        	} else {
2632
 			if (!isset($options['caps']['txcsum']))
2633
				$flags |= IFCAP_TXCSUM;
2634
			if (!isset($options['caps']['rxcsum']))
2635
				$flags |= IFCAP_RXCSUM;
2636
        	}
2637

    
2638
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2639
                	if (isset($options['encaps']['tso4']))
2640
				$flags |= IFCAP_TSO;
2641
                	if (isset($options['encaps']['tso6']))
2642
				$flags |= IFCAP_TSO;
2643
        	} else {
2644
                	if (!isset($options['caps']['tso4']))
2645
				$flags |= IFCAP_TSO;
2646
                	if (!isset($options['caps']['tso6']))
2647
				$flags |= IFCAP_TSO;
2648
        	}
2649

    
2650
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2651
                	if (isset($options['encaps']['lro']))
2652
				$flags |= IFCAP_LRO;
2653
        	} else {
2654
                	if (!isset($options['caps']['lro']))
2655
				$flags |= IFCAP_LRO;
2656
        	}
2657

    
2658
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2659
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2660
			$flags |= IFCAP_POLLING;
2661
		}
2662
               	pfSense_interface_capabilities($realhwif, -$flags);
2663
	}
2664

    
2665
	/* invalidate interface/ip/sn cache */
2666
	get_interface_arr(true);
2667
	unset($interface_ip_arr_cache[$realif]);
2668
	unset($interface_sn_arr_cache[$realif]);
2669
	unset($interface_ipv6_arr_cache[$realif]);
2670
	unset($interface_snv6_arr_cache[$realif]);
2671

    
2672
	switch ($wancfg['ipaddr']) {
2673
		case 'carpdev-dhcp':
2674
			interface_carpdev_dhcp_configure($interface);
2675
			break;
2676
		case 'dhcp':
2677
			interface_dhcp_configure($interface);
2678
			break;
2679
		case 'pppoe':
2680
		case 'l2tp':
2681
		case 'pptp':
2682
		case 'ppp':
2683
			interface_ppps_configure($interface);
2684
			break;
2685
		default:
2686
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2687
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2688
			} else if (substr($realif, 0, 3) == "gre") {
2689
				if (is_array($config['gres']['gre'])) {
2690
					foreach ($config['gres']['gre'] as $gre)
2691
						if ($gre['greif'] == $realif)
2692
							interface_gre_configure($gre);
2693
				}
2694
			} else if (substr($realif, 0, 3) == "gif") {
2695
				 if (is_array($config['gifs']['gif'])) {
2696
					foreach ($config['gifs']['gif'] as $gif)
2697
						if($gif['gifif'] == $realif)
2698
							interface_gif_configure($gif);
2699
				}
2700
			} else if (substr($realif, 0, 4) == "ovpn") {
2701
				/* XXX: Should be done anything?! */
2702
			}
2703
			break;
2704
	}
2705

    
2706
	switch ($wancfg['ipaddrv6']) {
2707
		case 'dhcpv6':
2708
			interface_dhcpv6_configure($interface);
2709
			break;
2710
		default:
2711
			if ($wancfg['ipaddrv6'] <> "" && $wancfg['subnetv6'] <> "") {
2712
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2713
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2714
			}
2715
			break;
2716
	}
2717

    
2718
	if(does_interface_exist($wancfg['if']))
2719
		interfaces_bring_up($wancfg['if']);
2720

    
2721
	interface_netgraph_needed($interface);
2722
 	
2723
	if (!$g['booting']) {
2724
		link_interface_to_vips($interface, "update");
2725

    
2726
		unset($gre);
2727
		$gre = link_interface_to_gre($interface);
2728
		if (!empty($gre))
2729
			array_walk($gre, 'interface_gre_configure');
2730

    
2731
		unset($gif);
2732
		$gif = link_interface_to_gif($interface);
2733
		if (!empty($gif))
2734
                       	array_walk($gif, 'interface_gif_configure');
2735

    
2736
		if ($linkupevent == false) {
2737
			unset($bridgetmp);
2738
			$bridgetmp = link_interface_to_bridge($interface);
2739
			if (!empty($bridgetmp))
2740
				interface_bridge_add_member($bridgetmp, $realif);
2741
		}
2742

    
2743
		$grouptmp = link_interface_to_group($interface);
2744
		if (!empty($grouptmp))
2745
			array_walk($grouptmp, 'interface_group_add_member');
2746

    
2747
		if ($interface == "lan")
2748
			/* make new hosts file */
2749
			system_hosts_generate();
2750

    
2751
		if ($reloadall == true) {
2752

    
2753
			/* reconfigure static routes (kernel may have deleted them) */
2754
			system_routing_configure($interface);
2755

    
2756
			/* reload ipsec tunnels */
2757
			vpn_ipsec_configure();
2758

    
2759
			/* restart dnsmasq */
2760
			services_dnsmasq_configure();
2761

    
2762
			/* update dyndns */
2763
			send_event("service reload dyndns {$interface}");
2764

    
2765
			/* reload captive portal */
2766
			captiveportal_init_rules();
2767
		}
2768
	}
2769

    
2770
	return 0;
2771
}
2772

    
2773
function interface_carpdev_dhcp_configure($interface = "wan") {
2774
	global $config, $g;
2775

    
2776
	$wancfg = $config['interfaces'][$interface];
2777
	$wanif = $wancfg['if'];
2778
	/* bring wan interface up before starting dhclient */
2779
	if($wanif)
2780
		interfaces_bring_up($wanif);
2781
	else 
2782
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2783

    
2784
	return 0;
2785
}
2786

    
2787
function interface_dhcp_configure($interface = "wan") {
2788
	global $config, $g;
2789

    
2790
	$wancfg = $config['interfaces'][$interface];
2791
	if (empty($wancfg))
2792
		$wancfg = array();
2793

    
2794
	/* generate dhclient_wan.conf */
2795
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2796
	if (!$fd) {
2797
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2798
		return 1;
2799
	}
2800

    
2801
	if ($wancfg['dhcphostname']) {
2802
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2803
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2804
	} else {
2805
		$dhclientconf_hostname = "";
2806
	}
2807

    
2808
	$wanif = get_real_interface($interface);
2809
	if (empty($wanif)) {
2810
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2811
		return 0;
2812
	}
2813
 	$dhclientconf = "";
2814
	
2815
	$dhclientconf .= <<<EOD
2816
interface "{$wanif}" {
2817
timeout 60;
2818
retry 1;
2819
select-timeout 0;
2820
initial-interval 1;
2821
	{$dhclientconf_hostname}
2822
	script "/sbin/dhclient-script";
2823
}
2824

    
2825
EOD;
2826

    
2827
if(is_ipaddr($wancfg['alias-address'])) {
2828
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2829
	$dhclientconf .= <<<EOD
2830
alias {
2831
	interface  "{$wanif}";
2832
	fixed-address {$wancfg['alias-address']};
2833
	option subnet-mask {$subnetmask};
2834
}
2835

    
2836
EOD;
2837
}
2838
	fwrite($fd, $dhclientconf);
2839
	fclose($fd);
2840

    
2841
	/* bring wan interface up before starting dhclient */
2842
	if($wanif)
2843
		interfaces_bring_up($wanif);
2844
	else 
2845
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2846

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

    
2850
	return 0;
2851
}
2852

    
2853
function interfaces_group_setup() {
2854
	global $config;
2855

    
2856
	if (!is_array($config['ifgroups']['ifgroupentry']))
2857
		return;
2858

    
2859
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2860
		interface_group_setup($groupar);
2861

    
2862
	return;
2863
}
2864

    
2865
function interface_group_setup(&$groupname /* The parameter is an array */) {
2866
	global $config;
2867

    
2868
	if (!is_array($groupname))
2869
		return;
2870
	$members = explode(" ", $groupname['members']);
2871
	foreach($members as $ifs) {
2872
		$realif = get_real_interface($ifs);
2873
		if ($realif)
2874
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2875
	}
2876

    
2877
	return;
2878
}
2879

    
2880
function interface_group_add_member($interface, $groupname) {
2881
	$interface = get_real_interface($interface);
2882
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2883
}
2884
 
2885
/* COMPAT Function */
2886
function convert_friendly_interface_to_real_interface_name($interface) {
2887
	return get_real_interface($interface);
2888
}
2889

    
2890
/* COMPAT Function */
2891
function get_real_wan_interface($interface = "wan") {
2892
	return get_real_interface($interface);
2893
}
2894

    
2895
/* COMPAT Function */
2896
function get_current_wan_address($interface = "wan") {
2897
	return get_interface_ip($interface);
2898
}
2899

    
2900
/*
2901
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2902
 */
2903
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2904
        global $config;
2905

    
2906
	if (stristr($interface, "vip")) {
2907
                $index = intval(substr($interface, 3));
2908
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2909
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2910
                                if ($index == $vip['vhid'])
2911
                                        return $vip['interface'];
2912
                        }
2913
                }
2914
        }
2915

    
2916
        /* XXX: For speed reasons reference directly the interface array */
2917
	$ifdescrs = &$config['interfaces'];
2918
        //$ifdescrs = get_configured_interface_list(false, true);
2919

    
2920
        foreach ($ifdescrs as $if => $ifname) {
2921
                if ($config['interfaces'][$if]['if'] == $interface)
2922
                        return $if;
2923

    
2924
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2925
                        return $if;
2926

    
2927
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
2928
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
2929
		/*
2930
                $int = get_parent_interface($if);
2931
                if ($int[0] == $interface)
2932
                        return $ifname;
2933
		*/
2934
        }
2935
        return NULL;
2936
}
2937

    
2938
/* attempt to resolve interface to friendly descr */
2939
function convert_friendly_interface_to_friendly_descr($interface) {
2940
        global $config;
2941

    
2942
        switch ($interface) {
2943
        case "l2tp":
2944
        	$ifdesc = "L2TP";
2945
                break;
2946
	case "pptp":
2947
		$ifdesc = "PPTP";
2948
		break;
2949
	case "pppoe":
2950
		$ifdesc = "PPPoE";
2951
		break;
2952
	case "openvpn":
2953
		$ifdesc = "OpenVPN";
2954
		break;
2955
	case "enc0":
2956
	case "ipsec":
2957
		$ifdesc = "IPsec";
2958
		break;
2959
        default:
2960
                if (isset($config['interfaces'][$interface])) {
2961
                        if (empty($config['interfaces'][$interface]['descr']))
2962
                                $ifdesc = strtoupper($interface);
2963
                        else
2964
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2965
			break;
2966
		} else if (substr($interface, 0, 3) == "vip") {
2967
			if (is_array($config['virtualip']['vip'])) {
2968
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
2969
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2970
						if ($interface == "vip{$vip['vhid']}")
2971
							return "{$vip['subnet']} - {$vip['descr']}";
2972
					}
2973
				}
2974
                        }
2975
                } else {
2976
			/* if list */
2977
			$ifdescrs = get_configured_interface_with_descr(false, true);
2978
			foreach ($ifdescrs as $if => $ifname) {
2979
					if ($if == $interface || $ifname == $interface)
2980
						return $ifname;
2981
			}
2982
		}
2983
                break;
2984
        }
2985

    
2986
        return $ifdesc;
2987
}
2988

    
2989
function convert_real_interface_to_friendly_descr($interface) {
2990
        global $config;
2991

    
2992
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2993

    
2994
        if ($ifdesc) {
2995
                $iflist = get_configured_interface_with_descr(false, true);
2996
                return $iflist[$ifdesc];
2997
        }
2998

    
2999
        return $interface;
3000
}
3001

    
3002
/*
3003
 *  get_parent_interface($interface):
3004
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3005
 *				or virtual interface (i.e. vlan)
3006
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3007
 *			-- returns $interface passed in if $interface parent is not found
3008
 *			-- returns empty array if an invalid interface is passed
3009
 *	(Only handles ppps and vlans now.)
3010
 */
3011
function get_parent_interface($interface) {
3012
	global $config;
3013

    
3014
	$parents = array();
3015
	//Check that we got a valid interface passed
3016
	$realif = get_real_interface($interface);
3017
	if ($realif == NULL)
3018
		return $parents;
3019

    
3020
	// If we got a real interface, find it's friendly assigned name
3021
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3022
		
3023
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3024
		$ifcfg = $config['interfaces'][$interface];
3025
		switch ($ifcfg['ipaddr']) {
3026
			case "ppp":
3027
			case "pppoe":
3028
			case "pptp":
3029
			case "l2tp":
3030
				if (empty($parents))
3031
					if (is_array($config['ppps']['ppp']))
3032
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3033
							if ($ppp_if == $ppp['if']) {
3034
								$ports = explode(',', $ppp['ports']);
3035
								foreach ($ports as $pid => $parent_if) 
3036
									$parents[$pid] = get_real_interface($parent_if);
3037
								break;
3038
							}
3039
						}
3040
				break;
3041
			case "dhcp":
3042
			case "static":
3043
			default:
3044
				// Handle _vlans
3045
				if (strstr($realif,"_vlan"))
3046
					if (is_array($config['vlans']['vlan'])) 
3047
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3048
							if ($ifcfg['if'] == $vlan['vlanif']){
3049
								$parents[0] = $vlan['if'];
3050
								break;
3051
							}
3052
				break;
3053
		}
3054
	}
3055
	
3056
	if (empty($parents))
3057
		$parents[0] = $realif;
3058
	
3059
	return $parents;
3060
}
3061

    
3062
function interface_is_wireless_clone($wlif) {
3063
	if(!stristr($wlif, "_wlan")) {
3064
		return false;
3065
	} else {
3066
		return true;
3067
	}
3068
}
3069

    
3070
function interface_get_wireless_base($wlif) {
3071
	if(!stristr($wlif, "_wlan")) {
3072
		return $wlif;
3073
	} else {
3074
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3075
	}
3076
}
3077

    
3078
function interface_get_wireless_clone($wlif) {
3079
	if(!stristr($wlif, "_wlan")) {
3080
		return $wlif . "_wlan0";
3081
	} else {
3082
		return $wlif;
3083
	}
3084
}
3085

    
3086
function get_real_interface($interface = "wan") {
3087
    global $config;
3088

    
3089
	$wanif = NULL;
3090

    
3091
	switch ($interface) {
3092
	case "l2tp":
3093
		$wanif = "l2tp";
3094
		break;
3095
	case "pptp":
3096
		$wanif = "pptp";
3097
		break;
3098
	case "pppoe":
3099
		$wanif = "pppoe";
3100
		break;
3101
	case "openvpn":
3102
		$wanif = "openvpn";
3103
		break;
3104
	case "ipsec":
3105
	case "enc0":
3106
		$wanif = "enc0";
3107
		break;
3108
	case "ppp":
3109
		$wanif = "ppp";
3110
		break;
3111
	default:
3112
		// If a real interface was alread passed simply
3113
		// pass the real interface back.  This encourages
3114
		// the usage of this function in more cases so that
3115
		// we can combine logic for more flexibility.
3116
		if(does_interface_exist($interface)) {
3117
			$wanif = $interface;
3118
			break;
3119
		}
3120
		if (empty($config['interfaces'][$interface]))
3121
			break;
3122

    
3123
		$cfg = &$config['interfaces'][$interface];
3124

    
3125
		// Wireless cloned NIC support (FreeBSD 8+)
3126
		// interface name format: $parentnic_wlanparentnic#
3127
		// example: ath0_wlan0
3128
		if (is_interface_wireless($cfg['if'])) {
3129
			$wanif = interface_get_wireless_clone($cfg['if']);
3130
			break;
3131
		}
3132
		/*
3133
		if (empty($cfg['if'])) {
3134
			$wancfg = $cfg['if'];
3135
			break;
3136
		}
3137
		*/
3138

    
3139
		switch ($cfg['ipaddr']) {
3140
			case "carpdev-dhcp":
3141
				$viparr = &$config['virtualip']['vip'];
3142
				if(is_array($viparr))
3143
				foreach ($viparr as $counter => $vip) {
3144
					if ($vip['mode'] == "carpdev-dhcp") {
3145
						if($vip['interface'] == $interface) {
3146
							$wanif = "carp{$counter}";
3147
							break;
3148
						}
3149
					}
3150
				}
3151
				break;
3152
			case "pppoe": 
3153
			case "pptp": 
3154
			case "l2tp": 
3155
			case "ppp":
3156
				$wanif = $cfg['if'];
3157
				break;
3158
			default:
3159
				$wanif = $cfg['if'];
3160
				break;
3161
		}
3162
		break;
3163
	}
3164

    
3165
    return $wanif;
3166
}
3167

    
3168
/* Guess the physical interface by providing a IP address */
3169
function guess_interface_from_ip($ipaddress) {
3170
	if(! is_ipaddr($ipaddress)) {
3171
		return false;
3172
	}
3173
	if(is_ipaddrv4($ipaddress)) {
3174
		/* create a route table we can search */
3175
		exec("netstat -rnWf inet", $output, $ret);
3176
		foreach($output as $line) {
3177
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3178
				$fields = preg_split("/[ ]+/", $line);
3179
				if(ip_in_subnet($ipaddress, $fields[0])) {
3180
					return $fields[6];
3181
				}
3182
			}
3183
		}
3184
	}
3185
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3186
	if(is_ipaddrv6($ipaddress)) {
3187
		/* create a route table we can search */
3188
		exec("netstat -rnWf inet6", $output, $ret);
3189
		foreach($output as $line) {
3190
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3191
				$fields = preg_split("/[ ]+/", $line);
3192
				if(ip_in_subnet($ipaddress, $fields[0])) {
3193
					return $fields[6];
3194
				}
3195
			}
3196
		}
3197
	}
3198
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3199
	if(empty($ret)) {
3200
        	return false;
3201
	}
3202
	return $ret;
3203
}
3204

    
3205
/*
3206
 * find_ip_interface($ip): return the interface where an ip is defined
3207
 */
3208
function find_ip_interface($ip)
3209
{
3210
        /* if list */
3211
        $ifdescrs = get_configured_interface_list();
3212

    
3213
        foreach ($ifdescrs as $ifdescr => $ifname) {
3214
		if ($ip == get_interface_ip($ifname)) {
3215
                	$int = get_real_interface($ifname);
3216
			return $int;
3217
		}
3218
        }
3219
        return false;
3220
}
3221

    
3222
/*
3223
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3224
 */
3225
function find_number_of_created_carp_interfaces() {
3226
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3227
}
3228

    
3229
function get_all_carp_interfaces() {
3230
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3231
	$ints = explode(" ", $ints);
3232
	return $ints;
3233
}
3234

    
3235
/*
3236
 * find_carp_interface($ip): return the carp interface where an ip is defined
3237
 */
3238
function find_carp_interface($ip) {
3239
	global $config;
3240
	if (is_array($config['virtualip']['vip'])) {
3241
		foreach ($config['virtualip']['vip'] as $vip) {
3242
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3243
				if(is_ipaddrv4($ip)) {
3244
					$carp_ip = get_interface_ip($vip['interface']);
3245
				}
3246
				if(is_ipaddrv6($ip)) {
3247
					$carp_ip = get_interface_ipv6($vip['interface']);
3248
				}
3249
				exec("/sbin/ifconfig", $output, $return);
3250
				foreach($output as $line) {
3251
					$elements = preg_split("/[ ]+/i", $line);
3252
					if(strstr($elements[0], "vip"))
3253
						$curif = str_replace(":", "", $elements[0]);
3254
					if(stristr($line, $ip)) {
3255
						$if = $curif;
3256
						continue;
3257
					}
3258
				}
3259
				if ($if)
3260
					return $if;
3261
			}
3262
		}
3263
	}
3264
}
3265

    
3266
function link_carp_interface_to_parent($interface) {
3267
        global $config;
3268

    
3269
        if ($interface == "")
3270
                return;
3271

    
3272
        $carp_ip = get_interface_ip($interface);
3273
        if (!is_ipaddr($carp_ip))
3274
                return;
3275

    
3276
        /* if list */
3277
        $ifdescrs = get_configured_interface_list();
3278
        foreach ($ifdescrs as $ifdescr => $ifname) {
3279
                $interfaceip = get_interface_ip($ifname);
3280
                $subnet_bits = get_interface_subnet($ifname);
3281
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3282
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3283
                        return $ifname;
3284
        }
3285

    
3286
        return "";
3287
}
3288

    
3289
/****f* interfaces/link_ip_to_carp_interface
3290
 * NAME
3291
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3292
 * INPUTS
3293
 *   $ip
3294
 * RESULT
3295
 *   $carp_ints
3296
 ******/
3297
function link_ip_to_carp_interface($ip) {
3298
        global $config;
3299

    
3300
        if (!is_ipaddr($ip))
3301
                return;
3302

    
3303
        $carp_ints = "";
3304
        if (is_array($config['virtualip']['vip'])) {
3305
		$first = 0;
3306
		$carp_int = array();
3307
                foreach ($config['virtualip']['vip'] as $vip) {
3308
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3309
                                $carp_ip = $vip['subnet'];
3310
                                $carp_sn = $vip['subnet_bits'];
3311
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3312
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3313
					$carp_int[] = "vip{$vip['vhid']}";
3314
                        }
3315
                }
3316
		if (!empty($carp_int))
3317
			$carp_ints = implode(" ", array_unique($carp_int));
3318
        }
3319

    
3320
        return $carp_ints;
3321
}
3322

    
3323
function link_interface_to_vlans($int, $action = "") {
3324
	global $config;
3325

    
3326
	if (empty($int))
3327
		return;
3328

    
3329
	if (is_array($config['vlans']['vlan'])) {
3330
                foreach ($config['vlans']['vlan'] as $vlan) {
3331
			if ($int == $vlan['if']) {
3332
				if ($action == "update") {
3333
					interfaces_bring_up($int);
3334
				} else if ($action == "")
3335
					return $vlan;
3336
			}
3337
		}
3338
	}
3339
}
3340

    
3341
function link_interface_to_vips($int, $action = "") {
3342
        global $config;
3343

    
3344
        if (is_array($config['virtualip']['vip'])) {
3345
		foreach ($config['virtualip']['vip'] as $vip) {
3346
			if ($int == $vip['interface']) {
3347
				if ($action == "update") {
3348
					interface_vip_bring_down($vip);
3349
					interfaces_vips_configure($int);
3350
				} else
3351
					return $vip;
3352
			}
3353
		}
3354
	}
3355
}
3356

    
3357
/****f* interfaces/link_interface_to_bridge
3358
 * NAME
3359
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3360
 * INPUTS
3361
 *   $ip
3362
 * RESULT
3363
 *   bridge[0-99]
3364
 ******/
3365
function link_interface_to_bridge($int) {
3366
        global $config;
3367

    
3368
        if (is_array($config['bridges']['bridged'])) {
3369
                foreach ($config['bridges']['bridged'] as $bridge) {
3370
			if (in_array($int, explode(',', $bridge['members'])))
3371
                                return "{$bridge['bridgeif']}";
3372
		}
3373
	}
3374
}
3375

    
3376
function link_interface_to_group($int) {
3377
        global $config;
3378

    
3379
	$result = array();
3380

    
3381
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3382
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3383
			if (in_array($int, explode(" ", $group['members'])))
3384
				$result[$group['ifname']] = $int;
3385
		}
3386
	}
3387

    
3388
	return $result;
3389
}
3390

    
3391
function link_interface_to_gre($interface) {
3392
        global $config;
3393

    
3394
	$result = array();
3395

    
3396
        if (is_array($config['gres']['gre'])) {
3397
                foreach ($config['gres']['gre'] as $gre)
3398
                        if($gre['if'] == $interface)
3399
				$result[] = $gre;
3400
	}
3401

    
3402
	return $result;
3403
}
3404

    
3405
function link_interface_to_gif($interface) {
3406
        global $config;
3407

    
3408
	$result = array();
3409

    
3410
        if (is_array($config['gifs']['gif'])) {
3411
                foreach ($config['gifs']['gif'] as $gif)
3412
                        if($gif['if'] == $interface)
3413
                                $result[] = $gif;
3414
	}
3415

    
3416
	return $result;
3417
}
3418

    
3419
/*
3420
 * find_interface_ip($interface): return the interface ip (first found)
3421
 */
3422
function find_interface_ip($interface, $flush = false)
3423
{
3424
	global $interface_ip_arr_cache;
3425
	global $interface_sn_arr_cache;
3426

    
3427
	$interface = str_replace("\n", "", $interface);
3428
	
3429
	if (!does_interface_exist($interface))
3430
		return;
3431

    
3432
	/* Setup IP cache */
3433
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3434
		$ifinfo = pfSense_get_interface_addresses($interface);
3435
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3436
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3437
	}
3438

    
3439
	return $interface_ip_arr_cache[$interface];
3440
}
3441

    
3442
/*
3443
 * find_interface_ipv6($interface): return the interface ip (first found)
3444
 */
3445
function find_interface_ipv6($interface, $flush = false)
3446
{
3447
	global $interface_ipv6_arr_cache;
3448
	global $interface_snv6_arr_cache;
3449
	global $config;
3450
	
3451
	$interface = str_replace("\n", "", $interface);
3452
	
3453
	if (!does_interface_exist($interface))
3454
		return;
3455

    
3456
	/* Setup IP cache */
3457
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3458
		$ifinfo = pfSense_get_interface_addresses($interface);
3459
		exec("/sbin/ifconfig {$interface} inet6", $output);
3460
		foreach($output as $line) {
3461
			if(preg_match("/inet6/", $line)) {
3462
				$parts = explode(" ", $line);
3463
				if(! preg_match("/fe80::/", $parts[1])) {
3464
					$ifinfo['ipaddrv6'] = $parts[1];
3465
					if($parts[2] == "-->") {
3466
						$parts[5] = "126";
3467
						$ifinfo['subnetbitsv6'] = $parts[5];
3468
					} else {
3469
						$ifinfo['subnetbitsv6'] = $parts[3];
3470
					}
3471
				}
3472
			}
3473
		}
3474
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3475
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3476
	}
3477

    
3478
	return $interface_ipv6_arr_cache[$interface];
3479
}
3480

    
3481
function find_interface_subnet($interface, $flush = false)
3482
{
3483
	global $interface_sn_arr_cache;
3484
	global $interface_ip_arr_cache;
3485

    
3486
	$interface = str_replace("\n", "", $interface);
3487
	if (does_interface_exist($interface) == false)
3488
		return;
3489

    
3490
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3491
		$ifinfo = pfSense_get_interface_addresses($interface);
3492
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3493
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3494
        }
3495

    
3496
	return $interface_sn_arr_cache[$interface];
3497
}
3498

    
3499
function find_interface_subnetv6($interface, $flush = false)
3500
{
3501
	global $interface_snv6_arr_cache;
3502
	global $interface_ipv6_arr_cache;
3503

    
3504
	$interface = str_replace("\n", "", $interface);
3505
	if (does_interface_exist($interface) == false)
3506
		return;
3507

    
3508
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3509
		$ifinfo = pfSense_get_interface_addresses($interface);
3510
		exec("/sbin/ifconfig {$interface} inet6", $output);
3511
		foreach($output as $line) {
3512
			if(preg_match("/inet6/", $line)) {
3513
				$parts = explode(" ", $line);
3514
				if(! preg_match("/fe80::/", $parts[1])) {
3515
					$ifinfo['ipaddrv6'] = $parts[1];
3516
					if($parts[2] == "-->") {
3517
						$parts[5] = "126";
3518
						$ifinfo['subnetbitsv6'] = $parts[5];
3519
					} else {
3520
						$ifinfo['subnetbitsv6'] = $parts[3];
3521
					}
3522
				}
3523
			}
3524
		}
3525
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3526
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3527
        }
3528

    
3529
	return $interface_snv6_arr_cache[$interface];
3530
}
3531

    
3532
function ip_in_interface_alias_subnet($interface, $ipalias) {
3533
	global $config;
3534

    
3535
	if (empty($interface) || !is_ipaddr($ipalias))
3536
		return false;
3537
	if (is_array($config['virtualip']['vip'])) {
3538
                foreach ($config['virtualip']['vip'] as $vip) {
3539
                        switch ($vip['mode']) {
3540
                        case "ipalias":
3541
                                if ($vip['interface'] <> $interface)
3542
                                        break;
3543
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3544
					return true;
3545
                                break;
3546
                        }
3547
                }
3548
	}
3549

    
3550
	return false;
3551
}
3552

    
3553
function get_interface_ip($interface = "wan")
3554
{
3555
	$realif = get_real_interface($interface);
3556
	if (!$realif) {
3557
		if (preg_match("/^carp/i", $interface))
3558
			$realif = $interface;
3559
		else if (preg_match("/^vip/i", $interface))
3560
			$realif = $interface;
3561
		else
3562
			return null;
3563
	}
3564

    
3565
	$curip = find_interface_ip($realif);
3566
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3567
		return $curip;
3568
	else
3569
		return null;
3570
}
3571

    
3572
function get_interface_ipv6($interface = "wan")
3573
{
3574
	$realif = get_real_interface($interface);
3575
	if (!$realif) {
3576
		if (preg_match("/^carp/i", $interface))
3577
			$realif = $interface;
3578
		else if (preg_match("/^vip/i", $interface))
3579
			$realif = $interface;
3580
		else
3581
			return null;
3582
	}
3583

    
3584
	$curip = find_interface_ipv6($realif);
3585
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3586
		return $curip;
3587
	else
3588
		return null;
3589
}
3590

    
3591
function get_interface_subnet($interface = "wan")
3592
{
3593
	$realif = get_real_interface($interface);
3594
	if (!$realif) {
3595
                if (preg_match("/^carp/i", $interface))
3596
                        $realif = $interface;
3597
                else if (preg_match("/^vip/i", $interface))
3598
                        $realif = $interface;
3599
                else
3600
                        return null;
3601
        }
3602

    
3603
	$cursn = find_interface_subnet($realif);
3604
	if (!empty($cursn))
3605
		return $cursn;
3606

    
3607
	return null;
3608
}
3609

    
3610
function get_interface_subnetv6($interface = "wan")
3611
{
3612
	$realif = get_real_interface($interface);
3613
	if (!$realif) {
3614
                if (preg_match("/^carp/i", $interface))
3615
                        $realif = $interface;
3616
                else if (preg_match("/^vip/i", $interface))
3617
                        $realif = $interface;
3618
                else
3619
                        return null;
3620
        }
3621

    
3622
	$cursn = find_interface_subnetv6($realif);
3623
	if (!empty($cursn))
3624
		return $cursn;
3625

    
3626
	return null;
3627
}
3628

    
3629
/* return outside interfaces with a gateway */
3630
function get_interfaces_with_gateway() {
3631
	global $config;
3632

    
3633
	$ints = array();
3634

    
3635
	/* loop interfaces, check config for outbound */
3636
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3637
		switch ($ifname['ipaddr']) {
3638
			case "dhcp":
3639
			case "carpdev-dhcp":
3640
			case "ppp";
3641
			case "pppoe":
3642
			case "pptp":
3643
			case "l2tp":
3644
			case "ppp";
3645
				$ints[$ifdescr] = $ifdescr;
3646
			break;
3647
			default:
3648
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3649
				    !empty($ifname['gateway']))
3650
					$ints[$ifdescr] = $ifdescr;
3651
			break;
3652
		}
3653
	}
3654
	return $ints;
3655
}
3656

    
3657
/* return true if interface has a gateway */
3658
function interface_has_gateway($friendly) {
3659
	global $config;
3660

    
3661
	if (!empty($config['interfaces'][$friendly])) {
3662
		$ifname = &$config['interfaces'][$friendly];
3663
		switch ($ifname['ipaddr']) {
3664
			case "dhcp":
3665
			case "carpdev-dhcp":
3666
			case "pppoe":
3667
			case "pptp":
3668
			case "l2tp":
3669
			case "ppp";
3670
				return true;
3671
			break;
3672
			default:
3673
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3674
					return true;
3675
				if (!empty($ifname['gateway']))
3676
					return true;
3677
			break;
3678
		}
3679
	}
3680

    
3681
	return false;
3682
}
3683

    
3684
/****f* interfaces/is_altq_capable
3685
 * NAME
3686
 *   is_altq_capable - Test if interface is capable of using ALTQ
3687
 * INPUTS
3688
 *   $int            - string containing interface name
3689
 * RESULT
3690
 *   boolean         - true or false
3691
 ******/
3692

    
3693
function is_altq_capable($int) {
3694
        /* Per:
3695
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3696
         * Only the following drivers have ALTQ support
3697
         */
3698
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3699
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3700
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3701
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3702
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3703
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3704
			"l2tp", "ppp");
3705

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

    
3708
        if (in_array($int_family[0], $capable))
3709
                return true;
3710
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3711
		return true;
3712
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3713
		return true;
3714
        else
3715
                return false;
3716
}
3717

    
3718
/****f* interfaces/is_interface_wireless
3719
 * NAME
3720
 *   is_interface_wireless - Returns if an interface is wireless
3721
 * RESULT
3722
 *   $tmp       - Returns if an interface is wireless
3723
 ******/
3724
function is_interface_wireless($interface) {
3725
        global $config, $g;
3726

    
3727
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3728
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3729
                if (preg_match($g['wireless_regex'], $interface)) {
3730
                        if (isset($config['interfaces'][$friendly]))
3731
                                $config['interfaces'][$friendly]['wireless'] = array();
3732
                        return true;
3733
                }
3734
                return false;
3735
        } else
3736
                return true;
3737
}
3738

    
3739
function get_wireless_modes($interface) {
3740
	/* return wireless modes and channels */
3741
	$wireless_modes = array();
3742

    
3743
	$cloned_interface = get_real_interface($interface);
3744

    
3745
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3746
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3747
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3748
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3749

    
3750
		$interface_channels = "";
3751
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3752
		$interface_channel_count = count($interface_channels);
3753

    
3754
		$c = 0;
3755
		while ($c < $interface_channel_count)
3756
		{
3757
			$channel_line = explode(",", $interface_channels["$c"]);
3758
			$wireless_mode = trim($channel_line[0]);
3759
			$wireless_channel = trim($channel_line[1]);
3760
			if(trim($wireless_mode) != "") {
3761
				/* if we only have 11g also set 11b channels */
3762
				if($wireless_mode == "11g") {
3763
					if(!isset($wireless_modes["11b"]))
3764
						$wireless_modes["11b"] = array();
3765
				} else if($wireless_mode == "11g ht") {
3766
					if(!isset($wireless_modes["11b"]))
3767
						$wireless_modes["11b"] = array();
3768
					if(!isset($wireless_modes["11g"]))
3769
						$wireless_modes["11g"] = array();
3770
					$wireless_mode = "11ng";
3771
				} else if($wireless_mode == "11a ht") {
3772
					if(!isset($wireless_modes["11a"]))
3773
						$wireless_modes["11a"] = array();
3774
					$wireless_mode = "11na";
3775
				}
3776
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3777
			}
3778
			$c++;
3779
		}
3780
	}
3781
	return($wireless_modes);
3782
}
3783

    
3784
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3785
function get_wireless_channel_info($interface) {
3786
	$wireless_channels = array();
3787

    
3788
	$cloned_interface = get_real_interface($interface);
3789

    
3790
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3791
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3792
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3793
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3794

    
3795
		$interface_channels = "";
3796
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3797

    
3798
		foreach ($interface_channels as $channel_line) {
3799
			$channel_line = explode(",", $channel_line);
3800
			if(!isset($wireless_channels[$channel_line[0]]))
3801
				$wireless_channels[$channel_line[0]] = $channel_line;
3802
		}
3803
	}
3804
	return($wireless_channels);
3805
}
3806

    
3807
/****f* interfaces/get_interface_mtu
3808
 * NAME
3809
 *   get_interface_mtu - Return the mtu of an interface
3810
 * RESULT
3811
 *   $tmp       - Returns the mtu of an interface
3812
 ******/
3813
function get_interface_mtu($interface) {
3814
        $mtu = pfSense_get_interface_addresses($interface);
3815
        return $mtu['mtu'];
3816
}
3817

    
3818
function get_interface_mac($interface) {
3819

    
3820
	$macinfo = pfSense_get_interface_addresses($interface);
3821
	return $macinfo["macaddr"];
3822
}
3823

    
3824
/****f* pfsense-utils/generate_random_mac_address
3825
 * NAME
3826
 *   generate_random_mac - generates a random mac address
3827
 * INPUTS
3828
 *   none
3829
 * RESULT
3830
 *   $mac - a random mac address
3831
 ******/
3832
function generate_random_mac_address() {
3833
        $mac = "02";
3834
        for($x=0; $x<5; $x++)
3835
                $mac .= ":" . dechex(rand(16, 255));
3836
        return $mac;
3837
}
3838

    
3839
/****f* interfaces/is_jumbo_capable
3840
 * NAME
3841
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3842
 * INPUTS
3843
 *   $int             - string containing interface name
3844
 * RESULT
3845
 *   boolean          - true or false
3846
 ******/
3847
function is_jumbo_capable($int) {
3848
        global $g;
3849

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

    
3852
        if (in_array($int_family[0], $g['vlan_long_frame']))
3853
                return true;
3854
        else
3855
                return false;
3856
}
3857

    
3858
function setup_pppoe_reset_file($pppif, $iface="") {
3859
	global $g;
3860
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3861

    
3862
	if(!empty($iface) && !empty($pppif)){
3863
		$cron_cmd = <<<EOD
3864
#!/bin/sh
3865
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3866
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3867

    
3868
EOD;
3869

    
3870
		file_put_contents($cron_file, $cron_cmd);
3871
		chmod($cron_file, 0700);
3872
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3873
	} else
3874
		unlink_if_exists($cron_file);
3875
}
3876

    
3877
function get_vip_descr($ipaddress) {
3878
	global $config;
3879

    
3880
	foreach ($config['virtualip']['vip'] as $vip) {
3881
		if ($vip['subnet'] == $ipaddress) {
3882
			return ($vip['descr']);
3883
		}
3884
	}
3885
	return "";
3886
}
3887

    
3888
?>
(25-25/61)