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
function interface_gre_configure(&$gre) {
625
        global $config, $g;
626

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

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

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

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

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

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

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

    
662
	return $greif;
663
}
664

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

    
679
function interface_gif_configure(&$gif) {
680
	global $config, $g;
681

    
682
	if (!is_array($gif))
683
		return -1;
684

    
685
	$realif = get_real_interface($gif['if']);
686
	$realifip = get_interface_ip($gif['if']);
687

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

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

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

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

    
717
	return $gifif;
718
}
719

    
720
function interfaces_configure() {
721
	global $config, $g;
722

    
723
	/* Set up our loopback interface */
724
	interfaces_loopback_configure();
725

    
726
	/* set up LAGG virtual interfaces */
727
	interfaces_lagg_configure();
728

    
729
	/* set up VLAN virtual interfaces */
730
	interfaces_vlan_configure();
731

    
732
	interfaces_qinq_configure();
733

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

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

    
765
	/* create the unconfigured wireless clones */
766
	interfaces_create_wireless_clones();
767

    
768
	/* set up GRE virtual interfaces */
769
	interfaces_gre_configure();
770

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

    
780
		interface_configure($if, $reload);
781

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

    
786
	/* set up BRIDGe virtual interfaces */
787
	interfaces_bridge_configure();
788

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

    
795
		interface_configure($if, $reload);
796

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

    
801
	/* bring up vip interfaces */
802
	interfaces_vips_configure();
803

    
804
	/* configure interface groups */
805
	interfaces_group_setup();
806

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

    
811
		/* reload IPsec tunnels */
812
		vpn_ipsec_configure();
813

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

    
817
		/* restart dnsmasq */
818
		services_dnsmasq_configure();
819

    
820
		/* reload captive portal */
821
		captiveportal_init_rules();
822

    
823
		/* set the reload filter dity flag */
824
		filter_configure();
825
	}
826

    
827
	return 0;
828
}
829

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

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

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

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

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

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

    
870
	$realif = get_real_interface($interface);
871

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

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

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

    
939
	return;
940
}
941

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

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

    
950
	return false;
951
}
952

    
953
function interfaces_ptpid_next() {
954

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

    
959
	return $ptpid;
960
}
961

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1251
EOD;
1252

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

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

    
1266
EOD;
1267

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

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

    
1278
EOD;
1279

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

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

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

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

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

    
1306
EOD;
1307

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

    
1312
EOD;
1313

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

    
1318
EOD;
1319

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

    
1325
EOD;
1326

    
1327

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

    
1332
EOD;
1333

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

    
1339
EOD;
1340

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

    
1345
EOD;
1346

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

    
1351
EOD;
1352

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

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

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

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

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

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

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

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

    
1406
EOD;
1407

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

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

    
1420

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

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

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

    
1461
	return 1;
1462
}
1463

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1665
function interface_ipalias_configure(&$vip) {
1666

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1825
EOD;
1826

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

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

    
1837
	return $vipif;
1838
}
1839

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2198
EOD;
2199

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

    
2206
EOD;
2207

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

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

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

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

    
2229
			}
2230
			break;
2231
	}
2232

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2378
	return 0;
2379

    
2380
}
2381

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

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

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

    
2396
	return $pid;
2397
}
2398

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

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

    
2405
	$realif = get_real_interface($interface);
2406

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2560
	if(does_interface_exist($wancfg['if']))
2561
		interfaces_bring_up($wancfg['if']);
2562
 	
2563
	if (!$g['booting']) {
2564
		interface_reload_carps($realif);
2565

    
2566
		unset($gre);
2567
		$gre = link_interface_to_gre($interface);
2568
		if (!empty($gre))
2569
			interface_gre_configure($gre);
2570

    
2571
		unset($gif);
2572
		$gif = link_interface_to_gif($interface);
2573
		if (!empty($gif))
2574
                       	interface_gif_configure($gif);
2575

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

    
2583
		link_interface_to_vips($interface, "update");
2584

    
2585
		$grouptmp = link_interface_to_group($interface);
2586
		if (!empty($grouptmp))
2587
			interface_group_add_member($realif, $grouptmp);
2588

    
2589
		if ($interface == "lan")
2590
			/* make new hosts file */
2591
			system_hosts_generate();
2592

    
2593
		if ($reloadall == true) {
2594

    
2595
			/* reconfigure static routes (kernel may have deleted them) */
2596
			system_routing_configure($interface);
2597

    
2598
			/* reload ipsec tunnels */
2599
			vpn_ipsec_configure();
2600

    
2601
			/* restart dnsmasq */
2602
			services_dnsmasq_configure();
2603

    
2604
			/* update dyndns */
2605
			services_dyndns_configure($interface);
2606

    
2607
			/* force DNS update */
2608
			services_dnsupdate_process($interface);
2609

    
2610
			/* reload captive portal */
2611
			captiveportal_init_rules();
2612

    
2613
			/* set the reload filter dity flag */
2614
			filter_configure();
2615
		}
2616
	}
2617

    
2618
	return 0;
2619
}
2620

    
2621
function interface_carpdev_dhcp_configure($interface = "wan") {
2622
	global $config, $g;
2623

    
2624
	$wancfg = $config['interfaces'][$interface];
2625
	$wanif = $wancfg['if'];
2626
	/* bring wan interface up before starting dhclient */
2627
	if($wanif)
2628
		interfaces_bring_up($wanif);
2629
	else 
2630
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2631

    
2632
	return 0;
2633
}
2634

    
2635
function interface_dhcp_configure($interface = "wan") {
2636
	global $config, $g;
2637

    
2638
	$wancfg = $config['interfaces'][$interface];
2639
	if (empty($wancfg))
2640
		$wancfg = array();
2641

    
2642
	/* generate dhclient_wan.conf */
2643
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2644
	if (!$fd) {
2645
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2646
		return 1;
2647
	}
2648

    
2649
	if ($wancfg['dhcphostname']) {
2650
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2651
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2652
	} else {
2653
		$dhclientconf_hostname = "";
2654
	}
2655

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

    
2673
EOD;
2674

    
2675
if(is_ipaddr($wancfg['alias-address'])) {
2676
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2677
	$dhclientconf .= <<<EOD
2678
alias {
2679
	interface  "{$wanif}";
2680
	fixed-address {$wancfg['alias-address']};
2681
	option subnet-mask {$subnetmask};
2682
}
2683

    
2684
EOD;
2685
}
2686
	fwrite($fd, $dhclientconf);
2687
	fclose($fd);
2688

    
2689
	/* bring wan interface up before starting dhclient */
2690
	if($wanif)
2691
		interfaces_bring_up($wanif);
2692
	else 
2693
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2694

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

    
2698
	return 0;
2699
}
2700

    
2701
function interfaces_group_setup() {
2702
	global $config;
2703

    
2704
	if (!is_array($config['ifgroups']['ifgroupentry']))
2705
		return;
2706

    
2707
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2708
		interface_group_setup($groupar);
2709

    
2710
	return;
2711
}
2712

    
2713
function interface_group_setup(&$groupname /* The parameter is an array */) {
2714
	global $config;
2715

    
2716
	if (!is_array($groupname))
2717
		return;
2718
	$members = explode(" ", $groupname['members']);
2719
	foreach($members as $ifs) {
2720
		$realif = get_real_interface($ifs);
2721
		if ($realif)
2722
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2723
	}
2724

    
2725
	return;
2726
}
2727

    
2728
function interface_group_add_member($interface, $groupname) {
2729
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2730
}
2731
 
2732
/* COMPAT Function */
2733
function convert_friendly_interface_to_real_interface_name($interface) {
2734
	return get_real_interface($interface);
2735
}
2736

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

    
2742
/* COMPAT Function */
2743
function get_current_wan_address($interface = "wan") {
2744
	return get_interface_ip($interface);
2745
}
2746

    
2747
/*
2748
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2749
 */
2750
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2751
        global $config;
2752

    
2753
	if (stristr($interface, "vip")) {
2754
                $index = intval(substr($interface, 3));
2755
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2756
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2757
                                if ($index == $counter)
2758
                                        return $vip['interface'];
2759
                        }
2760
                }
2761
        }
2762

    
2763
        /* XXX: For speed reasons reference directly the interface array */
2764
	$ifdescrs = &$config['interfaces'];
2765
        //$ifdescrs = get_configured_interface_list(false, true);
2766

    
2767
        foreach ($ifdescrs as $if => $ifname) {
2768
                if ($config['interfaces'][$if]['if'] == $interface)
2769
                        return $if;
2770

    
2771
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2772
                        return $if;
2773

    
2774
                $int = interface_translate_type_to_real($if);
2775
                if ($int == $interface)
2776
                        return $ifname;
2777
        }
2778
        return NULL;
2779
}
2780

    
2781
/* attempt to resolve interface to friendly descr */
2782
function convert_friendly_interface_to_friendly_descr($interface) {
2783
        global $config;
2784

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

    
2819
        return $ifdesc;
2820
}
2821

    
2822
function convert_real_interface_to_friendly_descr($interface) {
2823
        global $config;
2824

    
2825
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2826

    
2827
        if ($ifdesc) {
2828
                $iflist = get_configured_interface_with_descr(false, true);
2829
                return $iflist[$ifdesc];
2830
        }
2831

    
2832
        return $interface;
2833
}
2834

    
2835
/*
2836
 *  interface_translate_type_to_real($interface):
2837
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2838
 */
2839
function interface_translate_type_to_real($interface) {
2840
        global $config;
2841

    
2842
        if ($config['interfaces'][$interface]['if'] <> "")
2843
                return $config['interfaces'][$interface]['if'];
2844
        else
2845
		return $interface;
2846
}
2847

    
2848
function interface_is_wireless_clone($wlif) {
2849
	if(!stristr($wlif, "_wlan")) {
2850
		return false;
2851
	} else {
2852
		return true;
2853
	}
2854
}
2855

    
2856
function interface_get_wireless_base($wlif) {
2857
	if(!stristr($wlif, "_wlan")) {
2858
		return $wlif;
2859
	} else {
2860
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2861
	}
2862
}
2863

    
2864
function interface_get_wireless_clone($wlif) {
2865
	if(!stristr($wlif, "_wlan")) {
2866
		return $wlif . "_wlan0";
2867
	} else {
2868
		return $wlif;
2869
	}
2870
}
2871

    
2872
function get_real_interface($interface = "wan") {
2873
    global $config;
2874

    
2875
	$wanif = NULL;
2876

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

    
2909
		$cfg = &$config['interfaces'][$interface];
2910

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

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

    
2951
    return $wanif;
2952
}
2953

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

    
2976
/*
2977
 * find_ip_interface($ip): return the interface where an ip is defined
2978
 */
2979
function find_ip_interface($ip)
2980
{
2981
        /* if list */
2982
        $ifdescrs = get_configured_interface_list();
2983

    
2984
        foreach ($ifdescrs as $ifdescr => $ifname) {
2985
		if ($ip == get_interface_ip($ifname)) {
2986
                	$int = get_real_interface($ifname);
2987
			return $int;
2988
		}
2989
        }
2990
        return false;
2991
}
2992

    
2993
/*
2994
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2995
 */
2996
function find_number_of_created_carp_interfaces() {
2997
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2998
}
2999

    
3000
function get_all_carp_interfaces() {
3001
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3002
	$ints = explode(" ", $ints);
3003
	return $ints;
3004
}
3005

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

    
3023
function link_carp_interface_to_parent($interface) {
3024
        global $config;
3025

    
3026
        if ($interface == "")
3027
                return;
3028

    
3029
        $carp_ip = get_interface_ip($interface);
3030
        if (!is_ipaddr($carp_ip))
3031
                return;
3032

    
3033
        /* if list */
3034
        $ifdescrs = get_configured_interface_list();
3035
        foreach ($ifdescrs as $ifdescr => $ifname) {
3036
                $interfaceip = get_interface_ip($ifname);
3037
                $subnet_bits = get_interface_subnet($ifname);
3038
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3039
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3040
                        return $ifname;
3041
        }
3042

    
3043
        return "";
3044
}
3045

    
3046
/****f* interfaces/link_ip_to_carp_interface
3047
 * NAME
3048
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3049
 * INPUTS
3050
 *   $ip
3051
 * RESULT
3052
 *   $carp_ints
3053
 ******/
3054
function link_ip_to_carp_interface($ip) {
3055
        global $config;
3056

    
3057
        if (!is_ipaddr($ip))
3058
                return;
3059

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

    
3077
        return $carp_ints;
3078
}
3079

    
3080
function link_interface_to_vlans($int, $action = "") {
3081
	global $config;
3082

    
3083
	if (empty($int))
3084
		return;
3085

    
3086
	if (is_array($config['vlans']['vlan'])) {
3087
                foreach ($config['vlans']['vlan'] as $vlan) {
3088
			if ($int == $vlan['if']) {
3089
				if ($action == "update") {
3090
					interfaces_bring_up($int);
3091
				} else if ($action == "")
3092
					return $vlan;
3093
			}
3094
		}
3095
	}
3096
}
3097

    
3098
function link_interface_to_vips($int, $action = "") {
3099
        global $config;
3100

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

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

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

    
3130
function link_interface_to_group($int) {
3131
        global $config;
3132

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

    
3141
function link_interface_to_gre($interface) {
3142
        global $config;
3143

    
3144
        if (is_array($config['gres']['gre']))
3145
                foreach ($config['gres']['gre'] as $gre)
3146
                        if($gre['if'] == $interface)
3147
                                return $gre;
3148
}
3149

    
3150
function link_interface_to_gif($interface) {
3151
        global $config;
3152

    
3153
        if (is_array($config['gifs']['gif']))
3154
                foreach ($config['gifs']['gif'] as $gif)
3155
                        if($gif['if'] == $interface)
3156
                                return $gif;
3157
}
3158

    
3159
/*
3160
 * find_interface_ip($interface): return the interface ip (first found)
3161
 */
3162
function find_interface_ip($interface, $flush = false)
3163
{
3164
	global $interface_ip_arr_cache;
3165
	global $interface_sn_arr_cache;
3166

    
3167
	$interface = str_replace("\n", "", $interface);
3168
	
3169
	if (!does_interface_exist($interface))
3170
		return;
3171

    
3172
	/* Setup IP cache */
3173
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3174
		$ifinfo = pfSense_get_interface_addresses($interface);
3175
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3176
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3177
	}
3178

    
3179
	return $interface_ip_arr_cache[$interface];
3180
}
3181

    
3182
function find_interface_subnet($interface, $flush = false)
3183
{
3184
	global $interface_sn_arr_cache;
3185
	global $interface_ip_arr_cache;
3186

    
3187
	$interface = str_replace("\n", "", $interface);
3188
	if (does_interface_exist($interface) == false)
3189
		return;
3190

    
3191
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3192
		$ifinfo = pfSense_get_interface_addresses($interface);
3193
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3194
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3195
        }
3196

    
3197
	return $interface_sn_arr_cache[$interface];
3198
}
3199

    
3200
function ip_in_interface_alias_subnet($interface, $ipalias) {
3201
	global $config;
3202

    
3203
	if (empty($interface) || !is_ipaddr($ipalias))
3204
		return false;
3205
	if (is_array($config['virtualip']['vip'])) {
3206
                foreach ($config['virtualip']['vip'] as $vip) {
3207
                        switch ($vip['mode']) {
3208
                        case "ipalias":
3209
                                if ($vip['interface'] <> $interface)
3210
                                        break;
3211
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3212
					return true;
3213
                                break;
3214
                        }
3215
                }
3216
	}
3217

    
3218
	return false;
3219
}
3220

    
3221
function get_interface_ip($interface = "wan")
3222
{
3223
	$realif = get_real_interface($interface);
3224
	if (!$realif) {
3225
		if (preg_match("/^carp/i", $interface))
3226
			$realif = $interface;
3227
		else if (preg_match("/^vip/i", $interface))
3228
			$realif = $interface;
3229
		else
3230
			return null;
3231
	}
3232

    
3233
	$curip = find_interface_ip($realif);
3234
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3235
		return $curip;
3236
	else
3237
		return null;
3238
}
3239

    
3240
function get_interface_subnet($interface = "wan")
3241
{
3242
	$realif = get_real_interface($interface);
3243
	if (!$realif) {
3244
                if (preg_match("/^carp/i", $interface))
3245
                        $realif = $interface;
3246
                else if (preg_match("/^vip/i", $interface))
3247
                        $realif = $interface;
3248
                else
3249
                        return null;
3250
        }
3251

    
3252
	$cursn = find_interface_subnet($realif);
3253
	if (!empty($cursn))
3254
		return $cursn;
3255

    
3256
	return null;
3257
}
3258

    
3259
/* return outside interfaces with a gateway */
3260
function get_interfaces_with_gateway() {
3261
	global $config;
3262

    
3263
	$ints = array();
3264

    
3265
	/* loop interfaces, check config for outbound */
3266
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3267
		switch ($ifname['ipaddr']) {
3268
			case "dhcp":
3269
			case "carpdev-dhcp":
3270
			case "ppp";
3271
			case "pppoe":
3272
			case "pptp":
3273
			case "l2tp":
3274
			case "ppp";
3275
				$ints[$ifdescr] = $ifdescr;
3276
			break;
3277
			default:
3278
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3279
				    !empty($ifname['gateway']))
3280
					$ints[$ifdescr] = $ifdescr;
3281
			break;
3282
		}
3283
	}
3284
	return $ints;
3285
}
3286

    
3287
/* return true if interface has a gateway */
3288
function interface_has_gateway($friendly) {
3289
	global $config;
3290

    
3291
	if (!empty($config['interfaces'][$friendly])) {
3292
		$ifname = &$config['interfaces'][$friendly];
3293
		switch ($ifname['ipaddr']) {
3294
			case "dhcp":
3295
			case "carpdev-dhcp":
3296
			case "pppoe":
3297
			case "pptp":
3298
			case "l2tp":
3299
			case "ppp";
3300
				return true;
3301
			break;
3302
			default:
3303
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3304
					return true;
3305
				if (!empty($ifname['gateway']))
3306
					return true;
3307
			break;
3308
		}
3309
	}
3310

    
3311
	return false;
3312
}
3313

    
3314
/****f* interfaces/is_altq_capable
3315
 * NAME
3316
 *   is_altq_capable - Test if interface is capable of using ALTQ
3317
 * INPUTS
3318
 *   $int            - string containing interface name
3319
 * RESULT
3320
 *   boolean         - true or false
3321
 ******/
3322

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

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

    
3338
        if (in_array($int_family[0], $capable))
3339
                return true;
3340
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3341
		return true;
3342
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3343
		return true;
3344
        else
3345
                return false;
3346
}
3347

    
3348
/****f* interfaces/is_interface_wireless
3349
 * NAME
3350
 *   is_interface_wireless - Returns if an interface is wireless
3351
 * RESULT
3352
 *   $tmp       - Returns if an interface is wireless
3353
 ******/
3354
function is_interface_wireless($interface) {
3355
        global $config, $g;
3356

    
3357
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3358
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3359
                if (preg_match($g['wireless_regex'], $interface)) {
3360
                        if (isset($config['interfaces'][$friendly]))
3361
                                $config['interfaces'][$friendly]['wireless'] = array();
3362
                        return true;
3363
                }
3364
                return false;
3365
        } else
3366
                return true;
3367
}
3368

    
3369
function get_wireless_modes($interface) {
3370
	/* return wireless modes and channels */
3371
	$wireless_modes = array();
3372

    
3373
	$wlif = interface_translate_type_to_real($interface);
3374

    
3375
	if(is_interface_wireless($wlif)) {
3376
		$cloned_interface = get_real_interface($interface);
3377
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3378
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3379
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3380

    
3381
		$interface_channels = "";
3382
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3383
		$interface_channel_count = count($interface_channels);
3384

    
3385
		$c = 0;
3386
		while ($c < $interface_channel_count)
3387
		{
3388
			$channel_line = explode(",", $interface_channels["$c"]);
3389
			$wireless_mode = trim($channel_line[0]);
3390
			$wireless_channel = trim($channel_line[1]);
3391
			if(trim($wireless_mode) != "") {
3392
				/* if we only have 11g also set 11b channels */
3393
				if($wireless_mode == "11g") {
3394
					if(!isset($wireless_modes["11b"]))
3395
						$wireless_modes["11b"] = array();
3396
				} else if($wireless_mode == "11g ht") {
3397
					if(!isset($wireless_modes["11b"]))
3398
						$wireless_modes["11b"] = array();
3399
					if(!isset($wireless_modes["11g"]))
3400
						$wireless_modes["11g"] = array();
3401
					$wireless_mode = "11ng";
3402
				} else if($wireless_mode == "11a ht") {
3403
					if(!isset($wireless_modes["11a"]))
3404
						$wireless_modes["11a"] = array();
3405
					$wireless_mode = "11na";
3406
				}
3407
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3408
			}
3409
			$c++;
3410
		}
3411
	}
3412
	return($wireless_modes);
3413
}
3414

    
3415
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3416
function get_wireless_channel_info($interface) {
3417
	$wireless_channels = array();
3418

    
3419
	$wlif = interface_translate_type_to_real($interface);
3420

    
3421
	if(is_interface_wireless($wlif)) {
3422
		$cloned_interface = get_real_interface($interface);
3423
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3424
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3425
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3426

    
3427
		$interface_channels = "";
3428
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3429

    
3430
		foreach ($interface_channels as $channel_line) {
3431
			$channel_line = explode(",", $channel_line);
3432
			if(!isset($wireless_channels[$channel_line[0]]))
3433
				$wireless_channels[$channel_line[0]] = $channel_line;
3434
		}
3435
	}
3436
	return($wireless_channels);
3437
}
3438

    
3439
/****f* interfaces/get_interface_mtu
3440
 * NAME
3441
 *   get_interface_mtu - Return the mtu of an interface
3442
 * RESULT
3443
 *   $tmp       - Returns the mtu of an interface
3444
 ******/
3445
function get_interface_mtu($interface) {
3446
        $mtu = pfSense_get_interface_addresses($interface);
3447
        return $mtu['mtu'];
3448
}
3449

    
3450
function get_interface_mac($interface) {
3451

    
3452
	$macinfo = pfSense_get_interface_addresses($interface);
3453
	return $macinfo["macaddr"];
3454
}
3455

    
3456
/****f* pfsense-utils/generate_random_mac_address
3457
 * NAME
3458
 *   generate_random_mac - generates a random mac address
3459
 * INPUTS
3460
 *   none
3461
 * RESULT
3462
 *   $mac - a random mac address
3463
 ******/
3464
function generate_random_mac_address() {
3465
        $mac = "02";
3466
        for($x=0; $x<5; $x++)
3467
                $mac .= ":" . dechex(rand(16, 255));
3468
        return $mac;
3469
}
3470

    
3471
/****f* interfaces/is_jumbo_capable
3472
 * NAME
3473
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3474
 * INPUTS
3475
 *   $int             - string containing interface name
3476
 * RESULT
3477
 *   boolean          - true or false
3478
 ******/
3479
function is_jumbo_capable($int) {
3480
        global $g;
3481

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

    
3484
        if (in_array($int_family[0], $g['vlan_long_frame']))
3485
                return true;
3486
        else
3487
                return false;
3488
}
3489

    
3490
function setup_pppoe_reset_file($pppif, $iface="") {
3491
	global $g;
3492
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3493

    
3494
	if(!empty($iface) && !empty($pppif)){
3495
		$cron_cmd = <<<EOD
3496
#!/bin/sh
3497
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3498
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3499

    
3500
EOD;
3501

    
3502
		file_put_contents($cron_file, $cron_cmd);
3503
		chmod($cron_file, 0700);
3504
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3505
	} else
3506
		unlink_if_exists($cron_file);
3507
}
3508

    
3509
?>
(22-22/54)