Project

General

Profile

Download (108 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 = pfSense_interface_listget();
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
                        /* XXX: Maybe we should report any errors?! */
417
                        interface_bridge_configure($bridge, $checkmember);
418
                        $i++;
419
                }
420
        }
421
}
422

    
423
function interface_bridge_configure(&$bridge, $checkmember = 0) {
424
	global $config, $g;
425

    
426
	if (!is_array($bridge))
427
	        return -1;
428

    
429
	if (empty($bridge['members'])) {
430
		log_error("No members found on {$bridge['bridgeif']}");
431
		return -1;
432
	}
433

    
434
	$members = explode(',', $bridge['members']);
435
	if (!count($members))
436
		return -1;
437

    
438
	/* Calculate smaller mtu and enforce it */
439
	$smallermtu = 0;
440
	$commonrx = true;
441
	$commontx = true;
442
	$foundgif = false;
443
	foreach ($members as $member) {
444
		$realif = get_real_interface($member);
445
		$opts = pfSense_get_interface_addresses($realif);
446
		$mtu = $opts['mtu'];
447
		if (substr($realif, 0, 3) == "gif") {
448
			$foundgif = true;
449
			if ($checkmember == 1)
450
				return;
451
			if ($mtu <= 1500)
452
				continue;
453
		}
454
		if (!isset($opts['encaps']['txcsum']))
455
			$commontx = false;
456
		if (!isset($opts['encaps']['rxcsum']))
457
			$commonrx = false;
458
		if (!isset($opts['encaps']['tso4']))
459
			$commontso4 = false;
460
		if (!isset($opts['encaps']['tso6']))
461
			$commontso6 = false;
462
		if (!isset($opts['encaps']['lro']))
463
			$commonlro = false;
464
		if ($smallermtu == 0 && !empty($mtu))
465
			$smallermtu = $mtu;
466
		else if (!empty($mtu) && $mtu < $smallermtu)
467
			$smallermtu = $mtu;
468
	}
469
	if ($foundgif == false && $checkmember == 2)
470
		return;
471

    
472
	/* Just in case anything is not working well */
473
	if ($smallermtu == 0)
474
		$smallermtu = 1500; 
475

    
476
	$flags = 0;
477
	if ($commonrx === false)
478
		$flags |= IFCAP_RXCSUM;
479
	if ($commontx === false)
480
		$flags |= IFCAP_TXCSUM;
481
	if ($commontso4 === false)
482
		$flags |= IFCAP_TSO4;
483
	if ($commontso6 === false)
484
		$flags |= IFCAP_TSO6;
485
	if ($commonlro === false)
486
		$flags |= IFCAP_LRO;
487

    
488
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
489
		pfSense_interface_destroy($bridge['bridgeif']);
490
		pfSense_interface_create($bridge['bridgeif']);
491
		$bridgeif = $bridge['bridgeif'];
492
	} else
493
		$bridgeif = pfSense_interface_create("bridge");
494

    
495
	$checklist = get_configured_interface_list();
496

    
497
	/* Add interfaces to bridge */
498
	foreach ($members as $member) {
499
		if (!array_key_exists($member, $checklist))
500
			continue;
501
		$realif1 = get_real_interface($member);
502
		$realif =  escapeshellarg($realif1);
503
		if (!$realif) {
504
			log_error("realif not defined in interfaces bridge - up");
505
			continue;
506
		}
507
		/* make sure the parent interface is up */
508
		pfSense_interface_mtu($realif1, $smallermtu);
509
		pfSense_interface_capabilities($realif1, -$flags);
510
		interfaces_bring_up($realif1);
511
		pfSense_bridge_add_member($bridgeif, $realif1);
512
	}
513

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

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

    
614
	if($bridgeif)
615
		interfaces_bring_up($bridgeif);	
616
	else 
617
		log_error("bridgeif not defined -- could not bring interface up");
618

    
619
	return $bridgeif;
620
}
621

    
622
function interface_bridge_add_member($bridgeif, $interface) {
623

    
624
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
625
		return;
626

    
627
	$mtu = get_interface_mtu($bridgeif);
628
	$mtum = get_interface_mtu($interface);
629
	
630
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
631
		pfSense_interface_mtu($interface, $mtu);
632

    
633
	$options = pfSense_get_interface_addresses($bridgeif);
634
	$flags = 0;
635
	if (!isset($options['encaps']['txcsum']))
636
		$flags |= IFCAP_TXCSUM;
637

    
638
	if (!isset($options['encaps']['rxcsum']))
639
		$flags |= IFCAP_RXCSUM;
640

    
641
	pfSense_interface_capabilities($interface, -$flags);
642

    
643
	interfaces_bring_up($interface);
644
	pfSense_bridge_add_member($bridgeif, $interface);
645
}
646

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

    
666
function interface_lagg_configure(&$lagg) {
667
        global $config, $g;
668

    
669
        if (!is_array($lagg))
670
		return -1;
671

    
672
	$members = explode(',', $lagg['members']);
673
	if (!count($members))
674
		return -1;
675
	
676
	if ($g['booting'] || !(empty($lagg['laggif']))) {
677
		pfSense_interface_destroy($lagg['laggif']);
678
		pfSense_interface_create($lagg['laggif']);
679
                $laggif = $lagg['laggif'];
680
        } else
681
		$laggif = pfSense_interface_create("lagg");
682

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

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

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

    
720
	$checklist = get_interface_list();
721

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

    
734
	interfaces_bring_up($laggif);
735

    
736
	return $laggif;
737
}
738

    
739
function interfaces_gre_configure($checkparent = 0) {
740
        global $config;
741

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

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

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

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

    
766
	/* make sure the parent interface is up */
767
	interfaces_bring_up($realif);
768

    
769
	if ($g['booting'] || !(empty($gre['greif']))) {
770
		pfSense_interface_destroy($gre['greif']);
771
		pfSense_interface_create($gre['greif']);
772
		$greif = $gre['greif'];
773
	} else
774
		$greif = pfSense_interface_create("gre");
775

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

    
786
	if($greif)
787
		interfaces_bring_up($greif);
788
	else 
789
		log_error("Could not bring greif up -- variable not defined.");
790

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

    
795
	return $greif;
796
}
797

    
798
function interfaces_gif_configure($checkparent = 0) {
799
	global $config;
800

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

    
815
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
816
function interface_gif_configure(&$gif, $gifkey = "") {
817
	global $config, $g;
818

    
819
	if (!is_array($gif))
820
		return -1;
821

    
822
	$realif = get_real_interface($gif['if']);
823
	$realifip = get_interface_ip($gif['if']);
824

    
825
	/* make sure the parent interface is up */
826
	if($realif)
827
		interfaces_bring_up($realif);
828
	else 
829
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
830

    
831
	if ($g['booting'] || !(empty($gif['gifif']))) {
832
		pfSense_interface_destroy($gif['gifif']);
833
		pfSense_interface_create($gif['gifif']);
834
		$gifif = $gif['gifif'];
835
	} else
836
		$gifif = pfSense_interface_create("gif");
837

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

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

    
854
	return $gifif;
855
}
856

    
857
function interfaces_configure() {
858
	global $config, $g;
859

    
860
	/* Set up our loopback interface */
861
	interfaces_loopback_configure();
862

    
863
	/* set up LAGG virtual interfaces */
864
	interfaces_lagg_configure();
865

    
866
	/* set up VLAN virtual interfaces */
867
	interfaces_vlan_configure();
868

    
869
	interfaces_qinq_configure();
870

    
871
	$iflist = get_configured_interface_with_descr();
872
	$delayed_list = array();
873
	$bridge_list = array();
874
	
875
	/* This is needed to speedup interfaces on bootup. */
876
	$reload = false;
877
	if (!$g['booting'])
878
		$reload = true;
879

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

    
902
	/* create the unconfigured wireless clones */
903
	interfaces_create_wireless_clones();
904

    
905
	/*
906
	 * NOTE: The following function parameter consists of
907
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
908
	 *	2 - Do load gre/gif/bridge with parent/member as vip
909
	 */
910

    
911
	/* set up GRE virtual interfaces */
912
	interfaces_gre_configure(1);
913

    
914
	/* set up GIF virtual interfaces */
915
	interfaces_gif_configure(1);
916

    
917
	/* set up BRIDGe virtual interfaces */
918
	interfaces_bridge_configure(1);
919

    
920
	/* bring up vip interfaces */
921
	interfaces_vips_configure();
922

    
923
	/* set up GRE virtual interfaces */
924
	interfaces_gre_configure(2);
925

    
926
	/* set up GIF virtual interfaces */
927
	interfaces_gif_configure(2);
928

    
929
	foreach ($delayed_list as $if => $ifname) {
930
		if ($g['booting'])
931
			echo "Configuring {$ifname} interface...";
932
        	if ($g['debug'])
933
        		log_error("Configuring {$ifname}");
934

    
935
		interface_configure($if, $reload);
936

    
937
		if ($g['booting'])
938
			echo "done.\n";
939
	}
940

    
941
	/* set up BRIDGe virtual interfaces */
942
	interfaces_bridge_configure(2);
943

    
944
	foreach ($bridge_list as $if => $ifname) {
945
		if ($g['booting'])
946
			echo "Configuring {$ifname} interface...";
947
		if($g['debug'])
948
			log_error("Configuring {$ifname}");
949

    
950
		interface_configure($if, $reload);
951

    
952
		if ($g['booting'])
953
			echo "done.\n";
954
	}
955

    
956
	/* configure interface groups */
957
	interfaces_group_setup();
958

    
959
	if (!$g['booting']) {
960
		/* reconfigure static routes (kernel may have deleted them) */
961
		system_routing_configure();
962

    
963
		/* reload IPsec tunnels */
964
		vpn_ipsec_configure();
965

    
966
		/* reload dhcpd (interface enabled/disabled status may have changed) */
967
		services_dhcpd_configure();
968

    
969
		/* restart dnsmasq */
970
		services_dnsmasq_configure();
971

    
972
		/* reload captive portal */
973
		captiveportal_init_rules();
974
	}
975

    
976
	return 0;
977
}
978

    
979
function interface_reconfigure($interface = "wan", $reloadall = false) {
980
	interface_bring_down($interface);
981
	interface_configure($interface, $reloadall);
982
}
983

    
984
function interface_vip_bring_down($vip) {
985
	global $g;
986

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

    
1011
function interface_bring_down($interface = "wan", $destroy = false) {
1012
	global $config, $g;
1013

    
1014
	if (!isset($config['interfaces'][$interface]))
1015
		return; 
1016

    
1017
	$ifcfg = $config['interfaces'][$interface];
1018

    
1019
	$realif = get_real_interface($interface);
1020

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

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

    
1085
	if ($destroy == true) {
1086
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1087
			pfSense_interface_destroy($realif);
1088
	}	
1089

    
1090
	return;
1091
}
1092

    
1093
function interfaces_ptpid_used($ptpid) {
1094
	global $config;
1095

    
1096
	if (is_array($config['ppps']['ppp']))
1097
		foreach ($config['ppps']['ppp'] as & $settings)
1098
			if ($ptpid == $settings['ptpid'])
1099
				return true;
1100

    
1101
	return false;
1102
}
1103

    
1104
function interfaces_ptpid_next() {
1105

    
1106
	$ptpid = 0;
1107
	while(interfaces_ptpid_used($ptpid))
1108
		$ptpid++;
1109

    
1110
	return $ptpid;
1111
}
1112

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

    
1127
function handle_pppoe_reset($post_array) {
1128
	global $config, $g;
1129

    
1130
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1131

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

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

    
1214
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1215
*	It writes the mpd config file to /var/etc every time the link is opened.
1216
*/
1217

    
1218
function interface_ppps_configure($interface) {
1219
	global $config, $g;
1220

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

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

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

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

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

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

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

    
1346
	if (isset($ppp['ondemand'])) 
1347
		$ondemand = "enable";
1348
	else
1349
		$ondemand = "disable";
1350
	if (!isset($ppp['idletimeout']))
1351
		$ppp['idletimeout'] = 0;
1352

    
1353
	if (empty($ppp['username']) && $type == "modem"){
1354
		$ppp['username'] = "user";
1355
		$ppp['password'] = "none";
1356
	}
1357
	if (empty($ppp['password']) && $type == "modem")
1358
		$passwd = "none";
1359
	else
1360
		$passwd = base64_decode($ppp['password']);
1361

    
1362
	$bandwidths = explode(',',$ppp['bandwidth']);
1363
	$defaultmtu = "1492";
1364
	if (!empty($ifcfg['mtu']))
1365
		$defaultmtu = intval($ifcfg['mtu']);
1366
	$mtus = explode(',',$ppp['mtu']);
1367
	$mrus = explode(',',$ppp['mru']);
1368

    
1369
	if (isset($ppp['mrru']))
1370
		$mrrus = explode(',',$ppp['mrru']);
1371

    
1372
	// Construct the mpd.conf file
1373
	$mpdconf = <<<EOD
1374
startup:
1375
	# configure the console
1376
	set console close
1377
	# configure the web server
1378
	set web close
1379

    
1380
default:
1381
{$ppp['type']}client:
1382
	create bundle static {$interface}
1383
	set iface name {$pppif}
1384

    
1385
EOD;
1386
	$setdefaultgw = false;
1387
	$founddefaultgw = false;
1388
	if (is_array($config['gateways']['gateway_item'])) {
1389
		foreach($config['gateways']['gateway_item'] as $gateway) {
1390
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1391
				$setdefaultgw = true;
1392
				break;
1393
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1394
				$founddefaultgw = true;
1395
				break;
1396
			}
1397
		}
1398
	}
1399
	
1400
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1401
		$setdefaultgw = true;
1402
		$mpdconf .= <<<EOD
1403
	set iface route default
1404

    
1405
EOD;
1406
	}
1407
	$mpdconf .= <<<EOD
1408
	set iface {$ondemand} on-demand
1409
	set iface idle {$ppp['idletimeout']}
1410

    
1411
EOD;
1412

    
1413
	if (isset($ppp['ondemand']))
1414
		$mpdconf .= <<<EOD
1415
	set iface addrs 10.10.1.1 10.10.1.2
1416

    
1417
EOD;
1418
	
1419
	if (isset($ppp['tcpmssfix']))
1420
		$tcpmss = "disable";
1421
	else
1422
		$tcpmss = "enable";
1423
		$mpdconf .= <<<EOD
1424
	set iface {$tcpmss} tcpmssfix
1425

    
1426
EOD;
1427

    
1428
	$mpdconf .= <<<EOD
1429
	set iface up-script /usr/local/sbin/ppp-linkup
1430
	set iface down-script /usr/local/sbin/ppp-linkdown
1431
	set ipcp ranges {$ranges}
1432

    
1433
EOD;
1434
	if (isset($ppp['vjcomp']))
1435
		$mpdconf .= <<<EOD
1436
	set ipcp no vjcomp
1437

    
1438
EOD;
1439

    
1440
	if (isset($config['system']['dnsallowoverride']))
1441
		$mpdconf .= <<<EOD
1442
	set ipcp enable req-pri-dns
1443
	set ipcp enable req-sec-dns
1444

    
1445
EOD;
1446
	if (!isset($ppp['verbose_log']))
1447
		$mpdconf .= <<<EOD
1448
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1449

    
1450
EOD;
1451
	foreach($ports as $pid => $port){
1452
		$port = get_real_interface($port);
1453
		$mpdconf .= <<<EOD
1454

    
1455
	create link static {$interface}_link{$pid} {$type}
1456
	set link action bundle {$interface}
1457
	set link {$multilink} multilink
1458
	set link keep-alive 10 60
1459
	set link max-redial 0
1460

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

    
1466
EOD;
1467

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

    
1472
EOD;
1473

    
1474
		if (isset($ppp['protocomp']))
1475
			$mpdconf .= <<<EOD
1476
	set link no protocomp
1477

    
1478
EOD;
1479

    
1480
		$mpdconf .= <<<EOD
1481
	set link disable chap pap
1482
	set link accept chap pap eap
1483
	set link disable incoming
1484

    
1485
EOD;
1486

    
1487

    
1488
		if (!empty($bandwidths[$pid]))
1489
			$mpdconf .= <<<EOD
1490
	set link bandwidth {$bandwidths[$pid]}
1491

    
1492
EOD;
1493

    
1494
		if (empty($mtus[$pid]))
1495
			$mtus[$pid] = $defaultmtu;
1496
			$mpdconf .= <<<EOD
1497
	set link mtu {$mtus[$pid]}
1498

    
1499
EOD;
1500

    
1501
		if (!empty($mrus[$pid]))
1502
			$mpdconf .= <<<EOD
1503
	set link mru {$mrus[$pid]}
1504

    
1505
EOD;
1506

    
1507
		if (!empty($mrrus[$pid]))
1508
			$mpdconf .= <<<EOD
1509
	set link mrru {$mrrus[$pid]}
1510

    
1511
EOD;
1512

    
1513
		$mpdconf .= <<<EOD
1514
	set auth authname "{$ppp['username']}"
1515
	set auth password {$passwd}
1516

    
1517
EOD;
1518
		if ($type == "modem") {
1519
			$mpdconf .= <<<EOD
1520
	set modem device {$ppp['ports']}
1521
	set modem script DialPeer
1522
	set modem idle-script Ringback
1523
	set modem watch -cd
1524
	set modem var \$DialPrefix "DT"
1525
	set modem var \$Telephone "{$ppp['phone']}"
1526

    
1527
EOD;
1528
		}
1529
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1530
			$mpdconf .= <<<EOD
1531
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1532

    
1533
EOD;
1534
		}
1535
		if (isset($ppp['initstr']) && $type == "modem") {
1536
			$initstr = base64_decode($ppp['initstr']);
1537
			$mpdconf .= <<<EOD
1538
	set modem var \$InitString "{$initstr}"
1539

    
1540
EOD;
1541
		}
1542
		if (isset($ppp['simpin']) && $type == "modem") {
1543
			$mpdconf .= <<<EOD
1544
	set modem var \$SimPin "{$ppp['simpin']}"
1545
	set modem var \$PinWait "{$ppp['pin-wait']}"
1546

    
1547
EOD;
1548
		}
1549
		if (isset($ppp['apn']) && $type == "modem") {
1550
			$mpdconf .= <<<EOD
1551
	set modem var \$APN "{$ppp['apn']}"
1552
	set modem var \$APNum "{$ppp['apnum']}"
1553

    
1554
EOD;
1555
		}
1556
		if ($type == "pppoe") {
1557
			// Send a null service name if none is set.
1558
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1559
			$mpdconf .= <<<EOD
1560
	set pppoe service "{$provider}"
1561

    
1562
EOD;
1563
		}
1564
		if ($type == "pppoe")
1565
			$mpdconf .= <<<EOD
1566
	set pppoe iface {$port}
1567

    
1568
EOD;
1569

    
1570
		if ($type == "pptp" || $type == "l2tp") {
1571
			$mpdconf .= <<<EOD
1572
	set {$type} self {$localips[$pid]}
1573
	set {$type} peer {$gateways[$pid]}
1574

    
1575
EOD;
1576
		}
1577
		
1578
		$mpdconf .= "\topen\r\n";
1579
	} //end foreach($port)
1580

    
1581

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

    
1596
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1597
	if (isset($ppp['uptime'])) {
1598
		if (!file_exists("/conf/{$pppif}.log")) {
1599
			conf_mount_rw();
1600
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1601
			conf_mount_ro();
1602
		}
1603
	} else {
1604
		if (file_exists("/conf/{$pppif}.log")) {
1605
			conf_mount_rw();
1606
			mwexec("rm -f /conf/{$pppif}.log");
1607
			conf_mount_ro();
1608
		}
1609
	}
1610

    
1611
	/* fire up mpd */
1612
	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");
1613

    
1614
	// Check for PPPoE periodic reset request 
1615
	if ($type == "pppoe") {
1616
		if (isset($ppp['pppoe-reset-type']))
1617
			setup_pppoe_reset_file($ppp['if'], $interface);
1618
		else
1619
			setup_pppoe_reset_file($ppp['if']);
1620
	}
1621

    
1622
	return 1;
1623
}
1624

    
1625
function interfaces_carp_setup() {
1626
	global $g, $config;
1627

    
1628
	if(isset($config['system']['developerspew'])) {
1629
		$mt = microtime();
1630
		echo "interfaces_carp_setup() being called $mt\n";
1631
	}
1632

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

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

    
1654
	if($balanacing) {
1655
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1656
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1657
	} else
1658
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1659

    
1660
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1661
	if (!empty($pfsyncinterface))
1662
		$carp_sync_int = get_real_interface($pfsyncinterface);
1663
	else
1664
		unset($carp_sync_int);
1665

    
1666
	/* setup pfsync interface */
1667
	if ($carp_sync_int and $pfsyncenabled) {
1668
		if (is_ipaddr($pfsyncpeerip))
1669
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);
1670
		else
1671
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);
1672

    
1673
		sleep(1);
1674

    
1675
		/* XXX: Handle an issue with pfsync(4) and carp(4). In a cluster carp will come up before pfsync(4) has updated and so will cause issuese
1676
		 * for exiting sessions.
1677
		 */
1678
		$i = 0;
1679
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1680
			$i++;
1681
			sleep(1);
1682
		}
1683
	}
1684

    
1685
	if ($config['virtualip']['vip'])
1686
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1687
	else
1688
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1689
	
1690
	if ($g['booting']) {
1691
		unmute_kernel_msgs();
1692
		echo "done.\n";
1693
	}
1694
}
1695

    
1696
function interface_proxyarp_configure($interface = "") {
1697
	global $config, $g;
1698
	if(isset($config['system']['developerspew'])) {
1699
		$mt = microtime();
1700
		echo "interface_proxyarp_configure() being called $mt\n";
1701
	}
1702

    
1703
	/* kill any running choparp */
1704
	if (empty($interface))
1705
		killbyname("choparp");
1706
	else {
1707
		$vipif = get_real_interface($interface);
1708
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1709
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1710
	}
1711

    
1712
	$paa = array();
1713
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1714

    
1715
		/* group by interface */
1716
		foreach ($config['virtualip']['vip'] as $vipent) {
1717
			if ($vipent['mode'] === "proxyarp") {
1718
				if ($vipent['interface'])
1719
					$proxyif = $vipent['interface'];
1720
				else
1721
					$proxyif = "wan";
1722
				
1723
				if (!empty($interface) && $interface != $proxyif)
1724
					continue;
1725

    
1726
				if (!is_array($paa[$proxyif]))
1727
					$paa[$proxyif] = array();
1728

    
1729
				$paa[$proxyif][] = $vipent;
1730
			}
1731
		}
1732
	}
1733

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

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

    
1809
function interface_ipalias_configure(&$vip) {
1810

    
1811
	if ($vip['mode'] == "ipalias") {
1812
		$if = get_real_interface($vip['interface']);
1813
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1814
	}
1815
}
1816

    
1817
function interface_reload_carps($cif) {
1818
	global $config;
1819

    
1820
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1821
	if (empty($carpifs))
1822
		return;
1823

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

    
1851
function interface_carp_configure(&$vip) {
1852
	global $config, $g;
1853
	if(isset($config['system']['developerspew'])) {
1854
		$mt = microtime();
1855
		echo "interface_carp_configure() being called $mt\n";
1856
	}
1857

    
1858
	if ($vip['mode'] != "carp")
1859
		return;
1860

    
1861
	$vip_password = $vip['password'];
1862
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1863
	if ($vip['password'] != "")
1864
		$password = " pass {$vip_password}";
1865

    
1866
	// set the vip interface to the vhid
1867
	$vipif = "vip{$vip['vhid']}";
1868

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

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

    
1887
	/* create the carp interface and setup */
1888
	if (does_interface_exist($vipif)) {
1889
		pfSense_interface_flags($vipif, -IFF_UP);
1890
	} else {
1891
		$carpif = pfSense_interface_create("carp");
1892
		pfSense_interface_rename($carpif, $vipif);
1893
		pfSense_ngctl_name("{$carpif}:", $vipif);
1894
	}
1895

    
1896
	/* invalidate interface cache */
1897
	get_interface_arr(true);
1898

    
1899
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1900
	$advbase = "";
1901
	if (!empty($vip['advbase']))
1902
		$advbase = "advbase {$vip['advbase']}";
1903
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1904

    
1905
	interfaces_bring_up($vipif);
1906
	
1907
	return $vipif;
1908
}
1909

    
1910
function interface_carpdev_configure(&$vip) {
1911
	global $g;
1912

    
1913
	if ($vip['mode'] != "carpdev-dhcp")
1914
		return;
1915

    
1916
	$vip_password = $vip['password'];
1917
	$vip_password = str_replace(" ", "", $vip_password);
1918
	if($vip['password'] != "")
1919
		$password = " pass \"" . $vip_password . "\"";
1920

    
1921
	if (empty($vip['interface']))
1922
		return;
1923

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

    
1936
	if (does_interface_exist($vipif)) {
1937
		interface_bring_down($vipif);
1938
	} else {
1939
		$carpdevif = exec("/sbin/ifconfig carp create");
1940
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1941
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1942
	}
1943

    
1944
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1945
	interfaces_bring_up($vipif);
1946

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

    
1956
	/* generate dhclient_wan.conf */
1957
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1958
	if ($fd) {
1959
		$dhclientconf = "";
1960

    
1961
		$dhclientconf .= <<<EOD
1962
interface "{$vipif}" {
1963
timeout 60;
1964
retry 1;
1965
select-timeout 0;
1966
initial-interval 1;
1967
script "/sbin/dhclient-script";
1968
}
1969

    
1970
EOD;
1971

    
1972
		fwrite($fd, $dhclientconf);
1973
		fclose($fd);
1974

    
1975
		/* fire up dhclient */
1976
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1977
	} else {
1978
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1979
		mwexec("/sbin/dhclient -b {$vipif}");
1980
	}
1981

    
1982
	return $vipif;
1983
}
1984

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

    
2026
	if($needs_clone == true) {
2027
		/* remove previous instance if it exists */
2028
		if(does_interface_exist($realif))
2029
			pfSense_interface_destroy($realif);
2030

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

    
2049
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2050
	global $config, $g;
2051

    
2052
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2053
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2054
	                         'regdomain', 'regcountry', 'reglocation');
2055

    
2056
	if(!is_interface_wireless($ifcfg['if']))
2057
		return;
2058

    
2059
	$baseif = interface_get_wireless_base($ifcfg['if']);
2060

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

    
2085
	// Read or write settings at shared area
2086
	if (isset($config['wireless']['interfaces'][$baseif])) {
2087
		foreach ($shared_settings as $setting) {
2088
			if ($sync_changes) {
2089
				if (isset($ifcfg['wireless'][$setting]))
2090
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2091
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2092
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2093
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2094
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2095
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2096
				else if (isset($ifcfg['wireless'][$setting]))
2097
					unset($ifcfg['wireless'][$setting]);
2098
			}
2099
		}
2100
	}
2101

    
2102
	// Sync the mode on the clone creation page with the configured mode on the interface
2103
	if (interface_is_wireless_clone($ifcfg['if'])) {
2104
		foreach ($config['wireless']['clone'] as &$clone) {
2105
			if ($clone['cloneif'] == $ifcfg['if']) {
2106
				if ($sync_changes) {
2107
					$clone['mode'] = $ifcfg['wireless']['mode'];
2108
				} else {
2109
					$ifcfg['wireless']['mode'] = $clone['mode'];
2110
				}
2111
				break;
2112
			}
2113
		}
2114
		unset($clone);
2115
	}
2116
}
2117

    
2118
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2119
	global $config, $g;
2120

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

    
2128
	// Remove script file
2129
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2130

    
2131
	// Clone wireless nic if needed.
2132
	interface_wireless_clone($if, $wl);
2133

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

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

    
2141
	/* set values for /path/program */
2142
	$hostapd = "/usr/sbin/hostapd";
2143
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2144
	$ifconfig = "/sbin/ifconfig";
2145
	$sysctl = "/sbin/sysctl";
2146
	$killall = "/usr/bin/killall";
2147

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

    
2150
	$wlcmd = array();
2151
	$wl_sysctl = array();
2152
	/* Make sure it's up */
2153
	$wlcmd[] = "up";
2154
	/* Set a/b/g standard */
2155
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2156
	$wlcmd[] = "mode " . escapeshellarg($standard);
2157

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

    
2163
	/* Set ssid */
2164
	if($wlcfg['ssid'])
2165
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2166

    
2167
	/* Set 802.11g protection mode */
2168
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2169

    
2170
	/* set wireless channel value */
2171
	if(isset($wlcfg['channel'])) {
2172
		if($wlcfg['channel'] == "0") {
2173
			$wlcmd[] = "channel any";
2174
		} else {
2175
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2176
		}
2177
	}
2178

    
2179
	/* Set antenna diversity value */
2180
	if(isset($wlcfg['diversity']))
2181
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2182

    
2183
	/* Set txantenna value */
2184
	if(isset($wlcfg['txantenna']))
2185
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2186

    
2187
	/* Set rxantenna value */
2188
	if(isset($wlcfg['rxantenna']))
2189
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2190

    
2191
	/* set Distance value */
2192
	if($wlcfg['distance'])
2193
		$distance = escapeshellarg($wlcfg['distance']);
2194

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

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

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

    
2211
	/* handle hide ssid option */
2212
	if(isset($wlcfg['hidessid']['enable'])) {
2213
		$wlcmd[] = "hidessid";
2214
	} else {
2215
		$wlcmd[] = "-hidessid";
2216
	}
2217

    
2218
	/* handle pureg (802.11g) only option */
2219
	if(isset($wlcfg['pureg']['enable'])) {
2220
		$wlcmd[] = "mode 11g pureg";
2221
	} else {
2222
		$wlcmd[] = "-pureg";
2223
	}
2224

    
2225
	/* handle puren (802.11n) only option */
2226
	if(isset($wlcfg['puren']['enable'])) {
2227
		$wlcmd[] = "puren";
2228
	} else {
2229
		$wlcmd[] = "-puren";
2230
	}
2231

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

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

    
2246
	/* handle txpower setting */
2247
	/* if($wlcfg['txpower'] <> "")
2248
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2249
	*/
2250
	/* handle wme option */
2251
	if(isset($wlcfg['wme']['enable'])) {
2252
		$wlcmd[] = "wme";
2253
	} else {
2254
		$wlcmd[] = "-wme";
2255
	}
2256

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

    
2283
	mwexec(kill_hostapd("{$if}"));
2284
	mwexec(kill_wpasupplicant("{$if}"));
2285

    
2286
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2287
	conf_mount_rw();
2288

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

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

    
2343
EOD;
2344

    
2345
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2346
	$wpa .= <<<EOD
2347
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2348
rsn_preauth=1
2349
rsn_preauth_interfaces={$if}
2350

    
2351
EOD;
2352

    
2353
}
2354
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2355
					$auth_server_port = "1812";
2356
					if($wlcfg['auth_server_port']) 
2357
						$auth_server_port = $wlcfg['auth_server_port'];
2358
					$wpa .= <<<EOD
2359

    
2360
ieee8021x=1
2361
auth_server_addr={$wlcfg['auth_server_addr']}
2362
auth_server_port={$auth_server_port}
2363
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2364

    
2365
EOD;
2366
				} else {
2367
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2368
				}
2369

    
2370
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2371
				fwrite($fd, "{$wpa}");
2372
				fclose($fd);
2373

    
2374
			}
2375
			break;
2376
	}
2377

    
2378
	/*
2379
	 *    all variables are set, lets start up everything
2380
	 */
2381

    
2382
	$baseif = interface_get_wireless_base($if);
2383
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2384
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2385

    
2386
	/* set sysctls for the wireless interface */
2387
	if (!empty($wl_sysctl)) {
2388
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2389
		foreach ($wl_sysctl as $wl_sysctl_line) {
2390
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2391
		}
2392
	}
2393

    
2394
	/* set ack timers according to users preference (if he/she has any) */
2395
	if($distance) {
2396
		fwrite($fd_set, "# Enable ATH distance settings\n");
2397
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2398
	}
2399

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

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

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

    
2428
	fclose($fd_set);
2429
	conf_mount_ro();
2430

    
2431
	/* Making sure regulatory settings have actually changed
2432
	 * before applying, because changing them requires bringing
2433
	 * down all wireless networks on the interface. */
2434
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2435
	$ifconfig_str = implode($output);
2436
	unset($output);
2437
	$reg_changing = false;
2438

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

    
2451
	if ($reg_changing) {
2452
		/* set regulatory domain */
2453
		if($wlcfg['regdomain'])
2454
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2455

    
2456
		/* set country */
2457
		if($wlcfg['regcountry'])
2458
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2459

    
2460
		/* set location */
2461
		if($wlcfg['reglocation'])
2462
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2463

    
2464
		$wlregcmd_args = implode(" ", $wlregcmd);
2465

    
2466
		/* build a complete list of the wireless clones for this interface */
2467
		$clone_list = array();
2468
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2469
			$clone_list[] = interface_get_wireless_clone($baseif);
2470
		if (is_array($config['wireless']['clone'])) {
2471
			foreach ($config['wireless']['clone'] as $clone) {
2472
				if ($clone['if'] == $baseif)
2473
					$clone_list[] = $clone['cloneif'];
2474
			}
2475
		}
2476

    
2477
		/* find which clones are up and bring them down */
2478
		$clones_up = array();
2479
		foreach ($clone_list as $clone_if) {
2480
			$clone_status = pfSense_get_interface_addresses($clone_if);
2481
			if ($clone_status['status'] == 'up') {
2482
				$clones_up[] = $clone_if;
2483
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2484
			}
2485
		}
2486

    
2487
		/* apply the regulatory settings */
2488
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2489

    
2490
		/* bring the clones back up that were previously up */
2491
		foreach ($clones_up as $clone_if) {
2492
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2493

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

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

    
2514
	/* configure wireless */
2515
	$wlcmd_args = implode(" ", $wlcmd);
2516
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2517

    
2518
	
2519
	sleep(1);
2520
	/* execute hostapd and wpa_supplicant if required in shell */
2521
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2522

    
2523
	return 0;
2524

    
2525
}
2526

    
2527
function kill_hostapd($interface) {
2528
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2529
}
2530

    
2531
function kill_wpasupplicant($interface) {
2532
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2533
}
2534

    
2535
function find_dhclient_process($interface) {
2536
	if ($interface)
2537
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2538
	else
2539
		$pid = 0;
2540

    
2541
	return intval($pid);
2542
}
2543

    
2544
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2545
	global $config, $g;
2546
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2547

    
2548
	$wancfg = $config['interfaces'][$interface];
2549

    
2550
	$realif = get_real_interface($interface);
2551
	$realhwif_array = get_parent_interface($interface);
2552
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2553
	$realhwif = $realhwif_array[0];
2554

    
2555
			
2556
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2557
		/* remove all IPv4 addresses */
2558
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2559

    
2560
		switch ($wancfg['ipaddr']) {
2561
			case 'pppoe':
2562
			case 'l2tp':
2563
			case 'pptp':
2564
			case 'ppp':
2565
				break;
2566
			default:
2567
				interface_bring_down($interface);
2568
				break;
2569
		}
2570
	}
2571

    
2572
	/* wireless configuration? */
2573
	if (is_array($wancfg['wireless']))
2574
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2575

    
2576
	$mac = get_interface_mac($realhwif);
2577
	/*	Don't try to reapply the spoofed MAC if it's already applied.
2578
		When ifconfig link is used, it cycles the interface down/up, which triggers 
2579
		the interface config again, which attempts to spoof the MAC again, 
2580
		which cycles the link again... */
2581
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2582
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2583
			" link " . escapeshellarg($wancfg['spoofmac']));
2584

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2735
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2736
			unset($bridgetmp);
2737
			$bridgetmp = link_interface_to_bridge($interface);
2738
			if (!empty($bridgetmp))
2739
				interface_bridge_add_member($bridgetmp, $realif);
2740
		}
2741

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

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

    
2750
		if ($reloadall == true) {
2751

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

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

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

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

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

    
2769
	return 0;
2770
}
2771

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

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

    
2783
	return 0;
2784
}
2785

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

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

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

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

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

    
2824
EOD;
2825

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

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

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

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

    
2849
	return 0;
2850
}
2851

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

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

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

    
2861
	return;
2862
}
2863

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

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

    
2876
	return;
2877
}
2878

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

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

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

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

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

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

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

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

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

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

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

    
2985
        return $ifdesc;
2986
}
2987

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

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

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

    
2998
        return $interface;
2999
}
3000

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

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

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

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

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

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

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

    
3088
	$wanif = NULL;
3089

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

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

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

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

    
3164
    return $wanif;
3165
}
3166

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

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

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

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

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

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

    
3236
function link_carp_interface_to_parent($interface) {
3237
        global $config;
3238

    
3239
        if ($interface == "")
3240
                return;
3241

    
3242
        $carp_ip = get_interface_ip($interface);
3243
        if (!is_ipaddr($carp_ip))
3244
                return;
3245

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

    
3256
        return "";
3257
}
3258

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

    
3270
        if (!is_ipaddr($ip))
3271
                return;
3272

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

    
3290
        return $carp_ints;
3291
}
3292

    
3293
function link_interface_to_vlans($int, $action = "") {
3294
	global $config;
3295

    
3296
	if (empty($int))
3297
		return;
3298

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

    
3311
function link_interface_to_vips($int, $action = "") {
3312
        global $config;
3313

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

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

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

    
3350
function link_interface_to_group($int) {
3351
        global $config;
3352

    
3353
	$result = array();
3354

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

    
3362
	return $result;
3363
}
3364

    
3365
function link_interface_to_gre($interface) {
3366
        global $config;
3367

    
3368
	$result = array();
3369

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

    
3376
	return $result;
3377
}
3378

    
3379
function link_interface_to_gif($interface) {
3380
        global $config;
3381

    
3382
	$result = array();
3383

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

    
3390
	return $result;
3391
}
3392

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

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

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

    
3413
	return $interface_ip_arr_cache[$interface];
3414
}
3415

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

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

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

    
3431
	return $interface_sn_arr_cache[$interface];
3432
}
3433

    
3434
function ip_in_interface_alias_subnet($interface, $ipalias) {
3435
	global $config;
3436

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

    
3452
	return false;
3453
}
3454

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

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

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

    
3486
	$cursn = find_interface_subnet($realif);
3487
	if (!empty($cursn))
3488
		return $cursn;
3489

    
3490
	return null;
3491
}
3492

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

    
3497
	$ints = array();
3498

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

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

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

    
3545
	return false;
3546
}
3547

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

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

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

    
3572
        if (in_array($int_family[0], $capable))
3573
                return true;
3574
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
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($iface) {
3714

    
3715
	$iface = trim($iface);
3716
	$capable = pfSense_get_interface_addresses($iface);
3717
	if (isset($capable['caps']['vlanmtu']))
3718
                return true;
3719

    
3720
	return false;
3721
}
3722

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

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

    
3733
EOD;
3734

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

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

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

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

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

    
3774
function interfaces_staticarp_configure($if) {
3775
	global $config, $g;
3776
	if(isset($config['system']['developerspew'])) {
3777
		$mt = microtime();
3778
		echo "interfaces_staticarp_configure($if) being called $mt\n";
3779
	}
3780

    
3781
	$ifcfg = $config['interfaces'][$if];
3782

    
3783
	if (empty($if) || empty($ifcfg['if']))
3784
		return 0;
3785

    
3786
	/* Enable staticarp, if enabled */
3787
	if(isset($config['dhcpd'][$if]['staticarp'])) {
3788
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
3789
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
3790
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
3791

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

    
3795
			}
3796

    
3797
		}
3798
	} else {
3799
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
3800
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
3801
	}
3802

    
3803
	return 0;
3804
}
3805

    
3806
?>
(24-24/61)