Project

General

Profile

Download (101 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:	/usr/sbin/pppd	/sbin/dhclient	/bin/sh	/usr/bin/grep	/usr/bin/xargs	/usr/bin/awk	/usr/local/sbin/choparp
39
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig	/sbin/route	/usr/sbin/ngctl	/usr/sbin/arp	/bin/kill	/usr/local/sbin/mpd5
40
	pfSense_MODULE:	interfaces
41

    
42
*/
43

    
44
/* include all configuration functions */
45
require_once("globals.inc");
46
require_once("cmd_chain.inc");
47

    
48
function interfaces_bring_up($interface) {
49
	if(!$interface) {
50
		log_error("interfaces_bring_up() was called but no variable defined.");
51
		log_error( "Backtrace: " . debug_backtrace() );
52
		return;
53
	}
54
	pfSense_interface_flags($interface, IFF_UP);
55
}
56

    
57
/*
58
 * Return the interface array
59
 */
60
function get_interface_arr($flush = false) {
61
        global $interface_arr_cache;
62

    
63
        /* If the cache doesn't exist, build it */
64
        if (!isset($interface_arr_cache) or $flush)
65
                $interface_arr_cache = explode(" ", trim(`/sbin/ifconfig -l`));
66

    
67
        return $interface_arr_cache;
68
}
69

    
70
/*
71
 * does_interface_exist($interface): return true or false if a interface is
72
 * detected.
73
 */
74
function does_interface_exist($interface) {
75
	global $config;
76
	
77
	if(!$interface)
78
		return false;
79

    
80
	$ints = get_interface_arr(true);
81
	if (in_array($interface, $ints))
82
		return true;
83
	else
84
		return false;
85
}
86

    
87
function interfaces_loopback_configure() {
88
	if($g['booting'])
89
		echo "Configuring loopback interface...";
90
	pfSense_interface_setaddress("lo0", "127.0.0.1");
91
	interfaces_bring_up("lo0");
92
	if($g['booting'])
93
		echo "done.\n";
94
	return 0;
95
}
96

    
97
function interfaces_vlan_configure() {
98
	global $config, $g;
99
	if($g['booting'])
100
		echo "Configuring VLAN interfaces...";
101
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
102
		foreach ($config['vlans']['vlan'] as $vlan) {
103
			if(empty($vlan['vlanif']))
104
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
105
			/* XXX: Maybe we should report any errors?! */
106
			interface_vlan_configure($vlan);
107
		}
108
	}
109
	if($g['booting'])
110
		echo "done.\n";
111
}
112

    
113
function interface_vlan_configure(&$vlan) {
114
        global $config, $g;
115

    
116
	if (!is_array($vlan)) {
117
		log_error("VLAN: called with wrong options. Problems with config!");
118
		return;
119
	}
120
	$if = $vlan['if'];
121
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
122
	$tag = $vlan['tag'];
123

    
124
	if (empty($if)) {
125
		log_error("interface_vlan_confgure called with if undefined.");
126
		return;
127
	}
128

    
129
	/* make sure the parent interface is up */
130
	interfaces_bring_up($if);
131
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
132
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
133

    
134
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
135
		interface_bring_down($vlanif, true);
136
	} else {
137
		$tmpvlanif = pfSense_interface_create("vlan");
138
		pfSense_interface_rename($tmpvlanif, $vlanif);
139
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
140
	}
141

    
142
	pfSense_vlan_create($vlanif, $if, $tag);
143

    
144
	interfaces_bring_up($vlanif);
145

    
146
	/* invalidate interface cache */
147
	get_interface_arr(true);
148

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

    
152
	return $vlanif;
153
}
154

    
155
function interface_qinq_configure(&$vlan, $fd = NULL) {
156
        global $config, $g;
157

    
158
        if (!is_array($vlan)) {
159
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
160
                return;
161
        }
162

    
163
        $qinqif = $vlan['if'];
164
        $tag = $vlan['tag'];
165
        if(empty($qinqif)) {
166
                log_error("interface_qinq_confgure called with if undefined.\n");
167
                return;
168
        }
169
	$vlanif = interface_vlan_configure($vlan);
170

    
171
        if ($fd == NULL) {
172
                $exec = true;
173
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
174
        } else
175
                $exec = false;
176
        /* make sure the parent is converted to ng_vlan(4) and is up */
177
        interfaces_bring_up($qinqif);
178

    
179
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
180
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
181
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
182
                if (empty($result)) {
183
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
184
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
185
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
186
                }
187
        } else {
188
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
189
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
190
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
191
        }
192

    
193
        /* invalidate interface cache */
194
        get_interface_arr(true);
195

    
196
        if (!stristr($qinqif, "vlan"))
197
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
198

    
199
        $macaddr = get_interface_mac($qinqif);
200
        if (!empty($vlan['members'])) {
201
                $members = explode(" ", $vlan['members']);
202
                foreach ($members as $qtag) {
203
                        $qinq = array();
204
                        $qinq['tag'] = $qtag;
205
                        $qinq['if'] = $vlanif;
206
                        interface_qinq2_configure($qinq, $fd, $macaddr);
207
                }
208
        }
209
        if ($exec == true) {
210
                fclose($fd);
211
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
212
        }
213

    
214
        interfaces_bring_up($qinqif);
215
        if (!empty($vlan['members'])) {
216
                $members = explode(" ", $vlan['members']);
217
                foreach ($members as $qif)
218
                        interfaces_bring_up("{$vlanif}_{$qif}");
219
        }
220

    
221
        return $vlanif;
222
}
223

    
224
function interfaces_qinq_configure() {
225
	global $config, $g;
226
	if($g['booting'])
227
		echo "Configuring QinQ interfaces...";
228
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
229
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
230
			/* XXX: Maybe we should report any errors?! */
231
			interface_qinq_configure($qinq);
232
		}
233
	}
234
	if($g['booting'])
235
		echo "done.\n";
236
}
237

    
238
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
239
        global $config, $g;
240

    
241
        if (!is_array($qinq)) {
242
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
243
                return;
244
        }
245

    
246
        $if = $qinq['if'];
247
        $tag = $qinq['tag'];
248
        $vlanif = "{$if}_{$tag}";
249
        if(empty($if)) {
250
                log_error("interface_qinq_confgure called with if undefined.\n");
251
                return;
252
        }
253

    
254
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
255
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
256
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
257
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
258
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
259
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
260

    
261
        /* invalidate interface cache */
262
        get_interface_arr(true);
263

    
264
        return $vlanif;
265
}
266

    
267
function interfaces_create_wireless_clones() {
268
	global $config;
269

    
270
	if($g['booting'])
271
		echo "Creating other wireless clone interfaces...";
272
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
273
		foreach ($config['wireless']['clone'] as $clone) {
274
			if(empty($clone['cloneif']))
275
				continue;
276
			if(does_interface_exist($clone['cloneif']))
277
				continue;
278
			/* XXX: Maybe we should report any errors?! */
279
			if(interface_wireless_clone($clone['cloneif'], $clone))
280
				if($g['booting'])
281
					echo " " . $clone['cloneif'];
282
		}
283
	}
284
	if($g['booting'])
285
		echo " done.\n";
286
}
287

    
288
function interfaces_bridge_configure() {
289
        global $config;
290

    
291
        $i = 0;
292
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
293
                foreach ($config['bridges']['bridged'] as $bridge) {
294
                        if(empty($bridge['bridgeif']))
295
                                $bridge['bridgeif'] = "bridge{$i}";
296
                        /* XXX: Maybe we should report any errors?! */
297
                        interface_bridge_configure($bridge);
298
                        $i++;
299
                }
300
        }
301
}
302

    
303
function interface_bridge_configure(&$bridge) {
304
	global $config, $g;
305

    
306
	if (!is_array($bridge))
307
	        return -1;
308

    
309
	if (empty($bridge['members'])) {
310
		log_error("No members found on {$bridge['bridgeif']}");
311
		return -1;
312
	}
313

    
314
	$members = explode(',', $bridge['members']);
315
	if (!count($members))
316
		return -1;
317

    
318
	$checklist = get_configured_interface_list();
319

    
320
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
321
		pfSense_interface_destroy($bridge['bridgeif']);
322
		pfSense_interface_create($bridge['bridgeif']);
323
		$bridgeif = $bridge['bridgeif'];
324
	} else
325
		$bridgeif = pfSense_interface_create("bridge");
326

    
327
	/* Calculate smaller mtu and enforce it */
328
	$smallermtu = 0;
329
	$commonrx = true;
330
	$commontx = true;
331
	foreach ($members as $member) {
332
		$realif = get_real_interface($member);
333
		$opts = pfSense_get_interface_addresses($realif);
334
		$mtu = $opts['mtu'];
335
		if (!isset($opts['encaps']['txcsum']))
336
			$commontx = false;
337
		if (!isset($opts['encaps']['rxcsum']))
338
			$commonrx = false;
339
		if (!isset($opts['encaps']['tso4']))
340
			$commontso4 = false;
341
		if (!isset($opts['encaps']['tso6']))
342
			$commontso6 = false;
343
		if (!isset($opts['encaps']['lro']))
344
			$commonlro = false;
345
		if ($smallermtu == 0 && !empty($mtu))
346
			$smallermtu = $mtu;
347
		else if (!empty($mtu) && $mtu < $smallermtu)
348
			$smallermtu = $mtu;
349
	}
350
	 
351
	/* Just in case anything is not working well */
352
	if ($smallermtu == 0)
353
		$smallermtu = 1500; 
354

    
355
	$flags = 0;
356
	if ($commonrx === false)
357
		$flags |= IFCAP_RXCSUM;
358
	if ($commontx === false)
359
		$flags |= IFCAP_TXCSUM;
360
	if ($commontso4 === false)
361
		$flags |= IFCAP_TSO4;
362
	if ($commontso6 === false)
363
		$flags |= IFCAP_TSO6;
364
	if ($commonlro === false)
365
		$flags |= IFCAP_LRO;
366
		
367
	/* Add interfaces to bridge */
368
	foreach ($members as $member) {
369
		if (!array_key_exists($member, $checklist))
370
			continue;
371
		$realif1 = get_real_interface($member);
372
		$realif =  escapeshellarg($realif1);
373
		if (!$realif) {
374
			log_error("realif not defined in interfaces bridge - up");
375
			continue;
376
		}
377
		/* make sure the parent interface is up */
378
		pfSense_interface_mtu($realif1, $smallermtu);
379
		pfSense_interface_capabilities($realif1, -$flags);
380
		interfaces_bring_up($realif1);
381
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
382
	}
383

    
384
	if (isset($bridge['enablestp'])) {
385
		/* Choose spanning tree proto */
386
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
387
		
388
		if (!empty($bridge['stp'])) {
389
			$stpifs = explode(',', $bridge['stp']);
390
			foreach ($stpifs as $stpif) {
391
				$realif = get_real_interface($stpif);
392
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
393
			}
394
		}
395
		if (!empty($bridge['maxage']))
396
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
397
		if (!empty($brige['fwdelay']))
398
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
399
		if (!empty($brige['hellotime']))
400
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
401
		if (!empty($brige['priority']))
402
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
403
		if (!empty($brige['holdcount']))
404
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
405
		if (!empty($bridge['ifpriority'])) {
406
			$pconfig = explode(",", $bridge['ifpriority']);
407
			$ifpriority = array();
408
			foreach ($pconfig as $cfg) {
409
				$embcfg = explode(":", $cfg);
410
				foreach ($embcfg as $key => $value)
411
					$ifpriority[$key] = $value;
412
			}
413
			foreach ($ifpriority as $key => $value) {
414
				$realif = get_real_interface($key);
415
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
416
			}
417
		}
418
		if (!empty($bridge['ifpathcost'])) {
419
			$pconfig = explode(",", $bridges['ifpathcost']);
420
			$ifpathcost = array();
421
			foreach ($pconfig as $cfg) {
422
				$embcfg = explode(":", $cfg);
423
				foreach ($embcfg as $key => $value)
424
					$ifpathcost[$key] = $value;
425
			}
426
			foreach ($ifpathcost as $key => $value) {
427
                        	$realif = get_real_interface($key);
428
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
429
                	}
430
		}
431
	}
432

    
433
	if ($bridge['maxaddr'] <> "")
434
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
435
        if ($bridge['timeout'] <> "")
436
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
437
        if ($bridge['span'] <> "") {
438
		$realif = get_real_interface($bridge['span']);
439
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
440
	}
441
	if (!empty($bridge['edge'])) {
442
        	$edgeifs = explode(',', $bridge['edge']);
443
        	foreach ($edgeifs as $edgeif) {
444
			$realif = get_real_interface($edgeif);
445
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
446
        	}
447
	}
448
	if (!empty($bridge['autoedge'])) {
449
        	$edgeifs = explode(',', $bridge['autoedge']);
450
        	foreach ($edgeifs as $edgeif) {
451
                	$realif = get_real_interface($edgeif);
452
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
453
        	}
454
	}
455
	if (!empty($bridge['ptp'])) {
456
        	$ptpifs = explode(',', $bridge['ptp']);
457
        	foreach ($ptpifs as $ptpif) {
458
                	$realif = get_real_interface($ptpif);
459
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
460
        	}
461
	}
462
	if (!empty($bridge['autoptp'])) {
463
        	$ptpifs = explode(',', $bridge['autoptp']);
464
        	foreach ($ptpifs as $ptpif) {
465
                	$realif = get_real_interface($ptpif);
466
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
467
        	}
468
	}
469
	if (!empty($bridge['static'])) {
470
        	$stickyifs = explode(',', $bridge['static']);
471
        	foreach ($stickyifs as $stickyif) {
472
                	$realif = get_real_interface($stickyif);
473
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
474
        	}
475
	}
476
	if (!empty($bridge['private'])) {
477
        	$privateifs = explode(',', $bridge['private']);
478
        	foreach ($privateifs as $privateif) {
479
                	$realif = get_real_interface($privateif);
480
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
481
        	}
482
	}
483

    
484
	if($bridgeif)
485
		interfaces_bring_up($bridgeif);	
486
	else 
487
		log_error("bridgeif not defined -- could not bring interface up");
488

    
489
	return $bridgeif;
490
}
491

    
492
function interface_bridge_add_member($bridgeif, $interface) {
493

    
494
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
495
		return;
496

    
497
	$mtu = get_interface_mtu($brigeif);
498
	$mtum = get_interface_mtu($interface);
499
	
500
	if ($mtu != $mtum)
501
		pfSense_interface_mtu($interface, $mtu);
502

    
503
	$options = pfSense_get_interface_addresses($bridgeif);
504
	$flags = 0;
505
	if (!isset($options['encaps']['txcsum']))
506
		$flags |= IFCAP_TXCSUM;
507

    
508
	if (!isset($options['encaps']['rxcsum']))
509
		$flags |= IFCAP_RXCSUM;
510

    
511
	pfSense_interface_capabilities($interface, -$flags);
512

    
513
	interfaces_bring_up($interface);
514
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
515
}
516

    
517
function interfaces_lagg_configure() 
518
{
519
        global $config, $g;
520
		if($g['booting']) 
521
			echo "Configuring LAGG interfaces...";
522
        $i = 0;
523
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
524
			foreach ($config['laggs']['lagg'] as $lagg) {
525
				if(empty($lagg['laggif']))
526
					$lagg['laggif'] = "lagg{$i}";
527
				/* XXX: Maybe we should report any errors?! */
528
				interface_lagg_configure($lagg);
529
				$i++;
530
			}
531
		}
532
		if($g['booting']) 
533
			echo "done.\n";
534
}
535

    
536
function interface_lagg_configure(&$lagg) {
537
        global $config, $g;
538

    
539
        if (!is_array($lagg))
540
		return -1;
541

    
542
	$members = explode(',', $lagg['members']);
543
	if (!count($members))
544
		return -1;
545
	
546
	$checklist = get_interface_list();
547

    
548
	if ($g['booting'] || !(empty($lagg['laggif']))) {
549
		pfSense_interface_destroy($lagg['laggif']);
550
		pfSense_interface_create($lagg['laggif']);
551
                $laggif = $lagg['laggif'];
552
        } else
553
		$laggif = pfSense_interface_create("lagg");
554

    
555
	/* Calculate smaller mtu and enforce it */
556
        $smallermtu = 0;
557
        foreach ($members as $member) {
558
		$opts = pfSense_get_interface_addresses($member);
559
                $mtu = $opts['mtu'];
560
		if (!isset($opts['encaps']['txcsum']))
561
                        $commontx = false;
562
                if (!isset($opts['encaps']['rxcsum']))
563
                        $commonrx = false;
564
		if (!isset($opts['encaps']['tso4']))
565
			$commontso4 = false;
566
		if (!isset($opts['encaps']['tso6']))
567
			$commontso6 = false;
568
		if (!isset($opts['encaps']['lro']))
569
			$commonlro = false;
570
		if ($smallermtu == 0 && !empty($mtu))
571
			$smallermtu = $mtu;
572
                else if (!empty($mtu) && $mtu < $smallermtu)
573
                        $smallermtu = $mtu;
574
        }
575

    
576
	/* Just in case anything is not working well */
577
        if ($smallermtu == 0)
578
                $smallermtu = 1500;
579

    
580
	$flags = 0;
581
        if ($commonrx === false)
582
                $flags |= IFCAP_RXCSUM;
583
        if ($commontx === false)
584
                $flags |= IFCAP_TXCSUM;
585
	if ($commontso4 === false)
586
                $flags |= IFCAP_TSO4;
587
        if ($commontso6 === false)
588
                $flags |= IFCAP_TSO6;
589
        if ($commonlro === false)
590
                $flags |= IFCAP_LRO;
591

    
592
	foreach ($members as $member) {
593
		if (!array_key_exists($member, $checklist))
594
			continue;
595
		/* make sure the parent interface is up */
596
		pfSense_interface_mtu($member, $smallermtu);
597
		pfSense_interface_capabilities($member, -$flags);
598
		interfaces_bring_up($member);
599
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
600
	}
601
	
602
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
603

    
604
	interfaces_bring_up($laggif);
605

    
606
	return $laggif;
607
}
608

    
609
function interfaces_gre_configure() {
610
        global $config;
611

    
612
        $i = 0;
613
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
614
                foreach ($config['gres']['gre'] as $gre) {
615
                        if(empty($gre['greif']))
616
                                $gre['greif'] = "gre{$i}";
617
                        /* XXX: Maybe we should report any errors?! */
618
                        interface_gre_configure($gre);
619
                        $i++;
620
                }
621
        }
622
}
623

    
624
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
625
function interface_gre_configure(&$gre, $grekey = "") {
626
        global $config, $g;
627

    
628
	if (!is_array($gre))
629
		return -1;
630

    
631
	$realif = get_real_interface($gre['if']);
632
	$realifip = get_interface_ip($gre['if']);
633

    
634
	/* make sure the parent interface is up */
635
	interfaces_bring_up($realif);
636

    
637
	if ($g['booting'] || !(empty($gre['greif']))) {
638
		pfSense_interface_destroy($gre['greif']);
639
		pfSense_interface_create($gre['greif']);
640
		$greif = $gre['greif'];
641
	} else
642
		$greif = pfSense_interface_create("gre");
643

    
644
	/* Do not change the order here for more see gre(4) NOTES section. */
645
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
646
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
647
	if (isset($gre['link0']) && $gre['link0'])
648
		pfSense_interface_flags($greif, IFF_LINK0);
649
	if (isset($gre['link1']) && $gre['link1'])
650
		pfSense_interface_flags($greif, IFF_LINK1);
651
	if (isset($gre['link2']) && $gre['link2'])
652
		pfSense_interface_flags($greif, IFF_LINK2);
653

    
654
	if($greif)
655
		interfaces_bring_up($greif);
656
	else 
657
		log_error("Could not bring greif up -- variable not defined.");
658

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

    
663
	return $greif;
664
}
665

    
666
function interfaces_gif_configure() {
667
	global $config;
668
	$i = 0;
669
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
670
		foreach ($config['gifs']['gif'] as $gif) {
671
			if(empty($gif['gifif']))
672
				$gre['gifif'] = "gif{$i}";
673
			/* XXX: Maybe we should report any errors?! */
674
			interface_gif_configure($gif);
675
			$i++;
676
		}
677
	}
678
}
679

    
680
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
681
function interface_gif_configure(&$gif, $gifkey = "") {
682
	global $config, $g;
683

    
684
	if (!is_array($gif))
685
		return -1;
686

    
687
	$realif = get_real_interface($gif['if']);
688
	$realifip = get_interface_ip($gif['if']);
689

    
690
	/* make sure the parent interface is up */
691
	if($realif)
692
		interfaces_bring_up($realif);
693
	else 
694
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
695

    
696
	if ($g['booting'] || !(empty($gif['gifif']))) {
697
		pfSense_interface_destroy($gif['gifif']);
698
		pfSense_interface_create($gif['gifif']);
699
		$gifif = $gif['gifif'];
700
	} else
701
		$gifif = pfSense_interface_create("gif");
702

    
703
	/* Do not change the order here for more see gif(4) NOTES section. */
704
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
705
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
706
	if (isset($gif['link0']) && $gif['link0'])
707
		pfSense_interface_flags($gifif, IFF_LINK0);
708
	if (isset($gif['link1']) && $gif['link1'])
709
		pfSense_interface_flags($gifif, IFF_LINK1);
710
	if($gifif)
711
		interfaces_bring_up($gifif);
712
	else
713
		log_error("could not bring gifif up -- variable not defined");
714

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

    
719
	return $gifif;
720
}
721

    
722
function interfaces_configure() {
723
	global $config, $g;
724

    
725
	/* Set up our loopback interface */
726
	interfaces_loopback_configure();
727

    
728
	/* set up LAGG virtual interfaces */
729
	interfaces_lagg_configure();
730

    
731
	/* set up VLAN virtual interfaces */
732
	interfaces_vlan_configure();
733

    
734
	interfaces_qinq_configure();
735

    
736
	$iflist = get_configured_interface_with_descr();
737
	$delayed_list = array();
738
	$bridge_list = array();
739
	
740
	/* This is needed to speedup interfaces on bootup. */
741
	$reload = false;
742
	if ($g['booting'])
743
		$reload = true;
744

    
745
	foreach($iflist as $if => $ifname) {
746
		$realif = $config['interfaces'][$if]['if'];
747
		if (strstr($realif, "bridge")) 
748
			$bridge_list[$if] = $ifname;
749
		else if (strstr($realif, "gre"))
750
			$delayed_list[$if] = $ifname;
751
		else if (strstr($realif, "gif"))
752
			$delayed_list[$if] = $ifname;
753
		else if (strstr($realif, "ovpn")) {
754
			//echo "Delaying OpenVPN interface configuration...done.\n";
755
			continue;
756
		} else {
757
			if ($g['booting'])
758
				echo "Configuring {$ifname} interface...";
759
			if($g['debug'])
760
				log_error("Configuring {$ifname}");
761
			interface_configure($if, $reload);
762
			if ($g['booting']) 
763
				echo "done.\n";
764
		}
765
	}
766

    
767
	/* create the unconfigured wireless clones */
768
	interfaces_create_wireless_clones();
769

    
770
	/* set up GRE virtual interfaces */
771
	interfaces_gre_configure();
772

    
773
	/* set up GIF virtual interfaces */
774
	interfaces_gif_configure();
775
	
776
	foreach ($delayed_list as $if => $ifname) {
777
		if ($g['booting'])
778
			echo "Configuring {$ifname} interface...";
779
        	if ($g['debug'])
780
        		log_error("Configuring {$ifname}");
781

    
782
		interface_configure($if, $reload);
783

    
784
		if ($g['booting'])
785
			echo "done.\n";
786
	}
787

    
788
	/* set up BRIDGe virtual interfaces */
789
	interfaces_bridge_configure();
790

    
791
	foreach ($bridge_list as $if => $ifname) {
792
		if ($g['booting'])
793
			echo "Configuring {$ifname} interface...";
794
		if($g['debug'])
795
			log_error("Configuring {$ifname}");
796

    
797
		interface_configure($if, $reload);
798

    
799
		if ($g['booting'])
800
			echo "done.\n";
801
	}
802

    
803
	/* bring up vip interfaces */
804
	interfaces_vips_configure();
805

    
806
	/* configure interface groups */
807
	interfaces_group_setup();
808

    
809
	if (!$g['booting']) {
810
		/* reconfigure static routes (kernel may have deleted them) */
811
		system_routing_configure();
812

    
813
		/* reload IPsec tunnels */
814
		vpn_ipsec_configure();
815

    
816
		/* reload dhcpd (interface enabled/disabled status may have changed) */
817
		services_dhcpd_configure();
818

    
819
		/* restart dnsmasq */
820
		services_dnsmasq_configure();
821

    
822
		/* reload captive portal */
823
		captiveportal_init_rules();
824
	}
825

    
826
	return 0;
827
}
828

    
829
function interface_reconfigure($interface = "wan") {
830
	interface_bring_down($interface);
831
	interface_configure($interface, true);
832
}
833

    
834
function interface_vip_bring_down($vip) {
835
	global $g;
836

    
837
	switch ($vip['mode']) {
838
	case "proxyarp":
839
		$vipif = get_real_interface($vip['interface']);
840
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
841
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
842
		break;
843
	case "ipalias":
844
		$vipif = get_real_interface($vip['interface']);
845
		if(does_interface_exist($vipif))
846
			pfSense_interface_deladdress($vipif, $vip['subnet']);
847
		break;
848
	case "carp":
849
		$vipif = "vip" . $vip['vhid'];
850
		if(does_interface_exist($vipif)) 
851
			pfSense_interface_destroy($vipif);
852
		break;
853
	case "carpdev-dhcp":
854
		$vipif = "vip" . $vip['vhid'];
855
		if(does_interface_exist($vipif)) 
856
			pfSense_interface_destroy($vipif);
857
		break;
858
	}
859
}
860

    
861
function interface_bring_down($interface = "wan", $destroy = false) {
862
	global $config, $g;
863

    
864
	if (!isset($config['interfaces'][$interface]))
865
		return; 
866

    
867
	$ifcfg = $config['interfaces'][$interface];
868

    
869
	$realif = get_real_interface($interface);
870

    
871
	switch ($ifcfg['ipaddr']) {
872
	case "ppp":
873
	case "pppoe":
874
	case "pptp":
875
	case "l2tp":
876
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
877
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
878
				if ($realif == $ppp['if']) {
879
					if (file_exists("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid")) {
880
						killbypid("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid");
881
						sleep(5);
882
					}
883
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
884
					if (isset($ppp['ondemand']) && !$destroy)
885
						send_event("interface reconfigure {$interface}");
886
					break;
887
				}
888
			}
889
		}
890
		break;
891
	case "carpdev-dhcp":
892
		/* 
893
		 * NB: When carpdev gets enabled it would be better to be handled as all
894
		 *	   other interfaces! 
895
		 */
896
	case "dhcp":
897
		$pid = find_dhclient_process($realif);
898
		if($pid)
899
			mwexec("kill {$pid}");
900
		sleep(1);
901
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
902
		if(does_interface_exist("$realif")) {
903
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
904
			if ($destroy == true)
905
				pfSense_interface_flags($realif, -IFF_UP);
906
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
907
		}
908
		break;
909
	default:
910
		if(does_interface_exist("$realif")) {
911
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
912
			if ($destroy == true)
913
				pfSense_interface_flags($realif, -IFF_UP);
914
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
915
		}
916
		break;
917
	}
918

    
919
	/* remove interface up file if it exists */
920
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
921
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
922
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
923
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
924
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
925
	
926
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
927
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
928
	if (is_array($ifcfg['wireless'])) {
929
		mwexec(kill_hostapd($realif));
930
		mwexec(kill_wpasupplicant($realif));
931
	}
932

    
933
	if ($destroy == true) {
934
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
935
			pfSense_interface_destroy($realif);
936
	}	
937

    
938
	return;
939
}
940

    
941
function interfaces_ptpid_used($ptpid) {
942
	global $config;
943

    
944
	if (is_array($config['ppps']['ppp']))
945
		foreach ($config['ppps']['ppp'] as & $settings)
946
			if ($ptpid == $settings['ptpid'])
947
				return true;
948

    
949
	return false;
950
}
951

    
952
function interfaces_ptpid_next() {
953

    
954
	$ptpid = 0;
955
	while(interfaces_ptpid_used($ptpid))
956
		$ptpid++;
957

    
958
	return $ptpid;
959
}
960

    
961
function getMPDCRONSettings($pppif_) {
962
	global $config;
963
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
964
	if (is_array($config['cron']['item'])) {
965
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
966
			$item = $config['cron']['item'][$i];
967
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
968
				return array("ID" => $i, "ITEM" => $item);
969
			}
970
		}
971
	}
972
	return NULL;
973
}
974

    
975
function handle_pppoe_reset($post_array) {
976
	global $config, $g;
977

    
978
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
979

    
980
	$pppif = $post_array['type'].$post_array['ptpid'];
981
	if (!is_array($config['cron']['item'])) 
982
		$config['cron']['item'] = array(); 
983
	$itemhash = getMPDCRONSettings($pppif);
984
	$item = $itemhash['ITEM'];
985
	
986
	// reset cron items if necessary and return
987
	if (empty($post_array['pppoe-reset-type'])) {
988
		if (isset($item))
989
			unset($config['cron']['item'][$itemhash['ID']]);
990
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
991
		return;
992
	}
993

    
994
	if (empty($item)) 
995
		$item = array();
996
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
997
		$item['minute'] = $post_array['pppoe_resetminute'];
998
		$item['hour'] = $post_array['pppoe_resethour'];
999
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1000
			$date = explode("/", $post_array['pppoe_resetdate']);
1001
			$item['mday'] = $date[1];
1002
			$item['month'] = $date[0];
1003
		} else {
1004
			$item['mday'] = "*";
1005
			$item['month'] = "*";
1006
		}
1007
		$item['wday'] = "*";
1008
		$item['who'] = "root";
1009
		$item['command'] = $cron_cmd_file.$pppif;
1010
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1011
		switch ($post_array['pppoe_pr_preset_val']) {
1012
			case "monthly":
1013
				$item['minute'] = "0";
1014
				$item['hour'] = "0";
1015
				$item['mday'] = "1";
1016
				$item['month'] = "*";
1017
				$item['wday'] = "*";
1018
				$item['who'] = "root";
1019
				$item['command'] = $cron_cmd_file.$pppif;
1020
				break;
1021
	        case "weekly":
1022
				$item['minute'] = "0";
1023
				$item['hour'] = "0";
1024
				$item['mday'] = "*";
1025
				$item['month'] = "*";
1026
				$item['wday'] = "0";
1027
				$item['who'] = "root";
1028
				$item['command'] = $cron_cmd_file.$pppif;
1029
				break;
1030
			case "daily":
1031
				$item['minute'] = "0";
1032
				$item['hour'] = "0";
1033
				$item['mday'] = "*";
1034
				$item['month'] = "*";
1035
				$item['wday'] = "*";
1036
				$item['who'] = "root";
1037
				$item['command'] = $cron_cmd_file.$pppif;
1038
				break;
1039
			case "hourly":
1040
				$item['minute'] = "0";
1041
				$item['hour'] = "*";
1042
				$item['mday'] = "*";
1043
				$item['month'] = "*";
1044
				$item['wday'] = "*";
1045
				$item['who'] = "root";
1046
				$item['command'] = $cron_cmd_file.$pppif;
1047
				break;
1048
		} // end switch
1049
	} else {
1050
		/* test whether a cron item exists and unset() it if necessary */
1051
		$itemhash = getMPDCRONSettings($pppif);
1052
		$item = $itemhash['ITEM'];
1053
		if (isset($item))
1054
			unset($config['cron']['item'][$itemhash['ID']]); 
1055
	}// end if
1056
	if (isset($itemhash['ID'])) 
1057
		$config['cron']['item'][$itemhash['ID']] = $item;
1058
	else 
1059
		$config['cron']['item'][] = $item;
1060
}
1061

    
1062
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1063
*	It writes the mpd config file to /var/etc every time the link is opened.
1064
*/
1065

    
1066
function interface_ppps_configure($interface) {
1067
	global $config, $g;
1068
	
1069
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1070
	if(!is_dir("/var/spool/lock")) {
1071
		exec("/bin/mkdir -p /var/spool/lock");
1072
		exec("/bin/chmod a+rw /var/spool/lock/.");
1073
	}
1074
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1075
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1076
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1077
		
1078
	$ifcfg = $config['interfaces'][$interface];
1079
	if (!isset($ifcfg['enable']))
1080
		return 0;
1081
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1082
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1083
			if ($ifcfg['if'] == $ppp['if'])
1084
				break;
1085
		}
1086
	}
1087
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1088
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1089
		return 0;
1090
	}
1091
	$pppif = $ifcfg['if'];
1092
	if ($ppp['type'] == "ppp")
1093
		$type = "modem";
1094
	else
1095
		$type = $ppp['type'];
1096
	$upper_type = strtoupper($ppp['type']);	
1097
	
1098
	if($g['booting']) {
1099
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1100
		echo "starting {$pppif} link...";
1101
		// Do not re-configure the interface if we are booting and it's already been started
1102
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1103
			return 0;
1104
	}
1105
	
1106
	$ports = explode(',',$ppp['ports']);
1107
	if ($type != "modem") {
1108
		foreach ($ports as $pid => $port)
1109
			$ports[$pid] = get_real_interface($port);
1110
	}
1111
	$localips = explode(',',$ppp['localip']);
1112
	$gateways = explode(',',$ppp['gateway']);
1113
	$subnets = explode(',',$ppp['subnet']);
1114
	
1115
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1116
	to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1117
	*/
1118
	foreach($ports as $pid => $port){
1119
		switch ($ppp['type']) {
1120
			case "pppoe": 
1121
				/* Bring the parent interface up */
1122
				interfaces_bring_up($port);
1123
				break;
1124
			case "pptp":
1125
			case "l2tp":
1126
				/* configure interface */
1127
				if(is_ipaddr($localips[$pid])){
1128
					// Manually configure interface IP/subnet
1129
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1130
					interfaces_bring_up($port);
1131
				} else if (empty($localips[$pid]))
1132
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1133
				
1134
				if(!is_ipaddr($localips[$pid])){
1135
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure.");
1136
					return 0;
1137
				}
1138
				/* XXX: This needs to go away soon! [It's commented out!] */
1139
				/* Configure the gateway (remote IP ) */
1140
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1141
					/* XXX: Fix later 
1142
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1143
					if(!is_ipaddr($gateways[$pid])) {
1144
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1145
						return 0;
1146
					}
1147
					*/
1148
				}
1149
				if(!is_ipaddr($gateways[$pid])){
1150
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1151
					return 0;
1152
				}
1153
				break;
1154
			case "ppp":
1155
				if (!file_exists("{$port}")) {
1156
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1157
					return 0;
1158
				}
1159
				break;
1160
			default:
1161
				log_error("Unkown {$type} configured as ppp interface.");
1162
				break;
1163
		}
1164
	}
1165
	
1166
	if (is_array($ports) && count($ports) > 1)
1167
		$multilink = "enable";
1168
	else
1169
		$multilink = "disable";
1170
	
1171
	if ($type == "modem"){
1172
		if (is_ipaddr($ppp['localip']))
1173
			$localip = $ppp['localip'];
1174
		else
1175
			$localip = '0.0.0.0';
1176

    
1177
		if (is_ipaddr($ppp['gateway']))
1178
			$gateway = $ppp['gateway'];
1179
		else
1180
			$gateway = "10.64.64.{$pppid}";
1181
		$ranges = "{$localip}/0 {$gateway}/0";
1182
		
1183
		if (empty($ppp['apnum']))	
1184
			$ppp['apnum'] = 1;
1185
	} else
1186
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1187

    
1188
	if (isset($ppp['ondemand'])) 
1189
		$ondemand = "enable";
1190
	else
1191
		$ondemand = "disable";
1192
	if (!isset($ppp['idletimeout']))
1193
		$ppp['idletimeout'] = 0;
1194

    
1195
	if (empty($ppp['username']) && $type == "modem"){
1196
		$ppp['username'] = "user";
1197
		$ppp['password'] = "none";
1198
	}
1199
	if (empty($ppp['password']) && $type == "modem")
1200
		$passwd = "none";
1201
	else
1202
		$passwd = base64_decode($ppp['password']);
1203

    
1204
	$bandwidths = explode(',',$ppp['bandwidth']);
1205
	$mtus = explode(',',$ppp['mtu']);
1206
	$mrus = explode(',',$ppp['mru']);
1207

    
1208
	if (isset($ppp['mrru']))
1209
		$mrrus = explode(',',$ppp['mrru']);
1210

    
1211
	// Construct the mpd.conf file
1212
	$mpdconf = <<<EOD
1213
startup:
1214
	# configure the console
1215
	set console close
1216
	# configure the web server
1217
	set web close
1218

    
1219
default:
1220
{$ppp['type']}client:
1221
	create bundle static {$interface}
1222
	set iface name {$pppif}
1223

    
1224
EOD;
1225
	$setdefaultgw = false;
1226
	$founddefaultgw = false;
1227
	if (is_array($config['gateways']['gateway_item'])) {
1228
		foreach($config['gateways']['gateway_item'] as $gateway) {
1229
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1230
				$setdefaultgw = true;
1231
				break;
1232
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1233
				$founddefaultgw = true;
1234
				break;
1235
			}
1236
		}
1237
	}
1238
	
1239
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1240
		$setdefaultgw = true;
1241
		$mpdconf .= <<<EOD
1242
	set iface route default
1243

    
1244
EOD;
1245
	}
1246
	$mpdconf .= <<<EOD
1247
	set iface {$ondemand} on-demand
1248
	set iface idle {$ppp['idletimeout']}
1249

    
1250
EOD;
1251

    
1252
	if (isset($ppp['ondemand']))
1253
		$mpdconf .= <<<EOD
1254
	set iface addrs 10.10.1.1 10.10.1.2
1255

    
1256
EOD;
1257
	
1258
	if (isset($ppp['tcpmssfix']))
1259
		$tcpmss = "disable";
1260
	else
1261
		$tcpmss = "enable";
1262
		$mpdconf .= <<<EOD
1263
	set iface {$tcpmss} tcpmssfix
1264

    
1265
EOD;
1266

    
1267
	$mpdconf .= <<<EOD
1268
	set iface up-script /usr/local/sbin/ppp-linkup
1269
	set iface down-script /usr/local/sbin/ppp-linkdown
1270
	set ipcp ranges {$ranges}
1271

    
1272
EOD;
1273
	if (isset($ppp['vjcomp']))
1274
		$mpdconf .= <<<EOD
1275
	set ipcp no vjcomp
1276

    
1277
EOD;
1278

    
1279
	if (isset($config['system']['dnsallowoverride']))
1280
		$mpdconf .= <<<EOD
1281
	set ipcp enable req-pri-dns
1282
	set ipcp enable req-sec-dns
1283

    
1284
EOD;
1285
	if (!isset($ppp['verbose_log']))
1286
		$mpdconf .= <<<EOD
1287
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1288

    
1289
EOD;
1290
	foreach($ports as $pid => $port){
1291
		$port = get_real_interface($port);
1292
		$mpdconf .= <<<EOD
1293

    
1294
	create link static {$interface}_link{$pid} {$type}
1295
	set link action bundle {$interface}
1296
	set link {$multilink} multilink
1297
	set link keep-alive 10 60
1298
	set link max-redial 0
1299

    
1300
EOD;
1301
		if (isset($ppp['shortseq']))
1302
			$mpdconf .= <<<EOD
1303
	set link no shortseq
1304

    
1305
EOD;
1306

    
1307
		if (isset($ppp['acfcomp']))
1308
			$mpdconf .= <<<EOD
1309
	set link no acfcomp
1310

    
1311
EOD;
1312

    
1313
		if (isset($ppp['protocomp']))
1314
			$mpdconf .= <<<EOD
1315
	set link no protocomp
1316

    
1317
EOD;
1318

    
1319
		$mpdconf .= <<<EOD
1320
	set link disable chap pap
1321
	set link accept chap pap eap
1322
	set link disable incoming
1323

    
1324
EOD;
1325

    
1326

    
1327
		if (!empty($bandwidths[$pid]))
1328
			$mpdconf .= <<<EOD
1329
	set link bandwidth {$bandwidths[$pid]}
1330

    
1331
EOD;
1332

    
1333
		if (empty($mtus[$pid]))
1334
			$mtus[$pid] = "1492";
1335
			$mpdconf .= <<<EOD
1336
	set link mtu {$mtus[$pid]}
1337

    
1338
EOD;
1339

    
1340
		if (!empty($mrus[$pid]))
1341
			$mpdconf .= <<<EOD
1342
	set link mru {$mrus[$pid]}
1343

    
1344
EOD;
1345

    
1346
		if (!empty($mrrus[$pid]))
1347
			$mpdconf .= <<<EOD
1348
	set link mrru {$mrrus[$pid]}
1349

    
1350
EOD;
1351

    
1352
		$mpdconf .= <<<EOD
1353
	set auth authname "{$ppp['username']}"
1354
	set auth password {$passwd}
1355

    
1356
EOD;
1357
		if ($type == "modem") {
1358
			$mpdconf .= <<<EOD
1359
	set modem device {$ppp['ports']}
1360
	set modem script DialPeer
1361
	set modem idle-script Ringback
1362
	set modem watch -cd
1363
	set modem var \$DialPrefix "DT"
1364
	set modem var \$Telephone "{$ppp['phone']}"
1365

    
1366
EOD;
1367
		}
1368
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1369
			$mpdconf .= <<<EOD
1370
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1371

    
1372
EOD;
1373
		}
1374
		if (isset($ppp['initstr']) && $type == "modem") {
1375
			$initstr = base64_decode($ppp['initstr']);
1376
			$mpdconf .= <<<EOD
1377
	set modem var \$InitString "{$initstr}"
1378

    
1379
EOD;
1380
		}
1381
		if (isset($ppp['simpin']) && $type == "modem") {
1382
			$mpdconf .= <<<EOD
1383
	set modem var \$SimPin "{$ppp['simpin']}"
1384
	set modem var \$PinWait "{$ppp['pin-wait']}"
1385

    
1386
EOD;
1387
		}
1388
		if (isset($ppp['apn']) && $type == "modem") {
1389
			$mpdconf .= <<<EOD
1390
	set modem var \$APN "{$ppp['apn']}"
1391
	set modem var \$APNum "{$ppp['apnum']}"
1392

    
1393
EOD;
1394
		}
1395
		if (isset($ppp['provider']) && $type == "pppoe") {
1396
			$mpdconf .= <<<EOD
1397
	set pppoe service "{$ppp['provider']}"
1398

    
1399
EOD;
1400
		}
1401
		if ($type == "pppoe")
1402
			$mpdconf .= <<<EOD
1403
	set pppoe iface {$port}
1404

    
1405
EOD;
1406

    
1407
		if ($type == "pptp" || $type == "l2tp") {
1408
			$mpdconf .= <<<EOD
1409
	set {$type} self {$localips[$pid]}
1410
	set {$type} peer {$gateways[$pid]}
1411
	set {$type} disable windowing
1412

    
1413
EOD;
1414
		}
1415
		
1416
		$mpdconf .= "\topen\r\n";
1417
	} //end foreach($port)
1418

    
1419

    
1420
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1421
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1422
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1423
	else {
1424
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1425
		if (!$fd) {
1426
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1427
			return 0;
1428
		}
1429
		// Write out mpd_ppp.conf
1430
		fwrite($fd, $mpdconf);
1431
		fclose($fd);
1432
	}
1433

    
1434
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1435
	if (isset($ppp['uptime'])) {
1436
		if (!file_exists("/conf/{$pppif}.log")) {
1437
			conf_mount_rw();
1438
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1439
			conf_mount_ro();
1440
		}
1441
	} else {
1442
		if (file_exists("/conf/{$pppif}.log")) {
1443
			conf_mount_rw();
1444
			mwexec("rm -f /conf/{$pppif}.log");
1445
			conf_mount_ro();
1446
		}
1447
	}
1448
		
1449
	/* fire up mpd */
1450
	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");
1451

    
1452
	// Check for PPPoE periodic reset request 
1453
	if ($type == "pppoe") {
1454
		if (isset($ppp['pppoe-reset-type']))
1455
			setup_pppoe_reset_file($ppp['if'], $interface);
1456
		else
1457
			setup_pppoe_reset_file($ppp['if']);
1458
	}
1459

    
1460
	return 1;
1461
}
1462

    
1463
function interfaces_carp_setup() {
1464
	global $g, $config;
1465

    
1466
	$balanacing = "";
1467
	$pfsyncinterface = "";
1468
	$pfsyncenabled = "";
1469
	if(isset($config['system']['developerspew'])) {
1470
		$mt = microtime();
1471
		echo "interfaces_carp_setup() being called $mt\n";
1472
	}
1473

    
1474
	// Prepare CmdCHAIN that will be used to execute commands.
1475
	$cmdchain = new CmdCHAIN();	
1476

    
1477
	if ($g['booting']) {
1478
		echo "Configuring CARP settings...";
1479
		mute_kernel_msgs();
1480
	}
1481

    
1482
	/* suck in configuration items */
1483
	if($config['installedpackages']['carpsettings']) {
1484
		if($config['installedpackages']['carpsettings']['config']) {
1485
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1486
				$pfsyncenabled = $carp['pfsyncenabled'];
1487
				$balanacing = $carp['balancing'];
1488
				$pfsyncinterface = $carp['pfsyncinterface'];
1489
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1490
			}
1491
		}
1492
	} else {
1493
		unset($pfsyncinterface);
1494
		unset($balanacing);
1495
		unset($pfsyncenabled);
1496
	}
1497

    
1498
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1499
	if($balanacing) {
1500
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1501
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1502
	} else
1503
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1504

    
1505
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1506
	if (!empty($pfsyncinterface))
1507
		$carp_sync_int = get_real_interface($pfsyncinterface);
1508

    
1509
	if($g['booting']) {
1510
		/*    install rules to alllow pfsync to sync up during boot
1511
		 *    carp interfaces will remain down until the bootup sequence finishes
1512
		 */
1513
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1514
		if ($fd) {
1515
			fwrite($fd, "pass quick proto carp all keep state\n");
1516
			fwrite($fd, "pass quick proto pfsync all\n");
1517
			fwrite($fd, "pass out quick from any to any keep state\n");
1518
			fclose($fd);
1519
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1520
		} else
1521
			log_error("Could not create rules.boot file!");
1522
	}
1523

    
1524
	/* setup pfsync interface */
1525
	if($carp_sync_int and $pfsyncenabled) {
1526
		if (is_ipaddr($pfsyncpeerip))
1527
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1528
		else
1529
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1530
	} else
1531
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1532

    
1533
	if($config['virtualip']['vip'])
1534
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1535
	else
1536
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1537
	
1538
	if($g['debug'])
1539
		$cmdchain->setdebug(); // optional for verbose logging
1540

    
1541
	$cmdchain->execute();
1542
	$cmdchain->clear();
1543

    
1544
	if ($g['booting']) {
1545
		unmute_kernel_msgs();
1546
		echo "done.\n";
1547
	}
1548
}
1549

    
1550
function interface_proxyarp_configure($interface = "") {
1551
	global $config, $g;
1552
	if(isset($config['system']['developerspew'])) {
1553
		$mt = microtime();
1554
		echo "interface_proxyarp_configure() being called $mt\n";
1555
	}
1556

    
1557
	/* kill any running choparp */
1558
	if (empty($interface))
1559
		killbyname("choparp");
1560
	else {
1561
		$vipif = get_real_interface($interface);
1562
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1563
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1564
	}
1565

    
1566
	$paa = array();
1567
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1568

    
1569
		/* group by interface */
1570
		foreach ($config['virtualip']['vip'] as $vipent) {
1571
			if ($vipent['mode'] === "proxyarp") {
1572
				if ($vipent['interface'])
1573
					$proxyif = $vipent['interface'];
1574
				else
1575
					$proxyif = "wan";
1576
				
1577
				if (!empty($interface) && $interface != $proxyif)
1578
					continue;
1579

    
1580
				if (!is_array($paa[$proxyif]))
1581
					$paa[$proxyif] = array();
1582

    
1583
				$paa[$proxyif][] = $vipent;
1584
			}
1585
		}
1586
	}
1587

    
1588
	if (!empty($interface)) {
1589
		if (is_array($paa[$interface])) {
1590
			$paaifip = get_interface_ip($interface);
1591
                        if (!is_ipaddr($paaifip))
1592
                                return;
1593
                        $args = get_real_interface($interface) . " auto";
1594
                        foreach ($paa[$interface] as $paent) {
1595
                                if (isset($paent['subnet']))
1596
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1597
                                else if (isset($paent['range']))
1598
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1599
                        }
1600
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1601
		}
1602
	} else if (count($paa) > 0) {
1603
		foreach ($paa as $paif => $paents)  {
1604
			$paaifip = get_interface_ip($paif);
1605
			if (!is_ipaddr($paaifip))
1606
				continue;
1607
			$args = get_real_interface($paif) . " auto";
1608
			foreach ($paents as $paent) {
1609
				if (isset($paent['subnet']))
1610
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1611
				else if (isset($paent['range']))
1612
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1613
			}
1614
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1615
		}
1616
	}
1617
}
1618

    
1619
function interfaces_vips_configure($interface = "") {
1620
	global $g, $config;
1621
	if(isset($config['system']['developerspew'])) {
1622
		$mt = microtime();
1623
		echo "interfaces_vips_configure() being called $mt\n";
1624
	}
1625
	$paa = array();
1626
	if(is_array($config['virtualip']['vip'])) {
1627
		$carp_setuped = false;
1628
		$anyproxyarp = false;
1629
		foreach ($config['virtualip']['vip'] as $vip) {
1630
			switch ($vip['mode']) {
1631
			case "proxyarp":
1632
				/* nothing it is handled on interface_proxyarp_configure() */
1633
				if ($interface <> "" && $vip['interface'] <> $interface)
1634
					continue;
1635
				$anyproxyarp = true;
1636
				break;
1637
			case "ipalias":
1638
				if ($interface <> "" && $vip['interface'] <> $interface)
1639
					continue;
1640
				interface_ipalias_configure(&$vip);
1641
				break;
1642
			case "carp":
1643
				if ($interface <> "" && $vip['interface'] <> $interface)
1644
					continue;
1645
				if ($carp_setuped == false) {
1646
					interfaces_carp_setup();
1647
					$carp_setuped = true;
1648
				}
1649
				interface_carp_configure($vip);
1650
				break;
1651
			case "carpdev-dhcp":
1652
				if ($interface <> "" && $vip['interface'] <> $interface)
1653
					continue;
1654
				interface_carpdev_configure($vip);
1655
				break;
1656
			}
1657
		}
1658
		
1659
		if ($anyproxyarp == true)
1660
			interface_proxyarp_configure();
1661
	}
1662
}
1663

    
1664
function interface_ipalias_configure(&$vip) {
1665

    
1666
	if ($vip['mode'] == "ipalias") {
1667
		$if = get_real_interface($vip['interface']);
1668
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1669
	}
1670
}
1671

    
1672
function interface_reload_carps($cif) {
1673
	global $config;
1674

    
1675
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1676
	if (empty($carpifs))
1677
		return;
1678

    
1679
	$carps = explode(" ", $carpifs);
1680
	if(is_array($config['virtualip']['vip'])) {
1681
		$viparr = &$config['virtualip']['vip'];
1682
		foreach ($viparr as $vip) {
1683
			if (in_array($vip['carpif'], $carps)) {
1684
				switch ($vip['mode']) {
1685
				case "carp":
1686
					interface_vip_bring_down($vip);
1687
					sleep(1);
1688
					interface_carp_configure($vip);
1689
					break;
1690
				case "carpdev-dhcp":
1691
					interface_vip_bring_down($vip);
1692
					sleep(1);
1693
					interface_carpdev_configure($vip);
1694
					break;
1695
				case "ipalias":
1696
					interface_vip_bring_down($vip);
1697
					sleep(1);
1698
					interface_ipalias_configure($vip);
1699
					break;
1700
				}
1701
			}
1702
		}
1703
	}
1704
}
1705

    
1706
function interface_carp_configure(&$vip) {
1707
	global $config, $g;
1708
	if(isset($config['system']['developerspew'])) {
1709
		$mt = microtime();
1710
		echo "interface_carp_configure() being called $mt\n";
1711
	}
1712

    
1713
	if ($vip['mode'] != "carp")
1714
		return;
1715

    
1716
	$vip_password = $vip['password'];
1717
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1718
	if ($vip['password'] != "")
1719
		$password = " pass {$vip_password}";
1720

    
1721
	// set the vip interface to the vhid
1722
	$vipif = "vip{$vip['vhid']}";
1723

    
1724
	$interface = interface_translate_type_to_real($vip['interface']);
1725
	/*
1726
	 * ensure the interface containing the VIP really exists
1727
 	 * prevents a panic if the interface is missing or invalid
1728
	 */
1729
	$realif = get_real_interface($vip['interface']);
1730
	if (!does_interface_exist($realif)) {
1731
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1732
		return;
1733
	}
1734

    
1735
	/* Ensure CARP IP really exists prior to loading up. */
1736
	$ww_subnet_ip = find_interface_ip($realif);
1737
	$ww_subnet_bits = find_interface_subnet($realif);
1738
	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'])) {
1739
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1740
		return;
1741
	}
1742

    
1743
	/* create the carp interface and setup */
1744
	if (does_interface_exist($vipif)) {
1745
		pfSense_interface_flags($vipif, -IFF_UP);
1746
	} else {
1747
		$carpif = pfSense_interface_create("carp");
1748
		pfSense_interface_rename($carpif, $vipif);
1749
		pfSense_ngctl_name("{$carpif}:", $vipif);
1750
	}
1751

    
1752
	/* invalidate interface cache */
1753
	get_interface_arr(true);
1754

    
1755
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1756
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1757

    
1758
	interfaces_bring_up($vipif);
1759
	
1760
	return $vipif;
1761
}
1762

    
1763
function interface_carpdev_configure(&$vip) {
1764
	global $g;
1765

    
1766
	if ($vip['mode'] != "carpdev-dhcp")
1767
		return;
1768

    
1769
	$vip_password = $vip['password'];
1770
	$vip_password = str_replace(" ", "", $vip_password);
1771
	if($vip['password'] != "")
1772
		$password = " pass \"" . $vip_password . "\"";
1773

    
1774
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1775
	if (empty($vip['interface']))
1776
		return;
1777

    
1778
	$vipif = "vip" . $vip['vhid'];
1779
	$realif = interface_translate_type_to_real($vip['interface']);
1780
	interfaces_bring_up($realif);
1781
	/*
1782
	 * ensure the interface containing the VIP really exists
1783
	 * prevents a panic if the interface is missing or invalid
1784
	 */
1785
	if (!does_interface_exist($realif)) {
1786
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1787
		return;
1788
	}
1789

    
1790
	if (does_interface_exist($vipif)) {
1791
		interface_bring_down($vipif);
1792
	} else {
1793
		$carpdevif = exec("/sbin/ifconfig carp create");
1794
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1795
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1796
	}
1797

    
1798
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1799
	interfaces_bring_up($vipif);
1800

    
1801
	/*
1802
	 * XXX: BIG HACK but carpdev needs ip services active
1803
	 *      before even starting something as dhclient.
1804
	 *      I do not know if this is a feature or a bug
1805
	 *      but better than track it make it work ;) .
1806
	 */
1807
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1808
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1809

    
1810
	/* generate dhclient_wan.conf */
1811
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1812
	if ($fd) {
1813
		$dhclientconf = "";
1814

    
1815
		$dhclientconf .= <<<EOD
1816
interface "{$vipif}" {
1817
timeout 60;
1818
retry 1;
1819
select-timeout 0;
1820
initial-interval 1;
1821
script "/sbin/dhclient-script";
1822
}
1823

    
1824
EOD;
1825

    
1826
		fwrite($fd, $dhclientconf);
1827
		fclose($fd);
1828

    
1829
		/* fire up dhclient */
1830
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1831
	} else {
1832
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1833
		mwexec("/sbin/dhclient -b {$vipif}");
1834
	}
1835

    
1836
	return $vipif;
1837
}
1838

    
1839
function interface_wireless_clone($realif, $wlcfg) {
1840
	global $config, $g;
1841
	/*   Check to see if interface has been cloned as of yet.  
1842
	 *   If it has not been cloned then go ahead and clone it.
1843
	 */
1844
	$needs_clone = false;
1845
	if(is_array($wlcfg['wireless']))
1846
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1847
	else
1848
		$wlcfg_mode = $wlcfg['mode'];
1849
	switch($wlcfg_mode) {
1850
		 case "hostap":
1851
			$mode = "wlanmode hostap";
1852
			break;
1853
		 case "adhoc":
1854
			$mode = "wlanmode adhoc";
1855
			break;
1856
		 default:
1857
			$mode = "";
1858
			break;
1859
	}
1860
	$baseif = interface_get_wireless_base($wlcfg['if']);
1861
	if(does_interface_exist($realif)) {
1862
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1863
		$ifconfig_str = implode($output);
1864
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1865
			log_error("Interface {$realif} changed to hostap mode");
1866
			$needs_clone = true;
1867
		}
1868
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1869
			log_error("Interface {$realif} changed to adhoc mode");
1870
			$needs_clone = true;
1871
		}
1872
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1873
			log_error("Interface {$realif} changed to infrastructure mode");
1874
			$needs_clone = true;
1875
		}
1876
	} else {
1877
		$needs_clone = true;
1878
	}
1879

    
1880
	if($needs_clone == true) {
1881
		/* remove previous instance if it exists */
1882
		if(does_interface_exist($realif))
1883
			pfSense_interface_destroy($realif);
1884

    
1885
		log_error("Cloning new wireless interface {$realif}");
1886
		// Create the new wlan interface. FreeBSD returns the new interface name.
1887
		// example:  wlan2
1888
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1889
		if($ret <> 0) {
1890
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1891
			return false;
1892
		}
1893
		$newif = trim($out[0]);
1894
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1895
		pfSense_interface_rename($newif, $realif);
1896
		// FIXME: not sure what ngctl is for. Doesn't work.
1897
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1898
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
1899
	}
1900
	return true;
1901
}
1902

    
1903
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1904
	global $config, $g;
1905

    
1906
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1907
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1908
	                         'regdomain', 'regcountry', 'reglocation');
1909

    
1910
	if(!is_interface_wireless($ifcfg['if']))
1911
		return;
1912

    
1913
	$baseif = interface_get_wireless_base($ifcfg['if']);
1914

    
1915
	// Sync shared settings for assigned clones
1916
	$iflist = get_configured_interface_list(false, true);
1917
	foreach ($iflist as $if) {
1918
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1919
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1920
				foreach ($shared_settings as $setting) {
1921
					if ($sync_changes) {
1922
						if (isset($ifcfg['wireless'][$setting]))
1923
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1924
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1925
							unset($config['interfaces'][$if]['wireless'][$setting]);
1926
					} else {
1927
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1928
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1929
						else if (isset($ifcfg['wireless'][$setting]))
1930
							unset($ifcfg['wireless'][$setting]);
1931
					}
1932
				}
1933
				if (!$sync_changes)
1934
					break;
1935
			}
1936
		}
1937
	}
1938

    
1939
	// Read or write settings at shared area
1940
	if (isset($config['wireless']['interfaces'][$baseif])) {
1941
		foreach ($shared_settings as $setting) {
1942
			if ($sync_changes) {
1943
				if (isset($ifcfg['wireless'][$setting]))
1944
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
1945
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1946
					unset($config['wireless']['interfaces'][$baseif][$setting]);
1947
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
1948
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1949
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
1950
				else if (isset($ifcfg['wireless'][$setting]))
1951
					unset($ifcfg['wireless'][$setting]);
1952
			}
1953
		}
1954
	}
1955

    
1956
	// Sync the mode on the clone creation page with the configured mode on the interface
1957
	if (interface_is_wireless_clone($ifcfg['if'])) {
1958
		foreach ($config['wireless']['clone'] as &$clone) {
1959
			if ($clone['cloneif'] == $ifcfg['if']) {
1960
				if ($sync_changes) {
1961
					$clone['mode'] = $ifcfg['wireless']['mode'];
1962
				} else {
1963
					$ifcfg['wireless']['mode'] = $clone['mode'];
1964
				}
1965
				break;
1966
			}
1967
		}
1968
		unset($clone);
1969
	}
1970
}
1971

    
1972
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1973
	global $config, $g;
1974

    
1975
	/*    open up a shell script that will be used to output the commands.
1976
	 *    since wireless is changing a lot, these series of commands are fragile
1977
     *    and will sometimes need to be verified by a operator by executing the command
1978
     *    and returning the output of the command to the developers for inspection.  please
1979
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1980
	 */
1981

    
1982
	// Remove script file
1983
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1984

    
1985
	// Clone wireless nic if needed.
1986
	interface_wireless_clone($if, $wl);
1987

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

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

    
1995
	/* set values for /path/program */
1996
	$hostapd = "/usr/sbin/hostapd";
1997
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1998
	$ifconfig = "/sbin/ifconfig";
1999
	$sysctl = "/sbin/sysctl";
2000
	$killall = "/usr/bin/killall";
2001

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

    
2004
	$wlcmd = array();
2005
	$wl_sysctl = array();
2006
	/* Make sure it's up */
2007
	$wlcmd[] = "up";
2008
	/* Set a/b/g standard */
2009
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2010
	$wlcmd[] = "mode " . escapeshellarg($standard);
2011

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

    
2017
	/* Set ssid */
2018
	if($wlcfg['ssid'])
2019
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2020

    
2021
	/* Set 802.11g protection mode */
2022
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2023

    
2024
	/* set wireless channel value */
2025
	if(isset($wlcfg['channel'])) {
2026
		if($wlcfg['channel'] == "0") {
2027
			$wlcmd[] = "channel any";
2028
		} else {
2029
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2030
		}
2031
	}
2032

    
2033
	/* Set antenna diversity value */
2034
	if(isset($wlcfg['diversity']))
2035
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2036

    
2037
	/* Set txantenna value */
2038
	if(isset($wlcfg['txantenna']))
2039
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2040

    
2041
	/* Set rxantenna value */
2042
	if(isset($wlcfg['rxantenna']))
2043
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2044

    
2045
	/* set Distance value */
2046
	if($wlcfg['distance'])
2047
		$distance = escapeshellarg($wlcfg['distance']);
2048

    
2049
	/* Set wireless hostap mode */
2050
	if ($wlcfg['mode'] == "hostap") {
2051
		$wlcmd[] = "mediaopt hostap";
2052
	} else {
2053
		$wlcmd[] = "-mediaopt hostap";
2054
	}
2055

    
2056
	/* Set wireless adhoc mode */
2057
	if ($wlcfg['mode'] == "adhoc") {
2058
		$wlcmd[] = "mediaopt adhoc";
2059
	} else {
2060
		$wlcmd[] = "-mediaopt adhoc";
2061
	}
2062

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

    
2065
	/* handle hide ssid option */
2066
	if(isset($wlcfg['hidessid']['enable'])) {
2067
		$wlcmd[] = "hidessid";
2068
	} else {
2069
		$wlcmd[] = "-hidessid";
2070
	}
2071

    
2072
	/* handle pureg (802.11g) only option */
2073
	if(isset($wlcfg['pureg']['enable'])) {
2074
		$wlcmd[] = "mode 11g pureg";
2075
	} else {
2076
		$wlcmd[] = "-pureg";
2077
	}
2078

    
2079
	/* handle puren (802.11n) only option */
2080
	if(isset($wlcfg['puren']['enable'])) {
2081
		$wlcmd[] = "puren";
2082
	} else {
2083
		$wlcmd[] = "-puren";
2084
	}
2085

    
2086
	/* enable apbridge option */
2087
	if(isset($wlcfg['apbridge']['enable'])) {
2088
		$wlcmd[] = "apbridge";
2089
	} else {
2090
		$wlcmd[] = "-apbridge";
2091
	}
2092

    
2093
	/* handle turbo option */
2094
	if(isset($wlcfg['turbo']['enable'])) {
2095
		$wlcmd[] = "mediaopt turbo";
2096
	} else {
2097
		$wlcmd[] = "-mediaopt turbo";
2098
	}
2099

    
2100
	/* handle txpower setting */
2101
	/* if($wlcfg['txpower'] <> "")
2102
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2103
	*/
2104
	/* handle wme option */
2105
	if(isset($wlcfg['wme']['enable'])) {
2106
		$wlcmd[] = "wme";
2107
	} else {
2108
		$wlcmd[] = "-wme";
2109
	}
2110

    
2111
	/* set up wep if enabled */
2112
	$wepset = "";
2113
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2114
		switch($wlcfg['wpa']['auth_algs']) {
2115
			case "1":
2116
				$wepset .= "authmode open wepmode on ";
2117
				break;
2118
			case "2":
2119
				$wepset .= "authmode shared wepmode on ";
2120
				break;
2121
			case "3":
2122
				$wepset .= "authmode mixed wepmode on ";
2123
		}
2124
		$i = 1;
2125
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2126
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2127
			if (isset($wepkey['txkey'])) {
2128
				$wlcmd[] = "weptxkey {$i} ";
2129
			}
2130
			$i++;
2131
		}
2132
		$wlcmd[] = $wepset;
2133
	} else {
2134
		$wlcmd[] = "authmode open wepmode off ";
2135
	}
2136

    
2137
	mwexec(kill_hostapd("{$if}"));
2138
	mwexec(kill_wpasupplicant("{$if}"));
2139

    
2140
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2141
	conf_mount_rw();
2142

    
2143
	switch ($wlcfg['mode']) {
2144
		case 'bss':
2145
			if (isset($wlcfg['wpa']['enable'])) {
2146
				$wpa .= <<<EOD
2147
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2148
ctrl_interface_group=0
2149
ap_scan=1
2150
#fast_reauth=1
2151
network={
2152
ssid="{$wlcfg['ssid']}"
2153
scan_ssid=1
2154
priority=5
2155
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2156
psk="{$wlcfg['wpa']['passphrase']}"
2157
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2158
group={$wlcfg['wpa']['wpa_pairwise']}
2159
}
2160
EOD;
2161

    
2162
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2163
				fwrite($fd, "{$wpa}");
2164
				fclose($fd);
2165
			}
2166
			break;
2167
		case 'hostap':
2168
			if($wlcfg['wpa']['passphrase']) 
2169
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2170
			else 
2171
				$wpa_passphrase = "";
2172
			if (isset($wlcfg['wpa']['enable'])) {
2173
				$wpa .= <<<EOD
2174
interface={$if}
2175
driver=bsd
2176
logger_syslog=-1
2177
logger_syslog_level=0
2178
logger_stdout=-1
2179
logger_stdout_level=0
2180
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2181
ctrl_interface={$g['varrun_path']}/hostapd
2182
ctrl_interface_group=wheel
2183
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2184
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2185
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2186
ssid={$wlcfg['ssid']}
2187
debug={$wlcfg['wpa']['debug_mode']}
2188
auth_algs={$wlcfg['wpa']['auth_algs']}
2189
wpa={$wlcfg['wpa']['wpa_mode']}
2190
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2191
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2192
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2193
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2194
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2195
{$wpa_passphrase}
2196

    
2197
EOD;
2198

    
2199
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2200
	$wpa .= <<<EOD
2201
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2202
rsn_preauth=1
2203
rsn_preauth_interfaces={$if}
2204

    
2205
EOD;
2206

    
2207
}
2208
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2209
					$auth_server_port = "1812";
2210
					if($wlcfg['auth_server_port']) 
2211
						$auth_server_port = $wlcfg['auth_server_port'];
2212
					$wpa .= <<<EOD
2213

    
2214
ieee8021x=1
2215
auth_server_addr={$wlcfg['auth_server_addr']}
2216
auth_server_port={$auth_server_port}
2217
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2218

    
2219
EOD;
2220
				} else {
2221
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2222
				}
2223

    
2224
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2225
				fwrite($fd, "{$wpa}");
2226
				fclose($fd);
2227

    
2228
			}
2229
			break;
2230
	}
2231

    
2232
	/*
2233
	 *    all variables are set, lets start up everything
2234
	 */
2235

    
2236
	$baseif = interface_get_wireless_base($if);
2237
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2238
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2239

    
2240
	/* set sysctls for the wireless interface */
2241
	if (!empty($wl_sysctl)) {
2242
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2243
		foreach ($wl_sysctl as $wl_sysctl_line) {
2244
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2245
		}
2246
	}
2247

    
2248
	/* set ack timers according to users preference (if he/she has any) */
2249
	if($distance) {
2250
		fwrite($fd_set, "# Enable ATH distance settings\n");
2251
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2252
	}
2253

    
2254
	if (isset($wlcfg['wpa']['enable'])) {
2255
		if ($wlcfg['mode'] == "bss") {
2256
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2257
		}
2258
		if ($wlcfg['mode'] == "hostap") {
2259
			/* add line to script to restore old mac to make hostapd happy */
2260
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2261
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2262
				if (is_macaddr($if_oldmac))
2263
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2264
						" link " . escapeshellarg($if_oldmac) . "\n");
2265
			}
2266

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

    
2269
			/* add line to script to restore spoofed mac after running hostapd */
2270
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2271
				if ($wl['spoofmac'])
2272
					$if_curmac = $wl['spoofmac'];
2273
				else
2274
					$if_curmac = get_interface_mac($if);
2275
				if (is_macaddr($if_curmac))
2276
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2277
						" link " . escapeshellarg($if_curmac) . "\n");
2278
			}
2279
		}
2280
	}
2281

    
2282
	fclose($fd_set);
2283
	conf_mount_ro();
2284

    
2285
	/* Making sure regulatory settings have actually changed
2286
	 * before applying, because changing them requires bringing
2287
	 * down all wireless networks on the interface. */
2288
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2289
	$ifconfig_str = implode($output);
2290
	unset($output);
2291
	$reg_changing = false;
2292

    
2293
	/* special case for the debug country code */
2294
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2295
		$reg_changing = true;
2296
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2297
		$reg_changing = true;
2298
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2299
		$reg_changing = true;
2300
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2301
		$reg_changing = true;
2302
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2303
		$reg_changing = true;
2304

    
2305
	if ($reg_changing) {
2306
		/* set regulatory domain */
2307
		if($wlcfg['regdomain'])
2308
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2309

    
2310
		/* set country */
2311
		if($wlcfg['regcountry'])
2312
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2313

    
2314
		/* set location */
2315
		if($wlcfg['reglocation'])
2316
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2317

    
2318
		$wlregcmd_args = implode(" ", $wlregcmd);
2319

    
2320
		/* build a complete list of the wireless clones for this interface */
2321
		$clone_list = array();
2322
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2323
			$clone_list[] = interface_get_wireless_clone($baseif);
2324
		if (is_array($config['wireless']['clone'])) {
2325
			foreach ($config['wireless']['clone'] as $clone) {
2326
				if ($clone['if'] == $baseif)
2327
					$clone_list[] = $clone['cloneif'];
2328
			}
2329
		}
2330

    
2331
		/* find which clones are up and bring them down */
2332
		$clones_up = array();
2333
		foreach ($clone_list as $clone_if) {
2334
			$clone_status = pfSense_get_interface_addresses($clone_if);
2335
			if ($clone_status['status'] == 'up') {
2336
				$clones_up[] = $clone_if;
2337
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2338
			}
2339
		}
2340

    
2341
		/* apply the regulatory settings */
2342
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2343

    
2344
		/* bring the clones back up that were previously up */
2345
		foreach ($clones_up as $clone_if) {
2346
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2347

    
2348
			/*
2349
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2350
			 * is in infrastructure mode, and WPA is enabled.
2351
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2352
			 */
2353
			if ($clone_if != $if) {
2354
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2355
				if ( !empty($friendly_if)
2356
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2357
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2358
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2359
				}
2360
			}
2361
		}
2362
	}
2363

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

    
2368
	/* configure wireless */
2369
	$wlcmd_args = implode(" ", $wlcmd);
2370
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2371

    
2372
	
2373
	sleep(1);
2374
	/* execute hostapd and wpa_supplicant if required in shell */
2375
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2376

    
2377
	return 0;
2378

    
2379
}
2380

    
2381
function kill_hostapd($interface) {
2382
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2383
}
2384

    
2385
function kill_wpasupplicant($interface) {
2386
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2387
}
2388

    
2389
function find_dhclient_process($interface) {
2390
	if ($interface)
2391
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2392
	else
2393
		$pid = 0;
2394

    
2395
	return $pid;
2396
}
2397

    
2398
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2399
	global $config, $g;
2400
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2401

    
2402
	$wancfg = $config['interfaces'][$interface];
2403

    
2404
	$realif = get_real_interface($interface);
2405

    
2406
	if (!$g['booting']) {
2407
		/* remove all IPv4 addresses */
2408
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2409

    
2410
		switch ($wancfg['ipaddr']) {
2411
			case 'pppoe':
2412
			case 'l2tp':
2413
			case 'pptp':
2414
			case 'ppp':
2415
				interface_bring_down($interface, true);
2416
				break;
2417
			default:
2418
				interface_bring_down($interface);
2419
				break;
2420
		}
2421
	}
2422

    
2423
	/* wireless configuration? */
2424
	if (is_array($wancfg['wireless']))
2425
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2426

    
2427
	if ($wancfg['spoofmac']) {
2428
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2429
			" link " . escapeshellarg($wancfg['spoofmac']));
2430

    
2431
                /*
2432
                 * All vlans need to spoof their parent mac address, too.  see
2433
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2434
                 */
2435
                if (is_array($config['vlans']['vlan'])) {
2436
                        foreach ($config['vlans']['vlan'] as $vlan) {
2437
                                if ($vlan['if'] == $realif)
2438
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2439
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2440
                        }
2441
                }
2442
	}  else {
2443
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2444
		if($mac == "ff:ff:ff:ff:ff:ff") {
2445
			/*   this is not a valid mac address.  generate a
2446
			 *   temporary mac address so the machine can get online.
2447
			 */
2448
			echo "Generating new MAC address.";
2449
			$random_mac = generate_random_mac_address();
2450
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2451
				" link " . escapeshellarg($random_mac));
2452
			$wancfg['spoofmac'] = $random_mac;
2453
			write_config();
2454
			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");
2455
		}
2456
	}
2457

    
2458
	/* media */
2459
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2460
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2461
		if ($wancfg['media'])
2462
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2463
		if ($wancfg['mediaopt'])
2464
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2465
		mwexec($cmd);
2466
	}
2467
	if (!empty($wancfg['mtu']))
2468
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2469

    
2470
	$options = pfSense_get_interface_addresses($realif);
2471
	if (is_array($options) && isset($options['caps']['polling'])) {
2472
		if (isset($config['system']['polling']))
2473
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2474
		else
2475
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2476
	}
2477

    
2478
	/* skip vlans for checksumming and polling */
2479
        if (!stristr($realif, "vlan") && is_array($options)) {
2480
		$flags = 0;
2481
		if(isset($config['system']['disablechecksumoffloading'])) {
2482
			if (isset($options['encaps']['txcsum']))
2483
				$flags |= IFCAP_TXCSUM;
2484
			if (isset($options['encaps']['rxcsum']))
2485
				$flags |= IFCAP_RXCSUM;
2486
        	} else {
2487
 			if (!isset($options['caps']['txcsum']))
2488
				$flags |= IFCAP_TXCSUM;
2489
			if (!isset($options['caps']['rxcsum']))
2490
				$flags |= IFCAP_RXCSUM;
2491
        	}
2492

    
2493
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2494
                	if (isset($options['encaps']['tso4']))
2495
				$flags |= IFCAP_TSO;
2496
                	if (isset($options['encaps']['tso6']))
2497
				$flags |= IFCAP_TSO;
2498
        	} else {
2499
                	if (!isset($options['caps']['tso4']))
2500
				$flags |= IFCAP_TSO;
2501
                	if (!isset($options['caps']['tso6']))
2502
				$flags |= IFCAP_TSO;
2503
        	}
2504

    
2505
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2506
                	if (isset($options['encaps']['lro']))
2507
				$flags |= IFCAP_LRO;
2508
        	} else {
2509
                	if (!isset($options['caps']['lro']))
2510
				$flags |= IFCAP_LRO;
2511
        	}
2512

    
2513
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2514
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2515
			$flags |= IFCAP_POLLING;
2516
		}
2517
               	pfSense_interface_capabilities($realif, -$flags);
2518
	}
2519

    
2520
	/* invalidate interface/ip/sn cache */
2521
	get_interface_arr(true);
2522
	unset($interface_ip_arr_cache[$realif]);
2523
	unset($interface_sn_arr_cache[$realif]);
2524

    
2525
	switch ($wancfg['ipaddr']) {
2526
		case 'carpdev-dhcp':
2527
			interface_carpdev_dhcp_configure($interface);
2528
			break;
2529
		case 'dhcp':
2530
			interface_dhcp_configure($interface);
2531
			break;
2532
		case 'pppoe':
2533
		case 'l2tp':
2534
		case 'pptp':
2535
		case 'ppp':
2536
			interface_ppps_configure($interface);
2537
			break;
2538
		default:
2539
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2540
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2541
			} else if (substr($realif, 0, 3) == "gre") {
2542
				if (is_array($config['gres']['gre'])) {
2543
					foreach ($config['gres']['gre'] as $gre)
2544
						if ($gre['greif'] == $realif)
2545
							interface_gre_configure($gre);
2546
				}
2547
			} else if (substr($realif, 0, 3) == "gif") {
2548
				 if (is_array($config['gifs']['gif'])) {
2549
					foreach ($config['gifs']['gif'] as $gif)
2550
						if($gif['gifif'] == $interface)
2551
							interface_gif_configure($gif);
2552
				}
2553
			} else if (substr($realif, 0, 4) == "ovpn") {
2554
				/* XXX: Should be done anything?! */
2555
			}
2556
			break;
2557
	}
2558

    
2559
	if(does_interface_exist($wancfg['if']))
2560
		interfaces_bring_up($wancfg['if']);
2561
 	
2562
	if (!$g['booting']) {
2563
		link_interface_to_vips($interface, "update");
2564

    
2565
		unset($gre);
2566
		$gre = link_interface_to_gre($interface);
2567
		if (!empty($gre))
2568
			array_walk($gre, 'interface_gre_configure');
2569

    
2570
		unset($gif);
2571
		$gif = link_interface_to_gif($interface);
2572
		if (!empty($gif))
2573
                       	array_walk($gif, 'interface_gif_configure');
2574

    
2575
		if ($linkupevent == false) {
2576
			unset($bridgetmp);
2577
			$bridgetmp = link_interface_to_bridge($interface);
2578
			if (!empty($bridgetmp))
2579
				interface_bridge_add_member($bridgetmp, $realif);
2580
		}
2581

    
2582
		$grouptmp = link_interface_to_group($interface);
2583
		if (!empty($grouptmp))
2584
			array_walk($grouptmp, 'interface_group_add_member');
2585

    
2586
		if ($interface == "lan")
2587
			/* make new hosts file */
2588
			system_hosts_generate();
2589

    
2590
		if ($reloadall == true) {
2591

    
2592
			/* reconfigure static routes (kernel may have deleted them) */
2593
			system_routing_configure($interface);
2594

    
2595
			/* reload ipsec tunnels */
2596
			vpn_ipsec_configure();
2597

    
2598
			/* restart dnsmasq */
2599
			services_dnsmasq_configure();
2600

    
2601
			/* update dyndns */
2602
			services_dyndns_configure($interface);
2603

    
2604
			/* force DNS update */
2605
			services_dnsupdate_process($interface);
2606

    
2607
			/* reload captive portal */
2608
			captiveportal_init_rules();
2609
		}
2610
	}
2611

    
2612
	return 0;
2613
}
2614

    
2615
function interface_carpdev_dhcp_configure($interface = "wan") {
2616
	global $config, $g;
2617

    
2618
	$wancfg = $config['interfaces'][$interface];
2619
	$wanif = $wancfg['if'];
2620
	/* bring wan interface up before starting dhclient */
2621
	if($wanif)
2622
		interfaces_bring_up($wanif);
2623
	else 
2624
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2625

    
2626
	return 0;
2627
}
2628

    
2629
function interface_dhcp_configure($interface = "wan") {
2630
	global $config, $g;
2631

    
2632
	$wancfg = $config['interfaces'][$interface];
2633
	if (empty($wancfg))
2634
		$wancfg = array();
2635

    
2636
	/* generate dhclient_wan.conf */
2637
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2638
	if (!$fd) {
2639
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2640
		return 1;
2641
	}
2642

    
2643
	if ($wancfg['dhcphostname']) {
2644
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2645
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2646
	} else {
2647
		$dhclientconf_hostname = "";
2648
	}
2649

    
2650
	$wanif = get_real_interface($interface);
2651
	if (empty($wanif)) {
2652
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2653
		return 0;
2654
	}
2655
 	$dhclientconf = "";
2656
	
2657
	$dhclientconf .= <<<EOD
2658
interface "{$wanif}" {
2659
timeout 60;
2660
retry 1;
2661
select-timeout 0;
2662
initial-interval 1;
2663
	{$dhclientconf_hostname}
2664
	script "/sbin/dhclient-script";
2665
}
2666

    
2667
EOD;
2668

    
2669
if(is_ipaddr($wancfg['alias-address'])) {
2670
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2671
	$dhclientconf .= <<<EOD
2672
alias {
2673
	interface  "{$wanif}";
2674
	fixed-address {$wancfg['alias-address']};
2675
	option subnet-mask {$subnetmask};
2676
}
2677

    
2678
EOD;
2679
}
2680
	fwrite($fd, $dhclientconf);
2681
	fclose($fd);
2682

    
2683
	/* bring wan interface up before starting dhclient */
2684
	if($wanif)
2685
		interfaces_bring_up($wanif);
2686
	else 
2687
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2688

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

    
2692
	return 0;
2693
}
2694

    
2695
function interfaces_group_setup() {
2696
	global $config;
2697

    
2698
	if (!is_array($config['ifgroups']['ifgroupentry']))
2699
		return;
2700

    
2701
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2702
		interface_group_setup($groupar);
2703

    
2704
	return;
2705
}
2706

    
2707
function interface_group_setup(&$groupname /* The parameter is an array */) {
2708
	global $config;
2709

    
2710
	if (!is_array($groupname))
2711
		return;
2712
	$members = explode(" ", $groupname['members']);
2713
	foreach($members as $ifs) {
2714
		$realif = get_real_interface($ifs);
2715
		if ($realif)
2716
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2717
	}
2718

    
2719
	return;
2720
}
2721

    
2722
function interface_group_add_member($interface, $groupname) {
2723
	$interface = get_real_interface($interface);
2724
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2725
}
2726
 
2727
/* COMPAT Function */
2728
function convert_friendly_interface_to_real_interface_name($interface) {
2729
	return get_real_interface($interface);
2730
}
2731

    
2732
/* COMPAT Function */
2733
function get_real_wan_interface($interface = "wan") {
2734
	return get_real_interface($interface);
2735
}
2736

    
2737
/* COMPAT Function */
2738
function get_current_wan_address($interface = "wan") {
2739
	return get_interface_ip($interface);
2740
}
2741

    
2742
/*
2743
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2744
 */
2745
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2746
        global $config;
2747

    
2748
	if (stristr($interface, "vip")) {
2749
                $index = intval(substr($interface, 3));
2750
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2751
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2752
                                if ($index == $counter)
2753
                                        return $vip['interface'];
2754
                        }
2755
                }
2756
        }
2757

    
2758
        /* XXX: For speed reasons reference directly the interface array */
2759
	$ifdescrs = &$config['interfaces'];
2760
        //$ifdescrs = get_configured_interface_list(false, true);
2761

    
2762
        foreach ($ifdescrs as $if => $ifname) {
2763
                if ($config['interfaces'][$if]['if'] == $interface)
2764
                        return $if;
2765

    
2766
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2767
                        return $if;
2768

    
2769
                $int = interface_translate_type_to_real($if);
2770
                if ($int == $interface)
2771
                        return $ifname;
2772
        }
2773
        return NULL;
2774
}
2775

    
2776
/* attempt to resolve interface to friendly descr */
2777
function convert_friendly_interface_to_friendly_descr($interface) {
2778
        global $config;
2779

    
2780
        switch ($interface) {
2781
                case "l2tp":
2782
                                $ifdesc = "L2TP";
2783
                                break;
2784
                case "pptp":
2785
                                $ifdesc = "PPTP";
2786
                                break;
2787
                case "pppoe":
2788
                                $ifdesc = "PPPoE";
2789
                                break;
2790
                case "openvpn":
2791
                                $ifdesc = "OpenVPN";
2792
                                break;
2793
                case "enc0":
2794
                        case "ipsec":
2795
                                $ifdesc = "IPsec";
2796
                                break;
2797
        default:
2798
                if (isset($config['interfaces'][$interface])) {
2799
                        if (empty($config['interfaces'][$interface]['descr']))
2800
                                $ifdesc = strtoupper($interface);
2801
                        else
2802
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2803
			break;
2804
		}
2805
                /* if list */
2806
                $ifdescrs = get_configured_interface_with_descr(false, true);
2807
                foreach ($ifdescrs as $if => $ifname) {
2808
                                if ($if == $interface || $ifname == $interface)
2809
                                        return $ifname;
2810
                }
2811
                break;
2812
        }
2813

    
2814
        return $ifdesc;
2815
}
2816

    
2817
function convert_real_interface_to_friendly_descr($interface) {
2818
        global $config;
2819

    
2820
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2821

    
2822
        if ($ifdesc) {
2823
                $iflist = get_configured_interface_with_descr(false, true);
2824
                return $iflist[$ifdesc];
2825
        }
2826

    
2827
        return $interface;
2828
}
2829

    
2830
/*
2831
 *  interface_translate_type_to_real($interface):
2832
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2833
 */
2834
function interface_translate_type_to_real($interface) {
2835
        global $config;
2836

    
2837
        if ($config['interfaces'][$interface]['if'] <> "")
2838
                return $config['interfaces'][$interface]['if'];
2839
        else
2840
		return $interface;
2841
}
2842

    
2843
function interface_is_wireless_clone($wlif) {
2844
	if(!stristr($wlif, "_wlan")) {
2845
		return false;
2846
	} else {
2847
		return true;
2848
	}
2849
}
2850

    
2851
function interface_get_wireless_base($wlif) {
2852
	if(!stristr($wlif, "_wlan")) {
2853
		return $wlif;
2854
	} else {
2855
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2856
	}
2857
}
2858

    
2859
function interface_get_wireless_clone($wlif) {
2860
	if(!stristr($wlif, "_wlan")) {
2861
		return $wlif . "_wlan0";
2862
	} else {
2863
		return $wlif;
2864
	}
2865
}
2866

    
2867
function get_real_interface($interface = "wan") {
2868
    global $config;
2869

    
2870
	$wanif = NULL;
2871

    
2872
	switch ($interface) {
2873
	case "l2tp":
2874
		$wanif = "l2tp";
2875
		break;
2876
	case "pptp":
2877
		$wanif = "pptp";
2878
		break;
2879
	case "pppoe":
2880
		$wanif = "pppoe";
2881
		break;
2882
	case "openvpn":
2883
		$wanif = "openvpn";
2884
		break;
2885
	case "ipsec":
2886
	case "enc0":
2887
		$wanif = "enc0";
2888
		break;
2889
	case "ppp":
2890
		$wanif = "ppp";
2891
		break;
2892
	default:
2893
		// If a real interface was alread passed simply
2894
		// pass the real interface back.  This encourages
2895
		// the usage of this function in more cases so that
2896
		// we can combine logic for more flexibility.
2897
		if(does_interface_exist($interface)) {
2898
			$wanif = $interface;
2899
			break;
2900
		}
2901
		if (empty($config['interfaces'][$interface]))
2902
			break;
2903

    
2904
		$cfg = &$config['interfaces'][$interface];
2905

    
2906
		// Wireless cloned NIC support (FreeBSD 8+)
2907
		// interface name format: $parentnic_wlanparentnic#
2908
		// example: ath0_wlan0
2909
		if (is_interface_wireless($cfg['if'])) {
2910
			$wanif = interface_get_wireless_clone($cfg['if']);
2911
			break;
2912
		}
2913
		/*
2914
		if (empty($cfg['if'])) {
2915
			$wancfg = $cfg['if'];
2916
			break;
2917
		}
2918
		*/
2919

    
2920
		switch ($cfg['ipaddr']) {
2921
			case "carpdev-dhcp":
2922
				$viparr = &$config['virtualip']['vip'];
2923
				if(is_array($viparr))
2924
				foreach ($viparr as $counter => $vip) {
2925
					if ($vip['mode'] == "carpdev-dhcp") {
2926
						if($vip['interface'] == $interface) {
2927
							$wanif = "carp{$counter}";
2928
							break;
2929
						}
2930
					}
2931
				}
2932
				break;
2933
			case "pppoe": 
2934
			case "pptp": 
2935
			case "l2tp": 
2936
			case "ppp":
2937
				$wanif = $cfg['if'];
2938
				break;
2939
			default:
2940
				$wanif = $cfg['if'];
2941
				break;
2942
		}
2943
		break;
2944
	}
2945

    
2946
    return $wanif;
2947
}
2948

    
2949
/* Guess the physical interface by providing a IP address */
2950
function guess_interface_from_ip($ipaddress) {
2951
	if(! is_ipaddr($ipaddress)) {
2952
		return false;
2953
	}
2954
	/* create a route table we can search */
2955
	exec("netstat -rnWf inet", $output, $ret);
2956
	foreach($output as $line) {
2957
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2958
			$fields = preg_split("/[ ]+/", $line);
2959
			if(ip_in_subnet($ipaddress, $fields[0])) {
2960
				return $fields[6];
2961
			}
2962
		}
2963
	}
2964
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2965
	if(empty($ret)) {
2966
        	return false;
2967
	}
2968
	return $ret;
2969
}
2970

    
2971
/*
2972
 * find_ip_interface($ip): return the interface where an ip is defined
2973
 */
2974
function find_ip_interface($ip)
2975
{
2976
        /* if list */
2977
        $ifdescrs = get_configured_interface_list();
2978

    
2979
        foreach ($ifdescrs as $ifdescr => $ifname) {
2980
		if ($ip == get_interface_ip($ifname)) {
2981
                	$int = get_real_interface($ifname);
2982
			return $int;
2983
		}
2984
        }
2985
        return false;
2986
}
2987

    
2988
/*
2989
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2990
 */
2991
function find_number_of_created_carp_interfaces() {
2992
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2993
}
2994

    
2995
function get_all_carp_interfaces() {
2996
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2997
	$ints = explode(" ", $ints);
2998
	return $ints;
2999
}
3000

    
3001
/*
3002
 * find_carp_interface($ip): return the carp interface where an ip is defined
3003
 */
3004
function find_carp_interface($ip) {
3005
	global $config;
3006
	if (is_array($config['virtualip']['vip'])) {
3007
		foreach ($config['virtualip']['vip'] as $vip) {
3008
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3009
				$carp_ip = get_interface_ip($vip['interface']);
3010
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
3011
				if ($if)
3012
					return $if;
3013
			}
3014
		}
3015
	}
3016
}
3017

    
3018
function link_carp_interface_to_parent($interface) {
3019
        global $config;
3020

    
3021
        if ($interface == "")
3022
                return;
3023

    
3024
        $carp_ip = get_interface_ip($interface);
3025
        if (!is_ipaddr($carp_ip))
3026
                return;
3027

    
3028
        /* if list */
3029
        $ifdescrs = get_configured_interface_list();
3030
        foreach ($ifdescrs as $ifdescr => $ifname) {
3031
                $interfaceip = get_interface_ip($ifname);
3032
                $subnet_bits = get_interface_subnet($ifname);
3033
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3034
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3035
                        return $ifname;
3036
        }
3037

    
3038
        return "";
3039
}
3040

    
3041
/****f* interfaces/link_ip_to_carp_interface
3042
 * NAME
3043
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3044
 * INPUTS
3045
 *   $ip
3046
 * RESULT
3047
 *   $carp_ints
3048
 ******/
3049
function link_ip_to_carp_interface($ip) {
3050
        global $config;
3051

    
3052
        if (!is_ipaddr($ip))
3053
                return;
3054

    
3055
        $carp_ints = "";
3056
        if (is_array($config['virtualip']['vip'])) {
3057
		$first = 0;
3058
		$carp_int = array();
3059
                foreach ($config['virtualip']['vip'] as $vip) {
3060
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3061
                                $carp_ip = $vip['subnet'];
3062
                                $carp_sn = $vip['subnet_bits'];
3063
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3064
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3065
					$carp_int[] = "vip{$vip['vhid']}";
3066
                        }
3067
                }
3068
		if (!empty($carp_int))
3069
			$carp_ints = implode(" ", array_unique($carp_int));
3070
        }
3071

    
3072
        return $carp_ints;
3073
}
3074

    
3075
function link_interface_to_vlans($int, $action = "") {
3076
	global $config;
3077

    
3078
	if (empty($int))
3079
		return;
3080

    
3081
	if (is_array($config['vlans']['vlan'])) {
3082
                foreach ($config['vlans']['vlan'] as $vlan) {
3083
			if ($int == $vlan['if']) {
3084
				if ($action == "update") {
3085
					interfaces_bring_up($int);
3086
				} else if ($action == "")
3087
					return $vlan;
3088
			}
3089
		}
3090
	}
3091
}
3092

    
3093
function link_interface_to_vips($int, $action = "") {
3094
        global $config;
3095

    
3096
        if (is_array($config['virtualip']['vip'])) {
3097
		foreach ($config['virtualip']['vip'] as $vip) {
3098
			if ($int == $vip['interface']) {
3099
				if ($action == "update") {
3100
					interface_vip_bring_down($vip);
3101
					interfaces_vips_configure($int);
3102
				} else
3103
					return $vip;
3104
			}
3105
		}
3106
	}
3107
}
3108

    
3109
/****f* interfaces/link_interface_to_bridge
3110
 * NAME
3111
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3112
 * INPUTS
3113
 *   $ip
3114
 * RESULT
3115
 *   bridge[0-99]
3116
 ******/
3117
function link_interface_to_bridge($int) {
3118
        global $config;
3119

    
3120
        if (is_array($config['bridges']['bridged'])) {
3121
                foreach ($config['bridges']['bridged'] as $bridge) {
3122
			if (in_array($int, explode(',', $bridge['members'])))
3123
                                return "{$bridge['bridgeif']}";
3124
		}
3125
	}
3126
}
3127

    
3128
function link_interface_to_group($int) {
3129
        global $config;
3130

    
3131
	$result = array();
3132

    
3133
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3134
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3135
			if (in_array($int, explode(" ", $group['members'])))
3136
				$result[$group['ifname']] = $int;
3137
		}
3138
	}
3139

    
3140
	return $result;
3141
}
3142

    
3143
function link_interface_to_gre($interface) {
3144
        global $config;
3145

    
3146
	$result = array();
3147

    
3148
        if (is_array($config['gres']['gre'])) {
3149
                foreach ($config['gres']['gre'] as $gre)
3150
                        if($gre['if'] == $interface)
3151
				$result[] = $gre;
3152
	}
3153

    
3154
	return $result;
3155
}
3156

    
3157
function link_interface_to_gif($interface) {
3158
        global $config;
3159

    
3160
	$result = array();
3161

    
3162
        if (is_array($config['gifs']['gif'])) {
3163
                foreach ($config['gifs']['gif'] as $gif)
3164
                        if($gif['if'] == $interface)
3165
                                $result[] = $gif;
3166
	}
3167

    
3168
	return $result;
3169
}
3170

    
3171
/*
3172
 * find_interface_ip($interface): return the interface ip (first found)
3173
 */
3174
function find_interface_ip($interface, $flush = false)
3175
{
3176
	global $interface_ip_arr_cache;
3177
	global $interface_sn_arr_cache;
3178

    
3179
	$interface = str_replace("\n", "", $interface);
3180
	
3181
	if (!does_interface_exist($interface))
3182
		return;
3183

    
3184
	/* Setup IP cache */
3185
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3186
		$ifinfo = pfSense_get_interface_addresses($interface);
3187
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3188
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3189
	}
3190

    
3191
	return $interface_ip_arr_cache[$interface];
3192
}
3193

    
3194
function find_interface_subnet($interface, $flush = false)
3195
{
3196
	global $interface_sn_arr_cache;
3197
	global $interface_ip_arr_cache;
3198

    
3199
	$interface = str_replace("\n", "", $interface);
3200
	if (does_interface_exist($interface) == false)
3201
		return;
3202

    
3203
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3204
		$ifinfo = pfSense_get_interface_addresses($interface);
3205
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3206
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3207
        }
3208

    
3209
	return $interface_sn_arr_cache[$interface];
3210
}
3211

    
3212
function ip_in_interface_alias_subnet($interface, $ipalias) {
3213
	global $config;
3214

    
3215
	if (empty($interface) || !is_ipaddr($ipalias))
3216
		return false;
3217
	if (is_array($config['virtualip']['vip'])) {
3218
                foreach ($config['virtualip']['vip'] as $vip) {
3219
                        switch ($vip['mode']) {
3220
                        case "ipalias":
3221
                                if ($vip['interface'] <> $interface)
3222
                                        break;
3223
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3224
					return true;
3225
                                break;
3226
                        }
3227
                }
3228
	}
3229

    
3230
	return false;
3231
}
3232

    
3233
function get_interface_ip($interface = "wan")
3234
{
3235
	$realif = get_real_interface($interface);
3236
	if (!$realif) {
3237
		if (preg_match("/^carp/i", $interface))
3238
			$realif = $interface;
3239
		else if (preg_match("/^vip/i", $interface))
3240
			$realif = $interface;
3241
		else
3242
			return null;
3243
	}
3244

    
3245
	$curip = find_interface_ip($realif);
3246
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3247
		return $curip;
3248
	else
3249
		return null;
3250
}
3251

    
3252
function get_interface_subnet($interface = "wan")
3253
{
3254
	$realif = get_real_interface($interface);
3255
	if (!$realif) {
3256
                if (preg_match("/^carp/i", $interface))
3257
                        $realif = $interface;
3258
                else if (preg_match("/^vip/i", $interface))
3259
                        $realif = $interface;
3260
                else
3261
                        return null;
3262
        }
3263

    
3264
	$cursn = find_interface_subnet($realif);
3265
	if (!empty($cursn))
3266
		return $cursn;
3267

    
3268
	return null;
3269
}
3270

    
3271
/* return outside interfaces with a gateway */
3272
function get_interfaces_with_gateway() {
3273
	global $config;
3274

    
3275
	$ints = array();
3276

    
3277
	/* loop interfaces, check config for outbound */
3278
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3279
		switch ($ifname['ipaddr']) {
3280
			case "dhcp":
3281
			case "carpdev-dhcp":
3282
			case "ppp";
3283
			case "pppoe":
3284
			case "pptp":
3285
			case "l2tp":
3286
			case "ppp";
3287
				$ints[$ifdescr] = $ifdescr;
3288
			break;
3289
			default:
3290
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3291
				    !empty($ifname['gateway']))
3292
					$ints[$ifdescr] = $ifdescr;
3293
			break;
3294
		}
3295
	}
3296
	return $ints;
3297
}
3298

    
3299
/* return true if interface has a gateway */
3300
function interface_has_gateway($friendly) {
3301
	global $config;
3302

    
3303
	if (!empty($config['interfaces'][$friendly])) {
3304
		$ifname = &$config['interfaces'][$friendly];
3305
		switch ($ifname['ipaddr']) {
3306
			case "dhcp":
3307
			case "carpdev-dhcp":
3308
			case "pppoe":
3309
			case "pptp":
3310
			case "l2tp":
3311
			case "ppp";
3312
				return true;
3313
			break;
3314
			default:
3315
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3316
					return true;
3317
				if (!empty($ifname['gateway']))
3318
					return true;
3319
			break;
3320
		}
3321
	}
3322

    
3323
	return false;
3324
}
3325

    
3326
/****f* interfaces/is_altq_capable
3327
 * NAME
3328
 *   is_altq_capable - Test if interface is capable of using ALTQ
3329
 * INPUTS
3330
 *   $int            - string containing interface name
3331
 * RESULT
3332
 *   boolean         - true or false
3333
 ******/
3334

    
3335
function is_altq_capable($int) {
3336
        /* Per:
3337
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3338
         * Only the following drivers have ALTQ support
3339
         */
3340
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3341
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3342
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3343
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3344
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3345
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3346
			"l2tp", "ppp");
3347

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

    
3350
        if (in_array($int_family[0], $capable))
3351
                return true;
3352
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3353
		return true;
3354
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3355
		return true;
3356
        else
3357
                return false;
3358
}
3359

    
3360
/****f* interfaces/is_interface_wireless
3361
 * NAME
3362
 *   is_interface_wireless - Returns if an interface is wireless
3363
 * RESULT
3364
 *   $tmp       - Returns if an interface is wireless
3365
 ******/
3366
function is_interface_wireless($interface) {
3367
        global $config, $g;
3368

    
3369
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3370
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3371
                if (preg_match($g['wireless_regex'], $interface)) {
3372
                        if (isset($config['interfaces'][$friendly]))
3373
                                $config['interfaces'][$friendly]['wireless'] = array();
3374
                        return true;
3375
                }
3376
                return false;
3377
        } else
3378
                return true;
3379
}
3380

    
3381
function get_wireless_modes($interface) {
3382
	/* return wireless modes and channels */
3383
	$wireless_modes = array();
3384

    
3385
	$wlif = interface_translate_type_to_real($interface);
3386

    
3387
	if(is_interface_wireless($wlif)) {
3388
		$cloned_interface = get_real_interface($interface);
3389
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3390
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3391
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3392

    
3393
		$interface_channels = "";
3394
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3395
		$interface_channel_count = count($interface_channels);
3396

    
3397
		$c = 0;
3398
		while ($c < $interface_channel_count)
3399
		{
3400
			$channel_line = explode(",", $interface_channels["$c"]);
3401
			$wireless_mode = trim($channel_line[0]);
3402
			$wireless_channel = trim($channel_line[1]);
3403
			if(trim($wireless_mode) != "") {
3404
				/* if we only have 11g also set 11b channels */
3405
				if($wireless_mode == "11g") {
3406
					if(!isset($wireless_modes["11b"]))
3407
						$wireless_modes["11b"] = array();
3408
				} else if($wireless_mode == "11g ht") {
3409
					if(!isset($wireless_modes["11b"]))
3410
						$wireless_modes["11b"] = array();
3411
					if(!isset($wireless_modes["11g"]))
3412
						$wireless_modes["11g"] = array();
3413
					$wireless_mode = "11ng";
3414
				} else if($wireless_mode == "11a ht") {
3415
					if(!isset($wireless_modes["11a"]))
3416
						$wireless_modes["11a"] = array();
3417
					$wireless_mode = "11na";
3418
				}
3419
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3420
			}
3421
			$c++;
3422
		}
3423
	}
3424
	return($wireless_modes);
3425
}
3426

    
3427
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3428
function get_wireless_channel_info($interface) {
3429
	$wireless_channels = array();
3430

    
3431
	$wlif = interface_translate_type_to_real($interface);
3432

    
3433
	if(is_interface_wireless($wlif)) {
3434
		$cloned_interface = get_real_interface($interface);
3435
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3436
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3437
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3438

    
3439
		$interface_channels = "";
3440
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3441

    
3442
		foreach ($interface_channels as $channel_line) {
3443
			$channel_line = explode(",", $channel_line);
3444
			if(!isset($wireless_channels[$channel_line[0]]))
3445
				$wireless_channels[$channel_line[0]] = $channel_line;
3446
		}
3447
	}
3448
	return($wireless_channels);
3449
}
3450

    
3451
/****f* interfaces/get_interface_mtu
3452
 * NAME
3453
 *   get_interface_mtu - Return the mtu of an interface
3454
 * RESULT
3455
 *   $tmp       - Returns the mtu of an interface
3456
 ******/
3457
function get_interface_mtu($interface) {
3458
        $mtu = pfSense_get_interface_addresses($interface);
3459
        return $mtu['mtu'];
3460
}
3461

    
3462
function get_interface_mac($interface) {
3463

    
3464
	$macinfo = pfSense_get_interface_addresses($interface);
3465
	return $macinfo["macaddr"];
3466
}
3467

    
3468
/****f* pfsense-utils/generate_random_mac_address
3469
 * NAME
3470
 *   generate_random_mac - generates a random mac address
3471
 * INPUTS
3472
 *   none
3473
 * RESULT
3474
 *   $mac - a random mac address
3475
 ******/
3476
function generate_random_mac_address() {
3477
        $mac = "02";
3478
        for($x=0; $x<5; $x++)
3479
                $mac .= ":" . dechex(rand(16, 255));
3480
        return $mac;
3481
}
3482

    
3483
/****f* interfaces/is_jumbo_capable
3484
 * NAME
3485
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3486
 * INPUTS
3487
 *   $int             - string containing interface name
3488
 * RESULT
3489
 *   boolean          - true or false
3490
 ******/
3491
function is_jumbo_capable($int) {
3492
        global $g;
3493

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

    
3496
        if (in_array($int_family[0], $g['vlan_long_frame']))
3497
                return true;
3498
        else
3499
                return false;
3500
}
3501

    
3502
function setup_pppoe_reset_file($pppif, $iface="") {
3503
	global $g;
3504
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3505

    
3506
	if(!empty($iface) && !empty($pppif)){
3507
		$cron_cmd = <<<EOD
3508
#!/bin/sh
3509
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3510
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3511

    
3512
EOD;
3513

    
3514
		file_put_contents($cron_file, $cron_cmd);
3515
		chmod($cron_file, 0700);
3516
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3517
	} else
3518
		unlink_if_exists($cron_file);
3519
}
3520

    
3521
?>
(22-22/54)