Project

General

Profile

Download (110 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
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
259
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
260
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
261
                if (empty($result)) {
262
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
263
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
264
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
265
                }
266
        } else {
267
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
268
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
269
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
270
        }
271

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

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

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

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

    
300
        return $vlanif;
301
}
302

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

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

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

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

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

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

    
343
        return $vlanif;
344
}
345

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

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

    
367
function interfaces_bridge_configure() {
368
        global $config;
369

    
370
        $i = 0;
371
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
372
                foreach ($config['bridges']['bridged'] as $bridge) {
373
                        if(empty($bridge['bridgeif']))
374
                                $bridge['bridgeif'] = "bridge{$i}";
375
                        /* XXX: Maybe we should report any errors?! */
376
                        interface_bridge_configure($bridge);
377
                        $i++;
378
                }
379
        }
380
}
381

    
382
function interface_bridge_configure(&$bridge) {
383
	global $config, $g;
384

    
385
	if (!is_array($bridge))
386
	        return -1;
387

    
388
	if (empty($bridge['members'])) {
389
		log_error("No members found on {$bridge['bridgeif']}");
390
		return -1;
391
	}
392

    
393
	$members = explode(',', $bridge['members']);
394
	if (!count($members))
395
		return -1;
396

    
397
	$checklist = get_configured_interface_list();
398

    
399
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
400
		pfSense_interface_destroy($bridge['bridgeif']);
401
		pfSense_interface_create($bridge['bridgeif']);
402
		$bridgeif = $bridge['bridgeif'];
403
	} else
404
		$bridgeif = pfSense_interface_create("bridge");
405

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

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

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

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

    
563
	if($bridgeif)
564
		interfaces_bring_up($bridgeif);	
565
	else 
566
		log_error("bridgeif not defined -- could not bring interface up");
567

    
568
	return $bridgeif;
569
}
570

    
571
function interface_bridge_add_member($bridgeif, $interface) {
572

    
573
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
574
		return;
575

    
576
	$mtu = get_interface_mtu($brigeif);
577
	$mtum = get_interface_mtu($interface);
578
	
579
	if ($mtu != $mtum)
580
		pfSense_interface_mtu($interface, $mtu);
581

    
582
	$options = pfSense_get_interface_addresses($bridgeif);
583
	$flags = 0;
584
	if (!isset($options['encaps']['txcsum']))
585
		$flags |= IFCAP_TXCSUM;
586

    
587
	if (!isset($options['encaps']['rxcsum']))
588
		$flags |= IFCAP_RXCSUM;
589

    
590
	pfSense_interface_capabilities($interface, -$flags);
591

    
592
	interfaces_bring_up($interface);
593
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
594
}
595

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

    
615
function interface_lagg_configure(&$lagg) {
616
        global $config, $g;
617

    
618
        if (!is_array($lagg))
619
		return -1;
620

    
621
	$members = explode(',', $lagg['members']);
622
	if (!count($members))
623
		return -1;
624
	
625
	$checklist = get_interface_list();
626

    
627
	if ($g['booting'] || !(empty($lagg['laggif']))) {
628
		pfSense_interface_destroy($lagg['laggif']);
629
		pfSense_interface_create($lagg['laggif']);
630
                $laggif = $lagg['laggif'];
631
        } else
632
		$laggif = pfSense_interface_create("lagg");
633

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

    
655
	/* Just in case anything is not working well */
656
        if ($smallermtu == 0)
657
                $smallermtu = 1500;
658

    
659
	$flags = 0;
660
        if ($commonrx === false)
661
                $flags |= IFCAP_RXCSUM;
662
        if ($commontx === false)
663
                $flags |= IFCAP_TXCSUM;
664
	if ($commontso4 === false)
665
                $flags |= IFCAP_TSO4;
666
        if ($commontso6 === false)
667
                $flags |= IFCAP_TSO6;
668
        if ($commonlro === false)
669
                $flags |= IFCAP_LRO;
670

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

    
683
	interfaces_bring_up($laggif);
684

    
685
	return $laggif;
686
}
687

    
688
function interfaces_gre_configure() {
689
        global $config;
690

    
691
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
692
                foreach ($config['gres']['gre'] as $i => $gre) {
693
                        if(empty($gre['greif']))
694
                                $gre['greif'] = "gre{$i}";
695
                        /* XXX: Maybe we should report any errors?! */
696
                        interface_gre_configure($gre);
697
                }
698
        }
699
}
700

    
701
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
702
function interface_gre_configure(&$gre, $grekey = "") {
703
        global $config, $g;
704

    
705
	if (!is_array($gre))
706
		return -1;
707

    
708
	$realif = get_real_interface($gre['if']);
709
	$realifip = get_interface_ip($gre['if']);
710

    
711
	/* make sure the parent interface is up */
712
	interfaces_bring_up($realif);
713

    
714
	if ($g['booting'] || !(empty($gre['greif']))) {
715
		pfSense_interface_destroy($gre['greif']);
716
		pfSense_interface_create($gre['greif']);
717
		$greif = $gre['greif'];
718
	} else
719
		$greif = pfSense_interface_create("gre");
720

    
721
	/* Do not change the order here for more see gre(4) NOTES section. */
722
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
723
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
724
	if (isset($gre['link0']) && $gre['link0'])
725
		pfSense_interface_flags($greif, IFF_LINK0);
726
	if (isset($gre['link1']) && $gre['link1'])
727
		pfSense_interface_flags($greif, IFF_LINK1);
728
	if (isset($gre['link2']) && $gre['link2'])
729
		pfSense_interface_flags($greif, IFF_LINK2);
730

    
731
	if($greif)
732
		interfaces_bring_up($greif);
733
	else 
734
		log_error("Could not bring greif up -- variable not defined.");
735

    
736
	if (isset($gre['link1']) && $gre['link1'])
737
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
738
	file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
739

    
740
	return $greif;
741
}
742

    
743
function interfaces_gif_configure() {
744
	global $config;
745

    
746
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
747
		foreach ($config['gifs']['gif'] as $i => $gif) {
748
			if(empty($gif['gifif']))
749
				$gre['gifif'] = "gif{$i}";
750
			/* XXX: Maybe we should report any errors?! */
751
			interface_gif_configure($gif);
752
		}
753
	}
754
}
755

    
756
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
757
function interface_gif_configure(&$gif, $gifkey = "") {
758
	global $config, $g;
759

    
760
	if (!is_array($gif))
761
		return -1;
762

    
763
	$realif = get_real_interface($gif['if']);
764
	$realifip = get_interface_ip($gif['if']);
765

    
766
	/* make sure the parent interface is up */
767
	if($realif)
768
		interfaces_bring_up($realif);
769
	else 
770
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
771

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

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

    
795
	/* XXX: Needed?! Let them use the defined gateways instead */
796
	//mwexec("/sbin/route add {$gif['tunnel-remote-addr']}/{$gif['tunnel-remote-net']} -iface {$gifif}");
797
	file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
798

    
799
	return $gifif;
800
}
801

    
802
function interfaces_configure() {
803
	global $config, $g;
804

    
805
	/* Set up our loopback interface */
806
	interfaces_loopback_configure();
807

    
808
	/* set up LAGG virtual interfaces */
809
	interfaces_lagg_configure();
810

    
811
	/* set up VLAN virtual interfaces */
812
	interfaces_vlan_configure();
813

    
814
	interfaces_qinq_configure();
815

    
816
	$iflist = get_configured_interface_with_descr();
817
	$delayed_list = array();
818
	$bridge_list = array();
819
	
820
	/* This is needed to speedup interfaces on bootup. */
821
	$reload = false;
822
	if ($g['booting'])
823
		$reload = true;
824

    
825
	foreach($iflist as $if => $ifname) {
826
		$realif = $config['interfaces'][$if]['if'];
827
		if (strstr($realif, "bridge")) 
828
			$bridge_list[$if] = $ifname;
829
		else if (strstr($realif, "gre"))
830
			$delayed_list[$if] = $ifname;
831
		else if (strstr($realif, "gif"))
832
			$delayed_list[$if] = $ifname;
833
		else if (strstr($realif, "ovpn")) {
834
			//echo "Delaying OpenVPN interface configuration...done.\n";
835
			continue;
836
		} else {
837
			if ($g['booting'])
838
				echo "Configuring {$ifname} interface...";
839
			if($g['debug'])
840
				log_error("Configuring {$ifname}");
841
			interface_configure($if, $reload);
842
			if ($g['booting']) 
843
				echo "done.\n";
844
		}
845
	}
846

    
847
	/* create the unconfigured wireless clones */
848
	interfaces_create_wireless_clones();
849

    
850
	/* set up GRE virtual interfaces */
851
	interfaces_gre_configure();
852

    
853
	/* set up GIF virtual interfaces */
854
	interfaces_gif_configure();
855
	
856
	foreach ($delayed_list as $if => $ifname) {
857
		if ($g['booting'])
858
			echo "Configuring {$ifname} interface...";
859
        	if ($g['debug'])
860
        		log_error("Configuring {$ifname}");
861

    
862
		interface_configure($if, $reload);
863

    
864
		if ($g['booting'])
865
			echo "done.\n";
866
	}
867

    
868
	/* set up BRIDGe virtual interfaces */
869
	interfaces_bridge_configure();
870

    
871
	foreach ($bridge_list as $if => $ifname) {
872
		if ($g['booting'])
873
			echo "Configuring {$ifname} interface...";
874
		if($g['debug'])
875
			log_error("Configuring {$ifname}");
876

    
877
		interface_configure($if, $reload);
878

    
879
		if ($g['booting'])
880
			echo "done.\n";
881
	}
882

    
883
	/* bring up vip interfaces */
884
	interfaces_vips_configure();
885

    
886
	/* configure interface groups */
887
	interfaces_group_setup();
888

    
889
	if (!$g['booting']) {
890
		/* reconfigure static routes (kernel may have deleted them) */
891
		system_routing_configure();
892

    
893
		/* reload IPsec tunnels */
894
		vpn_ipsec_configure();
895

    
896
		/* reload dhcpd (interface enabled/disabled status may have changed) */
897
		services_dhcpd_configure();
898

    
899
		/* restart dnsmasq */
900
		services_dnsmasq_configure();
901

    
902
		/* reload captive portal */
903
		captiveportal_init_rules();
904
	}
905

    
906
	return 0;
907
}
908

    
909
function interface_reconfigure($interface = "wan") {
910
	interface_bring_down($interface);
911
	interface_configure($interface, true);
912
}
913

    
914
function interface_vip_bring_down($vip) {
915
	global $g;
916

    
917
	switch ($vip['mode']) {
918
	case "proxyarp":
919
		$vipif = get_real_interface($vip['interface']);
920
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
921
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
922
		break;
923
	case "ipalias":
924
		$vipif = get_real_interface($vip['interface']);
925
		if(does_interface_exist($vipif))
926
			pfSense_interface_deladdress($vipif, $vip['subnet']);
927
		break;
928
	case "carp":
929
		$vipif = "vip" . $vip['vhid'];
930
		if(does_interface_exist($vipif)) 
931
			pfSense_interface_destroy($vipif);
932
		break;
933
	case "carpdev-dhcp":
934
		$vipif = "vip" . $vip['vhid'];
935
		if(does_interface_exist($vipif)) 
936
			pfSense_interface_destroy($vipif);
937
		break;
938
	}
939
}
940

    
941
function interface_bring_down($interface = "wan", $destroy = false) {
942
	global $config, $g;
943

    
944
	if (!isset($config['interfaces'][$interface]))
945
		return; 
946

    
947
	$ifcfg = $config['interfaces'][$interface];
948

    
949
	$realif = get_real_interface($interface);
950

    
951
	switch ($ifcfg['ipaddr']) {
952
	case "ppp":
953
	case "pppoe":
954
	case "pptp":
955
	case "l2tp":
956
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
957
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
958
				if ($realif == $ppp['if']) {
959
					if (isset($ppp['ondemand']) && !$destroy){
960
						send_event("interface reconfigure {$interface}");
961
						break;
962
					}
963
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
964
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
965
						sleep(2);
966
					}
967
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
968
					break;
969
				}
970
			}
971
		}
972
		break;
973
	case "carpdev-dhcp":
974
		/* 
975
		 * NB: When carpdev gets enabled it would be better to be handled as all
976
		 *	   other interfaces! 
977
		 */
978
	case "dhcp":
979
		$pid = find_dhclient_process($realif);
980
		if($pid)
981
			mwexec("/bin/kill {$pid}");
982
		sleep(1);
983
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
984
		if(does_interface_exist("$realif")) {
985
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
986
			if ($destroy == true)
987
				pfSense_interface_flags($realif, -IFF_UP);
988
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
989
		}
990
		break;
991
	default:
992
		if(does_interface_exist("$realif")) {
993
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
994
			if ($destroy == true)
995
				pfSense_interface_flags($realif, -IFF_UP);
996
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
997
		}
998
		break;
999
	}
1000

    
1001
	/* remove interface up file if it exists */
1002
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1003
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1004
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1005
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1006
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1007
	
1008
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1009
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1010
	if (is_array($ifcfg['wireless'])) {
1011
		mwexec(kill_hostapd($realif));
1012
		mwexec(kill_wpasupplicant($realif));
1013
	}
1014

    
1015
	if ($destroy == true) {
1016
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1017
			pfSense_interface_destroy($realif);
1018
	}	
1019

    
1020
	return;
1021
}
1022

    
1023
function interfaces_ptpid_used($ptpid) {
1024
	global $config;
1025

    
1026
	if (is_array($config['ppps']['ppp']))
1027
		foreach ($config['ppps']['ppp'] as & $settings)
1028
			if ($ptpid == $settings['ptpid'])
1029
				return true;
1030

    
1031
	return false;
1032
}
1033

    
1034
function interfaces_ptpid_next() {
1035

    
1036
	$ptpid = 0;
1037
	while(interfaces_ptpid_used($ptpid))
1038
		$ptpid++;
1039

    
1040
	return $ptpid;
1041
}
1042

    
1043
function getMPDCRONSettings($pppif_) {
1044
	global $config;
1045
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1046
	if (is_array($config['cron']['item'])) {
1047
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1048
			$item = $config['cron']['item'][$i];
1049
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1050
				return array("ID" => $i, "ITEM" => $item);
1051
			}
1052
		}
1053
	}
1054
	return NULL;
1055
}
1056

    
1057
function handle_pppoe_reset($post_array) {
1058
	global $config, $g;
1059

    
1060
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1061

    
1062
	$pppif = $post_array['type'].$post_array['ptpid'];
1063
	if (!is_array($config['cron']['item'])) 
1064
		$config['cron']['item'] = array(); 
1065
	$itemhash = getMPDCRONSettings($pppif);
1066
	$item = $itemhash['ITEM'];
1067
	
1068
	// reset cron items if necessary and return
1069
	if (empty($post_array['pppoe-reset-type'])) {
1070
		if (isset($item))
1071
			unset($config['cron']['item'][$itemhash['ID']]);
1072
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1073
		return;
1074
	}
1075

    
1076
	if (empty($item)) 
1077
		$item = array();
1078
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1079
		$item['minute'] = $post_array['pppoe_resetminute'];
1080
		$item['hour'] = $post_array['pppoe_resethour'];
1081
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1082
			$date = explode("/", $post_array['pppoe_resetdate']);
1083
			$item['mday'] = $date[1];
1084
			$item['month'] = $date[0];
1085
		} else {
1086
			$item['mday'] = "*";
1087
			$item['month'] = "*";
1088
		}
1089
		$item['wday'] = "*";
1090
		$item['who'] = "root";
1091
		$item['command'] = $cron_cmd_file.$pppif;
1092
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1093
		switch ($post_array['pppoe_pr_preset_val']) {
1094
			case "monthly":
1095
				$item['minute'] = "0";
1096
				$item['hour'] = "0";
1097
				$item['mday'] = "1";
1098
				$item['month'] = "*";
1099
				$item['wday'] = "*";
1100
				$item['who'] = "root";
1101
				$item['command'] = $cron_cmd_file.$pppif;
1102
				break;
1103
	        case "weekly":
1104
				$item['minute'] = "0";
1105
				$item['hour'] = "0";
1106
				$item['mday'] = "*";
1107
				$item['month'] = "*";
1108
				$item['wday'] = "0";
1109
				$item['who'] = "root";
1110
				$item['command'] = $cron_cmd_file.$pppif;
1111
				break;
1112
			case "daily":
1113
				$item['minute'] = "0";
1114
				$item['hour'] = "0";
1115
				$item['mday'] = "*";
1116
				$item['month'] = "*";
1117
				$item['wday'] = "*";
1118
				$item['who'] = "root";
1119
				$item['command'] = $cron_cmd_file.$pppif;
1120
				break;
1121
			case "hourly":
1122
				$item['minute'] = "0";
1123
				$item['hour'] = "*";
1124
				$item['mday'] = "*";
1125
				$item['month'] = "*";
1126
				$item['wday'] = "*";
1127
				$item['who'] = "root";
1128
				$item['command'] = $cron_cmd_file.$pppif;
1129
				break;
1130
		} // end switch
1131
	} else {
1132
		/* test whether a cron item exists and unset() it if necessary */
1133
		$itemhash = getMPDCRONSettings($pppif);
1134
		$item = $itemhash['ITEM'];
1135
		if (isset($item))
1136
			unset($config['cron']['item'][$itemhash['ID']]); 
1137
	}// end if
1138
	if (isset($itemhash['ID'])) 
1139
		$config['cron']['item'][$itemhash['ID']] = $item;
1140
	else 
1141
		$config['cron']['item'][] = $item;
1142
}
1143

    
1144
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1145
*	It writes the mpd config file to /var/etc every time the link is opened.
1146
*/
1147

    
1148
function interface_ppps_configure($interface) {
1149
	global $config, $g;
1150
	
1151
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1152
	if(!is_dir("/var/spool/lock")) {
1153
		exec("/bin/mkdir -p /var/spool/lock");
1154
		exec("/bin/chmod a+rw /var/spool/lock/.");
1155
	}
1156
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1157
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1158
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1159
		
1160
	$ifcfg = $config['interfaces'][$interface];
1161
	if (!isset($ifcfg['enable']))
1162
		return 0;
1163
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1164
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1165
			if ($ifcfg['if'] == $ppp['if'])
1166
				break;
1167
		}
1168
	}
1169
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1170
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1171
		return 0;
1172
	}
1173
	$pppif = $ifcfg['if'];
1174
	if ($ppp['type'] == "ppp")
1175
		$type = "modem";
1176
	else
1177
		$type = $ppp['type'];
1178
	$upper_type = strtoupper($ppp['type']);	
1179
	
1180
	if($g['booting']) {
1181
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1182
		echo "starting {$pppif} link...";
1183
		// Do not re-configure the interface if we are booting and it's already been started
1184
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1185
			return 0;
1186
	}
1187
	
1188
	$ports = explode(',',$ppp['ports']);
1189
	if ($type != "modem") {
1190
		foreach ($ports as $pid => $port)
1191
			$ports[$pid] = get_real_interface($port);
1192
	}
1193
	$localips = explode(',',$ppp['localip']);
1194
	$gateways = explode(',',$ppp['gateway']);
1195
	$subnets = explode(',',$ppp['subnet']);
1196
	
1197
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1198
	to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1199
	*/
1200
	foreach($ports as $pid => $port){
1201
		switch ($ppp['type']) {
1202
			case "pppoe": 
1203
				/* Bring the parent interface up */
1204
				interfaces_bring_up($port);
1205
				pfSense_ngctl_attach(".", $port);
1206
				break;
1207
			case "pptp":
1208
			case "l2tp":
1209
				/* configure interface */
1210
				if(is_ipaddr($localips[$pid])){
1211
					// Manually configure interface IP/subnet
1212
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1213
					interfaces_bring_up($port);
1214
				} else if (empty($localips[$pid]))
1215
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1216
				
1217
				if(!is_ipaddr($localips[$pid])){
1218
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure.");
1219
					return 0;
1220
				}
1221
				/* XXX: This needs to go away soon! [It's commented out!] */
1222
				/* Configure the gateway (remote IP ) */
1223
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1224
					/* XXX: Fix later 
1225
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1226
					if(!is_ipaddr($gateways[$pid])) {
1227
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1228
						return 0;
1229
					}
1230
					*/
1231
				}
1232
				if(!is_ipaddr($gateways[$pid])){
1233
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1234
					return 0;
1235
				}
1236
				pfSense_ngctl_attach(".", $port);
1237
				break;
1238
			case "ppp":
1239
				if (!file_exists("{$port}")) {
1240
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1241
					return 0;
1242
				}
1243
				break;
1244
			default:
1245
				log_error("Unkown {$type} configured as ppp interface.");
1246
				break;
1247
		}
1248
	}
1249
	
1250
	if (is_array($ports) && count($ports) > 1)
1251
		$multilink = "enable";
1252
	else
1253
		$multilink = "disable";
1254
	
1255
	if ($type == "modem"){
1256
		if (is_ipaddr($ppp['localip']))
1257
			$localip = $ppp['localip'];
1258
		else
1259
			$localip = '0.0.0.0';
1260

    
1261
		if (is_ipaddr($ppp['gateway']))
1262
			$gateway = $ppp['gateway'];
1263
		else
1264
			$gateway = "10.64.64.{$pppid}";
1265
		$ranges = "{$localip}/0 {$gateway}/0";
1266
		
1267
		if (empty($ppp['apnum']))	
1268
			$ppp['apnum'] = 1;
1269
	} else
1270
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1271

    
1272
	if (isset($ppp['ondemand'])) 
1273
		$ondemand = "enable";
1274
	else
1275
		$ondemand = "disable";
1276
	if (!isset($ppp['idletimeout']))
1277
		$ppp['idletimeout'] = 0;
1278

    
1279
	if (empty($ppp['username']) && $type == "modem"){
1280
		$ppp['username'] = "user";
1281
		$ppp['password'] = "none";
1282
	}
1283
	if (empty($ppp['password']) && $type == "modem")
1284
		$passwd = "none";
1285
	else
1286
		$passwd = base64_decode($ppp['password']);
1287

    
1288
	$bandwidths = explode(',',$ppp['bandwidth']);
1289
	$mtus = explode(',',$ppp['mtu']);
1290
	$mrus = explode(',',$ppp['mru']);
1291

    
1292
	if (isset($ppp['mrru']))
1293
		$mrrus = explode(',',$ppp['mrru']);
1294

    
1295
	// Construct the mpd.conf file
1296
	$mpdconf = <<<EOD
1297
startup:
1298
	# configure the console
1299
	set console close
1300
	# configure the web server
1301
	set web close
1302

    
1303
default:
1304
{$ppp['type']}client:
1305
	create bundle static {$interface}
1306
	set iface name {$pppif}
1307

    
1308
EOD;
1309
	$setdefaultgw = false;
1310
	$founddefaultgw = false;
1311
	if (is_array($config['gateways']['gateway_item'])) {
1312
		foreach($config['gateways']['gateway_item'] as $gateway) {
1313
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1314
				$setdefaultgw = true;
1315
				break;
1316
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1317
				$founddefaultgw = true;
1318
				break;
1319
			}
1320
		}
1321
	}
1322
	
1323
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1324
		$setdefaultgw = true;
1325
		$mpdconf .= <<<EOD
1326
	set iface route default
1327

    
1328
EOD;
1329
	}
1330
	$mpdconf .= <<<EOD
1331
	set iface {$ondemand} on-demand
1332
	set iface idle {$ppp['idletimeout']}
1333

    
1334
EOD;
1335

    
1336
	if (isset($ppp['ondemand']))
1337
		$mpdconf .= <<<EOD
1338
	set iface addrs 10.10.1.1 10.10.1.2
1339

    
1340
EOD;
1341
	
1342
	if (isset($ppp['tcpmssfix']))
1343
		$tcpmss = "disable";
1344
	else
1345
		$tcpmss = "enable";
1346
		$mpdconf .= <<<EOD
1347
	set iface {$tcpmss} tcpmssfix
1348

    
1349
EOD;
1350

    
1351
	$mpdconf .= <<<EOD
1352
	set iface up-script /usr/local/sbin/ppp-linkup
1353
	set iface down-script /usr/local/sbin/ppp-linkdown
1354
	set ipcp ranges {$ranges}
1355

    
1356
EOD;
1357
	if (isset($ppp['vjcomp']))
1358
		$mpdconf .= <<<EOD
1359
	set ipcp no vjcomp
1360

    
1361
EOD;
1362

    
1363
	if (isset($config['system']['dnsallowoverride']))
1364
		$mpdconf .= <<<EOD
1365
	set ipcp enable req-pri-dns
1366
	set ipcp enable req-sec-dns
1367

    
1368
EOD;
1369
	if (!isset($ppp['verbose_log']))
1370
		$mpdconf .= <<<EOD
1371
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1372

    
1373
EOD;
1374
	foreach($ports as $pid => $port){
1375
		$port = get_real_interface($port);
1376
		$mpdconf .= <<<EOD
1377

    
1378
	create link static {$interface}_link{$pid} {$type}
1379
	set link action bundle {$interface}
1380
	set link {$multilink} multilink
1381
	set link keep-alive 10 60
1382
	set link max-redial 0
1383

    
1384
EOD;
1385
		if (isset($ppp['shortseq']))
1386
			$mpdconf .= <<<EOD
1387
	set link no shortseq
1388

    
1389
EOD;
1390

    
1391
		if (isset($ppp['acfcomp']))
1392
			$mpdconf .= <<<EOD
1393
	set link no acfcomp
1394

    
1395
EOD;
1396

    
1397
		if (isset($ppp['protocomp']))
1398
			$mpdconf .= <<<EOD
1399
	set link no protocomp
1400

    
1401
EOD;
1402

    
1403
		$mpdconf .= <<<EOD
1404
	set link disable chap pap
1405
	set link accept chap pap eap
1406
	set link disable incoming
1407

    
1408
EOD;
1409

    
1410

    
1411
		if (!empty($bandwidths[$pid]))
1412
			$mpdconf .= <<<EOD
1413
	set link bandwidth {$bandwidths[$pid]}
1414

    
1415
EOD;
1416

    
1417
		if (empty($mtus[$pid]))
1418
			$mtus[$pid] = "1492";
1419
			$mpdconf .= <<<EOD
1420
	set link mtu {$mtus[$pid]}
1421

    
1422
EOD;
1423

    
1424
		if (!empty($mrus[$pid]))
1425
			$mpdconf .= <<<EOD
1426
	set link mru {$mrus[$pid]}
1427

    
1428
EOD;
1429

    
1430
		if (!empty($mrrus[$pid]))
1431
			$mpdconf .= <<<EOD
1432
	set link mrru {$mrrus[$pid]}
1433

    
1434
EOD;
1435

    
1436
		$mpdconf .= <<<EOD
1437
	set auth authname "{$ppp['username']}"
1438
	set auth password {$passwd}
1439

    
1440
EOD;
1441
		if ($type == "modem") {
1442
			$mpdconf .= <<<EOD
1443
	set modem device {$ppp['ports']}
1444
	set modem script DialPeer
1445
	set modem idle-script Ringback
1446
	set modem watch -cd
1447
	set modem var \$DialPrefix "DT"
1448
	set modem var \$Telephone "{$ppp['phone']}"
1449

    
1450
EOD;
1451
		}
1452
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1453
			$mpdconf .= <<<EOD
1454
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1455

    
1456
EOD;
1457
		}
1458
		if (isset($ppp['initstr']) && $type == "modem") {
1459
			$initstr = base64_decode($ppp['initstr']);
1460
			$mpdconf .= <<<EOD
1461
	set modem var \$InitString "{$initstr}"
1462

    
1463
EOD;
1464
		}
1465
		if (isset($ppp['simpin']) && $type == "modem") {
1466
			$mpdconf .= <<<EOD
1467
	set modem var \$SimPin "{$ppp['simpin']}"
1468
	set modem var \$PinWait "{$ppp['pin-wait']}"
1469

    
1470
EOD;
1471
		}
1472
		if (isset($ppp['apn']) && $type == "modem") {
1473
			$mpdconf .= <<<EOD
1474
	set modem var \$APN "{$ppp['apn']}"
1475
	set modem var \$APNum "{$ppp['apnum']}"
1476

    
1477
EOD;
1478
		}
1479
		if (isset($ppp['provider']) && $type == "pppoe") {
1480
			$mpdconf .= <<<EOD
1481
	set pppoe service "{$ppp['provider']}"
1482

    
1483
EOD;
1484
		}
1485
		if ($type == "pppoe")
1486
			$mpdconf .= <<<EOD
1487
	set pppoe iface {$port}
1488

    
1489
EOD;
1490

    
1491
		if ($type == "pptp" || $type == "l2tp") {
1492
			$mpdconf .= <<<EOD
1493
	set {$type} self {$localips[$pid]}
1494
	set {$type} peer {$gateways[$pid]}
1495
	set {$type} disable windowing
1496

    
1497
EOD;
1498
		}
1499
		
1500
		$mpdconf .= "\topen\r\n";
1501
	} //end foreach($port)
1502

    
1503

    
1504
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1505
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1506
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1507
	else {
1508
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1509
		if (!$fd) {
1510
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1511
			return 0;
1512
		}
1513
		// Write out mpd_ppp.conf
1514
		fwrite($fd, $mpdconf);
1515
		fclose($fd);
1516
	}
1517

    
1518
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1519
	if (isset($ppp['uptime'])) {
1520
		if (!file_exists("/conf/{$pppif}.log")) {
1521
			conf_mount_rw();
1522
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1523
			conf_mount_ro();
1524
		}
1525
	} else {
1526
		if (file_exists("/conf/{$pppif}.log")) {
1527
			conf_mount_rw();
1528
			mwexec("rm -f /conf/{$pppif}.log");
1529
			conf_mount_ro();
1530
		}
1531
	}
1532

    
1533
	/* fire up mpd */
1534
	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");
1535

    
1536
	// Check for PPPoE periodic reset request 
1537
	if ($type == "pppoe") {
1538
		if (isset($ppp['pppoe-reset-type']))
1539
			setup_pppoe_reset_file($ppp['if'], $interface);
1540
		else
1541
			setup_pppoe_reset_file($ppp['if']);
1542
	}
1543

    
1544
	return 1;
1545
}
1546

    
1547
function interfaces_carp_setup() {
1548
	global $g, $config;
1549

    
1550
	$balanacing = "";
1551
	$pfsyncinterface = "";
1552
	$pfsyncenabled = "";
1553
	if(isset($config['system']['developerspew'])) {
1554
		$mt = microtime();
1555
		echo "interfaces_carp_setup() being called $mt\n";
1556
	}
1557

    
1558
	// Prepare CmdCHAIN that will be used to execute commands.
1559
	$cmdchain = new CmdCHAIN();	
1560

    
1561
	if ($g['booting']) {
1562
		echo "Configuring CARP settings...";
1563
		mute_kernel_msgs();
1564
	}
1565

    
1566
	/* suck in configuration items */
1567
	if($config['installedpackages']['carpsettings']) {
1568
		if($config['installedpackages']['carpsettings']['config']) {
1569
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1570
				$pfsyncenabled = $carp['pfsyncenabled'];
1571
				$balanacing = $carp['balancing'];
1572
				$pfsyncinterface = $carp['pfsyncinterface'];
1573
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1574
			}
1575
		}
1576
	} else {
1577
		unset($pfsyncinterface);
1578
		unset($balanacing);
1579
		unset($pfsyncenabled);
1580
	}
1581

    
1582
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1583
	if($balanacing) {
1584
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1585
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1586
	} else
1587
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1588

    
1589
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1590
	if (!empty($pfsyncinterface))
1591
		$carp_sync_int = get_real_interface($pfsyncinterface);
1592

    
1593
	if($g['booting']) {
1594
		/*    install rules to alllow pfsync to sync up during boot
1595
		 *    carp interfaces will remain down until the bootup sequence finishes
1596
		 */
1597
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1598
		if ($fd) {
1599
			fwrite($fd, "pass quick proto carp all keep state\n");
1600
			fwrite($fd, "pass quick proto pfsync all\n");
1601
			fwrite($fd, "pass out quick from any to any keep state\n");
1602
			fclose($fd);
1603
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1604
		} else
1605
			log_error("Could not create rules.boot file!");
1606
	}
1607

    
1608
	/* setup pfsync interface */
1609
	if($carp_sync_int and $pfsyncenabled) {
1610
		if (is_ipaddr($pfsyncpeerip))
1611
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1612
		else
1613
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1614
	} else
1615
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1616

    
1617
	if($config['virtualip']['vip'])
1618
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1619
	else
1620
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1621
	
1622
	if($g['debug'])
1623
		$cmdchain->setdebug(); // optional for verbose logging
1624

    
1625
	$cmdchain->execute();
1626
	$cmdchain->clear();
1627

    
1628
	if ($g['booting']) {
1629
		unmute_kernel_msgs();
1630
		echo "done.\n";
1631
	}
1632
}
1633

    
1634
function interface_proxyarp_configure($interface = "") {
1635
	global $config, $g;
1636
	if(isset($config['system']['developerspew'])) {
1637
		$mt = microtime();
1638
		echo "interface_proxyarp_configure() being called $mt\n";
1639
	}
1640

    
1641
	/* kill any running choparp */
1642
	if (empty($interface))
1643
		killbyname("choparp");
1644
	else {
1645
		$vipif = get_real_interface($interface);
1646
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1647
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1648
	}
1649

    
1650
	$paa = array();
1651
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1652

    
1653
		/* group by interface */
1654
		foreach ($config['virtualip']['vip'] as $vipent) {
1655
			if ($vipent['mode'] === "proxyarp") {
1656
				if ($vipent['interface'])
1657
					$proxyif = $vipent['interface'];
1658
				else
1659
					$proxyif = "wan";
1660
				
1661
				if (!empty($interface) && $interface != $proxyif)
1662
					continue;
1663

    
1664
				if (!is_array($paa[$proxyif]))
1665
					$paa[$proxyif] = array();
1666

    
1667
				$paa[$proxyif][] = $vipent;
1668
			}
1669
		}
1670
	}
1671

    
1672
	if (!empty($interface)) {
1673
		if (is_array($paa[$interface])) {
1674
			$paaifip = get_interface_ip($interface);
1675
                        if (!is_ipaddr($paaifip))
1676
                                return;
1677
                        $args = get_real_interface($interface) . " auto";
1678
                        foreach ($paa[$interface] as $paent) {
1679
                                if (isset($paent['subnet']))
1680
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1681
                                else if (isset($paent['range']))
1682
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1683
                        }
1684
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1685
		}
1686
	} else if (count($paa) > 0) {
1687
		foreach ($paa as $paif => $paents)  {
1688
			$paaifip = get_interface_ip($paif);
1689
			if (!is_ipaddr($paaifip))
1690
				continue;
1691
			$args = get_real_interface($paif) . " auto";
1692
			foreach ($paents as $paent) {
1693
				if (isset($paent['subnet']))
1694
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1695
				else if (isset($paent['range']))
1696
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1697
			}
1698
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1699
		}
1700
	}
1701
}
1702

    
1703
function interfaces_vips_configure($interface = "") {
1704
	global $g, $config;
1705
	if(isset($config['system']['developerspew'])) {
1706
		$mt = microtime();
1707
		echo "interfaces_vips_configure() being called $mt\n";
1708
	}
1709
	$paa = array();
1710
	if(is_array($config['virtualip']['vip'])) {
1711
		$carp_setuped = false;
1712
		$anyproxyarp = false;
1713
		foreach ($config['virtualip']['vip'] as $vip) {
1714
			switch ($vip['mode']) {
1715
			case "proxyarp":
1716
				/* nothing it is handled on interface_proxyarp_configure() */
1717
				if ($interface <> "" && $vip['interface'] <> $interface)
1718
					continue;
1719
				$anyproxyarp = true;
1720
				break;
1721
			case "ipalias":
1722
				if ($interface <> "" && $vip['interface'] <> $interface)
1723
					continue;
1724
				interface_ipalias_configure(&$vip);
1725
				break;
1726
			case "carp":
1727
				if ($interface <> "" && $vip['interface'] <> $interface)
1728
					continue;
1729
				if ($carp_setuped == false) {
1730
					interfaces_carp_setup();
1731
					$carp_setuped = true;
1732
				}
1733
				interface_carp_configure($vip);
1734
				break;
1735
			case "carpdev-dhcp":
1736
				if ($interface <> "" && $vip['interface'] <> $interface)
1737
					continue;
1738
				interface_carpdev_configure($vip);
1739
				break;
1740
			}
1741
		}
1742
		
1743
		if ($anyproxyarp == true)
1744
			interface_proxyarp_configure();
1745
	}
1746
}
1747

    
1748
function interface_ipalias_configure(&$vip) {
1749

    
1750
	if ($vip['mode'] == "ipalias") {
1751
		$if = get_real_interface($vip['interface']);
1752
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1753
	}
1754
}
1755

    
1756
function interface_reload_carps($cif) {
1757
	global $config;
1758

    
1759
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1760
	if (empty($carpifs))
1761
		return;
1762

    
1763
	$carps = explode(" ", $carpifs);
1764
	if(is_array($config['virtualip']['vip'])) {
1765
		$viparr = &$config['virtualip']['vip'];
1766
		foreach ($viparr as $vip) {
1767
			if (in_array($vip['carpif'], $carps)) {
1768
				switch ($vip['mode']) {
1769
				case "carp":
1770
					interface_vip_bring_down($vip);
1771
					sleep(1);
1772
					interface_carp_configure($vip);
1773
					break;
1774
				case "carpdev-dhcp":
1775
					interface_vip_bring_down($vip);
1776
					sleep(1);
1777
					interface_carpdev_configure($vip);
1778
					break;
1779
				case "ipalias":
1780
					interface_vip_bring_down($vip);
1781
					sleep(1);
1782
					interface_ipalias_configure($vip);
1783
					break;
1784
				}
1785
			}
1786
		}
1787
	}
1788
}
1789

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

    
1797
	if ($vip['mode'] != "carp")
1798
		return;
1799

    
1800
	$vip_password = $vip['password'];
1801
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1802
	if ($vip['password'] != "")
1803
		$password = " pass {$vip_password}";
1804

    
1805
	// set the vip interface to the vhid
1806
	$vipif = "vip{$vip['vhid']}";
1807

    
1808
	/*
1809
	 * ensure the interface containing the VIP really exists
1810
 	 * prevents a panic if the interface is missing or invalid
1811
	 */
1812
	$realif = get_real_interface($vip['interface']);
1813
	if (!does_interface_exist($realif)) {
1814
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1815
		return;
1816
	}
1817

    
1818
	if(is_ipaddrv4($vip['subnet'])) {
1819
		/* Ensure CARP IP really exists prior to loading up. */
1820
		$ww_subnet_ip = find_interface_ip($realif);
1821
		$ww_subnet_bits = find_interface_subnet($realif);
1822
		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'])) {
1823
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1824
			return;
1825
		}
1826
	}
1827
	if(is_ipaddrv6($vip['subnet'])) {
1828
		/* Ensure CARP IP really exists prior to loading up. */
1829
		$ww_subnet_ip = find_interface_ipv6($realif);
1830
		$ww_subnet_bits = find_interface_subnetv6($realif);
1831
		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'])) {
1832
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IPv6 address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1833
			return;
1834
		}
1835
	}
1836

    
1837
	/* create the carp interface and setup */
1838
	if (does_interface_exist($vipif)) {
1839
		pfSense_interface_flags($vipif, -IFF_UP);
1840
	} else {
1841
		$carpif = pfSense_interface_create("carp");
1842
		pfSense_interface_rename($carpif, $vipif);
1843
		pfSense_ngctl_name("{$carpif}:", $vipif);
1844
	}
1845

    
1846
	/* invalidate interface cache */
1847
	get_interface_arr(true);
1848

    
1849
	$advbase = "";
1850
	if (!empty($vip['advbase']))
1851
		$advbase = "advbase {$vip['advbase']}";
1852

    
1853
	if(is_ipaddrv4($vip['subnet'])) {
1854
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1855
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1856
	}
1857
	if(is_ipaddrv6($vip['subnet'])) {
1858
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1859
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1860
	}
1861

    
1862
	interfaces_bring_up($vipif);
1863
	
1864
	return $vipif;
1865
}
1866

    
1867
function interface_carpdev_configure(&$vip) {
1868
	global $g;
1869

    
1870
	if ($vip['mode'] != "carpdev-dhcp")
1871
		return;
1872

    
1873
	$vip_password = $vip['password'];
1874
	$vip_password = str_replace(" ", "", $vip_password);
1875
	if($vip['password'] != "")
1876
		$password = " pass \"" . $vip_password . "\"";
1877

    
1878
	if (empty($vip['interface']))
1879
		return;
1880

    
1881
	$vipif = "vip" . $vip['vhid'];
1882
	$realif = get_real_interface($vip['interface']);
1883
	interfaces_bring_up($realif);
1884
	/*
1885
	 * ensure the interface containing the VIP really exists
1886
	 * prevents a panic if the interface is missing or invalid
1887
	 */
1888
	if (!does_interface_exist($realif)) {
1889
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1890
		return;
1891
	}
1892

    
1893
	if (does_interface_exist($vipif)) {
1894
		interface_bring_down($vipif);
1895
	} else {
1896
		$carpdevif = exec("/sbin/ifconfig carp create");
1897
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1898
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1899
	}
1900

    
1901
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1902
	interfaces_bring_up($vipif);
1903

    
1904
	/*
1905
	 * XXX: BIG HACK but carpdev needs ip services active
1906
	 *      before even starting something as dhclient.
1907
	 *      I do not know if this is a feature or a bug
1908
	 *      but better than track it make it work ;) .
1909
	 */
1910
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1911
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1912

    
1913
	/* generate dhclient_wan.conf */
1914
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1915
	if ($fd) {
1916
		$dhclientconf = "";
1917

    
1918
		$dhclientconf .= <<<EOD
1919
interface "{$vipif}" {
1920
timeout 60;
1921
retry 1;
1922
select-timeout 0;
1923
initial-interval 1;
1924
script "/sbin/dhclient-script";
1925
}
1926

    
1927
EOD;
1928

    
1929
		fwrite($fd, $dhclientconf);
1930
		fclose($fd);
1931

    
1932
		/* fire up dhclient */
1933
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1934
	} else {
1935
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1936
		mwexec("/sbin/dhclient -b {$vipif}");
1937
	}
1938

    
1939
	return $vipif;
1940
}
1941

    
1942
function interface_wireless_clone($realif, $wlcfg) {
1943
	global $config, $g;
1944
	/*   Check to see if interface has been cloned as of yet.  
1945
	 *   If it has not been cloned then go ahead and clone it.
1946
	 */
1947
	$needs_clone = false;
1948
	if(is_array($wlcfg['wireless']))
1949
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1950
	else
1951
		$wlcfg_mode = $wlcfg['mode'];
1952
	switch($wlcfg_mode) {
1953
		 case "hostap":
1954
			$mode = "wlanmode hostap";
1955
			break;
1956
		 case "adhoc":
1957
			$mode = "wlanmode adhoc";
1958
			break;
1959
		 default:
1960
			$mode = "";
1961
			break;
1962
	}
1963
	$baseif = interface_get_wireless_base($wlcfg['if']);
1964
	if(does_interface_exist($realif)) {
1965
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1966
		$ifconfig_str = implode($output);
1967
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1968
			log_error("Interface {$realif} changed to hostap mode");
1969
			$needs_clone = true;
1970
		}
1971
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1972
			log_error("Interface {$realif} changed to adhoc mode");
1973
			$needs_clone = true;
1974
		}
1975
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1976
			log_error("Interface {$realif} changed to infrastructure mode");
1977
			$needs_clone = true;
1978
		}
1979
	} else {
1980
		$needs_clone = true;
1981
	}
1982

    
1983
	if($needs_clone == true) {
1984
		/* remove previous instance if it exists */
1985
		if(does_interface_exist($realif))
1986
			pfSense_interface_destroy($realif);
1987

    
1988
		log_error("Cloning new wireless interface {$realif}");
1989
		// Create the new wlan interface. FreeBSD returns the new interface name.
1990
		// example:  wlan2
1991
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1992
		if($ret <> 0) {
1993
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1994
			return false;
1995
		}
1996
		$newif = trim($out[0]);
1997
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1998
		pfSense_interface_rename($newif, $realif);
1999
		// FIXME: not sure what ngctl is for. Doesn't work.
2000
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2001
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2002
	}
2003
	return true;
2004
}
2005

    
2006
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2007
	global $config, $g;
2008

    
2009
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2010
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2011
	                         'regdomain', 'regcountry', 'reglocation');
2012

    
2013
	if(!is_interface_wireless($ifcfg['if']))
2014
		return;
2015

    
2016
	$baseif = interface_get_wireless_base($ifcfg['if']);
2017

    
2018
	// Sync shared settings for assigned clones
2019
	$iflist = get_configured_interface_list(false, true);
2020
	foreach ($iflist as $if) {
2021
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2022
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2023
				foreach ($shared_settings as $setting) {
2024
					if ($sync_changes) {
2025
						if (isset($ifcfg['wireless'][$setting]))
2026
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2027
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2028
							unset($config['interfaces'][$if]['wireless'][$setting]);
2029
					} else {
2030
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2031
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2032
						else if (isset($ifcfg['wireless'][$setting]))
2033
							unset($ifcfg['wireless'][$setting]);
2034
					}
2035
				}
2036
				if (!$sync_changes)
2037
					break;
2038
			}
2039
		}
2040
	}
2041

    
2042
	// Read or write settings at shared area
2043
	if (isset($config['wireless']['interfaces'][$baseif])) {
2044
		foreach ($shared_settings as $setting) {
2045
			if ($sync_changes) {
2046
				if (isset($ifcfg['wireless'][$setting]))
2047
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2048
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2049
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2050
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2051
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2052
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2053
				else if (isset($ifcfg['wireless'][$setting]))
2054
					unset($ifcfg['wireless'][$setting]);
2055
			}
2056
		}
2057
	}
2058

    
2059
	// Sync the mode on the clone creation page with the configured mode on the interface
2060
	if (interface_is_wireless_clone($ifcfg['if'])) {
2061
		foreach ($config['wireless']['clone'] as &$clone) {
2062
			if ($clone['cloneif'] == $ifcfg['if']) {
2063
				if ($sync_changes) {
2064
					$clone['mode'] = $ifcfg['wireless']['mode'];
2065
				} else {
2066
					$ifcfg['wireless']['mode'] = $clone['mode'];
2067
				}
2068
				break;
2069
			}
2070
		}
2071
		unset($clone);
2072
	}
2073
}
2074

    
2075
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2076
	global $config, $g;
2077

    
2078
	/*    open up a shell script that will be used to output the commands.
2079
	 *    since wireless is changing a lot, these series of commands are fragile
2080
     *    and will sometimes need to be verified by a operator by executing the command
2081
     *    and returning the output of the command to the developers for inspection.  please
2082
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2083
	 */
2084

    
2085
	// Remove script file
2086
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2087

    
2088
	// Clone wireless nic if needed.
2089
	interface_wireless_clone($if, $wl);
2090

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

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

    
2098
	/* set values for /path/program */
2099
	$hostapd = "/usr/sbin/hostapd";
2100
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2101
	$ifconfig = "/sbin/ifconfig";
2102
	$sysctl = "/sbin/sysctl";
2103
	$killall = "/usr/bin/killall";
2104

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

    
2107
	$wlcmd = array();
2108
	$wl_sysctl = array();
2109
	/* Make sure it's up */
2110
	$wlcmd[] = "up";
2111
	/* Set a/b/g standard */
2112
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2113
	$wlcmd[] = "mode " . escapeshellarg($standard);
2114

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

    
2120
	/* Set ssid */
2121
	if($wlcfg['ssid'])
2122
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2123

    
2124
	/* Set 802.11g protection mode */
2125
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2126

    
2127
	/* set wireless channel value */
2128
	if(isset($wlcfg['channel'])) {
2129
		if($wlcfg['channel'] == "0") {
2130
			$wlcmd[] = "channel any";
2131
		} else {
2132
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2133
		}
2134
	}
2135

    
2136
	/* Set antenna diversity value */
2137
	if(isset($wlcfg['diversity']))
2138
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2139

    
2140
	/* Set txantenna value */
2141
	if(isset($wlcfg['txantenna']))
2142
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2143

    
2144
	/* Set rxantenna value */
2145
	if(isset($wlcfg['rxantenna']))
2146
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2147

    
2148
	/* set Distance value */
2149
	if($wlcfg['distance'])
2150
		$distance = escapeshellarg($wlcfg['distance']);
2151

    
2152
	/* Set wireless hostap mode */
2153
	if ($wlcfg['mode'] == "hostap") {
2154
		$wlcmd[] = "mediaopt hostap";
2155
	} else {
2156
		$wlcmd[] = "-mediaopt hostap";
2157
	}
2158

    
2159
	/* Set wireless adhoc mode */
2160
	if ($wlcfg['mode'] == "adhoc") {
2161
		$wlcmd[] = "mediaopt adhoc";
2162
	} else {
2163
		$wlcmd[] = "-mediaopt adhoc";
2164
	}
2165

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

    
2168
	/* handle hide ssid option */
2169
	if(isset($wlcfg['hidessid']['enable'])) {
2170
		$wlcmd[] = "hidessid";
2171
	} else {
2172
		$wlcmd[] = "-hidessid";
2173
	}
2174

    
2175
	/* handle pureg (802.11g) only option */
2176
	if(isset($wlcfg['pureg']['enable'])) {
2177
		$wlcmd[] = "mode 11g pureg";
2178
	} else {
2179
		$wlcmd[] = "-pureg";
2180
	}
2181

    
2182
	/* handle puren (802.11n) only option */
2183
	if(isset($wlcfg['puren']['enable'])) {
2184
		$wlcmd[] = "puren";
2185
	} else {
2186
		$wlcmd[] = "-puren";
2187
	}
2188

    
2189
	/* enable apbridge option */
2190
	if(isset($wlcfg['apbridge']['enable'])) {
2191
		$wlcmd[] = "apbridge";
2192
	} else {
2193
		$wlcmd[] = "-apbridge";
2194
	}
2195

    
2196
	/* handle turbo option */
2197
	if(isset($wlcfg['turbo']['enable'])) {
2198
		$wlcmd[] = "mediaopt turbo";
2199
	} else {
2200
		$wlcmd[] = "-mediaopt turbo";
2201
	}
2202

    
2203
	/* handle txpower setting */
2204
	/* if($wlcfg['txpower'] <> "")
2205
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2206
	*/
2207
	/* handle wme option */
2208
	if(isset($wlcfg['wme']['enable'])) {
2209
		$wlcmd[] = "wme";
2210
	} else {
2211
		$wlcmd[] = "-wme";
2212
	}
2213

    
2214
	/* set up wep if enabled */
2215
	$wepset = "";
2216
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2217
		switch($wlcfg['wpa']['auth_algs']) {
2218
			case "1":
2219
				$wepset .= "authmode open wepmode on ";
2220
				break;
2221
			case "2":
2222
				$wepset .= "authmode shared wepmode on ";
2223
				break;
2224
			case "3":
2225
				$wepset .= "authmode mixed wepmode on ";
2226
		}
2227
		$i = 1;
2228
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2229
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2230
			if (isset($wepkey['txkey'])) {
2231
				$wlcmd[] = "weptxkey {$i} ";
2232
			}
2233
			$i++;
2234
		}
2235
		$wlcmd[] = $wepset;
2236
	} else {
2237
		$wlcmd[] = "authmode open wepmode off ";
2238
	}
2239

    
2240
	mwexec(kill_hostapd("{$if}"));
2241
	mwexec(kill_wpasupplicant("{$if}"));
2242

    
2243
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2244
	conf_mount_rw();
2245

    
2246
	switch ($wlcfg['mode']) {
2247
		case 'bss':
2248
			if (isset($wlcfg['wpa']['enable'])) {
2249
				$wpa .= <<<EOD
2250
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2251
ctrl_interface_group=0
2252
ap_scan=1
2253
#fast_reauth=1
2254
network={
2255
ssid="{$wlcfg['ssid']}"
2256
scan_ssid=1
2257
priority=5
2258
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2259
psk="{$wlcfg['wpa']['passphrase']}"
2260
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2261
group={$wlcfg['wpa']['wpa_pairwise']}
2262
}
2263
EOD;
2264

    
2265
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2266
				fwrite($fd, "{$wpa}");
2267
				fclose($fd);
2268
			}
2269
			break;
2270
		case 'hostap':
2271
			if($wlcfg['wpa']['passphrase']) 
2272
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2273
			else 
2274
				$wpa_passphrase = "";
2275
			if (isset($wlcfg['wpa']['enable'])) {
2276
				$wpa .= <<<EOD
2277
interface={$if}
2278
driver=bsd
2279
logger_syslog=-1
2280
logger_syslog_level=0
2281
logger_stdout=-1
2282
logger_stdout_level=0
2283
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2284
ctrl_interface={$g['varrun_path']}/hostapd
2285
ctrl_interface_group=wheel
2286
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2287
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2288
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2289
ssid={$wlcfg['ssid']}
2290
debug={$wlcfg['wpa']['debug_mode']}
2291
auth_algs={$wlcfg['wpa']['auth_algs']}
2292
wpa={$wlcfg['wpa']['wpa_mode']}
2293
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2294
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2295
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2296
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2297
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2298
{$wpa_passphrase}
2299

    
2300
EOD;
2301

    
2302
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2303
	$wpa .= <<<EOD
2304
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2305
rsn_preauth=1
2306
rsn_preauth_interfaces={$if}
2307

    
2308
EOD;
2309

    
2310
}
2311
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2312
					$auth_server_port = "1812";
2313
					if($wlcfg['auth_server_port']) 
2314
						$auth_server_port = $wlcfg['auth_server_port'];
2315
					$wpa .= <<<EOD
2316

    
2317
ieee8021x=1
2318
auth_server_addr={$wlcfg['auth_server_addr']}
2319
auth_server_port={$auth_server_port}
2320
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2321

    
2322
EOD;
2323
				} else {
2324
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2325
				}
2326

    
2327
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2328
				fwrite($fd, "{$wpa}");
2329
				fclose($fd);
2330

    
2331
			}
2332
			break;
2333
	}
2334

    
2335
	/*
2336
	 *    all variables are set, lets start up everything
2337
	 */
2338

    
2339
	$baseif = interface_get_wireless_base($if);
2340
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2341
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2342

    
2343
	/* set sysctls for the wireless interface */
2344
	if (!empty($wl_sysctl)) {
2345
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2346
		foreach ($wl_sysctl as $wl_sysctl_line) {
2347
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2348
		}
2349
	}
2350

    
2351
	/* set ack timers according to users preference (if he/she has any) */
2352
	if($distance) {
2353
		fwrite($fd_set, "# Enable ATH distance settings\n");
2354
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2355
	}
2356

    
2357
	if (isset($wlcfg['wpa']['enable'])) {
2358
		if ($wlcfg['mode'] == "bss") {
2359
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2360
		}
2361
		if ($wlcfg['mode'] == "hostap") {
2362
			/* add line to script to restore old mac to make hostapd happy */
2363
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2364
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2365
				if (is_macaddr($if_oldmac))
2366
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2367
						" link " . escapeshellarg($if_oldmac) . "\n");
2368
			}
2369

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

    
2372
			/* add line to script to restore spoofed mac after running hostapd */
2373
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2374
				if ($wl['spoofmac'])
2375
					$if_curmac = $wl['spoofmac'];
2376
				else
2377
					$if_curmac = get_interface_mac($if);
2378
				if (is_macaddr($if_curmac))
2379
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2380
						" link " . escapeshellarg($if_curmac) . "\n");
2381
			}
2382
		}
2383
	}
2384

    
2385
	fclose($fd_set);
2386
	conf_mount_ro();
2387

    
2388
	/* Making sure regulatory settings have actually changed
2389
	 * before applying, because changing them requires bringing
2390
	 * down all wireless networks on the interface. */
2391
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2392
	$ifconfig_str = implode($output);
2393
	unset($output);
2394
	$reg_changing = false;
2395

    
2396
	/* special case for the debug country code */
2397
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2398
		$reg_changing = true;
2399
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2400
		$reg_changing = true;
2401
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2402
		$reg_changing = true;
2403
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2404
		$reg_changing = true;
2405
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2406
		$reg_changing = true;
2407

    
2408
	if ($reg_changing) {
2409
		/* set regulatory domain */
2410
		if($wlcfg['regdomain'])
2411
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2412

    
2413
		/* set country */
2414
		if($wlcfg['regcountry'])
2415
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2416

    
2417
		/* set location */
2418
		if($wlcfg['reglocation'])
2419
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2420

    
2421
		$wlregcmd_args = implode(" ", $wlregcmd);
2422

    
2423
		/* build a complete list of the wireless clones for this interface */
2424
		$clone_list = array();
2425
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2426
			$clone_list[] = interface_get_wireless_clone($baseif);
2427
		if (is_array($config['wireless']['clone'])) {
2428
			foreach ($config['wireless']['clone'] as $clone) {
2429
				if ($clone['if'] == $baseif)
2430
					$clone_list[] = $clone['cloneif'];
2431
			}
2432
		}
2433

    
2434
		/* find which clones are up and bring them down */
2435
		$clones_up = array();
2436
		foreach ($clone_list as $clone_if) {
2437
			$clone_status = pfSense_get_interface_addresses($clone_if);
2438
			if ($clone_status['status'] == 'up') {
2439
				$clones_up[] = $clone_if;
2440
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2441
			}
2442
		}
2443

    
2444
		/* apply the regulatory settings */
2445
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2446

    
2447
		/* bring the clones back up that were previously up */
2448
		foreach ($clones_up as $clone_if) {
2449
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2450

    
2451
			/*
2452
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2453
			 * is in infrastructure mode, and WPA is enabled.
2454
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2455
			 */
2456
			if ($clone_if != $if) {
2457
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2458
				if ( !empty($friendly_if)
2459
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2460
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2461
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2462
				}
2463
			}
2464
		}
2465
	}
2466

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

    
2471
	/* configure wireless */
2472
	$wlcmd_args = implode(" ", $wlcmd);
2473
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2474

    
2475
	
2476
	sleep(1);
2477
	/* execute hostapd and wpa_supplicant if required in shell */
2478
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2479

    
2480
	return 0;
2481

    
2482
}
2483

    
2484
function kill_hostapd($interface) {
2485
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2486
}
2487

    
2488
function kill_wpasupplicant($interface) {
2489
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2490
}
2491

    
2492
function find_dhclient_process($interface) {
2493
	if ($interface)
2494
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2495
	else
2496
		$pid = 0;
2497

    
2498
	return intval($pid);
2499
}
2500

    
2501
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2502
	global $config, $g;
2503
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2504
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2505

    
2506
	$wancfg = $config['interfaces'][$interface];
2507

    
2508
	$realif = get_real_interface($interface);
2509
	$realhwif_array = get_parent_interface($interface);
2510
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2511
	$realhwif = $realhwif_array[0];
2512

    
2513
	if (!$g['booting']) {
2514
		/* remove all IPv4 addresses */
2515
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2516
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2517

    
2518
		switch ($wancfg['ipaddr']) {
2519
			case 'pppoe':
2520
			case 'l2tp':
2521
			case 'pptp':
2522
			case 'ppp':
2523
				break;
2524
			default:
2525
				interface_bring_down($interface);
2526
				break;
2527
		}
2528
	}
2529

    
2530
	/* wireless configuration? */
2531
	if (is_array($wancfg['wireless']))
2532
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2533

    
2534
	if ($wancfg['spoofmac']) {
2535
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2536
			" link " . escapeshellarg($wancfg['spoofmac']));
2537

    
2538
                /*
2539
                 * All vlans need to spoof their parent mac address, too.  see
2540
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2541
                 */
2542
                if (is_array($config['vlans']['vlan'])) {
2543
                        foreach ($config['vlans']['vlan'] as $vlan) {
2544
                                if ($vlan['if'] == $realhwif)
2545
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2546
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2547
                        }
2548
                }
2549
	}  else {
2550
		$mac = get_interface_mac($realhwif);
2551
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2552
			/*   this is not a valid mac address.  generate a
2553
			 *   temporary mac address so the machine can get online.
2554
			 */
2555
			echo "Generating new MAC address.";
2556
			$random_mac = generate_random_mac_address();
2557
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2558
				" link " . escapeshellarg($random_mac));
2559
			$wancfg['spoofmac'] = $random_mac;
2560
			write_config();
2561
			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");
2562
		}
2563
	}
2564

    
2565
	/* media */
2566
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2567
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2568
		if ($wancfg['media'])
2569
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2570
		if ($wancfg['mediaopt'])
2571
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2572
		mwexec($cmd);
2573
	}
2574
	if (!empty($wancfg['mtu']))
2575
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2576

    
2577
	$options = pfSense_get_interface_addresses($realhwif);
2578
	if (is_array($options) && isset($options['caps']['polling'])) {
2579
		if (isset($config['system']['polling']))
2580
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2581
		else
2582
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2583
	}
2584

    
2585
	/* skip vlans for checksumming and polling */
2586
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2587
		$flags = 0;
2588
		if(isset($config['system']['disablechecksumoffloading'])) {
2589
			if (isset($options['encaps']['txcsum']))
2590
				$flags |= IFCAP_TXCSUM;
2591
			if (isset($options['encaps']['rxcsum']))
2592
				$flags |= IFCAP_RXCSUM;
2593
        	} else {
2594
 			if (!isset($options['caps']['txcsum']))
2595
				$flags |= IFCAP_TXCSUM;
2596
			if (!isset($options['caps']['rxcsum']))
2597
				$flags |= IFCAP_RXCSUM;
2598
        	}
2599

    
2600
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2601
                	if (isset($options['encaps']['tso4']))
2602
				$flags |= IFCAP_TSO;
2603
                	if (isset($options['encaps']['tso6']))
2604
				$flags |= IFCAP_TSO;
2605
        	} else {
2606
                	if (!isset($options['caps']['tso4']))
2607
				$flags |= IFCAP_TSO;
2608
                	if (!isset($options['caps']['tso6']))
2609
				$flags |= IFCAP_TSO;
2610
        	}
2611

    
2612
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2613
                	if (isset($options['encaps']['lro']))
2614
				$flags |= IFCAP_LRO;
2615
        	} else {
2616
                	if (!isset($options['caps']['lro']))
2617
				$flags |= IFCAP_LRO;
2618
        	}
2619

    
2620
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2621
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2622
			$flags |= IFCAP_POLLING;
2623
		}
2624
               	pfSense_interface_capabilities($realhwif, -$flags);
2625
	}
2626

    
2627
	/* invalidate interface/ip/sn cache */
2628
	get_interface_arr(true);
2629
	unset($interface_ip_arr_cache[$realif]);
2630
	unset($interface_sn_arr_cache[$realif]);
2631
	unset($interface_ipv6_arr_cache[$realif]);
2632
	unset($interface_snv6_arr_cache[$realif]);
2633

    
2634
	switch ($wancfg['ipaddr']) {
2635
		case 'carpdev-dhcp':
2636
			interface_carpdev_dhcp_configure($interface);
2637
			break;
2638
		case 'dhcp':
2639
			interface_dhcp_configure($interface);
2640
			break;
2641
		case 'pppoe':
2642
		case 'l2tp':
2643
		case 'pptp':
2644
		case 'ppp':
2645
			interface_ppps_configure($interface);
2646
			break;
2647
		default:
2648
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2649
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2650
			} else if (substr($realif, 0, 3) == "gre") {
2651
				if (is_array($config['gres']['gre'])) {
2652
					foreach ($config['gres']['gre'] as $gre)
2653
						if ($gre['greif'] == $realif)
2654
							interface_gre_configure($gre);
2655
				}
2656
			} else if (substr($realif, 0, 3) == "gif") {
2657
				 if (is_array($config['gifs']['gif'])) {
2658
					foreach ($config['gifs']['gif'] as $gif)
2659
						if($gif['gifif'] == $interface)
2660
							interface_gif_configure($gif);
2661
				}
2662
			} else if (substr($realif, 0, 4) == "ovpn") {
2663
				/* XXX: Should be done anything?! */
2664
			}
2665
			break;
2666
	}
2667

    
2668
	switch ($wancfg['ipaddrv6']) {
2669
		case 'dhcpv6':
2670
			interface_dhcpv6_configure($interface);
2671
			break;
2672
		default:
2673
			if ($wancfg['ipaddrv6'] <> "" && $wancfg['subnetv6'] <> "") {
2674
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2675
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2676
			}
2677
			break;
2678
	}
2679

    
2680
	if(does_interface_exist($wancfg['if']))
2681
		interfaces_bring_up($wancfg['if']);
2682

    
2683
	interface_netgraph_needed($interface);
2684
 	
2685
	if (!$g['booting']) {
2686
		link_interface_to_vips($interface, "update");
2687

    
2688
		unset($gre);
2689
		$gre = link_interface_to_gre($interface);
2690
		if (!empty($gre))
2691
			array_walk($gre, 'interface_gre_configure');
2692

    
2693
		unset($gif);
2694
		$gif = link_interface_to_gif($interface);
2695
		if (!empty($gif))
2696
                       	array_walk($gif, 'interface_gif_configure');
2697

    
2698
		if ($linkupevent == false) {
2699
			unset($bridgetmp);
2700
			$bridgetmp = link_interface_to_bridge($interface);
2701
			if (!empty($bridgetmp))
2702
				interface_bridge_add_member($bridgetmp, $realif);
2703
		}
2704

    
2705
		$grouptmp = link_interface_to_group($interface);
2706
		if (!empty($grouptmp))
2707
			array_walk($grouptmp, 'interface_group_add_member');
2708

    
2709
		if ($interface == "lan")
2710
			/* make new hosts file */
2711
			system_hosts_generate();
2712

    
2713
		if ($reloadall == true) {
2714

    
2715
			/* reconfigure static routes (kernel may have deleted them) */
2716
			system_routing_configure($interface);
2717

    
2718
			/* reload ipsec tunnels */
2719
			vpn_ipsec_configure();
2720

    
2721
			/* restart dnsmasq */
2722
			services_dnsmasq_configure();
2723

    
2724
			/* update dyndns */
2725
			send_event("service reload dyndns {$interface}");
2726

    
2727
			/* reload captive portal */
2728
			captiveportal_init_rules();
2729
		}
2730
	}
2731

    
2732
	return 0;
2733
}
2734

    
2735
function interface_carpdev_dhcp_configure($interface = "wan") {
2736
	global $config, $g;
2737

    
2738
	$wancfg = $config['interfaces'][$interface];
2739
	$wanif = $wancfg['if'];
2740
	/* bring wan interface up before starting dhclient */
2741
	if($wanif)
2742
		interfaces_bring_up($wanif);
2743
	else 
2744
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2745

    
2746
	return 0;
2747
}
2748

    
2749
function interface_dhcp_configure($interface = "wan") {
2750
	global $config, $g;
2751

    
2752
	$wancfg = $config['interfaces'][$interface];
2753
	if (empty($wancfg))
2754
		$wancfg = array();
2755

    
2756
	/* generate dhclient_wan.conf */
2757
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2758
	if (!$fd) {
2759
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2760
		return 1;
2761
	}
2762

    
2763
	if ($wancfg['dhcphostname']) {
2764
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2765
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2766
	} else {
2767
		$dhclientconf_hostname = "";
2768
	}
2769

    
2770
	$wanif = get_real_interface($interface);
2771
	if (empty($wanif)) {
2772
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2773
		return 0;
2774
	}
2775
 	$dhclientconf = "";
2776
	
2777
	$dhclientconf .= <<<EOD
2778
interface "{$wanif}" {
2779
timeout 60;
2780
retry 1;
2781
select-timeout 0;
2782
initial-interval 1;
2783
	{$dhclientconf_hostname}
2784
	script "/sbin/dhclient-script";
2785
}
2786

    
2787
EOD;
2788

    
2789
if(is_ipaddr($wancfg['alias-address'])) {
2790
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2791
	$dhclientconf .= <<<EOD
2792
alias {
2793
	interface  "{$wanif}";
2794
	fixed-address {$wancfg['alias-address']};
2795
	option subnet-mask {$subnetmask};
2796
}
2797

    
2798
EOD;
2799
}
2800
	fwrite($fd, $dhclientconf);
2801
	fclose($fd);
2802

    
2803
	/* bring wan interface up before starting dhclient */
2804
	if($wanif)
2805
		interfaces_bring_up($wanif);
2806
	else 
2807
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2808

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

    
2812
	return 0;
2813
}
2814

    
2815
function interfaces_group_setup() {
2816
	global $config;
2817

    
2818
	if (!is_array($config['ifgroups']['ifgroupentry']))
2819
		return;
2820

    
2821
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2822
		interface_group_setup($groupar);
2823

    
2824
	return;
2825
}
2826

    
2827
function interface_group_setup(&$groupname /* The parameter is an array */) {
2828
	global $config;
2829

    
2830
	if (!is_array($groupname))
2831
		return;
2832
	$members = explode(" ", $groupname['members']);
2833
	foreach($members as $ifs) {
2834
		$realif = get_real_interface($ifs);
2835
		if ($realif)
2836
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2837
	}
2838

    
2839
	return;
2840
}
2841

    
2842
function interface_group_add_member($interface, $groupname) {
2843
	$interface = get_real_interface($interface);
2844
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2845
}
2846
 
2847
/* COMPAT Function */
2848
function convert_friendly_interface_to_real_interface_name($interface) {
2849
	return get_real_interface($interface);
2850
}
2851

    
2852
/* COMPAT Function */
2853
function get_real_wan_interface($interface = "wan") {
2854
	return get_real_interface($interface);
2855
}
2856

    
2857
/* COMPAT Function */
2858
function get_current_wan_address($interface = "wan") {
2859
	return get_interface_ip($interface);
2860
}
2861

    
2862
/*
2863
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2864
 */
2865
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2866
        global $config;
2867

    
2868
	if (stristr($interface, "vip")) {
2869
                $index = intval(substr($interface, 3));
2870
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2871
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2872
                                if ($index == $vip['vhid'])
2873
                                        return $vip['interface'];
2874
                        }
2875
                }
2876
        }
2877

    
2878
        /* XXX: For speed reasons reference directly the interface array */
2879
	$ifdescrs = &$config['interfaces'];
2880
        //$ifdescrs = get_configured_interface_list(false, true);
2881

    
2882
        foreach ($ifdescrs as $if => $ifname) {
2883
                if ($config['interfaces'][$if]['if'] == $interface)
2884
                        return $if;
2885

    
2886
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2887
                        return $if;
2888

    
2889
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
2890
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
2891
		/*
2892
                $int = get_parent_interface($if);
2893
                if ($int[0] == $interface)
2894
                        return $ifname;
2895
		*/
2896
        }
2897
        return NULL;
2898
}
2899

    
2900
/* attempt to resolve interface to friendly descr */
2901
function convert_friendly_interface_to_friendly_descr($interface) {
2902
        global $config;
2903

    
2904
        switch ($interface) {
2905
        case "l2tp":
2906
        	$ifdesc = "L2TP";
2907
                break;
2908
	case "pptp":
2909
		$ifdesc = "PPTP";
2910
		break;
2911
	case "pppoe":
2912
		$ifdesc = "PPPoE";
2913
		break;
2914
	case "openvpn":
2915
		$ifdesc = "OpenVPN";
2916
		break;
2917
	case "enc0":
2918
	case "ipsec":
2919
		$ifdesc = "IPsec";
2920
		break;
2921
        default:
2922
                if (isset($config['interfaces'][$interface])) {
2923
                        if (empty($config['interfaces'][$interface]['descr']))
2924
                                $ifdesc = strtoupper($interface);
2925
                        else
2926
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2927
			break;
2928
		} else if (substr($interface, 0, 3) == "vip") {
2929
			if (is_array($config['virtualip']['vip'])) {
2930
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
2931
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2932
						if ($interface == "vip{$vip['vhid']}")
2933
							return "{$vip['subnet']} - {$vip['descr']}";
2934
					}
2935
				}
2936
                        }
2937
                } else {
2938
			/* if list */
2939
			$ifdescrs = get_configured_interface_with_descr(false, true);
2940
			foreach ($ifdescrs as $if => $ifname) {
2941
					if ($if == $interface || $ifname == $interface)
2942
						return $ifname;
2943
			}
2944
		}
2945
                break;
2946
        }
2947

    
2948
        return $ifdesc;
2949
}
2950

    
2951
function convert_real_interface_to_friendly_descr($interface) {
2952
        global $config;
2953

    
2954
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2955

    
2956
        if ($ifdesc) {
2957
                $iflist = get_configured_interface_with_descr(false, true);
2958
                return $iflist[$ifdesc];
2959
        }
2960

    
2961
        return $interface;
2962
}
2963

    
2964
/*
2965
 *  get_parent_interface($interface):
2966
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
2967
 *				or virtual interface (i.e. vlan)
2968
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
2969
 *			-- returns $interface passed in if $interface parent is not found
2970
 *			-- returns empty array if an invalid interface is passed
2971
 *	(Only handles ppps and vlans now.)
2972
 */
2973
function get_parent_interface($interface) {
2974
	global $config;
2975

    
2976
	$parents = array();
2977
	//Check that we got a valid interface passed
2978
	$realif = get_real_interface($interface);
2979
	if ($realif == NULL)
2980
		return $parents;
2981

    
2982
	// If we got a real interface, find it's friendly assigned name
2983
	$interface = convert_real_interface_to_friendly_interface_name($interface);
2984
		
2985
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
2986
		$ifcfg = $config['interfaces'][$interface];
2987
		switch ($ifcfg['ipaddr']) {
2988
			case "ppp":
2989
			case "pppoe":
2990
			case "pptp":
2991
			case "l2tp":
2992
				if (empty($parents))
2993
					if (is_array($config['ppps']['ppp']))
2994
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
2995
							if ($ppp_if == $ppp['if']) {
2996
								$ports = explode(',', $ppp['ports']);
2997
								foreach ($ports as $pid => $parent_if) 
2998
									$parents[$pid] = get_real_interface($parent_if);
2999
								break;
3000
							}
3001
						}
3002
				break;
3003
			case "dhcp":
3004
			case "static":
3005
			default:
3006
				// Handle _vlans
3007
				if (strstr($realif,"_vlan"))
3008
					if (is_array($config['vlans']['vlan'])) 
3009
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3010
							if ($ifcfg['if'] == $vlan['vlanif']){
3011
								$parents[0] = $vlan['if'];
3012
								break;
3013
							}
3014
				break;
3015
		}
3016
	}
3017
	
3018
	if (empty($parents))
3019
		$parents[0] = $realif;
3020
	
3021
	return $parents;
3022
}
3023

    
3024
function interface_is_wireless_clone($wlif) {
3025
	if(!stristr($wlif, "_wlan")) {
3026
		return false;
3027
	} else {
3028
		return true;
3029
	}
3030
}
3031

    
3032
function interface_get_wireless_base($wlif) {
3033
	if(!stristr($wlif, "_wlan")) {
3034
		return $wlif;
3035
	} else {
3036
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3037
	}
3038
}
3039

    
3040
function interface_get_wireless_clone($wlif) {
3041
	if(!stristr($wlif, "_wlan")) {
3042
		return $wlif . "_wlan0";
3043
	} else {
3044
		return $wlif;
3045
	}
3046
}
3047

    
3048
function get_real_interface($interface = "wan") {
3049
    global $config;
3050

    
3051
	$wanif = NULL;
3052

    
3053
	switch ($interface) {
3054
	case "l2tp":
3055
		$wanif = "l2tp";
3056
		break;
3057
	case "pptp":
3058
		$wanif = "pptp";
3059
		break;
3060
	case "pppoe":
3061
		$wanif = "pppoe";
3062
		break;
3063
	case "openvpn":
3064
		$wanif = "openvpn";
3065
		break;
3066
	case "ipsec":
3067
	case "enc0":
3068
		$wanif = "enc0";
3069
		break;
3070
	case "ppp":
3071
		$wanif = "ppp";
3072
		break;
3073
	default:
3074
		// If a real interface was alread passed simply
3075
		// pass the real interface back.  This encourages
3076
		// the usage of this function in more cases so that
3077
		// we can combine logic for more flexibility.
3078
		if(does_interface_exist($interface)) {
3079
			$wanif = $interface;
3080
			break;
3081
		}
3082
		if (empty($config['interfaces'][$interface]))
3083
			break;
3084

    
3085
		$cfg = &$config['interfaces'][$interface];
3086

    
3087
		// Wireless cloned NIC support (FreeBSD 8+)
3088
		// interface name format: $parentnic_wlanparentnic#
3089
		// example: ath0_wlan0
3090
		if (is_interface_wireless($cfg['if'])) {
3091
			$wanif = interface_get_wireless_clone($cfg['if']);
3092
			break;
3093
		}
3094
		/*
3095
		if (empty($cfg['if'])) {
3096
			$wancfg = $cfg['if'];
3097
			break;
3098
		}
3099
		*/
3100

    
3101
		switch ($cfg['ipaddr']) {
3102
			case "carpdev-dhcp":
3103
				$viparr = &$config['virtualip']['vip'];
3104
				if(is_array($viparr))
3105
				foreach ($viparr as $counter => $vip) {
3106
					if ($vip['mode'] == "carpdev-dhcp") {
3107
						if($vip['interface'] == $interface) {
3108
							$wanif = "carp{$counter}";
3109
							break;
3110
						}
3111
					}
3112
				}
3113
				break;
3114
			case "pppoe": 
3115
			case "pptp": 
3116
			case "l2tp": 
3117
			case "ppp":
3118
				$wanif = $cfg['if'];
3119
				break;
3120
			default:
3121
				$wanif = $cfg['if'];
3122
				break;
3123
		}
3124
		break;
3125
	}
3126

    
3127
    return $wanif;
3128
}
3129

    
3130
/* Guess the physical interface by providing a IP address */
3131
function guess_interface_from_ip($ipaddress) {
3132
	if(! is_ipaddr($ipaddress)) {
3133
		return false;
3134
	}
3135
	if(is_ipaddrv4($ipaddress)) {
3136
		/* create a route table we can search */
3137
		exec("netstat -rnWf inet", $output, $ret);
3138
		foreach($output as $line) {
3139
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3140
				$fields = preg_split("/[ ]+/", $line);
3141
				if(ip_in_subnet($ipaddress, $fields[0])) {
3142
					return $fields[6];
3143
				}
3144
			}
3145
		}
3146
	}
3147
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3148
	if(is_ipaddrv6($ipaddress)) {
3149
		/* create a route table we can search */
3150
		exec("netstat -rnWf inet6", $output, $ret);
3151
		foreach($output as $line) {
3152
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3153
				$fields = preg_split("/[ ]+/", $line);
3154
				if(ip_in_subnet($ipaddress, $fields[0])) {
3155
					return $fields[6];
3156
				}
3157
			}
3158
		}
3159
	}
3160
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3161
	if(empty($ret)) {
3162
        	return false;
3163
	}
3164
	return $ret;
3165
}
3166

    
3167
/*
3168
 * find_ip_interface($ip): return the interface where an ip is defined
3169
 */
3170
function find_ip_interface($ip)
3171
{
3172
        /* if list */
3173
        $ifdescrs = get_configured_interface_list();
3174

    
3175
        foreach ($ifdescrs as $ifdescr => $ifname) {
3176
		if ($ip == get_interface_ip($ifname)) {
3177
                	$int = get_real_interface($ifname);
3178
			return $int;
3179
		}
3180
        }
3181
        return false;
3182
}
3183

    
3184
/*
3185
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3186
 */
3187
function find_number_of_created_carp_interfaces() {
3188
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3189
}
3190

    
3191
function get_all_carp_interfaces() {
3192
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3193
	$ints = explode(" ", $ints);
3194
	return $ints;
3195
}
3196

    
3197
/*
3198
 * find_carp_interface($ip): return the carp interface where an ip is defined
3199
 */
3200
function find_carp_interface($ip) {
3201
	global $config;
3202
	if (is_array($config['virtualip']['vip'])) {
3203
		foreach ($config['virtualip']['vip'] as $vip) {
3204
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3205
				if(is_ipaddrv4($ip)) {
3206
					$carp_ip = get_interface_ip($vip['interface']);
3207
				}
3208
				if(is_ipaddrv6($ip)) {
3209
					$carp_ip = get_interface_ipv6($vip['interface']);
3210
				}
3211
				exec("/sbin/ifconfig", $output, $return);
3212
				foreach($output as $line) {
3213
					$elements = preg_split("/[ ]+/i", $line);
3214
					if(strstr($elements[0], "vip"))
3215
						$curif = str_replace(":", "", $elements[0]);
3216
					if(stristr($line, $ip)) {
3217
						$if = $curif;
3218
						continue;
3219
					}
3220
				}
3221
				if ($if)
3222
					return $if;
3223
			}
3224
		}
3225
	}
3226
}
3227

    
3228
function link_carp_interface_to_parent($interface) {
3229
        global $config;
3230

    
3231
        if ($interface == "")
3232
                return;
3233

    
3234
        $carp_ip = get_interface_ip($interface);
3235
        if (!is_ipaddr($carp_ip))
3236
                return;
3237

    
3238
        /* if list */
3239
        $ifdescrs = get_configured_interface_list();
3240
        foreach ($ifdescrs as $ifdescr => $ifname) {
3241
                $interfaceip = get_interface_ip($ifname);
3242
                $subnet_bits = get_interface_subnet($ifname);
3243
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3244
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3245
                        return $ifname;
3246
        }
3247

    
3248
        return "";
3249
}
3250

    
3251
/****f* interfaces/link_ip_to_carp_interface
3252
 * NAME
3253
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3254
 * INPUTS
3255
 *   $ip
3256
 * RESULT
3257
 *   $carp_ints
3258
 ******/
3259
function link_ip_to_carp_interface($ip) {
3260
        global $config;
3261

    
3262
        if (!is_ipaddr($ip))
3263
                return;
3264

    
3265
        $carp_ints = "";
3266
        if (is_array($config['virtualip']['vip'])) {
3267
		$first = 0;
3268
		$carp_int = array();
3269
                foreach ($config['virtualip']['vip'] as $vip) {
3270
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3271
                                $carp_ip = $vip['subnet'];
3272
                                $carp_sn = $vip['subnet_bits'];
3273
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3274
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3275
					$carp_int[] = "vip{$vip['vhid']}";
3276
                        }
3277
                }
3278
		if (!empty($carp_int))
3279
			$carp_ints = implode(" ", array_unique($carp_int));
3280
        }
3281

    
3282
        return $carp_ints;
3283
}
3284

    
3285
function link_interface_to_vlans($int, $action = "") {
3286
	global $config;
3287

    
3288
	if (empty($int))
3289
		return;
3290

    
3291
	if (is_array($config['vlans']['vlan'])) {
3292
                foreach ($config['vlans']['vlan'] as $vlan) {
3293
			if ($int == $vlan['if']) {
3294
				if ($action == "update") {
3295
					interfaces_bring_up($int);
3296
				} else if ($action == "")
3297
					return $vlan;
3298
			}
3299
		}
3300
	}
3301
}
3302

    
3303
function link_interface_to_vips($int, $action = "") {
3304
        global $config;
3305

    
3306
        if (is_array($config['virtualip']['vip'])) {
3307
		foreach ($config['virtualip']['vip'] as $vip) {
3308
			if ($int == $vip['interface']) {
3309
				if ($action == "update") {
3310
					interface_vip_bring_down($vip);
3311
					interfaces_vips_configure($int);
3312
				} else
3313
					return $vip;
3314
			}
3315
		}
3316
	}
3317
}
3318

    
3319
/****f* interfaces/link_interface_to_bridge
3320
 * NAME
3321
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3322
 * INPUTS
3323
 *   $ip
3324
 * RESULT
3325
 *   bridge[0-99]
3326
 ******/
3327
function link_interface_to_bridge($int) {
3328
        global $config;
3329

    
3330
        if (is_array($config['bridges']['bridged'])) {
3331
                foreach ($config['bridges']['bridged'] as $bridge) {
3332
			if (in_array($int, explode(',', $bridge['members'])))
3333
                                return "{$bridge['bridgeif']}";
3334
		}
3335
	}
3336
}
3337

    
3338
function link_interface_to_group($int) {
3339
        global $config;
3340

    
3341
	$result = array();
3342

    
3343
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3344
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3345
			if (in_array($int, explode(" ", $group['members'])))
3346
				$result[$group['ifname']] = $int;
3347
		}
3348
	}
3349

    
3350
	return $result;
3351
}
3352

    
3353
function link_interface_to_gre($interface) {
3354
        global $config;
3355

    
3356
	$result = array();
3357

    
3358
        if (is_array($config['gres']['gre'])) {
3359
                foreach ($config['gres']['gre'] as $gre)
3360
                        if($gre['if'] == $interface)
3361
				$result[] = $gre;
3362
	}
3363

    
3364
	return $result;
3365
}
3366

    
3367
function link_interface_to_gif($interface) {
3368
        global $config;
3369

    
3370
	$result = array();
3371

    
3372
        if (is_array($config['gifs']['gif'])) {
3373
                foreach ($config['gifs']['gif'] as $gif)
3374
                        if($gif['if'] == $interface)
3375
                                $result[] = $gif;
3376
	}
3377

    
3378
	return $result;
3379
}
3380

    
3381
/*
3382
 * find_interface_ip($interface): return the interface ip (first found)
3383
 */
3384
function find_interface_ip($interface, $flush = false)
3385
{
3386
	global $interface_ip_arr_cache;
3387
	global $interface_sn_arr_cache;
3388

    
3389
	$interface = str_replace("\n", "", $interface);
3390
	
3391
	if (!does_interface_exist($interface))
3392
		return;
3393

    
3394
	/* Setup IP cache */
3395
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3396
		$ifinfo = pfSense_get_interface_addresses($interface);
3397
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3398
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3399
	}
3400

    
3401
	return $interface_ip_arr_cache[$interface];
3402
}
3403

    
3404
/*
3405
 * find_interface_ipv6($interface): return the interface ip (first found)
3406
 */
3407
function find_interface_ipv6($interface, $flush = false)
3408
{
3409
	global $interface_ipv6_arr_cache;
3410
	global $interface_snv6_arr_cache;
3411
	global $config;
3412
	
3413
	$interface = str_replace("\n", "", $interface);
3414
	
3415
	if (!does_interface_exist($interface))
3416
		return;
3417

    
3418
	/* Setup IP cache */
3419
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3420
		$ifinfo = pfSense_get_interface_addresses($interface);
3421
		exec("/sbin/ifconfig {$interface} inet6", $output);
3422
		foreach($output as $line) {
3423
			if(preg_match("/inet6/", $line)) {
3424
				$parts = explode(" ", $line);
3425
				if(! preg_match("/fe80::/", $parts[1])) {
3426
					$ifinfo['ipaddrv6'] = $parts[1];
3427
					$ifinfo['subnetbitsv6'] = $parts[3];
3428
				}
3429
			}
3430
		}
3431
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3432
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3433
	}
3434

    
3435
	return $interface_ipv6_arr_cache[$interface];
3436
}
3437

    
3438
function find_interface_subnet($interface, $flush = false)
3439
{
3440
	global $interface_sn_arr_cache;
3441
	global $interface_ip_arr_cache;
3442

    
3443
	$interface = str_replace("\n", "", $interface);
3444
	if (does_interface_exist($interface) == false)
3445
		return;
3446

    
3447
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3448
		$ifinfo = pfSense_get_interface_addresses($interface);
3449
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3450
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3451
        }
3452

    
3453
	return $interface_sn_arr_cache[$interface];
3454
}
3455

    
3456
function find_interface_subnetv6($interface, $flush = false)
3457
{
3458
	global $interface_snv6_arr_cache;
3459
	global $interface_ipv6_arr_cache;
3460

    
3461
	$interface = str_replace("\n", "", $interface);
3462
	if (does_interface_exist($interface) == false)
3463
		return;
3464

    
3465
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3466
		$ifinfo = pfSense_get_interface_addresses($interface);
3467
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3468
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3469
        }
3470

    
3471
	return $interface_snv6_arr_cache[$interface];
3472
}
3473

    
3474
function ip_in_interface_alias_subnet($interface, $ipalias) {
3475
	global $config;
3476

    
3477
	if (empty($interface) || !is_ipaddr($ipalias))
3478
		return false;
3479
	if (is_array($config['virtualip']['vip'])) {
3480
                foreach ($config['virtualip']['vip'] as $vip) {
3481
                        switch ($vip['mode']) {
3482
                        case "ipalias":
3483
                                if ($vip['interface'] <> $interface)
3484
                                        break;
3485
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3486
					return true;
3487
                                break;
3488
                        }
3489
                }
3490
	}
3491

    
3492
	return false;
3493
}
3494

    
3495
function get_interface_ip($interface = "wan")
3496
{
3497
	$realif = get_real_interface($interface);
3498
	if (!$realif) {
3499
		if (preg_match("/^carp/i", $interface))
3500
			$realif = $interface;
3501
		else if (preg_match("/^vip/i", $interface))
3502
			$realif = $interface;
3503
		else
3504
			return null;
3505
	}
3506

    
3507
	$curip = find_interface_ip($realif);
3508
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3509
		return $curip;
3510
	else
3511
		return null;
3512
}
3513

    
3514
function get_interface_ipv6($interface = "wan")
3515
{
3516
	$realif = get_real_interface($interface);
3517
	if (!$realif) {
3518
		if (preg_match("/^carp/i", $interface))
3519
			$realif = $interface;
3520
		else if (preg_match("/^vip/i", $interface))
3521
			$realif = $interface;
3522
		else
3523
			return null;
3524
	}
3525

    
3526
	$curip = find_interface_ipv6($realif);
3527
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3528
		return $curip;
3529
	else
3530
		return null;
3531
}
3532

    
3533
function get_interface_subnet($interface = "wan")
3534
{
3535
	$realif = get_real_interface($interface);
3536
	if (!$realif) {
3537
                if (preg_match("/^carp/i", $interface))
3538
                        $realif = $interface;
3539
                else if (preg_match("/^vip/i", $interface))
3540
                        $realif = $interface;
3541
                else
3542
                        return null;
3543
        }
3544

    
3545
	$cursn = find_interface_subnet($realif);
3546
	if (!empty($cursn))
3547
		return $cursn;
3548

    
3549
	return null;
3550
}
3551

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

    
3564
	$cursn = find_interface_subnetv6($realif);
3565
	if (!empty($cursn))
3566
		return $cursn;
3567

    
3568
	return null;
3569
}
3570

    
3571
/* return outside interfaces with a gateway */
3572
function get_interfaces_with_gateway() {
3573
	global $config;
3574

    
3575
	$ints = array();
3576

    
3577
	/* loop interfaces, check config for outbound */
3578
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3579
		switch ($ifname['ipaddr']) {
3580
			case "dhcp":
3581
			case "carpdev-dhcp":
3582
			case "ppp";
3583
			case "pppoe":
3584
			case "pptp":
3585
			case "l2tp":
3586
			case "ppp";
3587
				$ints[$ifdescr] = $ifdescr;
3588
			break;
3589
			default:
3590
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3591
				    !empty($ifname['gateway']))
3592
					$ints[$ifdescr] = $ifdescr;
3593
			break;
3594
		}
3595
	}
3596
	return $ints;
3597
}
3598

    
3599
/* return true if interface has a gateway */
3600
function interface_has_gateway($friendly) {
3601
	global $config;
3602

    
3603
	if (!empty($config['interfaces'][$friendly])) {
3604
		$ifname = &$config['interfaces'][$friendly];
3605
		switch ($ifname['ipaddr']) {
3606
			case "dhcp":
3607
			case "carpdev-dhcp":
3608
			case "pppoe":
3609
			case "pptp":
3610
			case "l2tp":
3611
			case "ppp";
3612
				return true;
3613
			break;
3614
			default:
3615
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3616
					return true;
3617
				if (!empty($ifname['gateway']))
3618
					return true;
3619
			break;
3620
		}
3621
	}
3622

    
3623
	return false;
3624
}
3625

    
3626
/****f* interfaces/is_altq_capable
3627
 * NAME
3628
 *   is_altq_capable - Test if interface is capable of using ALTQ
3629
 * INPUTS
3630
 *   $int            - string containing interface name
3631
 * RESULT
3632
 *   boolean         - true or false
3633
 ******/
3634

    
3635
function is_altq_capable($int) {
3636
        /* Per:
3637
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3638
         * Only the following drivers have ALTQ support
3639
         */
3640
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3641
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3642
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3643
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3644
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3645
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3646
			"l2tp", "ppp");
3647

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

    
3650
        if (in_array($int_family[0], $capable))
3651
                return true;
3652
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3653
		return true;
3654
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3655
		return true;
3656
        else
3657
                return false;
3658
}
3659

    
3660
/****f* interfaces/is_interface_wireless
3661
 * NAME
3662
 *   is_interface_wireless - Returns if an interface is wireless
3663
 * RESULT
3664
 *   $tmp       - Returns if an interface is wireless
3665
 ******/
3666
function is_interface_wireless($interface) {
3667
        global $config, $g;
3668

    
3669
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3670
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3671
                if (preg_match($g['wireless_regex'], $interface)) {
3672
                        if (isset($config['interfaces'][$friendly]))
3673
                                $config['interfaces'][$friendly]['wireless'] = array();
3674
                        return true;
3675
                }
3676
                return false;
3677
        } else
3678
                return true;
3679
}
3680

    
3681
function get_wireless_modes($interface) {
3682
	/* return wireless modes and channels */
3683
	$wireless_modes = array();
3684

    
3685
	$cloned_interface = get_real_interface($interface);
3686

    
3687
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3688
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3689
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3690
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3691

    
3692
		$interface_channels = "";
3693
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3694
		$interface_channel_count = count($interface_channels);
3695

    
3696
		$c = 0;
3697
		while ($c < $interface_channel_count)
3698
		{
3699
			$channel_line = explode(",", $interface_channels["$c"]);
3700
			$wireless_mode = trim($channel_line[0]);
3701
			$wireless_channel = trim($channel_line[1]);
3702
			if(trim($wireless_mode) != "") {
3703
				/* if we only have 11g also set 11b channels */
3704
				if($wireless_mode == "11g") {
3705
					if(!isset($wireless_modes["11b"]))
3706
						$wireless_modes["11b"] = array();
3707
				} else if($wireless_mode == "11g ht") {
3708
					if(!isset($wireless_modes["11b"]))
3709
						$wireless_modes["11b"] = array();
3710
					if(!isset($wireless_modes["11g"]))
3711
						$wireless_modes["11g"] = array();
3712
					$wireless_mode = "11ng";
3713
				} else if($wireless_mode == "11a ht") {
3714
					if(!isset($wireless_modes["11a"]))
3715
						$wireless_modes["11a"] = array();
3716
					$wireless_mode = "11na";
3717
				}
3718
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3719
			}
3720
			$c++;
3721
		}
3722
	}
3723
	return($wireless_modes);
3724
}
3725

    
3726
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3727
function get_wireless_channel_info($interface) {
3728
	$wireless_channels = array();
3729

    
3730
	$cloned_interface = get_real_interface($interface);
3731

    
3732
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3733
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3734
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3735
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3736

    
3737
		$interface_channels = "";
3738
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3739

    
3740
		foreach ($interface_channels as $channel_line) {
3741
			$channel_line = explode(",", $channel_line);
3742
			if(!isset($wireless_channels[$channel_line[0]]))
3743
				$wireless_channels[$channel_line[0]] = $channel_line;
3744
		}
3745
	}
3746
	return($wireless_channels);
3747
}
3748

    
3749
/****f* interfaces/get_interface_mtu
3750
 * NAME
3751
 *   get_interface_mtu - Return the mtu of an interface
3752
 * RESULT
3753
 *   $tmp       - Returns the mtu of an interface
3754
 ******/
3755
function get_interface_mtu($interface) {
3756
        $mtu = pfSense_get_interface_addresses($interface);
3757
        return $mtu['mtu'];
3758
}
3759

    
3760
function get_interface_mac($interface) {
3761

    
3762
	$macinfo = pfSense_get_interface_addresses($interface);
3763
	return $macinfo["macaddr"];
3764
}
3765

    
3766
/****f* pfsense-utils/generate_random_mac_address
3767
 * NAME
3768
 *   generate_random_mac - generates a random mac address
3769
 * INPUTS
3770
 *   none
3771
 * RESULT
3772
 *   $mac - a random mac address
3773
 ******/
3774
function generate_random_mac_address() {
3775
        $mac = "02";
3776
        for($x=0; $x<5; $x++)
3777
                $mac .= ":" . dechex(rand(16, 255));
3778
        return $mac;
3779
}
3780

    
3781
/****f* interfaces/is_jumbo_capable
3782
 * NAME
3783
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3784
 * INPUTS
3785
 *   $int             - string containing interface name
3786
 * RESULT
3787
 *   boolean          - true or false
3788
 ******/
3789
function is_jumbo_capable($int) {
3790
        global $g;
3791

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

    
3794
        if (in_array($int_family[0], $g['vlan_long_frame']))
3795
                return true;
3796
        else
3797
                return false;
3798
}
3799

    
3800
function setup_pppoe_reset_file($pppif, $iface="") {
3801
	global $g;
3802
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3803

    
3804
	if(!empty($iface) && !empty($pppif)){
3805
		$cron_cmd = <<<EOD
3806
#!/bin/sh
3807
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3808
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3809

    
3810
EOD;
3811

    
3812
		file_put_contents($cron_file, $cron_cmd);
3813
		chmod($cron_file, 0700);
3814
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3815
	} else
3816
		unlink_if_exists($cron_file);
3817
}
3818

    
3819
function get_vip_descr($ipaddress) {
3820
	global $config;
3821

    
3822
	foreach ($config['virtualip']['vip'] as $vip) {
3823
		if ($vip['subnet'] == $ipaddress) {
3824
			return ($vip['descr']);
3825
		}
3826
	}
3827
	return "";
3828
}
3829

    
3830
?>
(25-25/61)