Project

General

Profile

Download (109 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
/*
88
 * does_vip_exist($vip): return true or false if a vip is
89
 * configured.
90
 */
91
function does_vip_exist($vip) {
92
	global $config;
93
	
94
	if(!$vip)
95
		return false;
96

    
97

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

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

    
124
	return false;
125
}
126

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

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

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

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

    
206
function interfaces_loopback_configure() {
207
	if($g['booting'])
208
		echo "Configuring loopback interface...";
209
	pfSense_interface_setaddress("lo0", "127.0.0.1");
210
	interfaces_bring_up("lo0");
211
	if($g['booting'])
212
		echo "done.\n";
213
	return 0;
214
}
215

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

    
232
function interface_vlan_configure(&$vlan) {
233
        global $config, $g;
234

    
235
	if (!is_array($vlan)) {
236
		log_error("VLAN: called with wrong options. Problems with config!");
237
		return;
238
	}
239
	$if = $vlan['if'];
240
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
241
	$tag = $vlan['tag'];
242

    
243
	if (empty($if)) {
244
		log_error("interface_vlan_confgure called with if undefined.");
245
		return;
246
	}
247

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

    
253
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
254
		interface_bring_down($vlanif, true);
255
	} else {
256
		$tmpvlanif = pfSense_interface_create("vlan");
257
		pfSense_interface_rename($tmpvlanif, $vlanif);
258
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
259
	}
260

    
261
	pfSense_vlan_create($vlanif, $if, $tag);
262

    
263
	interfaces_bring_up($vlanif);
264

    
265
	/* invalidate interface cache */
266
	get_interface_arr(true);
267

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

    
271
	return $vlanif;
272
}
273

    
274
function interface_qinq_configure(&$vlan, $fd = NULL) {
275
        global $config, $g;
276

    
277
        if (!is_array($vlan)) {
278
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
279
                return;
280
        }
281

    
282
        $qinqif = $vlan['if'];
283
        $tag = $vlan['tag'];
284
        if(empty($qinqif)) {
285
                log_error("interface_qinq_confgure called with if undefined.\n");
286
                return;
287
        }
288
	$vlanif = interface_vlan_configure($vlan);
289

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

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

    
313
        /* invalidate interface cache */
314
        get_interface_arr(true);
315

    
316
        if (!stristr($qinqif, "vlan"))
317
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
318

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

    
334
        interfaces_bring_up($qinqif);
335
        if (!empty($vlan['members'])) {
336
                $members = explode(" ", $vlan['members']);
337
                foreach ($members as $qif)
338
                        interfaces_bring_up("{$vlanif}_{$qif}");
339
        }
340

    
341
        return $vlanif;
342
}
343

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

    
358
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
359
        global $config, $g;
360

    
361
        if (!is_array($qinq)) {
362
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
363
                return;
364
        }
365

    
366
        $if = $qinq['if'];
367
        $tag = $qinq['tag'];
368
        $vlanif = "{$if}_{$tag}";
369
        if(empty($if)) {
370
                log_error("interface_qinq_confgure called with if undefined.\n");
371
                return;
372
        }
373

    
374
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
375
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
376
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
377
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
378
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
379
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
380

    
381
        /* invalidate interface cache */
382
        get_interface_arr(true);
383

    
384
        return $vlanif;
385
}
386

    
387
function interfaces_create_wireless_clones() {
388
	global $config;
389

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

    
408
function interfaces_bridge_configure($checkmember = 0) {
409
        global $config;
410

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

    
427
function interface_bridge_configure(&$bridge) {
428
	global $config, $g;
429

    
430
	if (!is_array($bridge))
431
	        return -1;
432

    
433
	if (empty($bridge['members'])) {
434
		log_error("No members found on {$bridge['bridgeif']}");
435
		return -1;
436
	}
437

    
438
	$members = explode(',', $bridge['members']);
439
	if (!count($members))
440
		return -1;
441

    
442
	$checklist = get_configured_interface_list();
443

    
444
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
445
		pfSense_interface_destroy($bridge['bridgeif']);
446
		pfSense_interface_create($bridge['bridgeif']);
447
		$bridgeif = $bridge['bridgeif'];
448
	} else
449
		$bridgeif = pfSense_interface_create("bridge");
450

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

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

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

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

    
610
	if($bridgeif)
611
		interfaces_bring_up($bridgeif);	
612
	else 
613
		log_error("bridgeif not defined -- could not bring interface up");
614

    
615
	return $bridgeif;
616
}
617

    
618
function interface_bridge_add_member($bridgeif, $interface) {
619

    
620
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
621
		return;
622

    
623
	$mtu = get_interface_mtu($brigeif);
624
	$mtum = get_interface_mtu($interface);
625
	
626
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
627
		pfSense_interface_mtu($interface, $mtu);
628

    
629
	$options = pfSense_get_interface_addresses($bridgeif);
630
	$flags = 0;
631
	if (!isset($options['encaps']['txcsum']))
632
		$flags |= IFCAP_TXCSUM;
633

    
634
	if (!isset($options['encaps']['rxcsum']))
635
		$flags |= IFCAP_RXCSUM;
636

    
637
	pfSense_interface_capabilities($interface, -$flags);
638

    
639
	interfaces_bring_up($interface);
640
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
641
}
642

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

    
662
function interface_lagg_configure(&$lagg) {
663
        global $config, $g;
664

    
665
        if (!is_array($lagg))
666
		return -1;
667

    
668
	$members = explode(',', $lagg['members']);
669
	if (!count($members))
670
		return -1;
671
	
672
	$checklist = get_interface_list();
673

    
674
	if ($g['booting'] || !(empty($lagg['laggif']))) {
675
		pfSense_interface_destroy($lagg['laggif']);
676
		pfSense_interface_create($lagg['laggif']);
677
                $laggif = $lagg['laggif'];
678
        } else
679
		$laggif = pfSense_interface_create("lagg");
680

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

    
702
	/* Just in case anything is not working well */
703
        if ($smallermtu == 0)
704
                $smallermtu = 1500;
705

    
706
	$flags = 0;
707
        if ($commonrx === false)
708
                $flags |= IFCAP_RXCSUM;
709
        if ($commontx === false)
710
                $flags |= IFCAP_TXCSUM;
711
	if ($commontso4 === false)
712
                $flags |= IFCAP_TSO4;
713
        if ($commontso6 === false)
714
                $flags |= IFCAP_TSO6;
715
        if ($commonlro === false)
716
                $flags |= IFCAP_LRO;
717

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

    
730
	interfaces_bring_up($laggif);
731

    
732
	return $laggif;
733
}
734

    
735
function interfaces_gre_configure($checkparent = 0) {
736
        global $config;
737

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

    
752
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
753
function interface_gre_configure(&$gre, $grekey = "") {
754
        global $config, $g;
755

    
756
	if (!is_array($gre))
757
		return -1;
758

    
759
	$realif = get_real_interface($gre['if']);
760
	$realifip = get_interface_ip($gre['if']);
761

    
762
	/* make sure the parent interface is up */
763
	interfaces_bring_up($realif);
764

    
765
	if ($g['booting'] || !(empty($gre['greif']))) {
766
		pfSense_interface_destroy($gre['greif']);
767
		pfSense_interface_create($gre['greif']);
768
		$greif = $gre['greif'];
769
	} else
770
		$greif = pfSense_interface_create("gre");
771

    
772
	/* Do not change the order here for more see gre(4) NOTES section. */
773
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
774
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
775
	if (isset($gre['link0']) && $gre['link0'])
776
		pfSense_interface_flags($greif, IFF_LINK0);
777
	if (isset($gre['link1']) && $gre['link1'])
778
		pfSense_interface_flags($greif, IFF_LINK1);
779
	if (isset($gre['link2']) && $gre['link2'])
780
		pfSense_interface_flags($greif, IFF_LINK2);
781

    
782
	if($greif)
783
		interfaces_bring_up($greif);
784
	else 
785
		log_error("Could not bring greif up -- variable not defined.");
786

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

    
791
	return $greif;
792
}
793

    
794
function interfaces_gif_configure($checkparent = 0) {
795
	global $config;
796

    
797
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
798
		foreach ($config['gifs']['gif'] as $i => $gif) {
799
			if(empty($gif['gifif']))
800
				$gre['gifif'] = "gif{$i}";
801
			if ($checkparent == 1 && strstr($gif['if'], "vip"))
802
				continue;
803
			if ($checkparent == 2 && !strstr($gif['if'], "vip"))
804
				continue;
805
			/* XXX: Maybe we should report any errors?! */
806
			interface_gif_configure($gif);
807
		}
808
	}
809
}
810

    
811
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
812
function interface_gif_configure(&$gif, $gifkey = "") {
813
	global $config, $g;
814

    
815
	if (!is_array($gif))
816
		return -1;
817

    
818
	$realif = get_real_interface($gif['if']);
819
	$realifip = get_interface_ip($gif['if']);
820

    
821
	/* make sure the parent interface is up */
822
	if($realif)
823
		interfaces_bring_up($realif);
824
	else 
825
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
826

    
827
	if ($g['booting'] || !(empty($gif['gifif']))) {
828
		pfSense_interface_destroy($gif['gifif']);
829
		pfSense_interface_create($gif['gifif']);
830
		$gifif = $gif['gifif'];
831
	} else
832
		$gifif = pfSense_interface_create("gif");
833

    
834
	/* Do not change the order here for more see gif(4) NOTES section. */
835
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
836
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
837
	if (isset($gif['link0']) && $gif['link0'])
838
		pfSense_interface_flags($gifif, IFF_LINK0);
839
	if (isset($gif['link1']) && $gif['link1'])
840
		pfSense_interface_flags($gifif, IFF_LINK1);
841
	if($gifif)
842
		interfaces_bring_up($gifif);
843
	else
844
		log_error("could not bring gifif up -- variable not defined");
845

    
846
	/* XXX: Needed?! */
847
	//mwexec("/sbin/route add {$gif['tunnel-remote-addr']}/{$gif['tunnel-remote-net']} -iface {$gifif}");
848
	file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
849

    
850
	return $gifif;
851
}
852

    
853
function interfaces_configure() {
854
	global $config, $g;
855

    
856
	/* Set up our loopback interface */
857
	interfaces_loopback_configure();
858

    
859
	/* set up LAGG virtual interfaces */
860
	interfaces_lagg_configure();
861

    
862
	/* set up VLAN virtual interfaces */
863
	interfaces_vlan_configure();
864

    
865
	interfaces_qinq_configure();
866

    
867
	$iflist = get_configured_interface_with_descr();
868
	$delayed_list = array();
869
	$bridge_list = array();
870
	
871
	/* This is needed to speedup interfaces on bootup. */
872
	$reload = false;
873
	if ($g['booting'])
874
		$reload = true;
875

    
876
	foreach($iflist as $if => $ifname) {
877
		$realif = $config['interfaces'][$if]['if'];
878
		if (strstr($realif, "bridge")) 
879
			$bridge_list[$if] = $ifname;
880
		else if (strstr($realif, "gre"))
881
			$delayed_list[$if] = $ifname;
882
		else if (strstr($realif, "gif"))
883
			$delayed_list[$if] = $ifname;
884
		else if (strstr($realif, "ovpn")) {
885
			//echo "Delaying OpenVPN interface configuration...done.\n";
886
			continue;
887
		} else {
888
			if ($g['booting'])
889
				echo "Configuring {$ifname} interface...";
890
			if($g['debug'])
891
				log_error("Configuring {$ifname}");
892
			interface_configure($if, $reload);
893
			if ($g['booting']) 
894
				echo "done.\n";
895
		}
896
	}
897

    
898
	/* create the unconfigured wireless clones */
899
	interfaces_create_wireless_clones();
900

    
901
	/*
902
	 * NOTE: The following function parameter consists of
903
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
904
	 *	2 - Do load gre/gif/bridge with parent/member as vip
905
	 */
906

    
907
	/* set up GRE virtual interfaces */
908
	interfaces_gre_configure(1);
909

    
910
	/* set up GIF virtual interfaces */
911
	interfaces_gif_configure(1);
912

    
913
	/* set up BRIDGe virtual interfaces */
914
	interfaces_bridge_configure(1);
915

    
916
	/* bring up vip interfaces */
917
	interfaces_vips_configure();
918

    
919
	/* set up GRE virtual interfaces */
920
	interfaces_gre_configure(2);
921

    
922
	/* set up GIF virtual interfaces */
923
	interfaces_gif_configure(2);
924

    
925
	foreach ($delayed_list as $if => $ifname) {
926
		if ($g['booting'])
927
			echo "Configuring {$ifname} interface...";
928
        	if ($g['debug'])
929
        		log_error("Configuring {$ifname}");
930

    
931
		interface_configure($if, $reload);
932

    
933
		if ($g['booting'])
934
			echo "done.\n";
935
	}
936

    
937
	/* set up BRIDGe virtual interfaces */
938
	interfaces_bridge_configure(2);
939

    
940
	foreach ($bridge_list as $if => $ifname) {
941
		if ($g['booting'])
942
			echo "Configuring {$ifname} interface...";
943
		if($g['debug'])
944
			log_error("Configuring {$ifname}");
945

    
946
		interface_configure($if, $reload);
947

    
948
		if ($g['booting'])
949
			echo "done.\n";
950
	}
951

    
952
	/* configure interface groups */
953
	interfaces_group_setup();
954

    
955
	if (!$g['booting']) {
956
		/* reconfigure static routes (kernel may have deleted them) */
957
		system_routing_configure();
958

    
959
		/* reload IPsec tunnels */
960
		vpn_ipsec_configure();
961

    
962
		/* reload dhcpd (interface enabled/disabled status may have changed) */
963
		services_dhcpd_configure();
964

    
965
		/* restart dnsmasq */
966
		services_dnsmasq_configure();
967

    
968
		/* reload captive portal */
969
		captiveportal_init_rules();
970
	}
971

    
972
	return 0;
973
}
974

    
975
function interface_reconfigure($interface = "wan", $reloadall = false) {
976
	interface_bring_down($interface);
977
	interface_configure($interface, $reloadall);
978
}
979

    
980
function interface_vip_bring_down($vip) {
981
	global $g;
982

    
983
	switch ($vip['mode']) {
984
	case "proxyarp":
985
		$vipif = get_real_interface($vip['interface']);
986
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
987
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
988
		break;
989
	case "ipalias":
990
		$vipif = get_real_interface($vip['interface']);
991
		if(does_interface_exist($vipif))
992
			pfSense_interface_deladdress($vipif, $vip['subnet']);
993
		break;
994
	case "carp":
995
		$vipif = "vip" . $vip['vhid'];
996
		if(does_interface_exist($vipif)) 
997
			pfSense_interface_destroy($vipif);
998
		break;
999
	case "carpdev-dhcp":
1000
		$vipif = "vip" . $vip['vhid'];
1001
		if(does_interface_exist($vipif)) 
1002
			pfSense_interface_destroy($vipif);
1003
		break;
1004
	}
1005
}
1006

    
1007
function interface_bring_down($interface = "wan", $destroy = false) {
1008
	global $config, $g;
1009

    
1010
	if (!isset($config['interfaces'][$interface]))
1011
		return; 
1012

    
1013
	$ifcfg = $config['interfaces'][$interface];
1014

    
1015
	$realif = get_real_interface($interface);
1016

    
1017
	switch ($ifcfg['ipaddr']) {
1018
	case "ppp":
1019
	case "pppoe":
1020
	case "pptp":
1021
	case "l2tp":
1022
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1023
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1024
				if ($realif == $ppp['if']) {
1025
					if (isset($ppp['ondemand']) && !$destroy){
1026
						send_event("interface reconfigure {$interface}");
1027
						break;
1028
					}
1029
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1030
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1031
						sleep(2);
1032
					}
1033
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1034
					break;
1035
				}
1036
			}
1037
		}
1038
		break;
1039
	case "carpdev-dhcp":
1040
		/* 
1041
		 * NB: When carpdev gets enabled it would be better to be handled as all
1042
		 *	   other interfaces! 
1043
		 */
1044
	case "dhcp":
1045
		$pid = find_dhclient_process($realif);
1046
		if($pid)
1047
			mwexec("/bin/kill {$pid}");
1048
		sleep(1);
1049
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1050
		if(does_interface_exist("$realif")) {
1051
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1052
			if ($destroy == true)
1053
				pfSense_interface_flags($realif, -IFF_UP);
1054
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1055
		}
1056
		break;
1057
	default:
1058
		if(does_interface_exist("$realif")) {
1059
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1060
			if ($destroy == true)
1061
				pfSense_interface_flags($realif, -IFF_UP);
1062
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1063
		}
1064
		break;
1065
	}
1066

    
1067
	/* remove interface up file if it exists */
1068
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1069
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1070
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1071
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1072
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1073
	
1074
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1075
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1076
	if (is_array($ifcfg['wireless'])) {
1077
		mwexec(kill_hostapd($realif));
1078
		mwexec(kill_wpasupplicant($realif));
1079
	}
1080

    
1081
	if ($destroy == true) {
1082
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1083
			pfSense_interface_destroy($realif);
1084
	}	
1085

    
1086
	return;
1087
}
1088

    
1089
function interfaces_ptpid_used($ptpid) {
1090
	global $config;
1091

    
1092
	if (is_array($config['ppps']['ppp']))
1093
		foreach ($config['ppps']['ppp'] as & $settings)
1094
			if ($ptpid == $settings['ptpid'])
1095
				return true;
1096

    
1097
	return false;
1098
}
1099

    
1100
function interfaces_ptpid_next() {
1101

    
1102
	$ptpid = 0;
1103
	while(interfaces_ptpid_used($ptpid))
1104
		$ptpid++;
1105

    
1106
	return $ptpid;
1107
}
1108

    
1109
function getMPDCRONSettings($pppif_) {
1110
	global $config;
1111
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1112
	if (is_array($config['cron']['item'])) {
1113
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1114
			$item = $config['cron']['item'][$i];
1115
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1116
				return array("ID" => $i, "ITEM" => $item);
1117
			}
1118
		}
1119
	}
1120
	return NULL;
1121
}
1122

    
1123
function handle_pppoe_reset($post_array) {
1124
	global $config, $g;
1125

    
1126
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1127

    
1128
	$pppif = $post_array['type'].$post_array['ptpid'];
1129
	if (!is_array($config['cron']['item'])) 
1130
		$config['cron']['item'] = array(); 
1131
	$itemhash = getMPDCRONSettings($pppif);
1132
	$item = $itemhash['ITEM'];
1133
	
1134
	// reset cron items if necessary and return
1135
	if (empty($post_array['pppoe-reset-type'])) {
1136
		if (isset($item))
1137
			unset($config['cron']['item'][$itemhash['ID']]);
1138
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1139
		return;
1140
	}
1141

    
1142
	if (empty($item)) 
1143
		$item = array();
1144
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1145
		$item['minute'] = $post_array['pppoe_resetminute'];
1146
		$item['hour'] = $post_array['pppoe_resethour'];
1147
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1148
			$date = explode("/", $post_array['pppoe_resetdate']);
1149
			$item['mday'] = $date[1];
1150
			$item['month'] = $date[0];
1151
		} else {
1152
			$item['mday'] = "*";
1153
			$item['month'] = "*";
1154
		}
1155
		$item['wday'] = "*";
1156
		$item['who'] = "root";
1157
		$item['command'] = $cron_cmd_file.$pppif;
1158
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1159
		switch ($post_array['pppoe_pr_preset_val']) {
1160
			case "monthly":
1161
				$item['minute'] = "0";
1162
				$item['hour'] = "0";
1163
				$item['mday'] = "1";
1164
				$item['month'] = "*";
1165
				$item['wday'] = "*";
1166
				$item['who'] = "root";
1167
				$item['command'] = $cron_cmd_file.$pppif;
1168
				break;
1169
	        case "weekly":
1170
				$item['minute'] = "0";
1171
				$item['hour'] = "0";
1172
				$item['mday'] = "*";
1173
				$item['month'] = "*";
1174
				$item['wday'] = "0";
1175
				$item['who'] = "root";
1176
				$item['command'] = $cron_cmd_file.$pppif;
1177
				break;
1178
			case "daily":
1179
				$item['minute'] = "0";
1180
				$item['hour'] = "0";
1181
				$item['mday'] = "*";
1182
				$item['month'] = "*";
1183
				$item['wday'] = "*";
1184
				$item['who'] = "root";
1185
				$item['command'] = $cron_cmd_file.$pppif;
1186
				break;
1187
			case "hourly":
1188
				$item['minute'] = "0";
1189
				$item['hour'] = "*";
1190
				$item['mday'] = "*";
1191
				$item['month'] = "*";
1192
				$item['wday'] = "*";
1193
				$item['who'] = "root";
1194
				$item['command'] = $cron_cmd_file.$pppif;
1195
				break;
1196
		} // end switch
1197
	} else {
1198
		/* test whether a cron item exists and unset() it if necessary */
1199
		$itemhash = getMPDCRONSettings($pppif);
1200
		$item = $itemhash['ITEM'];
1201
		if (isset($item))
1202
			unset($config['cron']['item'][$itemhash['ID']]); 
1203
	}// end if
1204
	if (isset($itemhash['ID'])) 
1205
		$config['cron']['item'][$itemhash['ID']] = $item;
1206
	else 
1207
		$config['cron']['item'][] = $item;
1208
}
1209

    
1210
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1211
*	It writes the mpd config file to /var/etc every time the link is opened.
1212
*/
1213

    
1214
function interface_ppps_configure($interface) {
1215
	global $config, $g;
1216

    
1217
	/* Return for unassigned interfaces. This is a minimum requirement. */
1218
	if (empty($config['interfaces'][$interface]))
1219
		return 0;
1220
	$ifcfg = $config['interfaces'][$interface];
1221
	if (!isset($ifcfg['enable']))
1222
		return 0;
1223

    
1224
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1225
	if(!is_dir("/var/spool/lock")) {
1226
		exec("/bin/mkdir -p /var/spool/lock");
1227
		exec("/bin/chmod a+rw /var/spool/lock/.");
1228
	}
1229
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1230
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1231
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1232

    
1233
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1234
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1235
			if ($ifcfg['if'] == $ppp['if'])
1236
				break;
1237
		}
1238
	}
1239
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1240
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1241
		return 0;
1242
	}
1243
	$pppif = $ifcfg['if'];
1244
	if ($ppp['type'] == "ppp")
1245
		$type = "modem";
1246
	else
1247
		$type = $ppp['type'];
1248
	$upper_type = strtoupper($ppp['type']);	
1249

    
1250
	if($g['booting']) {
1251
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1252
		echo "starting {$pppif} link...";
1253
		// Do not re-configure the interface if we are booting and it's already been started
1254
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1255
			return 0;
1256
	}
1257

    
1258
	$ports = explode(',',$ppp['ports']);
1259
	if ($type != "modem") {
1260
		foreach ($ports as $pid => $port)
1261
			$ports[$pid] = get_real_interface($port);
1262
	}
1263
	$localips = explode(',',$ppp['localip']);
1264
	$gateways = explode(',',$ppp['gateway']);
1265
	$subnets = explode(',',$ppp['subnet']);
1266

    
1267
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1268
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1269
	 */
1270
	foreach($ports as $pid => $port){
1271
		switch ($ppp['type']) {
1272
			case "pppoe": 
1273
				/* Bring the parent interface up */
1274
				interfaces_bring_up($port);
1275
				pfSense_ngctl_attach(".", $port);
1276
				break;
1277
			case "pptp":
1278
			case "l2tp":
1279
				/* configure interface */
1280
				if(is_ipaddr($localips[$pid])){
1281
					// Manually configure interface IP/subnet
1282
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1283
					interfaces_bring_up($port);
1284
				} else if (empty($localips[$pid]))
1285
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1286
				
1287
				if(!is_ipaddr($localips[$pid])){
1288
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure. Using 0.0.0.0 ip!");
1289
					$localips[$pid] = "0.0.0.0";
1290
				}
1291
				/* XXX: This needs to go away soon! [It's commented out!] */
1292
				/* Configure the gateway (remote IP ) */
1293
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1294
					/* XXX: Fix later 
1295
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1296
					if(!is_ipaddr($gateways[$pid])) {
1297
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1298
						return 0;
1299
					}
1300
					*/
1301
				}
1302
				if(!is_ipaddr($gateways[$pid])){
1303
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1304
					return 0;
1305
				}
1306
				pfSense_ngctl_attach(".", $port);
1307
				break;
1308
			case "ppp":
1309
				if (!file_exists("{$port}")) {
1310
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1311
					return 0;
1312
				}
1313
				break;
1314
			default:
1315
				log_error("Unkown {$type} configured as ppp interface.");
1316
				break;
1317
		}
1318
	}
1319
	
1320
	if (is_array($ports) && count($ports) > 1)
1321
		$multilink = "enable";
1322
	else
1323
		$multilink = "disable";
1324
	
1325
	if ($type == "modem"){
1326
		if (is_ipaddr($ppp['localip']))
1327
			$localip = $ppp['localip'];
1328
		else
1329
			$localip = '0.0.0.0';
1330

    
1331
		if (is_ipaddr($ppp['gateway']))
1332
			$gateway = $ppp['gateway'];
1333
		else
1334
			$gateway = "10.64.64.{$pppid}";
1335
		$ranges = "{$localip}/0 {$gateway}/0";
1336
		
1337
		if (empty($ppp['apnum']))	
1338
			$ppp['apnum'] = 1;
1339
	} else
1340
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1341

    
1342
	if (isset($ppp['ondemand'])) 
1343
		$ondemand = "enable";
1344
	else
1345
		$ondemand = "disable";
1346
	if (!isset($ppp['idletimeout']))
1347
		$ppp['idletimeout'] = 0;
1348

    
1349
	if (empty($ppp['username']) && $type == "modem"){
1350
		$ppp['username'] = "user";
1351
		$ppp['password'] = "none";
1352
	}
1353
	if (empty($ppp['password']) && $type == "modem")
1354
		$passwd = "none";
1355
	else
1356
		$passwd = base64_decode($ppp['password']);
1357

    
1358
	$bandwidths = explode(',',$ppp['bandwidth']);
1359
	$mtus = explode(',',$ppp['mtu']);
1360
	$mrus = explode(',',$ppp['mru']);
1361

    
1362
	if (isset($ppp['mrru']))
1363
		$mrrus = explode(',',$ppp['mrru']);
1364

    
1365
	// Construct the mpd.conf file
1366
	$mpdconf = <<<EOD
1367
startup:
1368
	# configure the console
1369
	set console close
1370
	# configure the web server
1371
	set web close
1372

    
1373
default:
1374
{$ppp['type']}client:
1375
	create bundle static {$interface}
1376
	set iface name {$pppif}
1377

    
1378
EOD;
1379
	$setdefaultgw = false;
1380
	$founddefaultgw = false;
1381
	if (is_array($config['gateways']['gateway_item'])) {
1382
		foreach($config['gateways']['gateway_item'] as $gateway) {
1383
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1384
				$setdefaultgw = true;
1385
				break;
1386
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1387
				$founddefaultgw = true;
1388
				break;
1389
			}
1390
		}
1391
	}
1392
	
1393
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1394
		$setdefaultgw = true;
1395
		$mpdconf .= <<<EOD
1396
	set iface route default
1397

    
1398
EOD;
1399
	}
1400
	$mpdconf .= <<<EOD
1401
	set iface {$ondemand} on-demand
1402
	set iface idle {$ppp['idletimeout']}
1403

    
1404
EOD;
1405

    
1406
	if (isset($ppp['ondemand']))
1407
		$mpdconf .= <<<EOD
1408
	set iface addrs 10.10.1.1 10.10.1.2
1409

    
1410
EOD;
1411
	
1412
	if (isset($ppp['tcpmssfix']))
1413
		$tcpmss = "disable";
1414
	else
1415
		$tcpmss = "enable";
1416
		$mpdconf .= <<<EOD
1417
	set iface {$tcpmss} tcpmssfix
1418

    
1419
EOD;
1420

    
1421
	$mpdconf .= <<<EOD
1422
	set iface up-script /usr/local/sbin/ppp-linkup
1423
	set iface down-script /usr/local/sbin/ppp-linkdown
1424
	set ipcp ranges {$ranges}
1425

    
1426
EOD;
1427
	if (isset($ppp['vjcomp']))
1428
		$mpdconf .= <<<EOD
1429
	set ipcp no vjcomp
1430

    
1431
EOD;
1432

    
1433
	if (isset($config['system']['dnsallowoverride']))
1434
		$mpdconf .= <<<EOD
1435
	set ipcp enable req-pri-dns
1436
	set ipcp enable req-sec-dns
1437

    
1438
EOD;
1439
	if (!isset($ppp['verbose_log']))
1440
		$mpdconf .= <<<EOD
1441
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1442

    
1443
EOD;
1444
	foreach($ports as $pid => $port){
1445
		$port = get_real_interface($port);
1446
		$mpdconf .= <<<EOD
1447

    
1448
	create link static {$interface}_link{$pid} {$type}
1449
	set link action bundle {$interface}
1450
	set link {$multilink} multilink
1451
	set link keep-alive 10 60
1452
	set link max-redial 0
1453

    
1454
EOD;
1455
		if (isset($ppp['shortseq']))
1456
			$mpdconf .= <<<EOD
1457
	set link no shortseq
1458

    
1459
EOD;
1460

    
1461
		if (isset($ppp['acfcomp']))
1462
			$mpdconf .= <<<EOD
1463
	set link no acfcomp
1464

    
1465
EOD;
1466

    
1467
		if (isset($ppp['protocomp']))
1468
			$mpdconf .= <<<EOD
1469
	set link no protocomp
1470

    
1471
EOD;
1472

    
1473
		$mpdconf .= <<<EOD
1474
	set link disable chap pap
1475
	set link accept chap pap eap
1476
	set link disable incoming
1477

    
1478
EOD;
1479

    
1480

    
1481
		if (!empty($bandwidths[$pid]))
1482
			$mpdconf .= <<<EOD
1483
	set link bandwidth {$bandwidths[$pid]}
1484

    
1485
EOD;
1486

    
1487
		if (empty($mtus[$pid]))
1488
			$mtus[$pid] = "1492";
1489
			$mpdconf .= <<<EOD
1490
	set link mtu {$mtus[$pid]}
1491

    
1492
EOD;
1493

    
1494
		if (!empty($mrus[$pid]))
1495
			$mpdconf .= <<<EOD
1496
	set link mru {$mrus[$pid]}
1497

    
1498
EOD;
1499

    
1500
		if (!empty($mrrus[$pid]))
1501
			$mpdconf .= <<<EOD
1502
	set link mrru {$mrrus[$pid]}
1503

    
1504
EOD;
1505

    
1506
		$mpdconf .= <<<EOD
1507
	set auth authname "{$ppp['username']}"
1508
	set auth password {$passwd}
1509

    
1510
EOD;
1511
		if ($type == "modem") {
1512
			$mpdconf .= <<<EOD
1513
	set modem device {$ppp['ports']}
1514
	set modem script DialPeer
1515
	set modem idle-script Ringback
1516
	set modem watch -cd
1517
	set modem var \$DialPrefix "DT"
1518
	set modem var \$Telephone "{$ppp['phone']}"
1519

    
1520
EOD;
1521
		}
1522
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1523
			$mpdconf .= <<<EOD
1524
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1525

    
1526
EOD;
1527
		}
1528
		if (isset($ppp['initstr']) && $type == "modem") {
1529
			$initstr = base64_decode($ppp['initstr']);
1530
			$mpdconf .= <<<EOD
1531
	set modem var \$InitString "{$initstr}"
1532

    
1533
EOD;
1534
		}
1535
		if (isset($ppp['simpin']) && $type == "modem") {
1536
			$mpdconf .= <<<EOD
1537
	set modem var \$SimPin "{$ppp['simpin']}"
1538
	set modem var \$PinWait "{$ppp['pin-wait']}"
1539

    
1540
EOD;
1541
		}
1542
		if (isset($ppp['apn']) && $type == "modem") {
1543
			$mpdconf .= <<<EOD
1544
	set modem var \$APN "{$ppp['apn']}"
1545
	set modem var \$APNum "{$ppp['apnum']}"
1546

    
1547
EOD;
1548
		}
1549
		if (isset($ppp['provider']) && $type == "pppoe") {
1550
			$mpdconf .= <<<EOD
1551
	set pppoe service "{$ppp['provider']}"
1552

    
1553
EOD;
1554
		}
1555
		if ($type == "pppoe")
1556
			$mpdconf .= <<<EOD
1557
	set pppoe iface {$port}
1558

    
1559
EOD;
1560

    
1561
		if ($type == "pptp" || $type == "l2tp") {
1562
			$mpdconf .= <<<EOD
1563
	set {$type} self {$localips[$pid]}
1564
	set {$type} peer {$gateways[$pid]}
1565

    
1566
EOD;
1567
		}
1568
		
1569
		$mpdconf .= "\topen\r\n";
1570
	} //end foreach($port)
1571

    
1572

    
1573
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1574
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1575
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1576
	else {
1577
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1578
		if (!$fd) {
1579
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1580
			return 0;
1581
		}
1582
		// Write out mpd_ppp.conf
1583
		fwrite($fd, $mpdconf);
1584
		fclose($fd);
1585
	}
1586

    
1587
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1588
	if (isset($ppp['uptime'])) {
1589
		if (!file_exists("/conf/{$pppif}.log")) {
1590
			conf_mount_rw();
1591
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1592
			conf_mount_ro();
1593
		}
1594
	} else {
1595
		if (file_exists("/conf/{$pppif}.log")) {
1596
			conf_mount_rw();
1597
			mwexec("rm -f /conf/{$pppif}.log");
1598
			conf_mount_ro();
1599
		}
1600
	}
1601

    
1602
	/* fire up mpd */
1603
	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");
1604

    
1605
	// Check for PPPoE periodic reset request 
1606
	if ($type == "pppoe") {
1607
		if (isset($ppp['pppoe-reset-type']))
1608
			setup_pppoe_reset_file($ppp['if'], $interface);
1609
		else
1610
			setup_pppoe_reset_file($ppp['if']);
1611
	}
1612

    
1613
	return 1;
1614
}
1615

    
1616
function interfaces_carp_setup() {
1617
	global $g, $config;
1618

    
1619
	$balanacing = "";
1620
	$pfsyncinterface = "";
1621
	$pfsyncenabled = "";
1622
	if(isset($config['system']['developerspew'])) {
1623
		$mt = microtime();
1624
		echo "interfaces_carp_setup() being called $mt\n";
1625
	}
1626

    
1627
	// Prepare CmdCHAIN that will be used to execute commands.
1628
	$cmdchain = new CmdCHAIN();	
1629

    
1630
	if ($g['booting']) {
1631
		echo "Configuring CARP settings...";
1632
		mute_kernel_msgs();
1633
	}
1634

    
1635
	/* suck in configuration items */
1636
	if($config['installedpackages']['carpsettings']) {
1637
		if($config['installedpackages']['carpsettings']['config']) {
1638
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1639
				$pfsyncenabled = $carp['pfsyncenabled'];
1640
				$balanacing = $carp['balancing'];
1641
				$pfsyncinterface = $carp['pfsyncinterface'];
1642
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1643
			}
1644
		}
1645
	} else {
1646
		unset($pfsyncinterface);
1647
		unset($balanacing);
1648
		unset($pfsyncenabled);
1649
	}
1650

    
1651
	if($balanacing) {
1652
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1653
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1654
	} else
1655
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1656

    
1657
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1658
	if (!empty($pfsyncinterface))
1659
		$carp_sync_int = get_real_interface($pfsyncinterface);
1660

    
1661
	if($g['booting']) {
1662
		/*    install rules to alllow pfsync to sync up during boot
1663
		 *    carp interfaces will remain down until the bootup sequence finishes
1664
		 */
1665
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1666
		if ($fd) {
1667
			fwrite($fd, "block quick proto carp \n");
1668
			fwrite($fd, "block quick proto pfsync \n");
1669
			fwrite($fd, "pass out quick from any to any keep state\n");
1670
			fclose($fd);
1671
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1672
		} else
1673
			log_error("Could not create rules.boot file!");
1674
	}
1675

    
1676
	/* setup pfsync interface */
1677
	if($carp_sync_int and $pfsyncenabled) {
1678
		if (is_ipaddr($pfsyncpeerip))
1679
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1680
		else
1681
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1682
	} else
1683
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1684

    
1685
	sleep(1);
1686

    
1687
	/* XXX: Handle an issue with pfsync(4) and carp(4). In a cluster carp will come up before pfsync(4) has updated and so will cause issuese
1688
	 * for exiting sessions.
1689
	 */
1690
	$i = 0;
1691
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1692
		$i++;
1693
		sleep(1);
1694
	}
1695

    
1696
	if($config['virtualip']['vip'])
1697
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1698
	else
1699
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1700
	
1701
	if($g['debug'])
1702
		$cmdchain->setdebug(); // optional for verbose logging
1703

    
1704
	$cmdchain->execute();
1705
	$cmdchain->clear();
1706

    
1707
	if ($g['booting']) {
1708
		unmute_kernel_msgs();
1709
		echo "done.\n";
1710
	}
1711
}
1712

    
1713
function interface_proxyarp_configure($interface = "") {
1714
	global $config, $g;
1715
	if(isset($config['system']['developerspew'])) {
1716
		$mt = microtime();
1717
		echo "interface_proxyarp_configure() being called $mt\n";
1718
	}
1719

    
1720
	/* kill any running choparp */
1721
	if (empty($interface))
1722
		killbyname("choparp");
1723
	else {
1724
		$vipif = get_real_interface($interface);
1725
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1726
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1727
	}
1728

    
1729
	$paa = array();
1730
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1731

    
1732
		/* group by interface */
1733
		foreach ($config['virtualip']['vip'] as $vipent) {
1734
			if ($vipent['mode'] === "proxyarp") {
1735
				if ($vipent['interface'])
1736
					$proxyif = $vipent['interface'];
1737
				else
1738
					$proxyif = "wan";
1739
				
1740
				if (!empty($interface) && $interface != $proxyif)
1741
					continue;
1742

    
1743
				if (!is_array($paa[$proxyif]))
1744
					$paa[$proxyif] = array();
1745

    
1746
				$paa[$proxyif][] = $vipent;
1747
			}
1748
		}
1749
	}
1750

    
1751
	if (!empty($interface)) {
1752
		if (is_array($paa[$interface])) {
1753
			$paaifip = get_interface_ip($interface);
1754
                        if (!is_ipaddr($paaifip))
1755
                                return;
1756
                        $args = get_real_interface($interface) . " auto";
1757
                        foreach ($paa[$interface] as $paent) {
1758
                                if (isset($paent['subnet']))
1759
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1760
                                else if (isset($paent['range']))
1761
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1762
                        }
1763
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1764
		}
1765
	} else if (count($paa) > 0) {
1766
		foreach ($paa as $paif => $paents)  {
1767
			$paaifip = get_interface_ip($paif);
1768
			if (!is_ipaddr($paaifip))
1769
				continue;
1770
			$args = get_real_interface($paif) . " auto";
1771
			foreach ($paents as $paent) {
1772
				if (isset($paent['subnet']))
1773
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1774
				else if (isset($paent['range']))
1775
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1776
			}
1777
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1778
		}
1779
	}
1780
}
1781

    
1782
function interfaces_vips_configure($interface = "") {
1783
	global $g, $config;
1784
	if(isset($config['system']['developerspew'])) {
1785
		$mt = microtime();
1786
		echo "interfaces_vips_configure() being called $mt\n";
1787
	}
1788
	$paa = array();
1789
	if(is_array($config['virtualip']['vip'])) {
1790
		$carp_setuped = false;
1791
		$anyproxyarp = false;
1792
		foreach ($config['virtualip']['vip'] as $vip) {
1793
			switch ($vip['mode']) {
1794
			case "proxyarp":
1795
				/* nothing it is handled on interface_proxyarp_configure() */
1796
				if ($interface <> "" && $vip['interface'] <> $interface)
1797
					continue;
1798
				$anyproxyarp = true;
1799
				break;
1800
			case "ipalias":
1801
				if ($interface <> "" && $vip['interface'] <> $interface)
1802
					continue;
1803
				interface_ipalias_configure(&$vip);
1804
				break;
1805
			case "carp":
1806
				if ($interface <> "" && $vip['interface'] <> $interface)
1807
					continue;
1808
				if ($carp_setuped == false)
1809
					$carp_setuped = true;
1810
				interface_carp_configure($vip);
1811
				break;
1812
			case "carpdev-dhcp":
1813
				if ($interface <> "" && $vip['interface'] <> $interface)
1814
					continue;
1815
				interface_carpdev_configure($vip);
1816
				break;
1817
			}
1818
		}
1819
		if ($carp_setuped == true)
1820
			interfaces_carp_setup();
1821
		if ($anyproxyarp == true)
1822
			interface_proxyarp_configure();
1823
	}
1824
}
1825

    
1826
function interface_ipalias_configure(&$vip) {
1827

    
1828
	if ($vip['mode'] == "ipalias") {
1829
		$if = get_real_interface($vip['interface']);
1830
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1831
	}
1832
}
1833

    
1834
function interface_reload_carps($cif) {
1835
	global $config;
1836

    
1837
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1838
	if (empty($carpifs))
1839
		return;
1840

    
1841
	$carps = explode(" ", $carpifs);
1842
	if(is_array($config['virtualip']['vip'])) {
1843
		$viparr = &$config['virtualip']['vip'];
1844
		foreach ($viparr as $vip) {
1845
			if (in_array($vip['carpif'], $carps)) {
1846
				switch ($vip['mode']) {
1847
				case "carp":
1848
					interface_vip_bring_down($vip);
1849
					sleep(1);
1850
					interface_carp_configure($vip);
1851
					break;
1852
				case "carpdev-dhcp":
1853
					interface_vip_bring_down($vip);
1854
					sleep(1);
1855
					interface_carpdev_configure($vip);
1856
					break;
1857
				case "ipalias":
1858
					interface_vip_bring_down($vip);
1859
					sleep(1);
1860
					interface_ipalias_configure($vip);
1861
					break;
1862
				}
1863
			}
1864
		}
1865
	}
1866
}
1867

    
1868
function interface_carp_configure(&$vip) {
1869
	global $config, $g;
1870
	if(isset($config['system']['developerspew'])) {
1871
		$mt = microtime();
1872
		echo "interface_carp_configure() being called $mt\n";
1873
	}
1874

    
1875
	if ($vip['mode'] != "carp")
1876
		return;
1877

    
1878
	$vip_password = $vip['password'];
1879
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1880
	if ($vip['password'] != "")
1881
		$password = " pass {$vip_password}";
1882

    
1883
	// set the vip interface to the vhid
1884
	$vipif = "vip{$vip['vhid']}";
1885

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

    
1896
	/* Ensure CARP IP really exists prior to loading up. */
1897
	$ww_subnet_ip = find_interface_ip($realif);
1898
	$ww_subnet_bits = find_interface_subnet($realif);
1899
	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'])) {
1900
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1901
		return;
1902
	}
1903

    
1904
	/* create the carp interface and setup */
1905
	if (does_interface_exist($vipif)) {
1906
		pfSense_interface_flags($vipif, -IFF_UP);
1907
	} else {
1908
		$carpif = pfSense_interface_create("carp");
1909
		pfSense_interface_rename($carpif, $vipif);
1910
		pfSense_ngctl_name("{$carpif}:", $vipif);
1911
	}
1912

    
1913
	/* invalidate interface cache */
1914
	get_interface_arr(true);
1915

    
1916
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1917
	$advbase = "";
1918
	if (!empty($vip['advbase']))
1919
		$advbase = "advbase {$vip['advbase']}";
1920
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1921

    
1922
	interfaces_bring_up($vipif);
1923
	
1924
	return $vipif;
1925
}
1926

    
1927
function interface_carpdev_configure(&$vip) {
1928
	global $g;
1929

    
1930
	if ($vip['mode'] != "carpdev-dhcp")
1931
		return;
1932

    
1933
	$vip_password = $vip['password'];
1934
	$vip_password = str_replace(" ", "", $vip_password);
1935
	if($vip['password'] != "")
1936
		$password = " pass \"" . $vip_password . "\"";
1937

    
1938
	if (empty($vip['interface']))
1939
		return;
1940

    
1941
	$vipif = "vip" . $vip['vhid'];
1942
	$realif = get_real_interface($vip['interface']);
1943
	interfaces_bring_up($realif);
1944
	/*
1945
	 * ensure the interface containing the VIP really exists
1946
	 * prevents a panic if the interface is missing or invalid
1947
	 */
1948
	if (!does_interface_exist($realif)) {
1949
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1950
		return;
1951
	}
1952

    
1953
	if (does_interface_exist($vipif)) {
1954
		interface_bring_down($vipif);
1955
	} else {
1956
		$carpdevif = exec("/sbin/ifconfig carp create");
1957
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1958
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1959
	}
1960

    
1961
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1962
	interfaces_bring_up($vipif);
1963

    
1964
	/*
1965
	 * XXX: BIG HACK but carpdev needs ip services active
1966
	 *      before even starting something as dhclient.
1967
	 *      I do not know if this is a feature or a bug
1968
	 *      but better than track it make it work ;) .
1969
	 */
1970
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1971
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1972

    
1973
	/* generate dhclient_wan.conf */
1974
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1975
	if ($fd) {
1976
		$dhclientconf = "";
1977

    
1978
		$dhclientconf .= <<<EOD
1979
interface "{$vipif}" {
1980
timeout 60;
1981
retry 1;
1982
select-timeout 0;
1983
initial-interval 1;
1984
script "/sbin/dhclient-script";
1985
}
1986

    
1987
EOD;
1988

    
1989
		fwrite($fd, $dhclientconf);
1990
		fclose($fd);
1991

    
1992
		/* fire up dhclient */
1993
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1994
	} else {
1995
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1996
		mwexec("/sbin/dhclient -b {$vipif}");
1997
	}
1998

    
1999
	return $vipif;
2000
}
2001

    
2002
function interface_wireless_clone($realif, $wlcfg) {
2003
	global $config, $g;
2004
	/*   Check to see if interface has been cloned as of yet.  
2005
	 *   If it has not been cloned then go ahead and clone it.
2006
	 */
2007
	$needs_clone = false;
2008
	if(is_array($wlcfg['wireless']))
2009
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2010
	else
2011
		$wlcfg_mode = $wlcfg['mode'];
2012
	switch($wlcfg_mode) {
2013
		 case "hostap":
2014
			$mode = "wlanmode hostap";
2015
			break;
2016
		 case "adhoc":
2017
			$mode = "wlanmode adhoc";
2018
			break;
2019
		 default:
2020
			$mode = "";
2021
			break;
2022
	}
2023
	$baseif = interface_get_wireless_base($wlcfg['if']);
2024
	if(does_interface_exist($realif)) {
2025
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2026
		$ifconfig_str = implode($output);
2027
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2028
			log_error("Interface {$realif} changed to hostap mode");
2029
			$needs_clone = true;
2030
		}
2031
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2032
			log_error("Interface {$realif} changed to adhoc mode");
2033
			$needs_clone = true;
2034
		}
2035
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2036
			log_error("Interface {$realif} changed to infrastructure mode");
2037
			$needs_clone = true;
2038
		}
2039
	} else {
2040
		$needs_clone = true;
2041
	}
2042

    
2043
	if($needs_clone == true) {
2044
		/* remove previous instance if it exists */
2045
		if(does_interface_exist($realif))
2046
			pfSense_interface_destroy($realif);
2047

    
2048
		log_error("Cloning new wireless interface {$realif}");
2049
		// Create the new wlan interface. FreeBSD returns the new interface name.
2050
		// example:  wlan2
2051
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2052
		if($ret <> 0) {
2053
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
2054
			return false;
2055
		}
2056
		$newif = trim($out[0]);
2057
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2058
		pfSense_interface_rename($newif, $realif);
2059
		// FIXME: not sure what ngctl is for. Doesn't work.
2060
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2061
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2062
	}
2063
	return true;
2064
}
2065

    
2066
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2067
	global $config, $g;
2068

    
2069
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2070
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2071
	                         'regdomain', 'regcountry', 'reglocation');
2072

    
2073
	if(!is_interface_wireless($ifcfg['if']))
2074
		return;
2075

    
2076
	$baseif = interface_get_wireless_base($ifcfg['if']);
2077

    
2078
	// Sync shared settings for assigned clones
2079
	$iflist = get_configured_interface_list(false, true);
2080
	foreach ($iflist as $if) {
2081
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2082
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2083
				foreach ($shared_settings as $setting) {
2084
					if ($sync_changes) {
2085
						if (isset($ifcfg['wireless'][$setting]))
2086
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2087
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2088
							unset($config['interfaces'][$if]['wireless'][$setting]);
2089
					} else {
2090
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2091
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2092
						else if (isset($ifcfg['wireless'][$setting]))
2093
							unset($ifcfg['wireless'][$setting]);
2094
					}
2095
				}
2096
				if (!$sync_changes)
2097
					break;
2098
			}
2099
		}
2100
	}
2101

    
2102
	// Read or write settings at shared area
2103
	if (isset($config['wireless']['interfaces'][$baseif])) {
2104
		foreach ($shared_settings as $setting) {
2105
			if ($sync_changes) {
2106
				if (isset($ifcfg['wireless'][$setting]))
2107
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2108
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2109
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2110
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2111
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2112
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2113
				else if (isset($ifcfg['wireless'][$setting]))
2114
					unset($ifcfg['wireless'][$setting]);
2115
			}
2116
		}
2117
	}
2118

    
2119
	// Sync the mode on the clone creation page with the configured mode on the interface
2120
	if (interface_is_wireless_clone($ifcfg['if'])) {
2121
		foreach ($config['wireless']['clone'] as &$clone) {
2122
			if ($clone['cloneif'] == $ifcfg['if']) {
2123
				if ($sync_changes) {
2124
					$clone['mode'] = $ifcfg['wireless']['mode'];
2125
				} else {
2126
					$ifcfg['wireless']['mode'] = $clone['mode'];
2127
				}
2128
				break;
2129
			}
2130
		}
2131
		unset($clone);
2132
	}
2133
}
2134

    
2135
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2136
	global $config, $g;
2137

    
2138
	/*    open up a shell script that will be used to output the commands.
2139
	 *    since wireless is changing a lot, these series of commands are fragile
2140
     *    and will sometimes need to be verified by a operator by executing the command
2141
     *    and returning the output of the command to the developers for inspection.  please
2142
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2143
	 */
2144

    
2145
	// Remove script file
2146
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2147

    
2148
	// Clone wireless nic if needed.
2149
	interface_wireless_clone($if, $wl);
2150

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

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

    
2158
	/* set values for /path/program */
2159
	$hostapd = "/usr/sbin/hostapd";
2160
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2161
	$ifconfig = "/sbin/ifconfig";
2162
	$sysctl = "/sbin/sysctl";
2163
	$killall = "/usr/bin/killall";
2164

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

    
2167
	$wlcmd = array();
2168
	$wl_sysctl = array();
2169
	/* Make sure it's up */
2170
	$wlcmd[] = "up";
2171
	/* Set a/b/g standard */
2172
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2173
	$wlcmd[] = "mode " . escapeshellarg($standard);
2174

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

    
2180
	/* Set ssid */
2181
	if($wlcfg['ssid'])
2182
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2183

    
2184
	/* Set 802.11g protection mode */
2185
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2186

    
2187
	/* set wireless channel value */
2188
	if(isset($wlcfg['channel'])) {
2189
		if($wlcfg['channel'] == "0") {
2190
			$wlcmd[] = "channel any";
2191
		} else {
2192
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2193
		}
2194
	}
2195

    
2196
	/* Set antenna diversity value */
2197
	if(isset($wlcfg['diversity']))
2198
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2199

    
2200
	/* Set txantenna value */
2201
	if(isset($wlcfg['txantenna']))
2202
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2203

    
2204
	/* Set rxantenna value */
2205
	if(isset($wlcfg['rxantenna']))
2206
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2207

    
2208
	/* set Distance value */
2209
	if($wlcfg['distance'])
2210
		$distance = escapeshellarg($wlcfg['distance']);
2211

    
2212
	/* Set wireless hostap mode */
2213
	if ($wlcfg['mode'] == "hostap") {
2214
		$wlcmd[] = "mediaopt hostap";
2215
	} else {
2216
		$wlcmd[] = "-mediaopt hostap";
2217
	}
2218

    
2219
	/* Set wireless adhoc mode */
2220
	if ($wlcfg['mode'] == "adhoc") {
2221
		$wlcmd[] = "mediaopt adhoc";
2222
	} else {
2223
		$wlcmd[] = "-mediaopt adhoc";
2224
	}
2225

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

    
2228
	/* handle hide ssid option */
2229
	if(isset($wlcfg['hidessid']['enable'])) {
2230
		$wlcmd[] = "hidessid";
2231
	} else {
2232
		$wlcmd[] = "-hidessid";
2233
	}
2234

    
2235
	/* handle pureg (802.11g) only option */
2236
	if(isset($wlcfg['pureg']['enable'])) {
2237
		$wlcmd[] = "mode 11g pureg";
2238
	} else {
2239
		$wlcmd[] = "-pureg";
2240
	}
2241

    
2242
	/* handle puren (802.11n) only option */
2243
	if(isset($wlcfg['puren']['enable'])) {
2244
		$wlcmd[] = "puren";
2245
	} else {
2246
		$wlcmd[] = "-puren";
2247
	}
2248

    
2249
	/* enable apbridge option */
2250
	if(isset($wlcfg['apbridge']['enable'])) {
2251
		$wlcmd[] = "apbridge";
2252
	} else {
2253
		$wlcmd[] = "-apbridge";
2254
	}
2255

    
2256
	/* handle turbo option */
2257
	if(isset($wlcfg['turbo']['enable'])) {
2258
		$wlcmd[] = "mediaopt turbo";
2259
	} else {
2260
		$wlcmd[] = "-mediaopt turbo";
2261
	}
2262

    
2263
	/* handle txpower setting */
2264
	/* if($wlcfg['txpower'] <> "")
2265
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2266
	*/
2267
	/* handle wme option */
2268
	if(isset($wlcfg['wme']['enable'])) {
2269
		$wlcmd[] = "wme";
2270
	} else {
2271
		$wlcmd[] = "-wme";
2272
	}
2273

    
2274
	/* set up wep if enabled */
2275
	$wepset = "";
2276
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2277
		switch($wlcfg['wpa']['auth_algs']) {
2278
			case "1":
2279
				$wepset .= "authmode open wepmode on ";
2280
				break;
2281
			case "2":
2282
				$wepset .= "authmode shared wepmode on ";
2283
				break;
2284
			case "3":
2285
				$wepset .= "authmode mixed wepmode on ";
2286
		}
2287
		$i = 1;
2288
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2289
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2290
			if (isset($wepkey['txkey'])) {
2291
				$wlcmd[] = "weptxkey {$i} ";
2292
			}
2293
			$i++;
2294
		}
2295
		$wlcmd[] = $wepset;
2296
	} else {
2297
		$wlcmd[] = "authmode open wepmode off ";
2298
	}
2299

    
2300
	mwexec(kill_hostapd("{$if}"));
2301
	mwexec(kill_wpasupplicant("{$if}"));
2302

    
2303
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2304
	conf_mount_rw();
2305

    
2306
	switch ($wlcfg['mode']) {
2307
		case 'bss':
2308
			if (isset($wlcfg['wpa']['enable'])) {
2309
				$wpa .= <<<EOD
2310
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2311
ctrl_interface_group=0
2312
ap_scan=1
2313
#fast_reauth=1
2314
network={
2315
ssid="{$wlcfg['ssid']}"
2316
scan_ssid=1
2317
priority=5
2318
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2319
psk="{$wlcfg['wpa']['passphrase']}"
2320
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2321
group={$wlcfg['wpa']['wpa_pairwise']}
2322
}
2323
EOD;
2324

    
2325
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2326
				fwrite($fd, "{$wpa}");
2327
				fclose($fd);
2328
			}
2329
			break;
2330
		case 'hostap':
2331
			if($wlcfg['wpa']['passphrase']) 
2332
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2333
			else 
2334
				$wpa_passphrase = "";
2335
			if (isset($wlcfg['wpa']['enable'])) {
2336
				$wpa .= <<<EOD
2337
interface={$if}
2338
driver=bsd
2339
logger_syslog=-1
2340
logger_syslog_level=0
2341
logger_stdout=-1
2342
logger_stdout_level=0
2343
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2344
ctrl_interface={$g['varrun_path']}/hostapd
2345
ctrl_interface_group=wheel
2346
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2347
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2348
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2349
ssid={$wlcfg['ssid']}
2350
debug={$wlcfg['wpa']['debug_mode']}
2351
auth_algs={$wlcfg['wpa']['auth_algs']}
2352
wpa={$wlcfg['wpa']['wpa_mode']}
2353
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2354
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2355
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2356
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2357
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2358
{$wpa_passphrase}
2359

    
2360
EOD;
2361

    
2362
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2363
	$wpa .= <<<EOD
2364
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2365
rsn_preauth=1
2366
rsn_preauth_interfaces={$if}
2367

    
2368
EOD;
2369

    
2370
}
2371
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2372
					$auth_server_port = "1812";
2373
					if($wlcfg['auth_server_port']) 
2374
						$auth_server_port = $wlcfg['auth_server_port'];
2375
					$wpa .= <<<EOD
2376

    
2377
ieee8021x=1
2378
auth_server_addr={$wlcfg['auth_server_addr']}
2379
auth_server_port={$auth_server_port}
2380
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2381

    
2382
EOD;
2383
				} else {
2384
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2385
				}
2386

    
2387
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2388
				fwrite($fd, "{$wpa}");
2389
				fclose($fd);
2390

    
2391
			}
2392
			break;
2393
	}
2394

    
2395
	/*
2396
	 *    all variables are set, lets start up everything
2397
	 */
2398

    
2399
	$baseif = interface_get_wireless_base($if);
2400
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2401
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2402

    
2403
	/* set sysctls for the wireless interface */
2404
	if (!empty($wl_sysctl)) {
2405
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2406
		foreach ($wl_sysctl as $wl_sysctl_line) {
2407
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2408
		}
2409
	}
2410

    
2411
	/* set ack timers according to users preference (if he/she has any) */
2412
	if($distance) {
2413
		fwrite($fd_set, "# Enable ATH distance settings\n");
2414
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2415
	}
2416

    
2417
	if (isset($wlcfg['wpa']['enable'])) {
2418
		if ($wlcfg['mode'] == "bss") {
2419
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2420
		}
2421
		if ($wlcfg['mode'] == "hostap") {
2422
			/* add line to script to restore old mac to make hostapd happy */
2423
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2424
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2425
				if (is_macaddr($if_oldmac))
2426
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2427
						" link " . escapeshellarg($if_oldmac) . "\n");
2428
			}
2429

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

    
2432
			/* add line to script to restore spoofed mac after running hostapd */
2433
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2434
				if ($wl['spoofmac'])
2435
					$if_curmac = $wl['spoofmac'];
2436
				else
2437
					$if_curmac = get_interface_mac($if);
2438
				if (is_macaddr($if_curmac))
2439
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2440
						" link " . escapeshellarg($if_curmac) . "\n");
2441
			}
2442
		}
2443
	}
2444

    
2445
	fclose($fd_set);
2446
	conf_mount_ro();
2447

    
2448
	/* Making sure regulatory settings have actually changed
2449
	 * before applying, because changing them requires bringing
2450
	 * down all wireless networks on the interface. */
2451
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2452
	$ifconfig_str = implode($output);
2453
	unset($output);
2454
	$reg_changing = false;
2455

    
2456
	/* special case for the debug country code */
2457
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2458
		$reg_changing = true;
2459
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2460
		$reg_changing = true;
2461
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2462
		$reg_changing = true;
2463
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2464
		$reg_changing = true;
2465
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2466
		$reg_changing = true;
2467

    
2468
	if ($reg_changing) {
2469
		/* set regulatory domain */
2470
		if($wlcfg['regdomain'])
2471
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2472

    
2473
		/* set country */
2474
		if($wlcfg['regcountry'])
2475
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2476

    
2477
		/* set location */
2478
		if($wlcfg['reglocation'])
2479
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2480

    
2481
		$wlregcmd_args = implode(" ", $wlregcmd);
2482

    
2483
		/* build a complete list of the wireless clones for this interface */
2484
		$clone_list = array();
2485
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2486
			$clone_list[] = interface_get_wireless_clone($baseif);
2487
		if (is_array($config['wireless']['clone'])) {
2488
			foreach ($config['wireless']['clone'] as $clone) {
2489
				if ($clone['if'] == $baseif)
2490
					$clone_list[] = $clone['cloneif'];
2491
			}
2492
		}
2493

    
2494
		/* find which clones are up and bring them down */
2495
		$clones_up = array();
2496
		foreach ($clone_list as $clone_if) {
2497
			$clone_status = pfSense_get_interface_addresses($clone_if);
2498
			if ($clone_status['status'] == 'up') {
2499
				$clones_up[] = $clone_if;
2500
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2501
			}
2502
		}
2503

    
2504
		/* apply the regulatory settings */
2505
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2506

    
2507
		/* bring the clones back up that were previously up */
2508
		foreach ($clones_up as $clone_if) {
2509
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2510

    
2511
			/*
2512
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2513
			 * is in infrastructure mode, and WPA is enabled.
2514
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2515
			 */
2516
			if ($clone_if != $if) {
2517
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2518
				if ( !empty($friendly_if)
2519
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2520
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2521
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2522
				}
2523
			}
2524
		}
2525
	}
2526

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

    
2531
	/* configure wireless */
2532
	$wlcmd_args = implode(" ", $wlcmd);
2533
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2534

    
2535
	
2536
	sleep(1);
2537
	/* execute hostapd and wpa_supplicant if required in shell */
2538
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2539

    
2540
	return 0;
2541

    
2542
}
2543

    
2544
function kill_hostapd($interface) {
2545
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2546
}
2547

    
2548
function kill_wpasupplicant($interface) {
2549
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2550
}
2551

    
2552
function find_dhclient_process($interface) {
2553
	if ($interface)
2554
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2555
	else
2556
		$pid = 0;
2557

    
2558
	return intval($pid);
2559
}
2560

    
2561
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2562
	global $config, $g;
2563
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2564

    
2565
	$wancfg = $config['interfaces'][$interface];
2566

    
2567
	$realif = get_real_interface($interface);
2568
	$realhwif_array = get_parent_interface($interface);
2569
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2570
	$realhwif = $realhwif_array[0];
2571

    
2572
			
2573
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2574
		/* remove all IPv4 addresses */
2575
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2576

    
2577
		switch ($wancfg['ipaddr']) {
2578
			case 'pppoe':
2579
			case 'l2tp':
2580
			case 'pptp':
2581
			case 'ppp':
2582
				break;
2583
			default:
2584
				interface_bring_down($interface);
2585
				break;
2586
		}
2587
	}
2588

    
2589
	/* wireless configuration? */
2590
	if (is_array($wancfg['wireless']))
2591
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2592

    
2593
	if ($wancfg['spoofmac']) {
2594
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2595
			" link " . escapeshellarg($wancfg['spoofmac']));
2596

    
2597
                /*
2598
                 * All vlans need to spoof their parent mac address, too.  see
2599
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2600
                 */
2601
                if (is_array($config['vlans']['vlan'])) {
2602
                        foreach ($config['vlans']['vlan'] as $vlan) {
2603
                                if ($vlan['if'] == $realhwif)
2604
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2605
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2606
                        }
2607
                }
2608
	}  else {
2609
		$mac = get_interface_mac($realhwif);
2610
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2611
			/*   this is not a valid mac address.  generate a
2612
			 *   temporary mac address so the machine can get online.
2613
			 */
2614
			echo "Generating new MAC address.";
2615
			$random_mac = generate_random_mac_address();
2616
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2617
				" link " . escapeshellarg($random_mac));
2618
			$wancfg['spoofmac'] = $random_mac;
2619
			write_config();
2620
			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");
2621
		}
2622
	}
2623

    
2624
	/* media */
2625
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2626
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2627
		if ($wancfg['media'])
2628
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2629
		if ($wancfg['mediaopt'])
2630
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2631
		mwexec($cmd);
2632
	}
2633
	if (!empty($wancfg['mtu']))
2634
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2635
	else {
2636
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2637
		if ($mtu != get_interface_mtu($realhwif))
2638
			pfSense_interface_mtu($realhwif, $mtu);
2639
	}
2640

    
2641
	$options = pfSense_get_interface_addresses($realhwif);
2642
	if (is_array($options) && isset($options['caps']['polling'])) {
2643
		if (isset($config['system']['polling']))
2644
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2645
		else
2646
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2647
	}
2648

    
2649
	/* skip vlans for checksumming and polling */
2650
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2651
		$flags = 0;
2652
		if(isset($config['system']['disablechecksumoffloading'])) {
2653
			if (isset($options['encaps']['txcsum']))
2654
				$flags |= IFCAP_TXCSUM;
2655
			if (isset($options['encaps']['rxcsum']))
2656
				$flags |= IFCAP_RXCSUM;
2657
        	} else {
2658
 			if (!isset($options['caps']['txcsum']))
2659
				$flags |= IFCAP_TXCSUM;
2660
			if (!isset($options['caps']['rxcsum']))
2661
				$flags |= IFCAP_RXCSUM;
2662
        	}
2663

    
2664
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2665
                	if (isset($options['encaps']['tso4']))
2666
				$flags |= IFCAP_TSO;
2667
                	if (isset($options['encaps']['tso6']))
2668
				$flags |= IFCAP_TSO;
2669
        	} else {
2670
                	if (!isset($options['caps']['tso4']))
2671
				$flags |= IFCAP_TSO;
2672
                	if (!isset($options['caps']['tso6']))
2673
				$flags |= IFCAP_TSO;
2674
        	}
2675

    
2676
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2677
                	if (isset($options['encaps']['lro']))
2678
				$flags |= IFCAP_LRO;
2679
        	} else {
2680
                	if (!isset($options['caps']['lro']))
2681
				$flags |= IFCAP_LRO;
2682
        	}
2683

    
2684
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2685
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2686
			$flags |= IFCAP_POLLING;
2687
		}
2688
               	pfSense_interface_capabilities($realhwif, -$flags);
2689
	}
2690

    
2691
	/* invalidate interface/ip/sn cache */
2692
	get_interface_arr(true);
2693
	unset($interface_ip_arr_cache[$realif]);
2694
	unset($interface_sn_arr_cache[$realif]);
2695

    
2696
	switch ($wancfg['ipaddr']) {
2697
		case 'carpdev-dhcp':
2698
			interface_carpdev_dhcp_configure($interface);
2699
			break;
2700
		case 'dhcp':
2701
			interface_dhcp_configure($interface);
2702
			break;
2703
		case 'pppoe':
2704
		case 'l2tp':
2705
		case 'pptp':
2706
		case 'ppp':
2707
			interface_ppps_configure($interface);
2708
			break;
2709
		default:
2710
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2711
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2712
			} else if (substr($realif, 0, 3) == "gre") {
2713
				if (is_array($config['gres']['gre'])) {
2714
					foreach ($config['gres']['gre'] as $gre)
2715
						if ($gre['greif'] == $realif)
2716
							interface_gre_configure($gre);
2717
				}
2718
			} else if (substr($realif, 0, 3) == "gif") {
2719
				 if (is_array($config['gifs']['gif'])) {
2720
					foreach ($config['gifs']['gif'] as $gif)
2721
						if($gif['gifif'] == $realif)
2722
							interface_gif_configure($gif);
2723
				}
2724
			} else if (substr($realif, 0, 4) == "ovpn") {
2725
				/* XXX: Should be done anything?! */
2726
			}
2727
			break;
2728
	}
2729

    
2730
	if(does_interface_exist($wancfg['if']))
2731
		interfaces_bring_up($wancfg['if']);
2732

    
2733
	interface_netgraph_needed($interface);
2734
 	
2735
	if (!$g['booting']) {
2736
		link_interface_to_vips($interface, "update");
2737

    
2738
		unset($gre);
2739
		$gre = link_interface_to_gre($interface);
2740
		if (!empty($gre))
2741
			array_walk($gre, 'interface_gre_configure');
2742

    
2743
		unset($gif);
2744
		$gif = link_interface_to_gif($interface);
2745
		if (!empty($gif))
2746
                       	array_walk($gif, 'interface_gif_configure');
2747

    
2748
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2749
			unset($bridgetmp);
2750
			$bridgetmp = link_interface_to_bridge($interface);
2751
			if (!empty($bridgetmp))
2752
				interface_bridge_add_member($bridgetmp, $realif);
2753
		}
2754

    
2755
		$grouptmp = link_interface_to_group($interface);
2756
		if (!empty($grouptmp))
2757
			array_walk($grouptmp, 'interface_group_add_member');
2758

    
2759
		if ($interface == "lan")
2760
			/* make new hosts file */
2761
			system_hosts_generate();
2762

    
2763
		if ($reloadall == true) {
2764

    
2765
			/* reconfigure static routes (kernel may have deleted them) */
2766
			system_routing_configure($interface);
2767

    
2768
			/* reload ipsec tunnels */
2769
			vpn_ipsec_configure();
2770

    
2771
			/* restart dnsmasq */
2772
			services_dnsmasq_configure();
2773

    
2774
			/* update dyndns */
2775
			send_event("service reload dyndns {$interface}");
2776

    
2777
			/* reload captive portal */
2778
			captiveportal_init_rules();
2779
		}
2780
	}
2781

    
2782
	return 0;
2783
}
2784

    
2785
function interface_carpdev_dhcp_configure($interface = "wan") {
2786
	global $config, $g;
2787

    
2788
	$wancfg = $config['interfaces'][$interface];
2789
	$wanif = $wancfg['if'];
2790
	/* bring wan interface up before starting dhclient */
2791
	if($wanif)
2792
		interfaces_bring_up($wanif);
2793
	else 
2794
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2795

    
2796
	return 0;
2797
}
2798

    
2799
function interface_dhcp_configure($interface = "wan") {
2800
	global $config, $g;
2801

    
2802
	$wancfg = $config['interfaces'][$interface];
2803
	if (empty($wancfg))
2804
		$wancfg = array();
2805

    
2806
	/* generate dhclient_wan.conf */
2807
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2808
	if (!$fd) {
2809
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2810
		return 1;
2811
	}
2812

    
2813
	if ($wancfg['dhcphostname']) {
2814
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2815
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2816
	} else {
2817
		$dhclientconf_hostname = "";
2818
	}
2819

    
2820
	$wanif = get_real_interface($interface);
2821
	if (empty($wanif)) {
2822
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2823
		return 0;
2824
	}
2825
 	$dhclientconf = "";
2826
	
2827
	$dhclientconf .= <<<EOD
2828
interface "{$wanif}" {
2829
timeout 60;
2830
retry 1;
2831
select-timeout 0;
2832
initial-interval 1;
2833
	{$dhclientconf_hostname}
2834
	script "/sbin/dhclient-script";
2835
}
2836

    
2837
EOD;
2838

    
2839
if(is_ipaddr($wancfg['alias-address'])) {
2840
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2841
	$dhclientconf .= <<<EOD
2842
alias {
2843
	interface  "{$wanif}";
2844
	fixed-address {$wancfg['alias-address']};
2845
	option subnet-mask {$subnetmask};
2846
}
2847

    
2848
EOD;
2849
}
2850
	fwrite($fd, $dhclientconf);
2851
	fclose($fd);
2852

    
2853
	/* bring wan interface up before starting dhclient */
2854
	if($wanif)
2855
		interfaces_bring_up($wanif);
2856
	else 
2857
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2858

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

    
2862
	return 0;
2863
}
2864

    
2865
function interfaces_group_setup() {
2866
	global $config;
2867

    
2868
	if (!is_array($config['ifgroups']['ifgroupentry']))
2869
		return;
2870

    
2871
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2872
		interface_group_setup($groupar);
2873

    
2874
	return;
2875
}
2876

    
2877
function interface_group_setup(&$groupname /* The parameter is an array */) {
2878
	global $config;
2879

    
2880
	if (!is_array($groupname))
2881
		return;
2882
	$members = explode(" ", $groupname['members']);
2883
	foreach($members as $ifs) {
2884
		$realif = get_real_interface($ifs);
2885
		if ($realif)
2886
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2887
	}
2888

    
2889
	return;
2890
}
2891

    
2892
function interface_group_add_member($interface, $groupname) {
2893
	$interface = get_real_interface($interface);
2894
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2895
}
2896
 
2897
/* COMPAT Function */
2898
function convert_friendly_interface_to_real_interface_name($interface) {
2899
	return get_real_interface($interface);
2900
}
2901

    
2902
/* COMPAT Function */
2903
function get_real_wan_interface($interface = "wan") {
2904
	return get_real_interface($interface);
2905
}
2906

    
2907
/* COMPAT Function */
2908
function get_current_wan_address($interface = "wan") {
2909
	return get_interface_ip($interface);
2910
}
2911

    
2912
/*
2913
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2914
 */
2915
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2916
        global $config;
2917

    
2918
	if (stristr($interface, "vip")) {
2919
                $index = intval(substr($interface, 3));
2920
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2921
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2922
                                if ($index == $vip['vhid'])
2923
                                        return $vip['interface'];
2924
                        }
2925
                }
2926
        }
2927

    
2928
        /* XXX: For speed reasons reference directly the interface array */
2929
	$ifdescrs = &$config['interfaces'];
2930
        //$ifdescrs = get_configured_interface_list(false, true);
2931

    
2932
        foreach ($ifdescrs as $if => $ifname) {
2933
                if ($config['interfaces'][$if]['if'] == $interface)
2934
                        return $if;
2935

    
2936
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2937
                        return $if;
2938

    
2939
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
2940
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
2941
		/*
2942
                $int = get_parent_interface($if);
2943
                if ($int[0] == $interface)
2944
                        return $ifname;
2945
		*/
2946
        }
2947
        return NULL;
2948
}
2949

    
2950
/* attempt to resolve interface to friendly descr */
2951
function convert_friendly_interface_to_friendly_descr($interface) {
2952
        global $config;
2953

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

    
2998
        return $ifdesc;
2999
}
3000

    
3001
function convert_real_interface_to_friendly_descr($interface) {
3002
        global $config;
3003

    
3004
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3005

    
3006
        if ($ifdesc) {
3007
                $iflist = get_configured_interface_with_descr(false, true);
3008
                return $iflist[$ifdesc];
3009
        }
3010

    
3011
        return $interface;
3012
}
3013

    
3014
/*
3015
 *  get_parent_interface($interface):
3016
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3017
 *				or virtual interface (i.e. vlan)
3018
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3019
 *			-- returns $interface passed in if $interface parent is not found
3020
 *			-- returns empty array if an invalid interface is passed
3021
 *	(Only handles ppps and vlans now.)
3022
 */
3023
function get_parent_interface($interface) {
3024
	global $config;
3025

    
3026
	$parents = array();
3027
	//Check that we got a valid interface passed
3028
	$realif = get_real_interface($interface);
3029
	if ($realif == NULL)
3030
		return $parents;
3031

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

    
3074
function interface_is_wireless_clone($wlif) {
3075
	if(!stristr($wlif, "_wlan")) {
3076
		return false;
3077
	} else {
3078
		return true;
3079
	}
3080
}
3081

    
3082
function interface_get_wireless_base($wlif) {
3083
	if(!stristr($wlif, "_wlan")) {
3084
		return $wlif;
3085
	} else {
3086
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3087
	}
3088
}
3089

    
3090
function interface_get_wireless_clone($wlif) {
3091
	if(!stristr($wlif, "_wlan")) {
3092
		return $wlif . "_wlan0";
3093
	} else {
3094
		return $wlif;
3095
	}
3096
}
3097

    
3098
function get_real_interface($interface = "wan") {
3099
    global $config;
3100

    
3101
	$wanif = NULL;
3102

    
3103
	switch ($interface) {
3104
	case "l2tp":
3105
		$wanif = "l2tp";
3106
		break;
3107
	case "pptp":
3108
		$wanif = "pptp";
3109
		break;
3110
	case "pppoe":
3111
		$wanif = "pppoe";
3112
		break;
3113
	case "openvpn":
3114
		$wanif = "openvpn";
3115
		break;
3116
	case "ipsec":
3117
	case "enc0":
3118
		$wanif = "enc0";
3119
		break;
3120
	case "ppp":
3121
		$wanif = "ppp";
3122
		break;
3123
	default:
3124
		// If a real interface was alread passed simply
3125
		// pass the real interface back.  This encourages
3126
		// the usage of this function in more cases so that
3127
		// we can combine logic for more flexibility.
3128
		if(does_interface_exist($interface)) {
3129
			$wanif = $interface;
3130
			break;
3131
		}
3132
		if (empty($config['interfaces'][$interface]))
3133
			break;
3134

    
3135
		$cfg = &$config['interfaces'][$interface];
3136

    
3137
		// Wireless cloned NIC support (FreeBSD 8+)
3138
		// interface name format: $parentnic_wlanparentnic#
3139
		// example: ath0_wlan0
3140
		if (is_interface_wireless($cfg['if'])) {
3141
			$wanif = interface_get_wireless_clone($cfg['if']);
3142
			break;
3143
		}
3144
		/*
3145
		if (empty($cfg['if'])) {
3146
			$wancfg = $cfg['if'];
3147
			break;
3148
		}
3149
		*/
3150

    
3151
		switch ($cfg['ipaddr']) {
3152
			case "carpdev-dhcp":
3153
				$viparr = &$config['virtualip']['vip'];
3154
				if(is_array($viparr))
3155
				foreach ($viparr as $counter => $vip) {
3156
					if ($vip['mode'] == "carpdev-dhcp") {
3157
						if($vip['interface'] == $interface) {
3158
							$wanif = "carp{$counter}";
3159
							break;
3160
						}
3161
					}
3162
				}
3163
				break;
3164
			case "pppoe": 
3165
			case "pptp": 
3166
			case "l2tp": 
3167
			case "ppp":
3168
				$wanif = $cfg['if'];
3169
				break;
3170
			default:
3171
				$wanif = $cfg['if'];
3172
				break;
3173
		}
3174
		break;
3175
	}
3176

    
3177
    return $wanif;
3178
}
3179

    
3180
/* Guess the physical interface by providing a IP address */
3181
function guess_interface_from_ip($ipaddress) {
3182
	if(! is_ipaddr($ipaddress)) {
3183
		return false;
3184
	}
3185
	/* create a route table we can search */
3186
	exec("netstat -rnWf inet", $output, $ret);
3187
	foreach($output as $line) {
3188
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3189
			$fields = preg_split("/[ ]+/", $line);
3190
			if(ip_in_subnet($ipaddress, $fields[0])) {
3191
				return $fields[6];
3192
			}
3193
		}
3194
	}
3195
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3196
	if(empty($ret)) {
3197
        	return false;
3198
	}
3199
	return $ret;
3200
}
3201

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

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

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

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

    
3232
/*
3233
 * find_carp_interface($ip): return the carp interface where an ip is defined
3234
 */
3235
function find_carp_interface($ip) {
3236
	global $config;
3237
	if (is_array($config['virtualip']['vip'])) {
3238
		foreach ($config['virtualip']['vip'] as $vip) {
3239
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3240
				$carp_ip = get_interface_ip($vip['interface']);
3241
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
3242
				if ($if)
3243
					return $if;
3244
			}
3245
		}
3246
	}
3247
}
3248

    
3249
function link_carp_interface_to_parent($interface) {
3250
        global $config;
3251

    
3252
        if ($interface == "")
3253
                return;
3254

    
3255
        $carp_ip = get_interface_ip($interface);
3256
        if (!is_ipaddr($carp_ip))
3257
                return;
3258

    
3259
        /* if list */
3260
        $ifdescrs = get_configured_interface_list();
3261
        foreach ($ifdescrs as $ifdescr => $ifname) {
3262
                $interfaceip = get_interface_ip($ifname);
3263
                $subnet_bits = get_interface_subnet($ifname);
3264
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3265
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3266
                        return $ifname;
3267
        }
3268

    
3269
        return "";
3270
}
3271

    
3272
/****f* interfaces/link_ip_to_carp_interface
3273
 * NAME
3274
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3275
 * INPUTS
3276
 *   $ip
3277
 * RESULT
3278
 *   $carp_ints
3279
 ******/
3280
function link_ip_to_carp_interface($ip) {
3281
        global $config;
3282

    
3283
        if (!is_ipaddr($ip))
3284
                return;
3285

    
3286
        $carp_ints = "";
3287
        if (is_array($config['virtualip']['vip'])) {
3288
		$first = 0;
3289
		$carp_int = array();
3290
                foreach ($config['virtualip']['vip'] as $vip) {
3291
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3292
                                $carp_ip = $vip['subnet'];
3293
                                $carp_sn = $vip['subnet_bits'];
3294
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3295
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3296
					$carp_int[] = "vip{$vip['vhid']}";
3297
                        }
3298
                }
3299
		if (!empty($carp_int))
3300
			$carp_ints = implode(" ", array_unique($carp_int));
3301
        }
3302

    
3303
        return $carp_ints;
3304
}
3305

    
3306
function link_interface_to_vlans($int, $action = "") {
3307
	global $config;
3308

    
3309
	if (empty($int))
3310
		return;
3311

    
3312
	if (is_array($config['vlans']['vlan'])) {
3313
                foreach ($config['vlans']['vlan'] as $vlan) {
3314
			if ($int == $vlan['if']) {
3315
				if ($action == "update") {
3316
					interfaces_bring_up($int);
3317
				} else if ($action == "")
3318
					return $vlan;
3319
			}
3320
		}
3321
	}
3322
}
3323

    
3324
function link_interface_to_vips($int, $action = "") {
3325
        global $config;
3326

    
3327
        if (is_array($config['virtualip']['vip'])) {
3328
		foreach ($config['virtualip']['vip'] as $vip) {
3329
			if ($int == $vip['interface']) {
3330
				if ($action == "update") {
3331
					if ($vip['mode'] == "carp" && !does_interface_exist("vip{$vip['vhid']}"))
3332
						interfaces_vips_configure($int);
3333
					else {
3334
						interface_vip_bring_down($vip);
3335
						interfaces_vips_configure($int);
3336
					}
3337
				} else
3338
					return $vip;
3339
			}
3340
		}
3341
	}
3342
}
3343

    
3344
/****f* interfaces/link_interface_to_bridge
3345
 * NAME
3346
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3347
 * INPUTS
3348
 *   $ip
3349
 * RESULT
3350
 *   bridge[0-99]
3351
 ******/
3352
function link_interface_to_bridge($int) {
3353
        global $config;
3354

    
3355
        if (is_array($config['bridges']['bridged'])) {
3356
                foreach ($config['bridges']['bridged'] as $bridge) {
3357
			if (in_array($int, explode(',', $bridge['members'])))
3358
                                return "{$bridge['bridgeif']}";
3359
		}
3360
	}
3361
}
3362

    
3363
function link_interface_to_group($int) {
3364
        global $config;
3365

    
3366
	$result = array();
3367

    
3368
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3369
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3370
			if (in_array($int, explode(" ", $group['members'])))
3371
				$result[$group['ifname']] = $int;
3372
		}
3373
	}
3374

    
3375
	return $result;
3376
}
3377

    
3378
function link_interface_to_gre($interface) {
3379
        global $config;
3380

    
3381
	$result = array();
3382

    
3383
        if (is_array($config['gres']['gre'])) {
3384
                foreach ($config['gres']['gre'] as $gre)
3385
                        if($gre['if'] == $interface)
3386
				$result[] = $gre;
3387
	}
3388

    
3389
	return $result;
3390
}
3391

    
3392
function link_interface_to_gif($interface) {
3393
        global $config;
3394

    
3395
	$result = array();
3396

    
3397
        if (is_array($config['gifs']['gif'])) {
3398
                foreach ($config['gifs']['gif'] as $gif)
3399
                        if($gif['if'] == $interface)
3400
                                $result[] = $gif;
3401
	}
3402

    
3403
	return $result;
3404
}
3405

    
3406
/*
3407
 * find_interface_ip($interface): return the interface ip (first found)
3408
 */
3409
function find_interface_ip($interface, $flush = false)
3410
{
3411
	global $interface_ip_arr_cache;
3412
	global $interface_sn_arr_cache;
3413

    
3414
	$interface = str_replace("\n", "", $interface);
3415
	
3416
	if (!does_interface_exist($interface))
3417
		return;
3418

    
3419
	/* Setup IP cache */
3420
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3421
		$ifinfo = pfSense_get_interface_addresses($interface);
3422
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3423
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3424
	}
3425

    
3426
	return $interface_ip_arr_cache[$interface];
3427
}
3428

    
3429
function find_interface_subnet($interface, $flush = false)
3430
{
3431
	global $interface_sn_arr_cache;
3432
	global $interface_ip_arr_cache;
3433

    
3434
	$interface = str_replace("\n", "", $interface);
3435
	if (does_interface_exist($interface) == false)
3436
		return;
3437

    
3438
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3439
		$ifinfo = pfSense_get_interface_addresses($interface);
3440
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3441
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3442
        }
3443

    
3444
	return $interface_sn_arr_cache[$interface];
3445
}
3446

    
3447
function ip_in_interface_alias_subnet($interface, $ipalias) {
3448
	global $config;
3449

    
3450
	if (empty($interface) || !is_ipaddr($ipalias))
3451
		return false;
3452
	if (is_array($config['virtualip']['vip'])) {
3453
                foreach ($config['virtualip']['vip'] as $vip) {
3454
                        switch ($vip['mode']) {
3455
                        case "ipalias":
3456
                                if ($vip['interface'] <> $interface)
3457
                                        break;
3458
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3459
					return true;
3460
                                break;
3461
                        }
3462
                }
3463
	}
3464

    
3465
	return false;
3466
}
3467

    
3468
function get_interface_ip($interface = "wan")
3469
{
3470
	$realif = get_real_interface($interface);
3471
	if (!$realif) {
3472
		if (preg_match("/^carp/i", $interface))
3473
			$realif = $interface;
3474
		else if (preg_match("/^vip/i", $interface))
3475
			$realif = $interface;
3476
		else
3477
			return null;
3478
	}
3479

    
3480
	$curip = find_interface_ip($realif);
3481
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3482
		return $curip;
3483
	else
3484
		return null;
3485
}
3486

    
3487
function get_interface_subnet($interface = "wan")
3488
{
3489
	$realif = get_real_interface($interface);
3490
	if (!$realif) {
3491
                if (preg_match("/^carp/i", $interface))
3492
                        $realif = $interface;
3493
                else if (preg_match("/^vip/i", $interface))
3494
                        $realif = $interface;
3495
                else
3496
                        return null;
3497
        }
3498

    
3499
	$cursn = find_interface_subnet($realif);
3500
	if (!empty($cursn))
3501
		return $cursn;
3502

    
3503
	return null;
3504
}
3505

    
3506
/* return outside interfaces with a gateway */
3507
function get_interfaces_with_gateway() {
3508
	global $config;
3509

    
3510
	$ints = array();
3511

    
3512
	/* loop interfaces, check config for outbound */
3513
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3514
		switch ($ifname['ipaddr']) {
3515
			case "dhcp":
3516
			case "carpdev-dhcp":
3517
			case "ppp";
3518
			case "pppoe":
3519
			case "pptp":
3520
			case "l2tp":
3521
			case "ppp";
3522
				$ints[$ifdescr] = $ifdescr;
3523
			break;
3524
			default:
3525
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3526
				    !empty($ifname['gateway']))
3527
					$ints[$ifdescr] = $ifdescr;
3528
			break;
3529
		}
3530
	}
3531
	return $ints;
3532
}
3533

    
3534
/* return true if interface has a gateway */
3535
function interface_has_gateway($friendly) {
3536
	global $config;
3537

    
3538
	if (!empty($config['interfaces'][$friendly])) {
3539
		$ifname = &$config['interfaces'][$friendly];
3540
		switch ($ifname['ipaddr']) {
3541
			case "dhcp":
3542
			case "carpdev-dhcp":
3543
			case "pppoe":
3544
			case "pptp":
3545
			case "l2tp":
3546
			case "ppp";
3547
				return true;
3548
			break;
3549
			default:
3550
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3551
					return true;
3552
				if (!empty($ifname['gateway']))
3553
					return true;
3554
			break;
3555
		}
3556
	}
3557

    
3558
	return false;
3559
}
3560

    
3561
/****f* interfaces/is_altq_capable
3562
 * NAME
3563
 *   is_altq_capable - Test if interface is capable of using ALTQ
3564
 * INPUTS
3565
 *   $int            - string containing interface name
3566
 * RESULT
3567
 *   boolean         - true or false
3568
 ******/
3569

    
3570
function is_altq_capable($int) {
3571
        /* Per:
3572
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3573
         * Only the following drivers have ALTQ support
3574
         */
3575
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3576
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3577
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3578
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3579
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3580
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3581
			"l2tp", "ppp");
3582

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

    
3585
        if (in_array($int_family[0], $capable))
3586
                return true;
3587
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3588
		return true;
3589
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3590
		return true;
3591
        else
3592
                return false;
3593
}
3594

    
3595
/****f* interfaces/is_interface_wireless
3596
 * NAME
3597
 *   is_interface_wireless - Returns if an interface is wireless
3598
 * RESULT
3599
 *   $tmp       - Returns if an interface is wireless
3600
 ******/
3601
function is_interface_wireless($interface) {
3602
        global $config, $g;
3603

    
3604
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3605
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3606
                if (preg_match($g['wireless_regex'], $interface)) {
3607
                        if (isset($config['interfaces'][$friendly]))
3608
                                $config['interfaces'][$friendly]['wireless'] = array();
3609
                        return true;
3610
                }
3611
                return false;
3612
        } else
3613
                return true;
3614
}
3615

    
3616
function get_wireless_modes($interface) {
3617
	/* return wireless modes and channels */
3618
	$wireless_modes = array();
3619

    
3620
	$cloned_interface = get_real_interface($interface);
3621

    
3622
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3623
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3624
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3625
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3626

    
3627
		$interface_channels = "";
3628
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3629
		$interface_channel_count = count($interface_channels);
3630

    
3631
		$c = 0;
3632
		while ($c < $interface_channel_count)
3633
		{
3634
			$channel_line = explode(",", $interface_channels["$c"]);
3635
			$wireless_mode = trim($channel_line[0]);
3636
			$wireless_channel = trim($channel_line[1]);
3637
			if(trim($wireless_mode) != "") {
3638
				/* if we only have 11g also set 11b channels */
3639
				if($wireless_mode == "11g") {
3640
					if(!isset($wireless_modes["11b"]))
3641
						$wireless_modes["11b"] = array();
3642
				} else if($wireless_mode == "11g ht") {
3643
					if(!isset($wireless_modes["11b"]))
3644
						$wireless_modes["11b"] = array();
3645
					if(!isset($wireless_modes["11g"]))
3646
						$wireless_modes["11g"] = array();
3647
					$wireless_mode = "11ng";
3648
				} else if($wireless_mode == "11a ht") {
3649
					if(!isset($wireless_modes["11a"]))
3650
						$wireless_modes["11a"] = array();
3651
					$wireless_mode = "11na";
3652
				}
3653
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3654
			}
3655
			$c++;
3656
		}
3657
	}
3658
	return($wireless_modes);
3659
}
3660

    
3661
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3662
function get_wireless_channel_info($interface) {
3663
	$wireless_channels = array();
3664

    
3665
	$cloned_interface = get_real_interface($interface);
3666

    
3667
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3668
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3669
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3670
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3671

    
3672
		$interface_channels = "";
3673
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3674

    
3675
		foreach ($interface_channels as $channel_line) {
3676
			$channel_line = explode(",", $channel_line);
3677
			if(!isset($wireless_channels[$channel_line[0]]))
3678
				$wireless_channels[$channel_line[0]] = $channel_line;
3679
		}
3680
	}
3681
	return($wireless_channels);
3682
}
3683

    
3684
/****f* interfaces/get_interface_mtu
3685
 * NAME
3686
 *   get_interface_mtu - Return the mtu of an interface
3687
 * RESULT
3688
 *   $tmp       - Returns the mtu of an interface
3689
 ******/
3690
function get_interface_mtu($interface) {
3691
        $mtu = pfSense_get_interface_addresses($interface);
3692
        return $mtu['mtu'];
3693
}
3694

    
3695
function get_interface_mac($interface) {
3696

    
3697
	$macinfo = pfSense_get_interface_addresses($interface);
3698
	return $macinfo["macaddr"];
3699
}
3700

    
3701
/****f* pfsense-utils/generate_random_mac_address
3702
 * NAME
3703
 *   generate_random_mac - generates a random mac address
3704
 * INPUTS
3705
 *   none
3706
 * RESULT
3707
 *   $mac - a random mac address
3708
 ******/
3709
function generate_random_mac_address() {
3710
        $mac = "02";
3711
        for($x=0; $x<5; $x++)
3712
                $mac .= ":" . dechex(rand(16, 255));
3713
        return $mac;
3714
}
3715

    
3716
/****f* interfaces/is_jumbo_capable
3717
 * NAME
3718
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3719
 * INPUTS
3720
 *   $int             - string containing interface name
3721
 * RESULT
3722
 *   boolean          - true or false
3723
 ******/
3724
function is_jumbo_capable($int) {
3725
        global $g;
3726

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

    
3729
        if (in_array($int_family[0], $g['vlan_long_frame']))
3730
                return true;
3731
        else
3732
                return false;
3733
}
3734

    
3735
function setup_pppoe_reset_file($pppif, $iface="") {
3736
	global $g;
3737
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3738

    
3739
	if(!empty($iface) && !empty($pppif)){
3740
		$cron_cmd = <<<EOD
3741
#!/bin/sh
3742
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3743
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3744

    
3745
EOD;
3746

    
3747
		file_put_contents($cron_file, $cron_cmd);
3748
		chmod($cron_file, 0700);
3749
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3750
	} else
3751
		unlink_if_exists($cron_file);
3752
}
3753

    
3754
function get_interface_default_mtu($type = "ethernet") {
3755
	switch ($type) {
3756
	case "gre":
3757
		return 1476;
3758
		break;
3759
	case "gif":
3760
		return 1280;
3761
		break;
3762
	case "tun":
3763
	case "vlan":
3764
	case "tap":
3765
	case "ethernet":
3766
	default:
3767
		return 1500;
3768
		break;
3769
	}
3770

    
3771
	/* Never reached */
3772
	return 1500;
3773
}
3774

    
3775
function get_vip_descr($ipaddress) {
3776
	global $config;
3777

    
3778
	foreach ($config['virtualip']['vip'] as $vip) {
3779
		if ($vip['subnet'] == $ipaddress) {
3780
			return ($vip['descr']);
3781
		}
3782
	}
3783
	return "";
3784
}
3785

    
3786
function interfaces_staticarp_configure($if) {
3787
	global $config, $g;
3788
	if(isset($config['system']['developerspew'])) {
3789
		$mt = microtime();
3790
		echo "interfaces_staticarp_configure($if) being called $mt\n";
3791
	}
3792

    
3793
	$ifcfg = $config['interfaces'][$if];
3794

    
3795
	if (empty($if) || empty($ifcfg['if']))
3796
		return 0;
3797

    
3798
	/* Enable staticarp, if enabled */
3799
	if(isset($config['dhcpd'][$if]['staticarp'])) {
3800
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
3801
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
3802
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
3803

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

    
3807
			}
3808

    
3809
		}
3810
	} else {
3811
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
3812
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
3813
	}
3814

    
3815
	return 0;
3816
}
3817

    
3818
?>
(25-25/61)