Project

General

Profile

Download (107 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)
627
		pfSense_interface_mtu($interface, $mtu);
628

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

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

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

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

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

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

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

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

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

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

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

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

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

    
730
	interfaces_bring_up($laggif);
731

    
732
	return $laggif;
733
}
734

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

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

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

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

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

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

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

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

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

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

    
791
	return $greif;
792
}
793

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

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

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

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

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

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

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

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

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

    
850
	return $gifif;
851
}
852

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

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

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

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

    
865
	interfaces_qinq_configure();
866

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

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

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

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

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

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

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

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

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

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

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

    
931
		interface_configure($if, $reload);
932

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

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

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

    
946
		interface_configure($if, $reload);
947

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

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

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

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

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

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

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

    
972
	return 0;
973
}
974

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

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

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

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

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

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

    
1015
	$realif = get_real_interface($interface);
1016

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

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

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

    
1086
	return;
1087
}
1088

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

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

    
1097
	return false;
1098
}
1099

    
1100
function interfaces_ptpid_next() {
1101

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

    
1106
	return $ptpid;
1107
}
1108

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1404
EOD;
1405

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

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

    
1419
EOD;
1420

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

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

    
1431
EOD;
1432

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

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

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

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

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

    
1459
EOD;
1460

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

    
1465
EOD;
1466

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

    
1471
EOD;
1472

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

    
1478
EOD;
1479

    
1480

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

    
1485
EOD;
1486

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

    
1492
EOD;
1493

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

    
1498
EOD;
1499

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

    
1504
EOD;
1505

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

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

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

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

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

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

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

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

    
1559
EOD;
1560

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

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

    
1572

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

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

    
1602
	/* fire up mpd */
1603
	mwexec("/usr/local/sbin/mpd5 -b -k -d {$g['varetc_path']} -f mpd_{$interface}.conf -p {$g['varrun_path']}/{$ppp['type']}_{$interface}.pid -s ppp {$ppp['type']}client");
1604

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

    
1613
	return 1;
1614
}
1615

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

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

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

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

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

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

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

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

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

    
1685
	if($config['virtualip']['vip'])
1686
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1687
	else
1688
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1689
	
1690
	if($g['debug'])
1691
		$cmdchain->setdebug(); // optional for verbose logging
1692

    
1693
	$cmdchain->execute();
1694
	$cmdchain->clear();
1695

    
1696
	if ($g['booting']) {
1697
		unmute_kernel_msgs();
1698
		echo "done.\n";
1699
	}
1700
}
1701

    
1702
function interface_proxyarp_configure($interface = "") {
1703
	global $config, $g;
1704
	if(isset($config['system']['developerspew'])) {
1705
		$mt = microtime();
1706
		echo "interface_proxyarp_configure() being called $mt\n";
1707
	}
1708

    
1709
	/* kill any running choparp */
1710
	if (empty($interface))
1711
		killbyname("choparp");
1712
	else {
1713
		$vipif = get_real_interface($interface);
1714
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1715
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1716
	}
1717

    
1718
	$paa = array();
1719
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1720

    
1721
		/* group by interface */
1722
		foreach ($config['virtualip']['vip'] as $vipent) {
1723
			if ($vipent['mode'] === "proxyarp") {
1724
				if ($vipent['interface'])
1725
					$proxyif = $vipent['interface'];
1726
				else
1727
					$proxyif = "wan";
1728
				
1729
				if (!empty($interface) && $interface != $proxyif)
1730
					continue;
1731

    
1732
				if (!is_array($paa[$proxyif]))
1733
					$paa[$proxyif] = array();
1734

    
1735
				$paa[$proxyif][] = $vipent;
1736
			}
1737
		}
1738
	}
1739

    
1740
	if (!empty($interface)) {
1741
		if (is_array($paa[$interface])) {
1742
			$paaifip = get_interface_ip($interface);
1743
                        if (!is_ipaddr($paaifip))
1744
                                return;
1745
                        $args = get_real_interface($interface) . " auto";
1746
                        foreach ($paa[$interface] as $paent) {
1747
                                if (isset($paent['subnet']))
1748
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1749
                                else if (isset($paent['range']))
1750
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1751
                        }
1752
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1753
		}
1754
	} else if (count($paa) > 0) {
1755
		foreach ($paa as $paif => $paents)  {
1756
			$paaifip = get_interface_ip($paif);
1757
			if (!is_ipaddr($paaifip))
1758
				continue;
1759
			$args = get_real_interface($paif) . " auto";
1760
			foreach ($paents as $paent) {
1761
				if (isset($paent['subnet']))
1762
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1763
				else if (isset($paent['range']))
1764
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1765
			}
1766
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1767
		}
1768
	}
1769
}
1770

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

    
1815
function interface_ipalias_configure(&$vip) {
1816

    
1817
	if ($vip['mode'] == "ipalias") {
1818
		$if = get_real_interface($vip['interface']);
1819
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1820
	}
1821
}
1822

    
1823
function interface_reload_carps($cif) {
1824
	global $config;
1825

    
1826
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1827
	if (empty($carpifs))
1828
		return;
1829

    
1830
	$carps = explode(" ", $carpifs);
1831
	if(is_array($config['virtualip']['vip'])) {
1832
		$viparr = &$config['virtualip']['vip'];
1833
		foreach ($viparr as $vip) {
1834
			if (in_array($vip['carpif'], $carps)) {
1835
				switch ($vip['mode']) {
1836
				case "carp":
1837
					interface_vip_bring_down($vip);
1838
					sleep(1);
1839
					interface_carp_configure($vip);
1840
					break;
1841
				case "carpdev-dhcp":
1842
					interface_vip_bring_down($vip);
1843
					sleep(1);
1844
					interface_carpdev_configure($vip);
1845
					break;
1846
				case "ipalias":
1847
					interface_vip_bring_down($vip);
1848
					sleep(1);
1849
					interface_ipalias_configure($vip);
1850
					break;
1851
				}
1852
			}
1853
		}
1854
	}
1855
}
1856

    
1857
function interface_carp_configure(&$vip) {
1858
	global $config, $g;
1859
	if(isset($config['system']['developerspew'])) {
1860
		$mt = microtime();
1861
		echo "interface_carp_configure() being called $mt\n";
1862
	}
1863

    
1864
	if ($vip['mode'] != "carp")
1865
		return;
1866

    
1867
	$vip_password = $vip['password'];
1868
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1869
	if ($vip['password'] != "")
1870
		$password = " pass {$vip_password}";
1871

    
1872
	// set the vip interface to the vhid
1873
	$vipif = "vip{$vip['vhid']}";
1874

    
1875
	/*
1876
	 * ensure the interface containing the VIP really exists
1877
 	 * prevents a panic if the interface is missing or invalid
1878
	 */
1879
	$realif = get_real_interface($vip['interface']);
1880
	if (!does_interface_exist($realif)) {
1881
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1882
		return;
1883
	}
1884

    
1885
	/* Ensure CARP IP really exists prior to loading up. */
1886
	$ww_subnet_ip = find_interface_ip($realif);
1887
	$ww_subnet_bits = find_interface_subnet($realif);
1888
	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'])) {
1889
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1890
		return;
1891
	}
1892

    
1893
	/* create the carp interface and setup */
1894
	if (does_interface_exist($vipif)) {
1895
		pfSense_interface_flags($vipif, -IFF_UP);
1896
	} else {
1897
		$carpif = pfSense_interface_create("carp");
1898
		pfSense_interface_rename($carpif, $vipif);
1899
		pfSense_ngctl_name("{$carpif}:", $vipif);
1900
	}
1901

    
1902
	/* invalidate interface cache */
1903
	get_interface_arr(true);
1904

    
1905
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1906
	$advbase = "";
1907
	if (!empty($vip['advbase']))
1908
		$advbase = "advbase {$vip['advbase']}";
1909
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1910

    
1911
	interfaces_bring_up($vipif);
1912
	
1913
	return $vipif;
1914
}
1915

    
1916
function interface_carpdev_configure(&$vip) {
1917
	global $g;
1918

    
1919
	if ($vip['mode'] != "carpdev-dhcp")
1920
		return;
1921

    
1922
	$vip_password = $vip['password'];
1923
	$vip_password = str_replace(" ", "", $vip_password);
1924
	if($vip['password'] != "")
1925
		$password = " pass \"" . $vip_password . "\"";
1926

    
1927
	if (empty($vip['interface']))
1928
		return;
1929

    
1930
	$vipif = "vip" . $vip['vhid'];
1931
	$realif = get_real_interface($vip['interface']);
1932
	interfaces_bring_up($realif);
1933
	/*
1934
	 * ensure the interface containing the VIP really exists
1935
	 * prevents a panic if the interface is missing or invalid
1936
	 */
1937
	if (!does_interface_exist($realif)) {
1938
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1939
		return;
1940
	}
1941

    
1942
	if (does_interface_exist($vipif)) {
1943
		interface_bring_down($vipif);
1944
	} else {
1945
		$carpdevif = exec("/sbin/ifconfig carp create");
1946
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1947
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1948
	}
1949

    
1950
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1951
	interfaces_bring_up($vipif);
1952

    
1953
	/*
1954
	 * XXX: BIG HACK but carpdev needs ip services active
1955
	 *      before even starting something as dhclient.
1956
	 *      I do not know if this is a feature or a bug
1957
	 *      but better than track it make it work ;) .
1958
	 */
1959
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1960
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1961

    
1962
	/* generate dhclient_wan.conf */
1963
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1964
	if ($fd) {
1965
		$dhclientconf = "";
1966

    
1967
		$dhclientconf .= <<<EOD
1968
interface "{$vipif}" {
1969
timeout 60;
1970
retry 1;
1971
select-timeout 0;
1972
initial-interval 1;
1973
script "/sbin/dhclient-script";
1974
}
1975

    
1976
EOD;
1977

    
1978
		fwrite($fd, $dhclientconf);
1979
		fclose($fd);
1980

    
1981
		/* fire up dhclient */
1982
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1983
	} else {
1984
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1985
		mwexec("/sbin/dhclient -b {$vipif}");
1986
	}
1987

    
1988
	return $vipif;
1989
}
1990

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

    
2032
	if($needs_clone == true) {
2033
		/* remove previous instance if it exists */
2034
		if(does_interface_exist($realif))
2035
			pfSense_interface_destroy($realif);
2036

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

    
2055
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2056
	global $config, $g;
2057

    
2058
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2059
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2060
	                         'regdomain', 'regcountry', 'reglocation');
2061

    
2062
	if(!is_interface_wireless($ifcfg['if']))
2063
		return;
2064

    
2065
	$baseif = interface_get_wireless_base($ifcfg['if']);
2066

    
2067
	// Sync shared settings for assigned clones
2068
	$iflist = get_configured_interface_list(false, true);
2069
	foreach ($iflist as $if) {
2070
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2071
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2072
				foreach ($shared_settings as $setting) {
2073
					if ($sync_changes) {
2074
						if (isset($ifcfg['wireless'][$setting]))
2075
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2076
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2077
							unset($config['interfaces'][$if]['wireless'][$setting]);
2078
					} else {
2079
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2080
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2081
						else if (isset($ifcfg['wireless'][$setting]))
2082
							unset($ifcfg['wireless'][$setting]);
2083
					}
2084
				}
2085
				if (!$sync_changes)
2086
					break;
2087
			}
2088
		}
2089
	}
2090

    
2091
	// Read or write settings at shared area
2092
	if (isset($config['wireless']['interfaces'][$baseif])) {
2093
		foreach ($shared_settings as $setting) {
2094
			if ($sync_changes) {
2095
				if (isset($ifcfg['wireless'][$setting]))
2096
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2097
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2098
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2099
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2100
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2101
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2102
				else if (isset($ifcfg['wireless'][$setting]))
2103
					unset($ifcfg['wireless'][$setting]);
2104
			}
2105
		}
2106
	}
2107

    
2108
	// Sync the mode on the clone creation page with the configured mode on the interface
2109
	if (interface_is_wireless_clone($ifcfg['if'])) {
2110
		foreach ($config['wireless']['clone'] as &$clone) {
2111
			if ($clone['cloneif'] == $ifcfg['if']) {
2112
				if ($sync_changes) {
2113
					$clone['mode'] = $ifcfg['wireless']['mode'];
2114
				} else {
2115
					$ifcfg['wireless']['mode'] = $clone['mode'];
2116
				}
2117
				break;
2118
			}
2119
		}
2120
		unset($clone);
2121
	}
2122
}
2123

    
2124
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2125
	global $config, $g;
2126

    
2127
	/*    open up a shell script that will be used to output the commands.
2128
	 *    since wireless is changing a lot, these series of commands are fragile
2129
     *    and will sometimes need to be verified by a operator by executing the command
2130
     *    and returning the output of the command to the developers for inspection.  please
2131
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2132
	 */
2133

    
2134
	// Remove script file
2135
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2136

    
2137
	// Clone wireless nic if needed.
2138
	interface_wireless_clone($if, $wl);
2139

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

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

    
2147
	/* set values for /path/program */
2148
	$hostapd = "/usr/sbin/hostapd";
2149
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2150
	$ifconfig = "/sbin/ifconfig";
2151
	$sysctl = "/sbin/sysctl";
2152
	$killall = "/usr/bin/killall";
2153

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

    
2156
	$wlcmd = array();
2157
	$wl_sysctl = array();
2158
	/* Make sure it's up */
2159
	$wlcmd[] = "up";
2160
	/* Set a/b/g standard */
2161
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2162
	$wlcmd[] = "mode " . escapeshellarg($standard);
2163

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

    
2169
	/* Set ssid */
2170
	if($wlcfg['ssid'])
2171
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2172

    
2173
	/* Set 802.11g protection mode */
2174
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2175

    
2176
	/* set wireless channel value */
2177
	if(isset($wlcfg['channel'])) {
2178
		if($wlcfg['channel'] == "0") {
2179
			$wlcmd[] = "channel any";
2180
		} else {
2181
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2182
		}
2183
	}
2184

    
2185
	/* Set antenna diversity value */
2186
	if(isset($wlcfg['diversity']))
2187
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2188

    
2189
	/* Set txantenna value */
2190
	if(isset($wlcfg['txantenna']))
2191
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2192

    
2193
	/* Set rxantenna value */
2194
	if(isset($wlcfg['rxantenna']))
2195
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2196

    
2197
	/* set Distance value */
2198
	if($wlcfg['distance'])
2199
		$distance = escapeshellarg($wlcfg['distance']);
2200

    
2201
	/* Set wireless hostap mode */
2202
	if ($wlcfg['mode'] == "hostap") {
2203
		$wlcmd[] = "mediaopt hostap";
2204
	} else {
2205
		$wlcmd[] = "-mediaopt hostap";
2206
	}
2207

    
2208
	/* Set wireless adhoc mode */
2209
	if ($wlcfg['mode'] == "adhoc") {
2210
		$wlcmd[] = "mediaopt adhoc";
2211
	} else {
2212
		$wlcmd[] = "-mediaopt adhoc";
2213
	}
2214

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

    
2217
	/* handle hide ssid option */
2218
	if(isset($wlcfg['hidessid']['enable'])) {
2219
		$wlcmd[] = "hidessid";
2220
	} else {
2221
		$wlcmd[] = "-hidessid";
2222
	}
2223

    
2224
	/* handle pureg (802.11g) only option */
2225
	if(isset($wlcfg['pureg']['enable'])) {
2226
		$wlcmd[] = "mode 11g pureg";
2227
	} else {
2228
		$wlcmd[] = "-pureg";
2229
	}
2230

    
2231
	/* handle puren (802.11n) only option */
2232
	if(isset($wlcfg['puren']['enable'])) {
2233
		$wlcmd[] = "puren";
2234
	} else {
2235
		$wlcmd[] = "-puren";
2236
	}
2237

    
2238
	/* enable apbridge option */
2239
	if(isset($wlcfg['apbridge']['enable'])) {
2240
		$wlcmd[] = "apbridge";
2241
	} else {
2242
		$wlcmd[] = "-apbridge";
2243
	}
2244

    
2245
	/* handle turbo option */
2246
	if(isset($wlcfg['turbo']['enable'])) {
2247
		$wlcmd[] = "mediaopt turbo";
2248
	} else {
2249
		$wlcmd[] = "-mediaopt turbo";
2250
	}
2251

    
2252
	/* handle txpower setting */
2253
	/* if($wlcfg['txpower'] <> "")
2254
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2255
	*/
2256
	/* handle wme option */
2257
	if(isset($wlcfg['wme']['enable'])) {
2258
		$wlcmd[] = "wme";
2259
	} else {
2260
		$wlcmd[] = "-wme";
2261
	}
2262

    
2263
	/* set up wep if enabled */
2264
	$wepset = "";
2265
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2266
		switch($wlcfg['wpa']['auth_algs']) {
2267
			case "1":
2268
				$wepset .= "authmode open wepmode on ";
2269
				break;
2270
			case "2":
2271
				$wepset .= "authmode shared wepmode on ";
2272
				break;
2273
			case "3":
2274
				$wepset .= "authmode mixed wepmode on ";
2275
		}
2276
		$i = 1;
2277
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2278
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2279
			if (isset($wepkey['txkey'])) {
2280
				$wlcmd[] = "weptxkey {$i} ";
2281
			}
2282
			$i++;
2283
		}
2284
		$wlcmd[] = $wepset;
2285
	} else {
2286
		$wlcmd[] = "authmode open wepmode off ";
2287
	}
2288

    
2289
	mwexec(kill_hostapd("{$if}"));
2290
	mwexec(kill_wpasupplicant("{$if}"));
2291

    
2292
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2293
	conf_mount_rw();
2294

    
2295
	switch ($wlcfg['mode']) {
2296
		case 'bss':
2297
			if (isset($wlcfg['wpa']['enable'])) {
2298
				$wpa .= <<<EOD
2299
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2300
ctrl_interface_group=0
2301
ap_scan=1
2302
#fast_reauth=1
2303
network={
2304
ssid="{$wlcfg['ssid']}"
2305
scan_ssid=1
2306
priority=5
2307
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2308
psk="{$wlcfg['wpa']['passphrase']}"
2309
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2310
group={$wlcfg['wpa']['wpa_pairwise']}
2311
}
2312
EOD;
2313

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

    
2349
EOD;
2350

    
2351
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2352
	$wpa .= <<<EOD
2353
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2354
rsn_preauth=1
2355
rsn_preauth_interfaces={$if}
2356

    
2357
EOD;
2358

    
2359
}
2360
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2361
					$auth_server_port = "1812";
2362
					if($wlcfg['auth_server_port']) 
2363
						$auth_server_port = $wlcfg['auth_server_port'];
2364
					$wpa .= <<<EOD
2365

    
2366
ieee8021x=1
2367
auth_server_addr={$wlcfg['auth_server_addr']}
2368
auth_server_port={$auth_server_port}
2369
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2370

    
2371
EOD;
2372
				} else {
2373
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2374
				}
2375

    
2376
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2377
				fwrite($fd, "{$wpa}");
2378
				fclose($fd);
2379

    
2380
			}
2381
			break;
2382
	}
2383

    
2384
	/*
2385
	 *    all variables are set, lets start up everything
2386
	 */
2387

    
2388
	$baseif = interface_get_wireless_base($if);
2389
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2390
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2391

    
2392
	/* set sysctls for the wireless interface */
2393
	if (!empty($wl_sysctl)) {
2394
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2395
		foreach ($wl_sysctl as $wl_sysctl_line) {
2396
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2397
		}
2398
	}
2399

    
2400
	/* set ack timers according to users preference (if he/she has any) */
2401
	if($distance) {
2402
		fwrite($fd_set, "# Enable ATH distance settings\n");
2403
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2404
	}
2405

    
2406
	if (isset($wlcfg['wpa']['enable'])) {
2407
		if ($wlcfg['mode'] == "bss") {
2408
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2409
		}
2410
		if ($wlcfg['mode'] == "hostap") {
2411
			/* add line to script to restore old mac to make hostapd happy */
2412
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2413
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2414
				if (is_macaddr($if_oldmac))
2415
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2416
						" link " . escapeshellarg($if_oldmac) . "\n");
2417
			}
2418

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

    
2421
			/* add line to script to restore spoofed mac after running hostapd */
2422
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2423
				if ($wl['spoofmac'])
2424
					$if_curmac = $wl['spoofmac'];
2425
				else
2426
					$if_curmac = get_interface_mac($if);
2427
				if (is_macaddr($if_curmac))
2428
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2429
						" link " . escapeshellarg($if_curmac) . "\n");
2430
			}
2431
		}
2432
	}
2433

    
2434
	fclose($fd_set);
2435
	conf_mount_ro();
2436

    
2437
	/* Making sure regulatory settings have actually changed
2438
	 * before applying, because changing them requires bringing
2439
	 * down all wireless networks on the interface. */
2440
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2441
	$ifconfig_str = implode($output);
2442
	unset($output);
2443
	$reg_changing = false;
2444

    
2445
	/* special case for the debug country code */
2446
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2447
		$reg_changing = true;
2448
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2449
		$reg_changing = true;
2450
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2451
		$reg_changing = true;
2452
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2453
		$reg_changing = true;
2454
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2455
		$reg_changing = true;
2456

    
2457
	if ($reg_changing) {
2458
		/* set regulatory domain */
2459
		if($wlcfg['regdomain'])
2460
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2461

    
2462
		/* set country */
2463
		if($wlcfg['regcountry'])
2464
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2465

    
2466
		/* set location */
2467
		if($wlcfg['reglocation'])
2468
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2469

    
2470
		$wlregcmd_args = implode(" ", $wlregcmd);
2471

    
2472
		/* build a complete list of the wireless clones for this interface */
2473
		$clone_list = array();
2474
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2475
			$clone_list[] = interface_get_wireless_clone($baseif);
2476
		if (is_array($config['wireless']['clone'])) {
2477
			foreach ($config['wireless']['clone'] as $clone) {
2478
				if ($clone['if'] == $baseif)
2479
					$clone_list[] = $clone['cloneif'];
2480
			}
2481
		}
2482

    
2483
		/* find which clones are up and bring them down */
2484
		$clones_up = array();
2485
		foreach ($clone_list as $clone_if) {
2486
			$clone_status = pfSense_get_interface_addresses($clone_if);
2487
			if ($clone_status['status'] == 'up') {
2488
				$clones_up[] = $clone_if;
2489
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2490
			}
2491
		}
2492

    
2493
		/* apply the regulatory settings */
2494
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2495

    
2496
		/* bring the clones back up that were previously up */
2497
		foreach ($clones_up as $clone_if) {
2498
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2499

    
2500
			/*
2501
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2502
			 * is in infrastructure mode, and WPA is enabled.
2503
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2504
			 */
2505
			if ($clone_if != $if) {
2506
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2507
				if ( !empty($friendly_if)
2508
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2509
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2510
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2511
				}
2512
			}
2513
		}
2514
	}
2515

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

    
2520
	/* configure wireless */
2521
	$wlcmd_args = implode(" ", $wlcmd);
2522
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2523

    
2524
	
2525
	sleep(1);
2526
	/* execute hostapd and wpa_supplicant if required in shell */
2527
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2528

    
2529
	return 0;
2530

    
2531
}
2532

    
2533
function kill_hostapd($interface) {
2534
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2535
}
2536

    
2537
function kill_wpasupplicant($interface) {
2538
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2539
}
2540

    
2541
function find_dhclient_process($interface) {
2542
	if ($interface)
2543
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2544
	else
2545
		$pid = 0;
2546

    
2547
	return intval($pid);
2548
}
2549

    
2550
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2551
	global $config, $g;
2552
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2553

    
2554
	$wancfg = $config['interfaces'][$interface];
2555

    
2556
	$realif = get_real_interface($interface);
2557
	$realhwif_array = get_parent_interface($interface);
2558
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2559
	$realhwif = $realhwif_array[0];
2560

    
2561
			
2562
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2563
		/* remove all IPv4 addresses */
2564
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2565

    
2566
		switch ($wancfg['ipaddr']) {
2567
			case 'pppoe':
2568
			case 'l2tp':
2569
			case 'pptp':
2570
			case 'ppp':
2571
				break;
2572
			default:
2573
				interface_bring_down($interface);
2574
				break;
2575
		}
2576
	}
2577

    
2578
	/* wireless configuration? */
2579
	if (is_array($wancfg['wireless']))
2580
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2581

    
2582
	if ($wancfg['spoofmac']) {
2583
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2584
			" link " . escapeshellarg($wancfg['spoofmac']));
2585

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

    
2613
	/* media */
2614
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2615
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2616
		if ($wancfg['media'])
2617
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2618
		if ($wancfg['mediaopt'])
2619
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2620
		mwexec($cmd);
2621
	}
2622
	if (!empty($wancfg['mtu']))
2623
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2624
	else {
2625
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2626
		if ($mtu != get_interface_mtu($realhwif))
2627
			pfSense_interface_mtu($realhwif, $mtu);
2628
	}
2629

    
2630
	$options = pfSense_get_interface_addresses($realhwif);
2631
	if (is_array($options) && isset($options['caps']['polling'])) {
2632
		if (isset($config['system']['polling']))
2633
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2634
		else
2635
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2636
	}
2637

    
2638
	/* skip vlans for checksumming and polling */
2639
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2640
		$flags = 0;
2641
		if(isset($config['system']['disablechecksumoffloading'])) {
2642
			if (isset($options['encaps']['txcsum']))
2643
				$flags |= IFCAP_TXCSUM;
2644
			if (isset($options['encaps']['rxcsum']))
2645
				$flags |= IFCAP_RXCSUM;
2646
        	} else {
2647
 			if (!isset($options['caps']['txcsum']))
2648
				$flags |= IFCAP_TXCSUM;
2649
			if (!isset($options['caps']['rxcsum']))
2650
				$flags |= IFCAP_RXCSUM;
2651
        	}
2652

    
2653
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2654
                	if (isset($options['encaps']['tso4']))
2655
				$flags |= IFCAP_TSO;
2656
                	if (isset($options['encaps']['tso6']))
2657
				$flags |= IFCAP_TSO;
2658
        	} else {
2659
                	if (!isset($options['caps']['tso4']))
2660
				$flags |= IFCAP_TSO;
2661
                	if (!isset($options['caps']['tso6']))
2662
				$flags |= IFCAP_TSO;
2663
        	}
2664

    
2665
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2666
                	if (isset($options['encaps']['lro']))
2667
				$flags |= IFCAP_LRO;
2668
        	} else {
2669
                	if (!isset($options['caps']['lro']))
2670
				$flags |= IFCAP_LRO;
2671
        	}
2672

    
2673
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2674
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2675
			$flags |= IFCAP_POLLING;
2676
		}
2677
               	pfSense_interface_capabilities($realhwif, -$flags);
2678
	}
2679

    
2680
	/* invalidate interface/ip/sn cache */
2681
	get_interface_arr(true);
2682
	unset($interface_ip_arr_cache[$realif]);
2683
	unset($interface_sn_arr_cache[$realif]);
2684

    
2685
	switch ($wancfg['ipaddr']) {
2686
		case 'carpdev-dhcp':
2687
			interface_carpdev_dhcp_configure($interface);
2688
			break;
2689
		case 'dhcp':
2690
			interface_dhcp_configure($interface);
2691
			break;
2692
		case 'pppoe':
2693
		case 'l2tp':
2694
		case 'pptp':
2695
		case 'ppp':
2696
			interface_ppps_configure($interface);
2697
			break;
2698
		default:
2699
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2700
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2701
			} else if (substr($realif, 0, 3) == "gre") {
2702
				if (is_array($config['gres']['gre'])) {
2703
					foreach ($config['gres']['gre'] as $gre)
2704
						if ($gre['greif'] == $realif)
2705
							interface_gre_configure($gre);
2706
				}
2707
			} else if (substr($realif, 0, 3) == "gif") {
2708
				 if (is_array($config['gifs']['gif'])) {
2709
					foreach ($config['gifs']['gif'] as $gif)
2710
						if($gif['gifif'] == $realif)
2711
							interface_gif_configure($gif);
2712
				}
2713
			} else if (substr($realif, 0, 4) == "ovpn") {
2714
				/* XXX: Should be done anything?! */
2715
			}
2716
			break;
2717
	}
2718

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

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

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

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

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

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

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

    
2752
		if ($reloadall == true) {
2753

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

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

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

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

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

    
2771
	return 0;
2772
}
2773

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

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

    
2785
	return 0;
2786
}
2787

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

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

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

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

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

    
2826
EOD;
2827

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

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

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

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

    
2851
	return 0;
2852
}
2853

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

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

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

    
2863
	return;
2864
}
2865

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

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

    
2878
	return;
2879
}
2880

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

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

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

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

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

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

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

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

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

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

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

    
2987
        return $ifdesc;
2988
}
2989

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

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

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

    
3000
        return $interface;
3001
}
3002

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

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

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

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

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

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

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

    
3090
	$wanif = NULL;
3091

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

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

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

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

    
3166
    return $wanif;
3167
}
3168

    
3169
/* Guess the physical interface by providing a IP address */
3170
function guess_interface_from_ip($ipaddress) {
3171
	if(! is_ipaddr($ipaddress)) {
3172
		return false;
3173
	}
3174
	/* create a route table we can search */
3175
	exec("netstat -rnWf inet", $output, $ret);
3176
	foreach($output as $line) {
3177
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3178
			$fields = preg_split("/[ ]+/", $line);
3179
			if(ip_in_subnet($ipaddress, $fields[0])) {
3180
				return $fields[6];
3181
			}
3182
		}
3183
	}
3184
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3185
	if(empty($ret)) {
3186
        	return false;
3187
	}
3188
	return $ret;
3189
}
3190

    
3191
/*
3192
 * find_ip_interface($ip): return the interface where an ip is defined
3193
 */
3194
function find_ip_interface($ip)
3195
{
3196
        /* if list */
3197
        $ifdescrs = get_configured_interface_list();
3198

    
3199
        foreach ($ifdescrs as $ifdescr => $ifname) {
3200
		if ($ip == get_interface_ip($ifname)) {
3201
                	$int = get_real_interface($ifname);
3202
			return $int;
3203
		}
3204
        }
3205
        return false;
3206
}
3207

    
3208
/*
3209
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3210
 */
3211
function find_number_of_created_carp_interfaces() {
3212
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3213
}
3214

    
3215
function get_all_carp_interfaces() {
3216
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3217
	$ints = explode(" ", $ints);
3218
	return $ints;
3219
}
3220

    
3221
/*
3222
 * find_carp_interface($ip): return the carp interface where an ip is defined
3223
 */
3224
function find_carp_interface($ip) {
3225
	global $config;
3226
	if (is_array($config['virtualip']['vip'])) {
3227
		foreach ($config['virtualip']['vip'] as $vip) {
3228
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3229
				$carp_ip = get_interface_ip($vip['interface']);
3230
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
3231
				if ($if)
3232
					return $if;
3233
			}
3234
		}
3235
	}
3236
}
3237

    
3238
function link_carp_interface_to_parent($interface) {
3239
        global $config;
3240

    
3241
        if ($interface == "")
3242
                return;
3243

    
3244
        $carp_ip = get_interface_ip($interface);
3245
        if (!is_ipaddr($carp_ip))
3246
                return;
3247

    
3248
        /* if list */
3249
        $ifdescrs = get_configured_interface_list();
3250
        foreach ($ifdescrs as $ifdescr => $ifname) {
3251
                $interfaceip = get_interface_ip($ifname);
3252
                $subnet_bits = get_interface_subnet($ifname);
3253
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3254
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3255
                        return $ifname;
3256
        }
3257

    
3258
        return "";
3259
}
3260

    
3261
/****f* interfaces/link_ip_to_carp_interface
3262
 * NAME
3263
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3264
 * INPUTS
3265
 *   $ip
3266
 * RESULT
3267
 *   $carp_ints
3268
 ******/
3269
function link_ip_to_carp_interface($ip) {
3270
        global $config;
3271

    
3272
        if (!is_ipaddr($ip))
3273
                return;
3274

    
3275
        $carp_ints = "";
3276
        if (is_array($config['virtualip']['vip'])) {
3277
		$first = 0;
3278
		$carp_int = array();
3279
                foreach ($config['virtualip']['vip'] as $vip) {
3280
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3281
                                $carp_ip = $vip['subnet'];
3282
                                $carp_sn = $vip['subnet_bits'];
3283
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3284
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3285
					$carp_int[] = "vip{$vip['vhid']}";
3286
                        }
3287
                }
3288
		if (!empty($carp_int))
3289
			$carp_ints = implode(" ", array_unique($carp_int));
3290
        }
3291

    
3292
        return $carp_ints;
3293
}
3294

    
3295
function link_interface_to_vlans($int, $action = "") {
3296
	global $config;
3297

    
3298
	if (empty($int))
3299
		return;
3300

    
3301
	if (is_array($config['vlans']['vlan'])) {
3302
                foreach ($config['vlans']['vlan'] as $vlan) {
3303
			if ($int == $vlan['if']) {
3304
				if ($action == "update") {
3305
					interfaces_bring_up($int);
3306
				} else if ($action == "")
3307
					return $vlan;
3308
			}
3309
		}
3310
	}
3311
}
3312

    
3313
function link_interface_to_vips($int, $action = "") {
3314
        global $config;
3315

    
3316
        if (is_array($config['virtualip']['vip'])) {
3317
		foreach ($config['virtualip']['vip'] as $vip) {
3318
			if ($int == $vip['interface']) {
3319
				if ($action == "update") {
3320
					if ($vip['mode'] == "carp" && !does_interface_exist("vip{$vip['vhid']}"))
3321
						interfaces_vips_configure($int);
3322
					else {
3323
						interface_vip_bring_down($vip);
3324
						interfaces_vips_configure($int);
3325
					}
3326
				} else
3327
					return $vip;
3328
			}
3329
		}
3330
	}
3331
}
3332

    
3333
/****f* interfaces/link_interface_to_bridge
3334
 * NAME
3335
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3336
 * INPUTS
3337
 *   $ip
3338
 * RESULT
3339
 *   bridge[0-99]
3340
 ******/
3341
function link_interface_to_bridge($int) {
3342
        global $config;
3343

    
3344
        if (is_array($config['bridges']['bridged'])) {
3345
                foreach ($config['bridges']['bridged'] as $bridge) {
3346
			if (in_array($int, explode(',', $bridge['members'])))
3347
                                return "{$bridge['bridgeif']}";
3348
		}
3349
	}
3350
}
3351

    
3352
function link_interface_to_group($int) {
3353
        global $config;
3354

    
3355
	$result = array();
3356

    
3357
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3358
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3359
			if (in_array($int, explode(" ", $group['members'])))
3360
				$result[$group['ifname']] = $int;
3361
		}
3362
	}
3363

    
3364
	return $result;
3365
}
3366

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

    
3370
	$result = array();
3371

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

    
3378
	return $result;
3379
}
3380

    
3381
function link_interface_to_gif($interface) {
3382
        global $config;
3383

    
3384
	$result = array();
3385

    
3386
        if (is_array($config['gifs']['gif'])) {
3387
                foreach ($config['gifs']['gif'] as $gif)
3388
                        if($gif['if'] == $interface)
3389
                                $result[] = $gif;
3390
	}
3391

    
3392
	return $result;
3393
}
3394

    
3395
/*
3396
 * find_interface_ip($interface): return the interface ip (first found)
3397
 */
3398
function find_interface_ip($interface, $flush = false)
3399
{
3400
	global $interface_ip_arr_cache;
3401
	global $interface_sn_arr_cache;
3402

    
3403
	$interface = str_replace("\n", "", $interface);
3404
	
3405
	if (!does_interface_exist($interface))
3406
		return;
3407

    
3408
	/* Setup IP cache */
3409
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3410
		$ifinfo = pfSense_get_interface_addresses($interface);
3411
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3412
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3413
	}
3414

    
3415
	return $interface_ip_arr_cache[$interface];
3416
}
3417

    
3418
function find_interface_subnet($interface, $flush = false)
3419
{
3420
	global $interface_sn_arr_cache;
3421
	global $interface_ip_arr_cache;
3422

    
3423
	$interface = str_replace("\n", "", $interface);
3424
	if (does_interface_exist($interface) == false)
3425
		return;
3426

    
3427
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3428
		$ifinfo = pfSense_get_interface_addresses($interface);
3429
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3430
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3431
        }
3432

    
3433
	return $interface_sn_arr_cache[$interface];
3434
}
3435

    
3436
function ip_in_interface_alias_subnet($interface, $ipalias) {
3437
	global $config;
3438

    
3439
	if (empty($interface) || !is_ipaddr($ipalias))
3440
		return false;
3441
	if (is_array($config['virtualip']['vip'])) {
3442
                foreach ($config['virtualip']['vip'] as $vip) {
3443
                        switch ($vip['mode']) {
3444
                        case "ipalias":
3445
                                if ($vip['interface'] <> $interface)
3446
                                        break;
3447
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3448
					return true;
3449
                                break;
3450
                        }
3451
                }
3452
	}
3453

    
3454
	return false;
3455
}
3456

    
3457
function get_interface_ip($interface = "wan")
3458
{
3459
	$realif = get_real_interface($interface);
3460
	if (!$realif) {
3461
		if (preg_match("/^carp/i", $interface))
3462
			$realif = $interface;
3463
		else if (preg_match("/^vip/i", $interface))
3464
			$realif = $interface;
3465
		else
3466
			return null;
3467
	}
3468

    
3469
	$curip = find_interface_ip($realif);
3470
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3471
		return $curip;
3472
	else
3473
		return null;
3474
}
3475

    
3476
function get_interface_subnet($interface = "wan")
3477
{
3478
	$realif = get_real_interface($interface);
3479
	if (!$realif) {
3480
                if (preg_match("/^carp/i", $interface))
3481
                        $realif = $interface;
3482
                else if (preg_match("/^vip/i", $interface))
3483
                        $realif = $interface;
3484
                else
3485
                        return null;
3486
        }
3487

    
3488
	$cursn = find_interface_subnet($realif);
3489
	if (!empty($cursn))
3490
		return $cursn;
3491

    
3492
	return null;
3493
}
3494

    
3495
/* return outside interfaces with a gateway */
3496
function get_interfaces_with_gateway() {
3497
	global $config;
3498

    
3499
	$ints = array();
3500

    
3501
	/* loop interfaces, check config for outbound */
3502
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3503
		switch ($ifname['ipaddr']) {
3504
			case "dhcp":
3505
			case "carpdev-dhcp":
3506
			case "ppp";
3507
			case "pppoe":
3508
			case "pptp":
3509
			case "l2tp":
3510
			case "ppp";
3511
				$ints[$ifdescr] = $ifdescr;
3512
			break;
3513
			default:
3514
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3515
				    !empty($ifname['gateway']))
3516
					$ints[$ifdescr] = $ifdescr;
3517
			break;
3518
		}
3519
	}
3520
	return $ints;
3521
}
3522

    
3523
/* return true if interface has a gateway */
3524
function interface_has_gateway($friendly) {
3525
	global $config;
3526

    
3527
	if (!empty($config['interfaces'][$friendly])) {
3528
		$ifname = &$config['interfaces'][$friendly];
3529
		switch ($ifname['ipaddr']) {
3530
			case "dhcp":
3531
			case "carpdev-dhcp":
3532
			case "pppoe":
3533
			case "pptp":
3534
			case "l2tp":
3535
			case "ppp";
3536
				return true;
3537
			break;
3538
			default:
3539
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3540
					return true;
3541
				if (!empty($ifname['gateway']))
3542
					return true;
3543
			break;
3544
		}
3545
	}
3546

    
3547
	return false;
3548
}
3549

    
3550
/****f* interfaces/is_altq_capable
3551
 * NAME
3552
 *   is_altq_capable - Test if interface is capable of using ALTQ
3553
 * INPUTS
3554
 *   $int            - string containing interface name
3555
 * RESULT
3556
 *   boolean         - true or false
3557
 ******/
3558

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

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

    
3574
        if (in_array($int_family[0], $capable))
3575
                return true;
3576
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3577
		return true;
3578
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3579
		return true;
3580
        else
3581
                return false;
3582
}
3583

    
3584
/****f* interfaces/is_interface_wireless
3585
 * NAME
3586
 *   is_interface_wireless - Returns if an interface is wireless
3587
 * RESULT
3588
 *   $tmp       - Returns if an interface is wireless
3589
 ******/
3590
function is_interface_wireless($interface) {
3591
        global $config, $g;
3592

    
3593
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3594
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3595
                if (preg_match($g['wireless_regex'], $interface)) {
3596
                        if (isset($config['interfaces'][$friendly]))
3597
                                $config['interfaces'][$friendly]['wireless'] = array();
3598
                        return true;
3599
                }
3600
                return false;
3601
        } else
3602
                return true;
3603
}
3604

    
3605
function get_wireless_modes($interface) {
3606
	/* return wireless modes and channels */
3607
	$wireless_modes = array();
3608

    
3609
	$cloned_interface = get_real_interface($interface);
3610

    
3611
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3612
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3613
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3614
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3615

    
3616
		$interface_channels = "";
3617
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3618
		$interface_channel_count = count($interface_channels);
3619

    
3620
		$c = 0;
3621
		while ($c < $interface_channel_count)
3622
		{
3623
			$channel_line = explode(",", $interface_channels["$c"]);
3624
			$wireless_mode = trim($channel_line[0]);
3625
			$wireless_channel = trim($channel_line[1]);
3626
			if(trim($wireless_mode) != "") {
3627
				/* if we only have 11g also set 11b channels */
3628
				if($wireless_mode == "11g") {
3629
					if(!isset($wireless_modes["11b"]))
3630
						$wireless_modes["11b"] = array();
3631
				} else if($wireless_mode == "11g ht") {
3632
					if(!isset($wireless_modes["11b"]))
3633
						$wireless_modes["11b"] = array();
3634
					if(!isset($wireless_modes["11g"]))
3635
						$wireless_modes["11g"] = array();
3636
					$wireless_mode = "11ng";
3637
				} else if($wireless_mode == "11a ht") {
3638
					if(!isset($wireless_modes["11a"]))
3639
						$wireless_modes["11a"] = array();
3640
					$wireless_mode = "11na";
3641
				}
3642
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3643
			}
3644
			$c++;
3645
		}
3646
	}
3647
	return($wireless_modes);
3648
}
3649

    
3650
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3651
function get_wireless_channel_info($interface) {
3652
	$wireless_channels = array();
3653

    
3654
	$cloned_interface = get_real_interface($interface);
3655

    
3656
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3657
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3658
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3659
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3660

    
3661
		$interface_channels = "";
3662
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3663

    
3664
		foreach ($interface_channels as $channel_line) {
3665
			$channel_line = explode(",", $channel_line);
3666
			if(!isset($wireless_channels[$channel_line[0]]))
3667
				$wireless_channels[$channel_line[0]] = $channel_line;
3668
		}
3669
	}
3670
	return($wireless_channels);
3671
}
3672

    
3673
/****f* interfaces/get_interface_mtu
3674
 * NAME
3675
 *   get_interface_mtu - Return the mtu of an interface
3676
 * RESULT
3677
 *   $tmp       - Returns the mtu of an interface
3678
 ******/
3679
function get_interface_mtu($interface) {
3680
        $mtu = pfSense_get_interface_addresses($interface);
3681
        return $mtu['mtu'];
3682
}
3683

    
3684
function get_interface_mac($interface) {
3685

    
3686
	$macinfo = pfSense_get_interface_addresses($interface);
3687
	return $macinfo["macaddr"];
3688
}
3689

    
3690
/****f* pfsense-utils/generate_random_mac_address
3691
 * NAME
3692
 *   generate_random_mac - generates a random mac address
3693
 * INPUTS
3694
 *   none
3695
 * RESULT
3696
 *   $mac - a random mac address
3697
 ******/
3698
function generate_random_mac_address() {
3699
        $mac = "02";
3700
        for($x=0; $x<5; $x++)
3701
                $mac .= ":" . dechex(rand(16, 255));
3702
        return $mac;
3703
}
3704

    
3705
/****f* interfaces/is_jumbo_capable
3706
 * NAME
3707
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3708
 * INPUTS
3709
 *   $int             - string containing interface name
3710
 * RESULT
3711
 *   boolean          - true or false
3712
 ******/
3713
function is_jumbo_capable($int) {
3714
        global $g;
3715

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

    
3718
        if (in_array($int_family[0], $g['vlan_long_frame']))
3719
                return true;
3720
        else
3721
                return false;
3722
}
3723

    
3724
function setup_pppoe_reset_file($pppif, $iface="") {
3725
	global $g;
3726
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3727

    
3728
	if(!empty($iface) && !empty($pppif)){
3729
		$cron_cmd = <<<EOD
3730
#!/bin/sh
3731
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3732
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3733

    
3734
EOD;
3735

    
3736
		file_put_contents($cron_file, $cron_cmd);
3737
		chmod($cron_file, 0700);
3738
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3739
	} else
3740
		unlink_if_exists($cron_file);
3741
}
3742

    
3743
function get_interface_default_mtu($type = "ethernet") {
3744
	switch ($type) {
3745
	case "gre":
3746
		return 1476;
3747
		break;
3748
	case "gif":
3749
		return 1280;
3750
		break;
3751
	case "tun":
3752
	case "vlan":
3753
	case "tap":
3754
	case "ethernet":
3755
	default:
3756
		return 1500;
3757
		break;
3758
	}
3759

    
3760
	/* Never reached */
3761
	return 1500;
3762
}
3763

    
3764
function get_vip_descr($ipaddress) {
3765
	global $config;
3766

    
3767
	foreach ($config['virtualip']['vip'] as $vip) {
3768
		if ($vip['subnet'] == $ipaddress) {
3769
			return ($vip['descr']);
3770
		}
3771
	}
3772
	return "";
3773
}
3774

    
3775
?>
(25-25/61)