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 ($type == "pppoe") {
1550
			// Send a null service name if none is set.
1551
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1552
			$mpdconf .= <<<EOD
1553
	set pppoe service "{$provider}"
1554

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

    
1561
EOD;
1562

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

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

    
1574

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

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

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

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

    
1615
	return 1;
1616
}
1617

    
1618
function interfaces_carp_setup() {
1619
	global $g, $config;
1620

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

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

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

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

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

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

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

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

    
1687
	sleep(1);
1688

    
1689
	/* 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
1690
	 * for exiting sessions.
1691
	 */
1692
	$i = 0;
1693
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1694
		$i++;
1695
		sleep(1);
1696
	}
1697

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

    
1706
	$cmdchain->execute();
1707
	$cmdchain->clear();
1708

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

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

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

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

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

    
1745
				if (!is_array($paa[$proxyif]))
1746
					$paa[$proxyif] = array();
1747

    
1748
				$paa[$proxyif][] = $vipent;
1749
			}
1750
		}
1751
	}
1752

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

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

    
1828
function interface_ipalias_configure(&$vip) {
1829

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

    
1836
function interface_reload_carps($cif) {
1837
	global $config;
1838

    
1839
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1840
	if (empty($carpifs))
1841
		return;
1842

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

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

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

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

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

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

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

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

    
1915
	/* invalidate interface cache */
1916
	get_interface_arr(true);
1917

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

    
1924
	interfaces_bring_up($vipif);
1925
	
1926
	return $vipif;
1927
}
1928

    
1929
function interface_carpdev_configure(&$vip) {
1930
	global $g;
1931

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

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

    
1940
	if (empty($vip['interface']))
1941
		return;
1942

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

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

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

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

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

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

    
1989
EOD;
1990

    
1991
		fwrite($fd, $dhclientconf);
1992
		fclose($fd);
1993

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

    
2001
	return $vipif;
2002
}
2003

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

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

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

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

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

    
2075
	if(!is_interface_wireless($ifcfg['if']))
2076
		return;
2077

    
2078
	$baseif = interface_get_wireless_base($ifcfg['if']);
2079

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

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

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

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

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

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

    
2150
	// Clone wireless nic if needed.
2151
	interface_wireless_clone($if, $wl);
2152

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2302
	mwexec(kill_hostapd("{$if}"));
2303
	mwexec(kill_wpasupplicant("{$if}"));
2304

    
2305
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2306
	conf_mount_rw();
2307

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

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

    
2362
EOD;
2363

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

    
2370
EOD;
2371

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

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

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

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

    
2393
			}
2394
			break;
2395
	}
2396

    
2397
	/*
2398
	 *    all variables are set, lets start up everything
2399
	 */
2400

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

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

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

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

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

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

    
2447
	fclose($fd_set);
2448
	conf_mount_ro();
2449

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

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

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

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

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

    
2483
		$wlregcmd_args = implode(" ", $wlregcmd);
2484

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

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

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

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

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

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

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

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

    
2542
	return 0;
2543

    
2544
}
2545

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

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

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

    
2560
	return intval($pid);
2561
}
2562

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

    
2567
	$wancfg = $config['interfaces'][$interface];
2568

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2732
	if(does_interface_exist($wancfg['if']))
2733
		interfaces_bring_up($wancfg['if']);
2734

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

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

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

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

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

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

    
2765
		if ($reloadall == true) {
2766

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

    
2770
			/* reload ipsec tunnels */
2771
			vpn_ipsec_configure();
2772

    
2773
			/* restart dnsmasq */
2774
			services_dnsmasq_configure();
2775

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

    
2779
			/* reload captive portal */
2780
			captiveportal_init_rules();
2781
		}
2782
	}
2783

    
2784
	return 0;
2785
}
2786

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

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

    
2798
	return 0;
2799
}
2800

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

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

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

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

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

    
2839
EOD;
2840

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

    
2850
EOD;
2851
}
2852
	fwrite($fd, $dhclientconf);
2853
	fclose($fd);
2854

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

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

    
2864
	return 0;
2865
}
2866

    
2867
function interfaces_group_setup() {
2868
	global $config;
2869

    
2870
	if (!is_array($config['ifgroups']['ifgroupentry']))
2871
		return;
2872

    
2873
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2874
		interface_group_setup($groupar);
2875

    
2876
	return;
2877
}
2878

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

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

    
2891
	return;
2892
}
2893

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

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

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

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

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

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

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

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

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

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

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

    
3000
        return $ifdesc;
3001
}
3002

    
3003
function convert_real_interface_to_friendly_descr($interface) {
3004
        global $config;
3005

    
3006
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3007

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

    
3013
        return $interface;
3014
}
3015

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

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

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

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

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

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

    
3100
function get_real_interface($interface = "wan") {
3101
    global $config;
3102

    
3103
	$wanif = NULL;
3104

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

    
3137
		$cfg = &$config['interfaces'][$interface];
3138

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

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

    
3179
    return $wanif;
3180
}
3181

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

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

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

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

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

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

    
3251
function link_carp_interface_to_parent($interface) {
3252
        global $config;
3253

    
3254
        if ($interface == "")
3255
                return;
3256

    
3257
        $carp_ip = get_interface_ip($interface);
3258
        if (!is_ipaddr($carp_ip))
3259
                return;
3260

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

    
3271
        return "";
3272
}
3273

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

    
3285
        if (!is_ipaddr($ip))
3286
                return;
3287

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

    
3305
        return $carp_ints;
3306
}
3307

    
3308
function link_interface_to_vlans($int, $action = "") {
3309
	global $config;
3310

    
3311
	if (empty($int))
3312
		return;
3313

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

    
3326
function link_interface_to_vips($int, $action = "") {
3327
        global $config;
3328

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

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

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

    
3365
function link_interface_to_group($int) {
3366
        global $config;
3367

    
3368
	$result = array();
3369

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

    
3377
	return $result;
3378
}
3379

    
3380
function link_interface_to_gre($interface) {
3381
        global $config;
3382

    
3383
	$result = array();
3384

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

    
3391
	return $result;
3392
}
3393

    
3394
function link_interface_to_gif($interface) {
3395
        global $config;
3396

    
3397
	$result = array();
3398

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

    
3405
	return $result;
3406
}
3407

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

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

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

    
3428
	return $interface_ip_arr_cache[$interface];
3429
}
3430

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

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

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

    
3446
	return $interface_sn_arr_cache[$interface];
3447
}
3448

    
3449
function ip_in_interface_alias_subnet($interface, $ipalias) {
3450
	global $config;
3451

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

    
3467
	return false;
3468
}
3469

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

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

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

    
3501
	$cursn = find_interface_subnet($realif);
3502
	if (!empty($cursn))
3503
		return $cursn;
3504

    
3505
	return null;
3506
}
3507

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

    
3512
	$ints = array();
3513

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

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

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

    
3560
	return false;
3561
}
3562

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

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

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

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

    
3599
/****f* interfaces/is_interface_wireless
3600
 * NAME
3601
 *   is_interface_wireless - Returns if an interface is wireless
3602
 * RESULT
3603
 *   $tmp       - Returns if an interface is wireless
3604
 ******/
3605
function is_interface_wireless($interface) {
3606
        global $config, $g;
3607

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

    
3620
function get_wireless_modes($interface) {
3621
	/* return wireless modes and channels */
3622
	$wireless_modes = array();
3623

    
3624
	$cloned_interface = get_real_interface($interface);
3625

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

    
3631
		$interface_channels = "";
3632
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3633
		$interface_channel_count = count($interface_channels);
3634

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

    
3665
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3666
function get_wireless_channel_info($interface) {
3667
	$wireless_channels = array();
3668

    
3669
	$cloned_interface = get_real_interface($interface);
3670

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

    
3676
		$interface_channels = "";
3677
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3678

    
3679
		foreach ($interface_channels as $channel_line) {
3680
			$channel_line = explode(",", $channel_line);
3681
			if(!isset($wireless_channels[$channel_line[0]]))
3682
				$wireless_channels[$channel_line[0]] = $channel_line;
3683
		}
3684
	}
3685
	return($wireless_channels);
3686
}
3687

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

    
3699
function get_interface_mac($interface) {
3700

    
3701
	$macinfo = pfSense_get_interface_addresses($interface);
3702
	return $macinfo["macaddr"];
3703
}
3704

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

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

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

    
3733
        if (in_array($int_family[0], $g['vlan_long_frame']))
3734
                return true;
3735
        else
3736
                return false;
3737
}
3738

    
3739
function setup_pppoe_reset_file($pppif, $iface="") {
3740
	global $g;
3741
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3742

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

    
3749
EOD;
3750

    
3751
		file_put_contents($cron_file, $cron_cmd);
3752
		chmod($cron_file, 0700);
3753
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3754
	} else
3755
		unlink_if_exists($cron_file);
3756
}
3757

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

    
3775
	/* Never reached */
3776
	return 1500;
3777
}
3778

    
3779
function get_vip_descr($ipaddress) {
3780
	global $config;
3781

    
3782
	foreach ($config['virtualip']['vip'] as $vip) {
3783
		if ($vip['subnet'] == $ipaddress) {
3784
			return ($vip['descr']);
3785
		}
3786
	}
3787
	return "";
3788
}
3789

    
3790
function interfaces_staticarp_configure($if) {
3791
	global $config, $g;
3792
	if(isset($config['system']['developerspew'])) {
3793
		$mt = microtime();
3794
		echo "interfaces_staticarp_configure($if) being called $mt\n";
3795
	}
3796

    
3797
	$ifcfg = $config['interfaces'][$if];
3798

    
3799
	if (empty($if) || empty($ifcfg['if']))
3800
		return 0;
3801

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

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

    
3811
			}
3812

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

    
3819
	return 0;
3820
}
3821

    
3822
?>
(25-25/61)