Project

General

Profile

Download (94.7 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();
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
	exec("/sbin/route add 127.0.0.2 127.0.0.1");
93
	if($g['booting'])
94
		echo "done.\n";
95
	return 0;
96
}
97

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

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

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

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

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

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

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

    
145
	interfaces_bring_up($vlanif);
146

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

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

    
153
	return $vlanif;
154
}
155

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

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

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

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

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

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

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

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

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

    
222
        return $vlanif;
223
}
224

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

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

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

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

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

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

    
265
        return $vlanif;
266
}
267

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

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

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

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

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

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

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

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

    
319
	$checklist = get_configured_interface_list();
320

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

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

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

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

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

    
477
	if($bridgeif)
478
		interfaces_bring_up($bridgeif);	
479
	else 
480
		log_error("bridgeif not defined -- could not bring interface up");
481

    
482
	return $bridgeif;
483
}
484

    
485
function interface_bridge_add_member($bridgeif, $interface) {
486

    
487
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
488
		return;
489

    
490
	$mtu = get_interface_mtu($brigeif);
491
	$mtum = get_interface_mtu($interface);
492
	
493
	if ($mtu != $mtum)
494
		pfSense_interface_mtu($interface, $mtu);
495

    
496
	$options = pfSense_get_interface_addresses($bridgeif);
497
	if (isset($options['encaps']['txcsum']))
498
		pfSense_interface_capabilities($interface, IFCAP_TXCSUM);
499
	else
500
		pfSense_interface_capabilities($interface, -IFCAP_TXCSUM);
501

    
502
	if (isset($options['encaps']['rxcsum']))
503
		pfSense_interface_capabilities($interface, IFCAP_RXCSUM);
504
	else
505
		pfSense_interface_capabilities($interface, -IFCAP_RXCSUM);
506

    
507
	interfaces_bring_up($interface);
508
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
509
}
510

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

    
530
function interface_lagg_configure(&$lagg) {
531
        global $config, $g;
532

    
533
        if (!is_array($lagg))
534
		return -1;
535

    
536
	$members = explode(',', $lagg['members']);
537
	if (!count($members))
538
		return -1;
539
	
540
	$checklist = get_interface_list();
541

    
542
	if ($g['booting'] || !(empty($lagg['laggif']))) {
543
		pfSense_interface_destroy($lagg['laggif']);
544
		pfSense_interface_create($lagg['laggif']);
545
                $laggif = $lagg['laggif'];
546
        } else
547
		$laggif = pfSense_interface_create("lagg");
548

    
549
	/* Calculate smaller mtu and enforce it */
550
        $smallermtu = 0;
551
        foreach ($members as $member) {
552
                $mtu = get_interface_mtu($member);
553
		if ($smallermtu == 0 && !empty($mtu))
554
			$smallermtu = $mtu;
555
                else if (!empty($mtu) && $mtu < $smallermtu)
556
                        $smallermtu = $mtu;
557
        }
558

    
559
	/* Just in case anything is not working well */
560
        if ($smallermtu == 0)
561
                $smallermtu = 1500;
562

    
563
	foreach ($members as $member) {
564
		if (!array_key_exists($member, $checklist))
565
			continue;
566
		/* make sure the parent interface is up */
567
		pfSense_interface_mtu($member, $smallermtu);
568
		interfaces_bring_up($member);
569
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
570
	}
571
	
572
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
573

    
574
	interfaces_bring_up($laggif);
575

    
576
	return $laggif;
577
}
578

    
579
function interfaces_gre_configure() {
580
        global $config;
581

    
582
        $i = 0;
583
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
584
                foreach ($config['gres']['gre'] as $gre) {
585
                        if(empty($gre['greif']))
586
                                $gre['greif'] = "gre{$i}";
587
                        /* XXX: Maybe we should report any errors?! */
588
                        interface_gre_configure($gre);
589
                        $i++;
590
                }
591
        }
592
}
593

    
594
function interface_gre_configure(&$gre) {
595
        global $config, $g;
596

    
597
	if (!is_array($gre))
598
		return -1;
599

    
600
	$realif = get_real_interface($gre['if']);
601
	$realifip = get_interface_ip($gre['if']);
602

    
603
	/* make sure the parent interface is up */
604
	interfaces_bring_up($realif);
605

    
606
	if ($g['booting'] || !(empty($gre['greif']))) {
607
		pfSense_interface_destroy($gre['greif']);
608
		pfSense_interface_create($gre['greif']);
609
		$greif = $gre['greif'];
610
	} else
611
		$greif = pfSense_interface_create("gre");
612

    
613
	/* Do not change the order here for more see gre(4) NOTES section. */
614
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
615
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
616
	if (isset($gre['link0']) && $gre['link0'])
617
		pfSense_interface_flags($greif, IFF_LINK0);
618
	if (isset($gre['link1']) && $gre['link1'])
619
		pfSense_interface_flags($greif, IFF_LINK1);
620
	if (isset($gre['link2']) && $gre['link2'])
621
		pfSense_interface_flags($greif, IFF_LINK2);
622

    
623
	if($greif)
624
		interfaces_bring_up($greif);
625
	else 
626
		log_error("Could not bring greif up -- variable not defined.");
627

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

    
632
	return $greif;
633
}
634

    
635
function interfaces_gif_configure() {
636
	global $config;
637
	$i = 0;
638
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
639
		foreach ($config['gifs']['gif'] as $gif) {
640
			if(empty($gif['gifif']))
641
				$gre['gifif'] = "gif{$i}";
642
			/* XXX: Maybe we should report any errors?! */
643
			interface_gif_configure($gif);
644
			$i++;
645
		}
646
	}
647
}
648

    
649
function interface_gif_configure(&$gif) {
650
	global $config, $g;
651

    
652
	if (!is_array($gif))
653
		return -1;
654

    
655
	$realif = get_real_interface($gif['if']);
656
	$realifip = get_interface_ip($gif['if']);
657

    
658
	/* make sure the parent interface is up */
659
	if($realif)
660
		interfaces_bring_up($realif);
661
	else 
662
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
663

    
664
	if ($g['booting'] || !(empty($gif['gifif']))) {
665
		pfSense_interface_destroy($gif['gifif']);
666
		pfSense_interface_create($gif['gifif']);
667
		$gifif = $gif['gifif'];
668
	} else
669
		$gifif = pfSense_interface_create("gif");
670

    
671
	/* Do not change the order here for more see gif(4) NOTES section. */
672
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
673
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
674
	if (isset($gif['link0']) && $gif['link0'])
675
		pfSense_interface_flags($gifif, IFF_LINK0);
676
	if (isset($gif['link1']) && $gif['link1'])
677
		pfSense_interface_flags($gifif, IFF_LINK1);
678
	if($gifif)
679
		interfaces_bring_up($gifif);
680
	else
681
		log_error("could not bring gifif up -- variable not defined");
682

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

    
687
	return $gifif;
688
}
689

    
690
function interfaces_configure() {
691
	global $config, $g;
692

    
693
	/* Set up our loopback interface */
694
	interfaces_loopback_configure();
695

    
696
	/* set up LAGG virtual interfaces */
697
	interfaces_lagg_configure();
698

    
699
	/* set up VLAN virtual interfaces */
700
	interfaces_vlan_configure();
701

    
702
	interfaces_qinq_configure();
703

    
704
	$iflist = get_configured_interface_with_descr();
705
	$delayed_list = array();
706
	$bridge_list = array();
707
	
708
	/* This is needed to speedup interfaces on bootup. */
709
	$reload = false;
710
	if ($g['booting'])
711
		$reload = true;
712

    
713
	foreach($iflist as $if => $ifname) {
714
		$realif = $config['interfaces'][$if]['if'];
715
		if (strstr($realif, "bridge")) 
716
			$bridge_list[$if] = $ifname;
717
		else if (strstr($realif, "gre"))
718
			$delayed_list[$if] = $ifname;
719
		else if (strstr($realif, "gif"))
720
			$delayed_list[$if] = $ifname;
721
		else {
722
			if ($g['booting'])
723
				echo "Configuring {$ifname} interface...";
724
			if($g['debug'])
725
				log_error("Configuring {$ifname}");
726
			interface_configure($if, $reload);
727
			if ($g['booting']) 
728
				echo "done.\n";
729
		}
730
	}
731

    
732
	/* create the unconfigured wireless clones */
733
	interfaces_create_wireless_clones();
734

    
735
	/* set up GRE virtual interfaces */
736
	interfaces_gre_configure();
737

    
738
	/* set up GIF virtual interfaces */
739
	interfaces_gif_configure();
740
	
741
	foreach ($delayed_list as $if => $ifname) {
742
		if ($g['booting'])
743
			echo "Configuring {$ifname} interface...";
744
        	if ($g['debug'])
745
        		log_error("Configuring {$ifname}");
746

    
747
		interface_configure($if, $reload);
748

    
749
		if ($g['booting'])
750
			echo "done.\n";
751
	}
752

    
753
	/* set up BRIDGe virtual interfaces */
754
	interfaces_bridge_configure();
755

    
756
	foreach ($bridge_list as $if => $ifname) {
757
		if ($g['booting'])
758
			echo "Configuring {$ifname} interface...";
759
		if($g['debug'])
760
			log_error("Configuring {$ifname}");
761

    
762
		interface_configure($if, $reload);
763

    
764
		if ($g['booting'])
765
			echo "done.\n";
766
	}
767

    
768
	/* bring up vip interfaces */
769
	interfaces_vips_configure();
770

    
771
	/* configure interface groups */
772
	interfaces_group_setup();
773

    
774
	if (!$g['booting']) {
775
		/* reconfigure static routes (kernel may have deleted them) */
776
		system_routing_configure();
777

    
778
		/* reload IPsec tunnels */
779
		vpn_ipsec_configure();
780

    
781
		/* reload dhcpd (interface enabled/disabled status may have changed) */
782
		services_dhcpd_configure();
783

    
784
		/* restart dnsmasq */
785
		services_dnsmasq_configure();
786

    
787
		/* reload captive portal */
788
		captiveportal_init_rules();
789

    
790
		/* set the reload filter dity flag */
791
		filter_configure();
792
	}
793

    
794
	return 0;
795
}
796

    
797
function interface_reconfigure($interface = "wan") {
798
	interface_bring_down($interface);
799
	interface_configure($interface, true);
800
}
801

    
802
function interface_vip_bring_down($vip) {
803
	global $g;
804

    
805
	switch ($vip['mode']) {
806
	case "proxyarp":
807
		$vipif = get_real_interface($vip['interface']);
808
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
809
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
810
		break;
811
	case "ipalias":
812
		$vipif = get_real_interface($vip['interface']);
813
		if(does_interface_exist($vipif))
814
			pfSense_interface_deladdress($vipif, $vip['subnet']);
815
		break;
816
	case "carp":
817
		$vipif = "vip" . $vip['vhid'];
818
		if(does_interface_exist($vipif)) 
819
			pfSense_interface_destroy($vipif);
820
		break;
821
	case "carpdev-dhcp":
822
		$vipif = "vip" . $vip['vhid'];
823
		if(does_interface_exist($vipif)) 
824
			pfSense_interface_destroy($vipif);
825
		break;
826
	}
827
}
828

    
829
function interface_bring_down($interface = "wan", $destroy = false) {
830
	global $config, $g;
831

    
832
	if (!isset($config['interfaces'][$interface]))
833
		return; 
834

    
835
	$ifcfg = $config['interfaces'][$interface];
836

    
837
	$realif = get_real_interface($interface);
838

    
839
	switch ($ifcfg['ipaddr']) {
840
	case "ppp":
841
	case "pppoe":
842
	case "pptp":
843
	case "l2tp":
844
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
845
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
846
				if ($realif == $ppp['if']) {
847
					if (file_exists("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid")) {
848
						killbypid("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid");
849
						sleep(2);
850
					}
851
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
852
					if (isset($ppp['ondemand']) && !$destroy) {
853
						interface_configure($interface);
854
					}
855
					break;
856
				}
857
			}
858
		}
859
		break;
860
	case "carpdev-dhcp":
861
		/* 
862
		 * NB: When carpdev gets enabled it would be better to be handled as all
863
		 *	   other interfaces! 
864
		 */
865
	case "dhcp":
866
		$pid = find_dhclient_process($realif);
867
		if($pid)
868
			mwexec("kill {$pid}");
869
		sleep(1);
870
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
871
		if(does_interface_exist("$realif")) {
872
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
873
			pfSense_interface_flags($realif, -IFF_UP);
874
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
875
		}
876
		break;
877
	default:
878
		if(does_interface_exist("$realif")) {
879
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
880
			pfSense_interface_flags($realif, -IFF_UP);
881
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
882
		}
883
		break;
884
	}
885

    
886
	/* remove interface up file if it exists */
887
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
888
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
889
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
890
	
891
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
892
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
893
	if (is_array($ifcfg['wireless'])) {
894
		mwexec(kill_hostapd($realif));
895
		mwexec(kill_wpasupplicant($realif));
896
	}
897

    
898
	if ($destroy == true) {
899
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
900
			pfSense_interface_destroy($realif);
901
	}	
902

    
903
	return;
904
}
905

    
906
function interfaces_ptpid_used($ptpid) {
907
	global $config;
908

    
909
	if (is_array($config['ppps']['ppp']))
910
		foreach ($config['ppps']['ppp'] as & $settings)
911
			if ($ptpid == $settings['ptpid'])
912
				return true;
913

    
914
	return false;
915
}
916

    
917
function interfaces_ptpid_next() {
918

    
919
	$ptpid = 0;
920
	while(interfaces_ptpid_used($ptpid))
921
		$ptpid++;
922

    
923
	return $ptpid;
924
}
925

    
926
function getMPDCRONSettings($pppif_) {
927
	global $config;
928
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
929
	if (is_array($config['cron']['item'])) {
930
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
931
			$item = $config['cron']['item'][$i];
932
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
933
				return array("ID" => $i, "ITEM" => $item);
934
			}
935
		}
936
	}
937
	return NULL;
938
}
939

    
940
function handle_pppoe_reset($post_array) {
941
	global $config, $g;
942

    
943
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
944

    
945
	$pppif = $post_array['type'].$post_array['ptpid'];
946
	if (!is_array($config['cron']['item'])) 
947
		$config['cron']['item'] = array(); 
948
	$itemhash = getMPDCRONSettings($pppif);
949
	$item = $itemhash['ITEM'];
950
	
951
	// reset cron items if necessary and return
952
	if (empty($post_array['pppoe-reset-type'])) {
953
		if (isset($item))
954
			unset($config['cron']['item'][$itemhash['ID']]);
955
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
956
		return;
957
	}
958

    
959
	if (empty($item)) 
960
		$item = array();
961
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
962
		$item['minute'] = $post_array['pppoe_resetminute'];
963
		$item['hour'] = $post_array['pppoe_resethour'];
964
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
965
			$date = explode("/", $post_array['pppoe_resetdate']);
966
			$item['mday'] = $date[1];
967
			$item['month'] = $date[0];
968
		} else {
969
			$item['mday'] = "*";
970
			$item['month'] = "*";
971
		}
972
		$item['wday'] = "*";
973
		$item['who'] = "root";
974
		$item['command'] = $cron_cmd_file.$pppif;
975
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
976
		switch ($post_array['pppoe_pr_preset_val']) {
977
			case "monthly":
978
				$item['minute'] = "0";
979
				$item['hour'] = "0";
980
				$item['mday'] = "1";
981
				$item['month'] = "*";
982
				$item['wday'] = "*";
983
				$item['who'] = "root";
984
				$item['command'] = $cron_cmd_file.$pppif;
985
				break;
986
	        case "weekly":
987
				$item['minute'] = "0";
988
				$item['hour'] = "0";
989
				$item['mday'] = "*";
990
				$item['month'] = "*";
991
				$item['wday'] = "0";
992
				$item['who'] = "root";
993
				$item['command'] = $cron_cmd_file.$pppif;
994
				break;
995
			case "daily":
996
				$item['minute'] = "0";
997
				$item['hour'] = "0";
998
				$item['mday'] = "*";
999
				$item['month'] = "*";
1000
				$item['wday'] = "*";
1001
				$item['who'] = "root";
1002
				$item['command'] = $cron_cmd_file.$pppif;
1003
				break;
1004
			case "hourly":
1005
				$item['minute'] = "0";
1006
				$item['hour'] = "*";
1007
				$item['mday'] = "*";
1008
				$item['month'] = "*";
1009
				$item['wday'] = "*";
1010
				$item['who'] = "root";
1011
				$item['command'] = $cron_cmd_file.$pppif;
1012
				break;
1013
		} // end switch
1014
	} else {
1015
		/* test whether a cron item exists and unset() it if necessary */
1016
		$itemhash = getMPDCRONSettings($pppif);
1017
		$item = $itemhash['ITEM'];
1018
		if (isset($item))
1019
			unset($config['cron']['item'][$itemhash['ID']]); 
1020
	}// end if
1021
	if (isset($itemhash['ID'])) 
1022
		$config['cron']['item'][$itemhash['ID']] = $item;
1023
	else 
1024
		$config['cron']['item'][] = $item;
1025
}
1026

    
1027
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1028
*	It writes the mpd config file to /var/etc every time the link is opened.
1029
*/
1030

    
1031
function interface_ppps_configure($interface) {
1032
	global $config, $g;
1033
	
1034
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1035
	if(!is_dir("/var/spool/lock")) {
1036
		exec("/bin/mkdir -p /var/spool/lock");
1037
		exec("/bin/chmod a+rw /var/spool/lock/.");
1038
	}
1039
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1040
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1041
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1042
		
1043
	$ifcfg = &$config['interfaces'][$interface];
1044
	if (!isset($ifcfg['enable']))
1045
		return 0;
1046
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1047
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1048
			if ($ifcfg['if'] == $ppp['if'])
1049
				break;
1050
		}
1051
	}
1052
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1053
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1054
		return 0;
1055
	}
1056
	$pppif = $ifcfg['if'];
1057
	if ($ppp['type'] == "ppp")
1058
		$type = "modem";
1059
	else
1060
		$type = $ppp['type'];
1061
	$upper_type = strtoupper($ppp['type']);	
1062
	
1063
	if($g['booting']) {
1064
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1065
		echo " configuring {$upper_type} on {$descr} interface...\n";
1066
		// Do not re-configure the interface if we are booting and it's already been started
1067
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1068
			return 0;
1069
	}
1070
	
1071
	$ports = explode(',',$ppp['ports']);
1072
	if ($type != "modem") {
1073
		foreach ($ports as $pid => $port)
1074
			$ports[$pid] = get_real_interface($port);
1075
	}
1076
	$localips = explode(',',$ppp['localip']);
1077
	$gateways = explode(',',$ppp['gateway']);
1078
	$subnets = explode(',',$ppp['subnet']);
1079
	
1080
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1081
	to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1082
	*/
1083
	foreach($ports as $pid => $port){
1084
		switch ($ppp['type']) {
1085
			case "pppoe": 
1086
				/* Bring the parent interface up */
1087
				interfaces_bring_up($port);
1088
				break;
1089
			case "pptp":
1090
			case "l2tp":
1091
				/* configure interface */
1092
				if(is_ipaddr($localips[$pid])){
1093
					// Manually configure interface IP/subnet
1094
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1095
					interfaces_bring_up($port);
1096
				} else if (empty($localips[$pid]))
1097
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1098
				
1099
				if(!is_ipaddr($localips[$pid])){
1100
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure.");
1101
					return 0;
1102
				}
1103
				/* XXX: This needs to go away soon! [It's commented out!] */
1104
				/* Configure the gateway (remote IP ) */
1105
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1106
					/* XXX: Fix later 
1107
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1108
					if(!is_ipaddr($gateways[$pid])) {
1109
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1110
						return 0;
1111
					}
1112
					*/
1113
				}
1114
				if(!is_ipaddr($gateways[$pid])){
1115
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1116
					return 0;
1117
				}
1118
				break;
1119
			case "ppp":
1120
				if (!file_exists("{$port}")) {
1121
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1122
					return 0;
1123
				}
1124
				break;
1125
			default:
1126
				log_error("Unkown {$type} configured as ppp interface.");
1127
				break;
1128
		}
1129
	}
1130
	
1131
	if (is_array($ports) && count($ports) > 1)
1132
		$multilink = "enable";
1133
	else
1134
		$multilink = "disable";
1135
	
1136
	if ($type == "modem"){
1137
		if (is_ipaddr($ppp['localip']))
1138
			$localip = $ppp['localip'];
1139
		else
1140
			$localip = '0.0.0.0';
1141

    
1142
		if (is_ipaddr($ppp['gateway']))
1143
			$gateway = $ppp['gateway'];
1144
		else
1145
			$gateway = "10.64.64.{$pppid}";
1146
		$ranges = "{$localip}/0 {$gateway}/0";
1147
		
1148
		if (empty($ppp['apnum']))	
1149
			$ppp['apnum'] = 1;
1150
	} else
1151
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1152

    
1153
	if (isset($ppp['ondemand'])) 
1154
		$ondemand = "enable";
1155
	else
1156
		$ondemand = "disable";
1157
	if (!isset($ppp['idletimeout']))
1158
		$ppp['idletimeout'] = 0;
1159

    
1160
	if (empty($ppp['username']) && $type == "modem"){
1161
		$ppp['username'] = "user";
1162
		$ppp['password'] = "none";
1163
	}
1164
	if (empty($ppp['password']) && $type == "modem")
1165
		$passwd = "none";
1166
	else
1167
		$passwd = base64_decode($ppp['password']);
1168

    
1169
	$bandwidths = explode(',',$ppp['bandwidth']);
1170
	$mtus = explode(',',$ppp['mtu']);
1171
	$mrus = explode(',',$ppp['mru']);
1172

    
1173
	if (isset($ppp['mrru']))
1174
		$mrrus = explode(',',$ppp['mrru']);
1175

    
1176
	// Construct the mpd.conf file
1177
	$mpdconf = <<<EOD
1178
startup:
1179
	# configure the console
1180
	set console close
1181
	# configure the web server
1182
	set web close
1183

    
1184
default:
1185
{$ppp['type']}client:
1186
	create bundle static {$interface}
1187
	set iface name {$pppif}
1188

    
1189
EOD;
1190
	$setdefaultgw = false;
1191
	$founddefaultgw = false;
1192
	if (is_array($config['gateways']['gateway_item'])) {
1193
		foreach($config['gateways']['gateway_item'] as $gateway) {
1194
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1195
				$setdefaultgw = true;
1196
				break;
1197
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1198
				$founddefaultgw = true;
1199
				break;
1200
			}
1201
		}
1202
	}
1203
	
1204
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1205
		$setdefaultgw = true;
1206
		$mpdconf .= <<<EOD
1207
	set iface route default
1208

    
1209
EOD;
1210
	}
1211
	$mpdconf .= <<<EOD
1212
	set iface {$ondemand} on-demand
1213
	set iface idle {$ppp['idletimeout']}
1214

    
1215
EOD;
1216

    
1217
	if (isset($ppp['ondemand']))
1218
		$mpdconf .= <<<EOD
1219
	set iface addrs 10.10.1.1 10.10.1.2
1220

    
1221
EOD;
1222
	
1223
	if (isset($ppp['tcpmssfix']))
1224
		$tcpmss = "disable";
1225
	else
1226
		$tcpmss = "enable";
1227
		$mpdconf .= <<<EOD
1228
	set iface {$tcpmss} tcpmssfix
1229

    
1230
EOD;
1231

    
1232
	$mpdconf .= <<<EOD
1233
	set iface up-script /usr/local/sbin/ppp-linkup
1234
	set iface down-script /usr/local/sbin/ppp-linkdown
1235
	set ipcp ranges {$ranges}
1236

    
1237
EOD;
1238
	if (isset($ppp['vjcomp']))
1239
		$mpdconf .= <<<EOD
1240
	set ipcp no vjcomp
1241

    
1242
EOD;
1243

    
1244
	if (isset($config['system']['dnsallowoverride']))
1245
		$mpdconf .= <<<EOD
1246
	set ipcp enable req-pri-dns
1247
	set ipcp enable req-sec-dns
1248

    
1249
EOD;
1250
	if (!isset($ppp['verbose_log']))
1251
		$mpdconf .= <<<EOD
1252
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1253

    
1254
EOD;
1255
	foreach($ports as $pid => $port){
1256
		$port = get_real_interface($port);
1257
		$mpdconf .= <<<EOD
1258

    
1259
	create link static {$interface}_link{$pid} {$type}
1260
	set link action bundle {$interface}
1261
	set link {$multilink} multilink
1262
	set link keep-alive 10 60
1263
	set link max-redial 0
1264

    
1265
EOD;
1266
		if (isset($ppp['shortseq']))
1267
			$mpdconf .= <<<EOD
1268
	set link no shortseq
1269

    
1270
EOD;
1271

    
1272
		if (isset($ppp['acfcomp']))
1273
			$mpdconf .= <<<EOD
1274
	set link no acfcomp
1275

    
1276
EOD;
1277

    
1278
		if (isset($ppp['protocomp']))
1279
			$mpdconf .= <<<EOD
1280
	set link no protocomp
1281

    
1282
EOD;
1283

    
1284
		$mpdconf .= <<<EOD
1285
	set link disable chap pap
1286
	set link accept chap pap eap
1287
	set link disable incoming
1288

    
1289
EOD;
1290

    
1291

    
1292
		if (!empty($bandwidths[$pid]))
1293
			$mpdconf .= <<<EOD
1294
	set link bandwidth {$bandwidths[$pid]}
1295

    
1296
EOD;
1297

    
1298
		if (empty($mtus[$pid]))
1299
			$mtus[$pid] = "1492";
1300
			$mpdconf .= <<<EOD
1301
	set link mtu {$mtus[$pid]}
1302

    
1303
EOD;
1304

    
1305
		if (!empty($mrus[$pid]))
1306
			$mpdconf .= <<<EOD
1307
	set link mru {$mrus[$pid]}
1308

    
1309
EOD;
1310

    
1311
		if (!empty($mrrus[$pid]))
1312
			$mpdconf .= <<<EOD
1313
	set link mrru {$mrrus[$pid]}
1314

    
1315
EOD;
1316

    
1317
		$mpdconf .= <<<EOD
1318
	set auth authname "{$ppp['username']}"
1319
	set auth password {$passwd}
1320

    
1321
EOD;
1322
		if ($type == "modem") {
1323
			$mpdconf .= <<<EOD
1324
	set modem device {$ppp['ports']}
1325
	set modem script DialPeer
1326
	set modem idle-script Ringback
1327
	set modem watch -cd
1328
	set modem var \$DialPrefix "DT"
1329
	set modem var \$Telephone "{$ppp['phone']}"
1330

    
1331
EOD;
1332
		}
1333
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1334
			$mpdconf .= <<<EOD
1335
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1336

    
1337
EOD;
1338
		}
1339
		if (isset($ppp['initstr']) && $type == "modem") {
1340
			$initstr = base64_decode($ppp['initstr']);
1341
			$mpdconf .= <<<EOD
1342
	set modem var \$InitString "{$initstr}"
1343

    
1344
EOD;
1345
		}
1346
		if (isset($ppp['simpin']) && $type == "modem") {
1347
			$mpdconf .= <<<EOD
1348
	set modem var \$SimPin "{$ppp['simpin']}"
1349
	set modem var \$PinWait "{$ppp['pin-wait']}"
1350

    
1351
EOD;
1352
		}
1353
		if (isset($ppp['apn']) && $type == "modem") {
1354
			$mpdconf .= <<<EOD
1355
	set modem var \$APN "{$ppp['apn']}"
1356
	set modem var \$APNum "{$ppp['apnum']}"
1357

    
1358
EOD;
1359
		}
1360
		if (isset($ppp['provider']) && $type == "pppoe") {
1361
			$mpdconf .= <<<EOD
1362
	set pppoe service "{$ppp['provider']}"
1363

    
1364
EOD;
1365
		}
1366
		if ($type == "pppoe")
1367
			$mpdconf .= <<<EOD
1368
	set pppoe iface {$port}
1369

    
1370
EOD;
1371

    
1372
		if ($type == "pptp" || $type == "l2tp") {
1373
			$mpdconf .= <<<EOD
1374
	set {$type} self {$localips[$pid]}
1375
	set {$type} peer {$gateways[$pid]}
1376
	set {$type} disable windowing
1377

    
1378
EOD;
1379
		}
1380
		
1381
		$mpdconf .= "\topen\r\n";
1382
	} //end foreach($port)
1383

    
1384

    
1385
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1386
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1387
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1388
	else {
1389
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1390
		if (!$fd) {
1391
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1392
			return 0;
1393
		}
1394
		// Write out mpd_ppp.conf
1395
		fwrite($fd, $mpdconf);
1396
		fclose($fd);
1397
	}
1398

    
1399
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1400
	if (isset($ppp['uptime'])) {
1401
		if (!file_exists("/conf/{$pppif}.log")) {
1402
			conf_mount_rw();
1403
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1404
			conf_mount_ro();
1405
		}
1406
	} else {
1407
		if (file_exists("/conf/{$pppif}.log")) {
1408
			conf_mount_rw();
1409
			mwexec("rm -f /conf/{$pppif}.log");
1410
			conf_mount_ro();
1411
		}
1412
	}
1413
		
1414
	/* fire up mpd */
1415
	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");
1416

    
1417
	// Check for PPPoE periodic reset request 
1418
	if ($type == "pppoe") {
1419
		if (isset($ppp['pppoe-reset-type']))
1420
			setup_pppoe_reset_file($ppp['if'], $interface);
1421
		else
1422
			setup_pppoe_reset_file($ppp['if']);
1423
	}
1424

    
1425
	return 1;
1426
}
1427

    
1428
function interfaces_carp_setup() {
1429
	global $g, $config;
1430

    
1431
	$balanacing = "";
1432
	$pfsyncinterface = "";
1433
	$pfsyncenabled = "";
1434
	if(isset($config['system']['developerspew'])) {
1435
		$mt = microtime();
1436
		echo "interfaces_carp_setup() being called $mt\n";
1437
	}
1438

    
1439
	// Prepare CmdCHAIN that will be used to execute commands.
1440
	$cmdchain = new CmdCHAIN();	
1441

    
1442
	if ($g['booting']) {
1443
		echo "Configuring CARP settings...";
1444
		mute_kernel_msgs();
1445
	}
1446

    
1447
	/* suck in configuration items */
1448
	if($config['installedpackages']['carpsettings']) {
1449
		if($config['installedpackages']['carpsettings']['config']) {
1450
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1451
				$pfsyncenabled = $carp['pfsyncenabled'];
1452
				$balanacing = $carp['balancing'];
1453
				$pfsyncinterface = $carp['pfsyncinterface'];
1454
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1455
			}
1456
		}
1457
	} else {
1458
		unset($pfsyncinterface);
1459
		unset($balanacing);
1460
		unset($pfsyncenabled);
1461
	}
1462

    
1463
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1464
	if($balanacing) {
1465
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1466
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1467
	} else
1468
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1469

    
1470
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1471
	if (!empty($pfsyncinterface))
1472
		$carp_sync_int = get_real_interface($pfsyncinterface);
1473

    
1474
	if($g['booting']) {
1475
		/*    install rules to alllow pfsync to sync up during boot
1476
		 *    carp interfaces will remain down until the bootup sequence finishes
1477
		 */
1478
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1479
		if ($fd) {
1480
			fwrite($fd, "pass quick proto carp all keep state\n");
1481
			fwrite($fd, "pass quick proto pfsync all\n");
1482
			fwrite($fd, "pass out quick from any to any keep state\n");
1483
			fclose($fd);
1484
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1485
		} else
1486
			log_error("Could not create rules.boot file!");
1487
	}
1488

    
1489
	/* setup pfsync interface */
1490
	if($carp_sync_int and $pfsyncenabled) {
1491
		if (is_ipaddr($pfsyncpeerip))
1492
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1493
		else
1494
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1495
	} else
1496
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1497

    
1498
	if($config['virtualip']['vip'])
1499
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1500
	else
1501
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1502
	
1503
	if($g['debug'])
1504
		$cmdchain->setdebug(); // optional for verbose logging
1505

    
1506
	$cmdchain->execute();
1507
	$cmdchain->clear();
1508

    
1509
	if ($g['booting']) {
1510
		unmute_kernel_msgs();
1511
		echo "done.\n";
1512
	}
1513
}
1514

    
1515
function interface_proxyarp_configure($interface = "") {
1516
	global $config, $g;
1517
	if(isset($config['system']['developerspew'])) {
1518
		$mt = microtime();
1519
		echo "interface_proxyarp_configure() being called $mt\n";
1520
	}
1521

    
1522
	/* kill any running choparp */
1523
	if (empty($interface))
1524
		killbyname("choparp");
1525

    
1526
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1527
		$paa = array();
1528

    
1529
		/* group by interface */
1530
		foreach ($config['virtualip']['vip'] as $vipent) {
1531
			if ($vipent['mode'] === "proxyarp") {
1532
				if ($vipent['interface'])
1533
					$proxyif = $vipent['interface'];
1534
				else
1535
					$proxyif = "wan";
1536

    
1537
				if (!is_array($paa[$if]))
1538
					$paa[$proxyif] = array();
1539

    
1540
				$paa[$proxyif][] = $vipent;
1541
			}
1542
		}
1543
	}
1544

    
1545
	if (!empty($interface)) {
1546
		if (is_array($paa[$interface])) {
1547
			$paaifip = get_interface_ip($interface);
1548
                        if (!is_ipaddr($paaifip))
1549
                                return;
1550
                        $args = get_real_interface($interface) . " auto";
1551
                        foreach ($paa[$interface] as $paent) {
1552
                                if (isset($paent['subnet']))
1553
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1554
                                else if (isset($paent['range']))
1555
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1556
                        }
1557
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1558
		}
1559
	} else if (count($paa)) {
1560
		foreach ($paa as $paif => $paents) {
1561
			$paaifip = get_interface_ip($paif);
1562
			if (!(is_ipaddr($paaifip)))
1563
				continue;
1564
			$args = get_real_interface($paif) . " auto";
1565
			foreach ($paents as $paent) {
1566
				if (isset($paent['subnet']))
1567
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1568
				else if (isset($paent['range']))
1569
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1570
			}
1571
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1572
		}
1573
	}
1574
}
1575

    
1576
function interfaces_vips_configure($interface = "") {
1577
	global $g, $config;
1578
	if(isset($config['system']['developerspew'])) {
1579
		$mt = microtime();
1580
		echo "interfaces_vips_configure() being called $mt\n";
1581
	}
1582
	$paa = array();
1583
	if(is_array($config['virtualip']['vip'])) {
1584
		$carp_setuped = false;
1585
		$anyproxyarp = false;
1586
		foreach ($config['virtualip']['vip'] as $vip) {
1587
			switch ($vip['mode']) {
1588
			case "proxyarp":
1589
				/* nothing it is handled on interface_proxyarp_configure() */
1590
				if ($interface <> "" && $vip['interface'] <> $interface)
1591
					continue;
1592
				$anyproxyarp = true;
1593
				break;
1594
			case "ipalias":
1595
				if ($interface <> "" && $vip['interface'] <> $interface)
1596
					continue;
1597
				interface_ipalias_configure(&$vip);
1598
				break;
1599
			case "carp":
1600
				if ($interface <> "" && $vip['interface'] <> $interface)
1601
					continue;
1602
				if ($carp_setuped == false) {
1603
					interfaces_carp_setup();
1604
					$carp_setuped = true;
1605
				}
1606
				interface_carp_configure($vip);
1607
				break;
1608
			case "carpdev-dhcp":
1609
				if ($interface <> "" && $vip['interface'] <> $interface)
1610
					continue;
1611
				interface_carpdev_configure($vip);
1612
				break;
1613
			}
1614
		}
1615
		
1616
		if ($anyproxyarp == true)
1617
			interface_proxyarp_configure();
1618
	}
1619
}
1620

    
1621
function interface_ipalias_configure(&$vip) {
1622

    
1623
	if ($vip['mode'] == "ipalias") {
1624
		$if = get_real_interface($vip['interface']);
1625
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1626
	}
1627
}
1628

    
1629
function interface_reload_carps($cif) {
1630
	global $config;
1631

    
1632
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1633
	if (empty($carpifs))
1634
		return;
1635

    
1636
	$carps = explode(" ", $carpifs);
1637
	if(is_array($config['virtualip']['vip'])) {
1638
		$viparr = &$config['virtualip']['vip'];
1639
		foreach ($viparr as $vip) {
1640
			if (in_array($vip['carpif'], $carps)) {
1641
				switch ($vip['mode']) {
1642
				case "carp":
1643
					interface_vip_bring_down($vip);
1644
					sleep(1);
1645
					interface_carp_configure($vip);
1646
					break;
1647
				case "carpdev-dhcp":
1648
					interface_vip_bring_down($vip);
1649
					sleep(1);
1650
					interface_carpdev_configure($vip);
1651
					break;
1652
				case "ipalias":
1653
					interface_vip_bring_down($vip);
1654
					sleep(1);
1655
					interface_ipalias_configure($vip);
1656
					break;
1657
				}
1658
			}
1659
		}
1660
	}
1661
}
1662

    
1663
function interface_carp_configure(&$vip) {
1664
	global $config, $g;
1665
	if(isset($config['system']['developerspew'])) {
1666
		$mt = microtime();
1667
		echo "interface_carp_configure() being called $mt\n";
1668
	}
1669

    
1670
	if ($vip['mode'] != "carp")
1671
		return;
1672

    
1673
	$vip_password = $vip['password'];
1674
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1675
	if ($vip['password'] != "")
1676
		$password = " pass {$vip_password}";
1677

    
1678
	// set the vip interface to the vhid
1679
	$vipif = "vip{$vip['vhid']}";
1680

    
1681
	$interface = interface_translate_type_to_real($vip['interface']);
1682
	/*
1683
	 * ensure the interface containing the VIP really exists
1684
 	 * prevents a panic if the interface is missing or invalid
1685
	 */
1686
	$realif = get_real_interface($vip['interface']);
1687
	if (!does_interface_exist($realif)) {
1688
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1689
		return;
1690
	}
1691

    
1692
	/* Ensure CARP IP really exists prior to loading up. */
1693
	$ww_subnet_ip = find_interface_ip($realif);
1694
	$ww_subnet_bits = find_interface_subnet($realif);
1695
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1696
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1697
		return;
1698
	}
1699

    
1700
	/* create the carp interface and setup */
1701
	if (does_interface_exist($vipif)) {
1702
		pfSense_interface_flags($vipif, -IFF_UP);
1703
	} else {
1704
		$carpif = pfSense_interface_create("carp");
1705
		pfSense_interface_rename($carpif, $vipif);
1706
		pfSense_ngctl_name("{$carpif}:", $vipif);
1707
	}
1708

    
1709
	/* invalidate interface cache */
1710
	get_interface_arr(true);
1711

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

    
1715
	interfaces_bring_up($vipif);
1716
	
1717
	return $vipif;
1718
}
1719

    
1720
function interface_carpdev_configure(&$vip) {
1721
	global $g;
1722

    
1723
	if ($vip['mode'] != "carpdev-dhcp")
1724
		return;
1725

    
1726
	$vip_password = $vip['password'];
1727
	$vip_password = str_replace(" ", "", $vip_password);
1728
	if($vip['password'] != "")
1729
		$password = " pass \"" . $vip_password . "\"";
1730

    
1731
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1732
	if (empty($vip['interface']))
1733
		return;
1734

    
1735
	$vipif = "vip" . $vip['vhid'];
1736
	$realif = interface_translate_type_to_real($vip['interface']);
1737
	interfaces_bring_up($realif);
1738
	/*
1739
	 * ensure the interface containing the VIP really exists
1740
	 * prevents a panic if the interface is missing or invalid
1741
	 */
1742
	if (!does_interface_exist($realif)) {
1743
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1744
		return;
1745
	}
1746

    
1747
	if (does_interface_exist($vipif)) {
1748
		interface_bring_down($vipif);
1749
	} else {
1750
		$carpdevif = exec("/sbin/ifconfig carp create");
1751
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1752
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1753
	}
1754

    
1755
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1756
	interfaces_bring_up($vipif);
1757

    
1758
	/*
1759
	 * XXX: BIG HACK but carpdev needs ip services active
1760
	 *      before even starting something as dhclient.
1761
	 *      I do not know if this is a feature or a bug
1762
	 *      but better than track it make it work ;) .
1763
	 */
1764
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1765
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1766

    
1767
	/* generate dhclient_wan.conf */
1768
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1769
	if ($fd) {
1770
		$dhclientconf = "";
1771

    
1772
		$dhclientconf .= <<<EOD
1773
interface "{$vipif}" {
1774
timeout 60;
1775
retry 1;
1776
select-timeout 0;
1777
initial-interval 1;
1778
script "/sbin/dhclient-script";
1779
}
1780

    
1781
EOD;
1782

    
1783
		fwrite($fd, $dhclientconf);
1784
		fclose($fd);
1785

    
1786
		/* fire up dhclient */
1787
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1788
	} else {
1789
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1790
		mwexec("/sbin/dhclient -b {$vipif}");
1791
	}
1792

    
1793
	return $vipif;
1794
}
1795

    
1796
function interface_wireless_clone($realif, $wlcfg) {
1797
	global $config, $g;
1798
	/*   Check to see if interface has been cloned as of yet.  
1799
	 *   If it has not been cloned then go ahead and clone it.
1800
	 */
1801
	$needs_clone = false;
1802
	if(is_array($wlcfg['wireless']))
1803
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1804
	else
1805
		$wlcfg_mode = $wlcfg['mode'];
1806
	switch($wlcfg_mode) {
1807
		 case "hostap":
1808
			$mode = "wlanmode hostap";
1809
			break;
1810
		 case "adhoc":
1811
			$mode = "wlanmode adhoc";
1812
			break;
1813
		 default:
1814
			$mode = "";
1815
			break;
1816
	}
1817
	$baseif = interface_get_wireless_base($wlcfg['if']);
1818
	if(does_interface_exist($realif)) {
1819
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1820
		$ifconfig_str = implode($output);
1821
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1822
			log_error("Interface {$realif} changed to hostap mode");
1823
			$needs_clone = true;
1824
		}
1825
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1826
			log_error("Interface {$realif} changed to adhoc mode");
1827
			$needs_clone = true;
1828
		}
1829
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1830
			log_error("Interface {$realif} changed to infrastructure mode");
1831
			$needs_clone = true;
1832
		}
1833
	} else {
1834
		$needs_clone = true;
1835
	}
1836

    
1837
	if($needs_clone == true) {
1838
		/* remove previous instance if it exists */
1839
		if(does_interface_exist($realif))
1840
			pfSense_interface_destroy($realif);
1841

    
1842
		log_error("Cloning new wireless interface {$realif}");
1843
		// Create the new wlan interface. FreeBSD returns the new interface name.
1844
		// example:  wlan2
1845
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1846
		if($ret <> 0) {
1847
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1848
			return false;
1849
		}
1850
		$newif = trim($out[0]);
1851
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1852
		pfSense_interface_rename($newif, $realif);
1853
		// FIXME: not sure what ngctl is for. Doesn't work.
1854
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1855
	}
1856
	return true;
1857
}
1858

    
1859
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1860
	global $config, $g;
1861

    
1862
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1863
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1864
	                         'regdomain', 'regcountry', 'reglocation');
1865

    
1866
	if(!is_interface_wireless($ifcfg['if']))
1867
		return;
1868

    
1869
	$baseif = interface_get_wireless_base($ifcfg['if']);
1870

    
1871
	// Sync shared settings for assigned clones
1872
	$iflist = get_configured_interface_list(false, true);
1873
	foreach ($iflist as $if) {
1874
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1875
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1876
				foreach ($shared_settings as $setting) {
1877
					if ($sync_changes) {
1878
						if (isset($ifcfg['wireless'][$setting]))
1879
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1880
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1881
							unset($config['interfaces'][$if]['wireless'][$setting]);
1882
					} else {
1883
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1884
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1885
						else if (isset($ifcfg['wireless'][$setting]))
1886
							unset($ifcfg['wireless'][$setting]);
1887
					}
1888
				}
1889
				if (!$sync_changes)
1890
					break;
1891
			}
1892
		}
1893
	}
1894

    
1895
	// Read or write settings at shared area
1896
	if (isset($config['wireless']['interfaces'][$baseif])) {
1897
		foreach ($shared_settings as $setting) {
1898
			if ($sync_changes) {
1899
				if (isset($ifcfg['wireless'][$setting]))
1900
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
1901
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1902
					unset($config['wireless']['interfaces'][$baseif][$setting]);
1903
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
1904
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1905
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
1906
				else if (isset($ifcfg['wireless'][$setting]))
1907
					unset($ifcfg['wireless'][$setting]);
1908
			}
1909
		}
1910
	}
1911

    
1912
	// Sync the mode on the clone creation page with the configured mode on the interface
1913
	if (interface_is_wireless_clone($ifcfg['if'])) {
1914
		foreach ($config['wireless']['clone'] as &$clone) {
1915
			if ($clone['cloneif'] == $ifcfg['if']) {
1916
				if ($sync_changes) {
1917
					$clone['mode'] = $ifcfg['wireless']['mode'];
1918
				} else {
1919
					$ifcfg['wireless']['mode'] = $clone['mode'];
1920
				}
1921
				break;
1922
			}
1923
		}
1924
		unset($clone);
1925
	}
1926
}
1927

    
1928
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1929
	global $config, $g;
1930

    
1931
	/*    open up a shell script that will be used to output the commands.
1932
	 *    since wireless is changing a lot, these series of commands are fragile
1933
     *    and will sometimes need to be verified by a operator by executing the command
1934
     *    and returning the output of the command to the developers for inspection.  please
1935
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1936
	 */
1937

    
1938
	// Remove script file
1939
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1940

    
1941
	// Clone wireless nic if needed.
1942
	interface_wireless_clone($if, $wl);
1943

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

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

    
1951
	/* set values for /path/program */
1952
	$hostapd = "/usr/sbin/hostapd";
1953
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1954
	$ifconfig = "/sbin/ifconfig";
1955
	$sysctl = "/sbin/sysctl";
1956
	$killall = "/usr/bin/killall";
1957

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

    
1960
	$wlcmd = array();
1961
	$wl_sysctl = array();
1962
	/* Make sure it's up */
1963
	$wlcmd[] = "up";
1964
	/* Set a/b/g standard */
1965
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
1966
	$wlcmd[] = "mode " . escapeshellarg($standard);
1967

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

    
1973
	/* Set ssid */
1974
	if($wlcfg['ssid'])
1975
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1976

    
1977
	/* Set 802.11g protection mode */
1978
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1979

    
1980
	/* set wireless channel value */
1981
	if(isset($wlcfg['channel'])) {
1982
		if($wlcfg['channel'] == "0") {
1983
			$wlcmd[] = "channel any";
1984
		} else {
1985
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1986
		}
1987
	}
1988

    
1989
	/* Set antenna diversity value */
1990
	if(isset($wlcfg['diversity']))
1991
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
1992

    
1993
	/* Set txantenna value */
1994
	if(isset($wlcfg['txantenna']))
1995
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
1996

    
1997
	/* Set rxantenna value */
1998
	if(isset($wlcfg['rxantenna']))
1999
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2000

    
2001
	/* set Distance value */
2002
	if($wlcfg['distance'])
2003
		$distance = escapeshellarg($wlcfg['distance']);
2004

    
2005
	/* Set wireless hostap mode */
2006
	if ($wlcfg['mode'] == "hostap") {
2007
		$wlcmd[] = "mediaopt hostap";
2008
	} else {
2009
		$wlcmd[] = "-mediaopt hostap";
2010
	}
2011

    
2012
	/* Set wireless adhoc mode */
2013
	if ($wlcfg['mode'] == "adhoc") {
2014
		$wlcmd[] = "mediaopt adhoc";
2015
	} else {
2016
		$wlcmd[] = "-mediaopt adhoc";
2017
	}
2018

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

    
2021
	/* handle hide ssid option */
2022
	if(isset($wlcfg['hidessid']['enable'])) {
2023
		$wlcmd[] = "hidessid";
2024
	} else {
2025
		$wlcmd[] = "-hidessid";
2026
	}
2027

    
2028
	/* handle pureg (802.11g) only option */
2029
	if(isset($wlcfg['pureg']['enable'])) {
2030
		$wlcmd[] = "mode 11g pureg";
2031
	} else {
2032
		$wlcmd[] = "-pureg";
2033
	}
2034

    
2035
	/* handle puren (802.11n) only option */
2036
	if(isset($wlcfg['puren']['enable'])) {
2037
		$wlcmd[] = "puren";
2038
	} else {
2039
		$wlcmd[] = "-puren";
2040
	}
2041

    
2042
	/* enable apbridge option */
2043
	if(isset($wlcfg['apbridge']['enable'])) {
2044
		$wlcmd[] = "apbridge";
2045
	} else {
2046
		$wlcmd[] = "-apbridge";
2047
	}
2048

    
2049
	/* handle turbo option */
2050
	if(isset($wlcfg['turbo']['enable'])) {
2051
		$wlcmd[] = "mediaopt turbo";
2052
	} else {
2053
		$wlcmd[] = "-mediaopt turbo";
2054
	}
2055

    
2056
	/* handle txpower setting */
2057
	/* if($wlcfg['txpower'] <> "")
2058
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2059
	*/
2060
	/* handle wme option */
2061
	if(isset($wlcfg['wme']['enable'])) {
2062
		$wlcmd[] = "wme";
2063
	} else {
2064
		$wlcmd[] = "-wme";
2065
	}
2066

    
2067
	/* set up wep if enabled */
2068
	$wepset = "";
2069
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2070
		switch($wlcfg['wpa']['auth_algs']) {
2071
			case "1":
2072
				$wepset .= "authmode open wepmode on ";
2073
				break;
2074
			case "2":
2075
				$wepset .= "authmode shared wepmode on ";
2076
				break;
2077
			case "3":
2078
				$wepset .= "authmode mixed wepmode on ";
2079
		}
2080
		$i = 1;
2081
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2082
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2083
			if (isset($wepkey['txkey'])) {
2084
				$wlcmd[] = "weptxkey {$i} ";
2085
			}
2086
			$i++;
2087
		}
2088
		$wlcmd[] = $wepset;
2089
	} else {
2090
		$wlcmd[] = "authmode open wepmode off ";
2091
	}
2092

    
2093
	mwexec(kill_hostapd("{$if}"));
2094
	mwexec(kill_wpasupplicant("{$if}"));
2095

    
2096
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2097
	conf_mount_rw();
2098

    
2099
	switch ($wlcfg['mode']) {
2100
		case 'bss':
2101
			if (isset($wlcfg['wpa']['enable'])) {
2102
				$wpa .= <<<EOD
2103
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2104
ctrl_interface_group=0
2105
ap_scan=1
2106
#fast_reauth=1
2107
network={
2108
ssid="{$wlcfg['ssid']}"
2109
scan_ssid=1
2110
priority=5
2111
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2112
psk="{$wlcfg['wpa']['passphrase']}"
2113
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2114
group={$wlcfg['wpa']['wpa_pairwise']}
2115
}
2116
EOD;
2117

    
2118
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2119
				fwrite($fd, "{$wpa}");
2120
				fclose($fd);
2121
			}
2122
			break;
2123
		case 'hostap':
2124
			if($wlcfg['wpa']['passphrase']) 
2125
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2126
			else 
2127
				$wpa_passphrase = "";
2128
			if (isset($wlcfg['wpa']['enable'])) {
2129
				$wpa .= <<<EOD
2130
interface={$if}
2131
driver=bsd
2132
logger_syslog=-1
2133
logger_syslog_level=0
2134
logger_stdout=-1
2135
logger_stdout_level=0
2136
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2137
ctrl_interface={$g['varrun_path']}/hostapd
2138
ctrl_interface_group=wheel
2139
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2140
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2141
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2142
ssid={$wlcfg['ssid']}
2143
debug={$wlcfg['wpa']['debug_mode']}
2144
auth_algs={$wlcfg['wpa']['auth_algs']}
2145
wpa={$wlcfg['wpa']['wpa_mode']}
2146
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2147
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2148
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2149
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2150
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2151
{$wpa_passphrase}
2152

    
2153
EOD;
2154

    
2155
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2156
	$wpa .= <<<EOD
2157
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2158
rsn_preauth=1
2159
rsn_preauth_interfaces={$if}
2160

    
2161
EOD;
2162

    
2163
}
2164
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2165
					$auth_server_port = "1812";
2166
					if($wlcfg['auth_server_port']) 
2167
						$auth_server_port = $wlcfg['auth_server_port'];
2168
					$wpa .= <<<EOD
2169

    
2170
ieee8021x=1
2171
auth_server_addr={$wlcfg['auth_server_addr']}
2172
auth_server_port={$auth_server_port}
2173
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2174

    
2175
EOD;
2176
				} else {
2177
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2178
				}
2179

    
2180
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2181
				fwrite($fd, "{$wpa}");
2182
				fclose($fd);
2183

    
2184
			}
2185
			break;
2186
	}
2187

    
2188
	/*
2189
	 *    all variables are set, lets start up everything
2190
	 */
2191

    
2192
	$baseif = interface_get_wireless_base($if);
2193
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2194
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2195

    
2196
	/* set sysctls for the wireless interface */
2197
	if (!empty($wl_sysctl)) {
2198
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2199
		foreach ($wl_sysctl as $wl_sysctl_line) {
2200
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2201
		}
2202
	}
2203

    
2204
	/* set ack timers according to users preference (if he/she has any) */
2205
	if($distance) {
2206
		fwrite($fd_set, "# Enable ATH distance settings\n");
2207
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2208
	}
2209

    
2210
	if (isset($wlcfg['wpa']['enable'])) {
2211
		if ($wlcfg['mode'] == "bss") {
2212
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2213
		}
2214
		if ($wlcfg['mode'] == "hostap") {
2215
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2216
		}
2217
	}
2218

    
2219
	fclose($fd_set);
2220
	conf_mount_ro();
2221

    
2222
	/* Making sure regulatory settings have actually changed
2223
	 * before applying, because changing them requires bringing
2224
	 * down all wireless networks on the interface. */
2225
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2226
	$ifconfig_str = implode($output);
2227
	unset($output);
2228
	$reg_changing = false;
2229

    
2230
	/* special case for the debug country code */
2231
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2232
		$reg_changing = true;
2233
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2234
		$reg_changing = true;
2235
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2236
		$reg_changing = true;
2237
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2238
		$reg_changing = true;
2239
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2240
		$reg_changing = true;
2241

    
2242
	if ($reg_changing) {
2243
		/* set regulatory domain */
2244
		if($wlcfg['regdomain'])
2245
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2246

    
2247
		/* set country */
2248
		if($wlcfg['regcountry'])
2249
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2250

    
2251
		/* set location */
2252
		if($wlcfg['reglocation'])
2253
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2254

    
2255
		$wlregcmd_args = implode(" ", $wlregcmd);
2256

    
2257
		/* build a complete list of the wireless clones for this interface */
2258
		$clone_list = array();
2259
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2260
			$clone_list[] = interface_get_wireless_clone($baseif);
2261
		if (is_array($config['wireless']['clone'])) {
2262
			foreach ($config['wireless']['clone'] as $clone) {
2263
				if ($clone['if'] == $baseif)
2264
					$clone_list[] = $clone['cloneif'];
2265
			}
2266
		}
2267

    
2268
		/* find which clones are up and bring them down */
2269
		$clones_up = array();
2270
		foreach ($clone_list as $clone_if) {
2271
			$clone_status = pfSense_get_interface_addresses($clone_if);
2272
			if ($clone_status['status'] == 'up') {
2273
				$clones_up[] = $clone_if;
2274
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2275
			}
2276
		}
2277

    
2278
		/* apply the regulatory settings */
2279
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2280

    
2281
		/* bring the clones back up that were previously up */
2282
		foreach ($clones_up as $clone_if) {
2283
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2284
		}
2285
	}
2286

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

    
2291
	/* configure wireless */
2292
	$wlcmd_args = implode(" ", $wlcmd);
2293
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2294

    
2295
	
2296
	sleep(1);
2297
	/* execute hostapd and wpa_supplicant if required in shell */
2298
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2299

    
2300
	return 0;
2301

    
2302
}
2303

    
2304
function kill_hostapd($interface) {
2305
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2306
}
2307

    
2308
function kill_wpasupplicant($interface) {
2309
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2310
}
2311

    
2312
function find_dhclient_process($interface) {
2313
	if($interface) {
2314
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2315
	}
2316
	return $pid;
2317
}
2318

    
2319
function interface_configure($interface = "wan", $reloadall = false) {
2320
	global $config, $g;
2321
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2322

    
2323
	$wancfg = $config['interfaces'][$interface];
2324

    
2325
	$realif = get_real_interface($interface);
2326

    
2327
	if (!$g['booting']) {
2328
		/* remove all IPv4 addresses */
2329
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2330
			interface_bring_down($interface);
2331
	}
2332

    
2333
	/* wireless configuration? */
2334
	if (is_array($wancfg['wireless']))
2335
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2336

    
2337
	if ($wancfg['spoofmac']) {
2338
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2339
			" link " . escapeshellarg($wancfg['spoofmac']));
2340

    
2341
                /*
2342
                 * All vlans need to spoof their parent mac address, too.  see
2343
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2344
                 */
2345
                if (is_array($config['vlans']['vlan'])) {
2346
                        foreach ($config['vlans']['vlan'] as $vlan) {
2347
                                if ($vlan['if'] == $realif)
2348
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2349
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2350
                        }
2351
                }
2352
	}  else {
2353
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2354
		if($mac == "ff:ff:ff:ff:ff:ff") {
2355
			/*   this is not a valid mac address.  generate a
2356
			 *   temporary mac address so the machine can get online.
2357
			 */
2358
			echo "Generating new MAC address.";
2359
			$random_mac = generate_random_mac_address();
2360
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2361
				" link " . escapeshellarg($random_mac));
2362
			$wancfg['spoofmac'] = $random_mac;
2363
			write_config();
2364
			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");
2365
		}
2366
	}
2367

    
2368
	/* media */
2369
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2370
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2371
		if ($wancfg['media'])
2372
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2373
		if ($wancfg['mediaopt'])
2374
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2375
		mwexec($cmd);
2376
	}
2377
	if (!empty($wancfg['mtu']))
2378
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2379

    
2380
	/* invalidate interface/ip/sn cache */
2381
	get_interface_arr(true);
2382
	unset($interface_ip_arr_cache[$realif]);
2383
	unset($interface_sn_arr_cache[$realif]);
2384

    
2385
	switch ($wancfg['ipaddr']) {
2386
		case 'carpdev-dhcp':
2387
			interface_carpdev_dhcp_configure($interface);
2388
			break;
2389
		case 'dhcp':
2390
			interface_dhcp_configure($interface);
2391
			break;
2392
		case 'pppoe':
2393
		case 'l2tp':
2394
		case 'pptp':
2395
		case 'ppp':
2396
			interface_ppps_configure($interface);
2397
			break;
2398
		default:
2399
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2400
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2401
			} else if (substr($realif, 0, 3) == "gre") {
2402
				if (is_array($config['gres']['gre'])) {
2403
					foreach ($config['gres']['gre'] as $gre)
2404
						if ($gre['greif'] == $realif)
2405
							interface_gre_configure($gre);
2406
				}
2407
			} else if (substr($realif, 0, 3) == "gif") {
2408
				 if (is_array($config['gifs']['gif'])) {
2409
					foreach ($config['gifs']['gif'] as $gif)
2410
						if($gif['gifif'] == $interface)
2411
							interface_gif_configure($gif);
2412
				}
2413
			} else if (substr($realif, 0, 4) == "ovpn") {
2414
				/* XXX: Should be done anything?! */
2415
			}
2416

    
2417
			if (is_ipaddr($wancfg['gateway']))
2418
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2419
			break;
2420
	}
2421

    
2422
	if(does_interface_exist($wancfg['if']))
2423
		interfaces_bring_up($wancfg['if']);
2424
 	
2425
	if (!$g['booting'])
2426
		interface_reload_carps($realif);
2427
	
2428
	if (!$g['booting']) {
2429
		unset($gre);
2430
		$gre = link_interface_to_gre($interface);
2431
		if (!empty($gre))
2432
			interface_gre_configure($gre);
2433

    
2434
		unset($gif);
2435
		$gif = link_interface_to_gif($interface);
2436
		if (!empty($gif))
2437
                       	interface_gif_configure($gif);
2438

    
2439
		unset($bridgetmp);
2440
		$bridgetmp = link_interface_to_bridge($interface);
2441
		if (!empty($bridgetmp))
2442
			interface_bridge_add_member($bridgetmp, $realif);
2443

    
2444
		link_interface_to_vips($interface, "update");
2445

    
2446
		if ($interface == "lan")
2447
			/* make new hosts file */
2448
			system_hosts_generate();
2449

    
2450
		if ($reloadall == true) {
2451

    
2452
			/* reconfigure static routes (kernel may have deleted them) */
2453
			system_routing_configure($interface);
2454

    
2455
			/* reload ipsec tunnels */
2456
			vpn_ipsec_configure();
2457

    
2458
			/* update dyndns */
2459
			services_dyndns_configure($interface);
2460

    
2461
			/* force DNS update */
2462
			services_dnsupdate_process($interface);
2463

    
2464
			/* restart dnsmasq */
2465
			services_dnsmasq_configure();
2466

    
2467
			/* reload captive portal */
2468
			captiveportal_init_rules();
2469

    
2470
			/* set the reload filter dity flag */
2471
			filter_configure();
2472
		}
2473
	}
2474

    
2475
	return 0;
2476
}
2477

    
2478
function interface_carpdev_dhcp_configure($interface = "wan") {
2479
	global $config, $g;
2480

    
2481
	$wancfg = $config['interfaces'][$interface];
2482
	$wanif = $wancfg['if'];
2483
	/* bring wan interface up before starting dhclient */
2484
	if($wanif)
2485
		interfaces_bring_up($wanif);
2486
	else 
2487
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2488

    
2489
	return 0;
2490
}
2491

    
2492
function interface_dhcp_configure($interface = "wan") {
2493
	global $config, $g;
2494

    
2495
	$wancfg = $config['interfaces'][$interface];
2496
	if (empty($wancfg))
2497
		$wancfg = array();
2498

    
2499
	/* generate dhclient_wan.conf */
2500
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2501
	if (!$fd) {
2502
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2503
		return 1;
2504
	}
2505

    
2506
	if ($wancfg['dhcphostname']) {
2507
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2508
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2509
	} else {
2510
		$dhclientconf_hostname = "";
2511
	}
2512

    
2513
	$wanif = get_real_interface($interface);
2514
	if (empty($wanif)) {
2515
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2516
		return 0;
2517
	}
2518
 	$dhclientconf = "";
2519
	
2520
	$dhclientconf .= <<<EOD
2521
interface "{$wanif}" {
2522
timeout 60;
2523
retry 1;
2524
select-timeout 0;
2525
initial-interval 1;
2526
	{$dhclientconf_hostname}
2527
	script "/sbin/dhclient-script";
2528
}
2529

    
2530
EOD;
2531

    
2532
if(is_ipaddr($wancfg['alias-address'])) {
2533
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2534
	$dhclientconf .= <<<EOD
2535
alias {
2536
	interface  "{$wanif}";
2537
	fixed-address {$wancfg['alias-address']};
2538
	option subnet-mask {$subnetmask};
2539
}
2540

    
2541
EOD;
2542
}
2543
	fwrite($fd, $dhclientconf);
2544
	fclose($fd);
2545

    
2546
	/* bring wan interface up before starting dhclient */
2547
	if($wanif)
2548
		interfaces_bring_up($wanif);
2549
	else 
2550
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2551

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

    
2555
	return 0;
2556
}
2557

    
2558
function interfaces_group_setup() {
2559
	global $config;
2560

    
2561
	if (!is_array($config['ifgroups']['ifgroupentry']))
2562
		return;
2563

    
2564
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2565
		interface_group_setup($groupar);
2566

    
2567
	return;
2568
}
2569

    
2570
function interface_group_setup(&$groupname /* The parameter is an array */) {
2571
	global $config;
2572

    
2573
	if (!is_array($groupname))
2574
		return;
2575
	$members = explode(" ", $groupname['members']);
2576
	foreach($members as $ifs) {
2577
		$realif = get_real_interface($ifs);
2578
		if ($realif)
2579
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2580
	}
2581

    
2582
	return;
2583
}
2584
 
2585
/* COMPAT Function */
2586
function convert_friendly_interface_to_real_interface_name($interface) {
2587
	return get_real_interface($interface);
2588
}
2589

    
2590
/* COMPAT Function */
2591
function get_real_wan_interface($interface = "wan") {
2592
	return get_real_interface($interface);
2593
}
2594

    
2595
/* COMPAT Function */
2596
function get_current_wan_address($interface = "wan") {
2597
	return get_interface_ip($interface);
2598
}
2599

    
2600
/*
2601
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2602
 */
2603
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2604
        global $config;
2605

    
2606
	if (stristr($interface, "vip")) {
2607
                $index = intval(substr($interface, 3));
2608
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2609
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2610
                                if ($index == $counter)
2611
                                        return $vip['interface'];
2612
                        }
2613
                }
2614
        }
2615

    
2616
        /* XXX: For speed reasons reference directly the interface array */
2617
	$ifdescrs =& $config['interfaces'];
2618
        //$ifdescrs = get_configured_interface_list(false, true);
2619

    
2620
        foreach ($ifdescrs as $if => $ifname) {
2621
                if ($config['interfaces'][$if]['if'] == $interface)
2622
                        return $if;
2623

    
2624
                if (get_real_interface($if) == $interface)
2625
                        return $if;
2626

    
2627
                $int = interface_translate_type_to_real($if);
2628
                if ($int == $interface)
2629
                        return $ifname;
2630
        }
2631
        return NULL;
2632
}
2633

    
2634
/* attempt to resolve interface to friendly descr */
2635
function convert_friendly_interface_to_friendly_descr($interface) {
2636
        global $config;
2637

    
2638
        switch ($interface) {
2639
                case "l2tp":
2640
                                $ifdesc = "L2TP";
2641
                                break;
2642
                case "pptp":
2643
                                $ifdesc = "PPTP";
2644
                                break;
2645
                case "pppoe":
2646
                                $ifdesc = "PPPoE";
2647
                                break;
2648
                case "openvpn":
2649
                                $ifdesc = "OpenVPN";
2650
                                break;
2651
                case "enc0":
2652
                        case "ipsec":
2653
                                $ifdesc = "IPsec";
2654
                                break;
2655
        default:
2656
                if (isset($config['interfaces'][$interface])) {
2657
                        if (empty($config['interfaces'][$interface]['descr']))
2658
                                $ifdesc = strtoupper($interface);
2659
                        else
2660
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2661
			break;
2662
		}
2663
                /* if list */
2664
                $ifdescrs = get_configured_interface_with_descr(false, true);
2665
                foreach ($ifdescrs as $if => $ifname) {
2666
                                if ($if == $interface || $ifname == $interface)
2667
                                        return $ifname;
2668
                }
2669
                break;
2670
        }
2671

    
2672
        return $ifdesc;
2673
}
2674

    
2675
function convert_real_interface_to_friendly_descr($interface) {
2676
        global $config;
2677

    
2678
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2679

    
2680
        if ($ifdesc) {
2681
                $iflist = get_configured_interface_with_descr(false, true);
2682
                return $iflist[$ifdesc];
2683
        }
2684

    
2685
        return $interface;
2686
}
2687

    
2688
/*
2689
 *  interface_translate_type_to_real($interface):
2690
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2691
 */
2692
function interface_translate_type_to_real($interface) {
2693
        global $config;
2694

    
2695
        if ($config['interfaces'][$interface]['if'] <> "")
2696
                return $config['interfaces'][$interface]['if'];
2697
        else
2698
		return $interface;
2699
}
2700

    
2701
function interface_is_wireless_clone($wlif) {
2702
	if(!stristr($wlif, "_wlan")) {
2703
		return false;
2704
	} else {
2705
		return true;
2706
	}
2707
}
2708

    
2709
function interface_get_wireless_base($wlif) {
2710
	if(!stristr($wlif, "_wlan")) {
2711
		return $wlif;
2712
	} else {
2713
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2714
	}
2715
}
2716

    
2717
function interface_get_wireless_clone($wlif) {
2718
	if(!stristr($wlif, "_wlan")) {
2719
		return $wlif . "_wlan0";
2720
	} else {
2721
		return $wlif;
2722
	}
2723
}
2724

    
2725
function get_real_interface($interface = "wan") {
2726
    global $config;
2727

    
2728
	$wanif = NULL;
2729

    
2730
	switch ($interface) {
2731
	case "l2tp":
2732
		$wanif = "l2tp";
2733
		break;
2734
	case "pptp":
2735
		$wanif = "pptp";
2736
		break;
2737
	case "pppoe":
2738
		$wanif = "pppoe";
2739
		break;
2740
	case "openvpn":
2741
		$wanif = "openvpn";
2742
		break;
2743
	case "ipsec":
2744
	case "enc0":
2745
		$wanif = "enc0";
2746
		break;
2747
	case "ppp":
2748
		$wanif = "ppp";
2749
		break;
2750
	default:
2751
		// If a real interface was alread passed simply
2752
		// pass the real interface back.  This encourages
2753
		// the usage of this function in more cases so that
2754
		// we can combine logic for more flexibility.
2755
		if(does_interface_exist($interface)) {
2756
			$wanif = $interface;
2757
			break;
2758
		}
2759
		if (empty($config['interfaces'][$interface]))
2760
			break;
2761

    
2762
		$cfg =& $config['interfaces'][$interface];
2763

    
2764
		// Wireless cloned NIC support (FreeBSD 8+)
2765
		// interface name format: $parentnic_wlanparentnic#
2766
		// example: ath0_wlan0
2767
		if (is_interface_wireless($cfg['if'])) {
2768
			$wanif = interface_get_wireless_clone($cfg['if']);
2769
			break;
2770
		}
2771
		/*
2772
		if (empty($cfg['if'])) {
2773
			$wancfg = $cfg['if'];
2774
			break;
2775
		}
2776
		*/
2777

    
2778
		switch ($cfg['ipaddr']) {
2779
			case "carpdev-dhcp":
2780
				$viparr = &$config['virtualip']['vip'];
2781
				if(is_array($viparr))
2782
				foreach ($viparr as $counter => $vip) {
2783
					if ($vip['mode'] == "carpdev-dhcp") {
2784
						if($vip['interface'] == $interface) {
2785
							$wanif = "carp{$counter}";
2786
							break;
2787
						}
2788
					}
2789
				}
2790
				break;
2791
			case "pppoe": 
2792
			case "pptp": 
2793
			case "l2tp": 
2794
			case "ppp":
2795
				$wanif = $cfg['if'];
2796
				break;
2797
			default:
2798
				$wanif = $cfg['if'];
2799
				break;
2800
		}
2801
		break;
2802
	}
2803

    
2804
    return $wanif;
2805
}
2806

    
2807
/* Guess the physical interface by providing a IP address */
2808
function guess_interface_from_ip($ipaddress) {
2809
	if(! is_ipaddr($ipaddress)) {
2810
		return false;
2811
	}
2812
	/* create a route table we can search */
2813
	exec("netstat -rnW", $output, $ret);
2814
	foreach($output as $line) {
2815
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2816
			$fields = preg_split("/[ ]+/", $line);
2817
			if(ip_in_subnet($ipaddress, $fields[0])) {
2818
				return $fields[6];
2819
			}
2820
		}
2821
	}
2822
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2823
	if(empty($ret)) {
2824
        	return false;
2825
	}
2826
	return $ret;
2827
}
2828

    
2829
/*
2830
 * find_ip_interface($ip): return the interface where an ip is defined
2831
 */
2832
function find_ip_interface($ip)
2833
{
2834
        /* if list */
2835
        $ifdescrs = get_configured_interface_list();
2836

    
2837
        foreach ($ifdescrs as $ifdescr => $ifname) {
2838
		if ($ip == get_interface_ip($ifname)) {
2839
                	$int = get_real_interface($ifname);
2840
			return $int;
2841
		}
2842
        }
2843
        return false;
2844
}
2845

    
2846
/*
2847
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2848
 */
2849
function find_number_of_created_carp_interfaces() {
2850
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2851
}
2852

    
2853
function get_all_carp_interfaces() {
2854
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2855
	$ints = explode(" ", $ints);
2856
	return $ints;
2857
}
2858

    
2859
/*
2860
 * find_carp_interface($ip): return the carp interface where an ip is defined
2861
 */
2862
function find_carp_interface($ip) {
2863
	global $config;
2864
	if (is_array($config['virtualip']['vip'])) {
2865
		foreach ($config['virtualip']['vip'] as $vip) {
2866
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2867
				$carp_ip = get_interface_ip($vip['interface']);
2868
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2869
				if ($if)
2870
					return $if;
2871
			}
2872
		}
2873
	}
2874
}
2875

    
2876
function link_carp_interface_to_parent($interface) {
2877
        global $config;
2878

    
2879
        if ($interface == "")
2880
                return;
2881

    
2882
        $carp_ip = get_interface_ip($interface);
2883
        if (!is_ipaddr($carp_ip))
2884
                return;
2885

    
2886
        /* if list */
2887
        $ifdescrs = get_configured_interface_list();
2888
        foreach ($ifdescrs as $ifdescr => $ifname) {
2889
                $interfaceip = get_interface_ip($ifname);
2890
                $subnet_bits = get_interface_subnet($ifname);
2891
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2892
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2893
                        return $ifname;
2894
        }
2895

    
2896
        return "";
2897
}
2898

    
2899
/****f* interfaces/link_ip_to_carp_interface
2900
 * NAME
2901
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2902
 * INPUTS
2903
 *   $ip
2904
 * RESULT
2905
 *   $carp_ints
2906
 ******/
2907
function link_ip_to_carp_interface($ip) {
2908
        global $config;
2909

    
2910
        if (!is_ipaddr($ip))
2911
                return;
2912

    
2913
        $carp_ints = "";
2914
        if (is_array($config['virtualip']['vip'])) {
2915
		$first = 0;
2916
		$carp_int = array();
2917
                foreach ($config['virtualip']['vip'] as $vip) {
2918
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2919
                                $carp_ip = $vip['subnet'];
2920
                                $carp_sn = $vip['subnet_bits'];
2921
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2922
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
2923
					$carp_int[] = "vip{$vip['vhid']}";
2924
                        }
2925
                }
2926
		if (!empty($carp_int))
2927
			$carp_ints = implode(" ", array_unique($carp_int));
2928
        }
2929

    
2930
        return $carp_ints;
2931
}
2932

    
2933
function link_interface_to_vlans($int, $action = "") {
2934
	global $config;
2935

    
2936
	if (empty($int))
2937
		return;
2938

    
2939
	if (is_array($config['vlans']['vlan'])) {
2940
                foreach ($config['vlans']['vlan'] as $vlan) {
2941
			if ($int == $vlan['if']) {
2942
				if ($action == "update") {
2943
					interfaces_bring_up($int);
2944
				} else if ($action == "")
2945
					return $vlan;
2946
			}
2947
		}
2948
	}
2949
}
2950

    
2951
function link_interface_to_vips($int, $action = "") {
2952
        global $config;
2953

    
2954
        if (is_array($config['virtualip']['vip']))
2955
                foreach ($config['virtualip']['vip'] as $vip)
2956
                        if ($int == $vip['interface']) {
2957
				if ($action == "update")
2958
					interfaces_vips_configure($int);
2959
				else
2960
                                	return $vip;
2961
			}
2962
}
2963

    
2964
/****f* interfaces/link_interface_to_bridge
2965
 * NAME
2966
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2967
 * INPUTS
2968
 *   $ip
2969
 * RESULT
2970
 *   bridge[0-99]
2971
 ******/
2972
function link_interface_to_bridge($int) {
2973
        global $config;
2974

    
2975
        if (is_array($config['bridges']['bridged'])) {
2976
                foreach ($config['bridges']['bridged'] as $bridge) {
2977
			if (in_array($int, explode(',', $bridge['members'])))
2978
                                return "{$bridge['bridgeif']}";
2979
		}
2980
	}
2981
}
2982

    
2983
function link_interface_to_gre($interface) {
2984
        global $config;
2985

    
2986
        if (is_array($config['gres']['gre']))
2987
                foreach ($config['gres']['gre'] as $gre)
2988
                        if($gre['if'] == $interface)
2989
                                return $gre;
2990
}
2991

    
2992
function link_interface_to_gif($interface) {
2993
        global $config;
2994

    
2995
        if (is_array($config['gifs']['gif']))
2996
                foreach ($config['gifs']['gif'] as $gif)
2997
                        if($gif['if'] == $interface)
2998
                                return $gif;
2999
}
3000

    
3001
/*
3002
 * find_interface_ip($interface): return the interface ip (first found)
3003
 */
3004
function find_interface_ip($interface, $flush = false)
3005
{
3006
	global $interface_ip_arr_cache;
3007

    
3008
	$interface = str_replace("\n", "", $interface);
3009
	
3010
	if (!does_interface_exist($interface))
3011
		return;
3012

    
3013
	/* Setup IP cache */
3014
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3015
		$ifinfo = pfSense_get_interface_addresses($interface);
3016
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3017
	}
3018

    
3019
	return $interface_ip_arr_cache[$interface];
3020
}
3021

    
3022
function find_interface_subnet($interface, $flush = false)
3023
{
3024
	global $interface_sn_arr_cache;
3025

    
3026
	$interface = str_replace("\n", "", $interface);
3027
	if (does_interface_exist($interface) == false)
3028
		return;
3029

    
3030
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3031
		$ifinfo = pfSense_get_interface_addresses($interface);
3032
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3033
        }
3034

    
3035
	return $interface_sn_arr_cache[$interface];
3036
}
3037

    
3038
function get_interface_ip($interface = "wan")
3039
{
3040
	$realif = get_real_interface($interface);
3041
	if (!$realif) {
3042
		if (preg_match("/^carp/i", $interface))
3043
			$realif = $interface;
3044
		else if (preg_match("/^vip/i", $interface))
3045
			$realif = $interface;
3046
		else
3047
			return null;
3048
	}
3049

    
3050
	$curip = find_interface_ip($realif);
3051
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3052
		return $curip;
3053
	else
3054
		return null;
3055
}
3056

    
3057
function get_interface_subnet($interface = "wan")
3058
{
3059
	$realif = get_real_interface($interface);
3060
	if (!$realif) {
3061
                if (preg_match("/^carp/i", $interface))
3062
                        $realif = $interface;
3063
                else if (preg_match("/^vip/i", $interface))
3064
                        $realif = $interface;
3065
                else
3066
                        return null;
3067
        }
3068

    
3069
	$cursn = find_interface_subnet($realif);
3070
	if (!empty($cursn))
3071
		return $cursn;
3072

    
3073
	return null;
3074
}
3075

    
3076
/* return outside interfaces with a gateway */
3077
function get_interfaces_with_gateway() {
3078
	global $config;
3079

    
3080
	$ints = array();
3081

    
3082
	/* loop interfaces, check config for outbound */
3083
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3084
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3085
			return true;
3086

    
3087
		switch ($ifname['ipaddr']) {
3088
			case "dhcp":
3089
			case "carpdev-dhcp":
3090
			case "ppp";
3091
			case "pppoe":
3092
			case "pptp":
3093
			case "l2tp":
3094
			case "ppp";
3095
				$ints[$ifdescr] = $ifdescr;
3096
			break;
3097
			default:
3098
				if (!empty($ifname['gateway']))
3099
					$ints[$ifdescr] = $ifdescr;
3100
			break;
3101
		}
3102
	}
3103
	return $ints;
3104
}
3105

    
3106
/* return true if interface has a gateway */
3107
function interface_has_gateway($friendly) {
3108
	global $config;
3109

    
3110
	if (!empty($config['interfaces'][$friendly])) {
3111
		if (substr($friendly, 0, 5) ==  "ovpnc")
3112
			return true;
3113
		$ifname =& $config['interfaces'][$friendly];
3114
		switch ($ifname['ipaddr']) {
3115
			case "dhcp":
3116
			case "carpdev-dhcp":
3117
			case "pppoe":
3118
			case "pptp":
3119
			case "l2tp":
3120
			case "ppp";
3121
				return true;
3122
			break;
3123
			default:
3124
				if (!empty($ifname['gateway']))
3125
					return true;
3126
			break;
3127
		}
3128
	}
3129

    
3130
	return false;
3131
}
3132

    
3133
/****f* interfaces/is_altq_capable
3134
 * NAME
3135
 *   is_altq_capable - Test if interface is capable of using ALTQ
3136
 * INPUTS
3137
 *   $int            - string containing interface name
3138
 * RESULT
3139
 *   boolean         - true or false
3140
 ******/
3141

    
3142
function is_altq_capable($int) {
3143
        /* Per:
3144
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3145
         * Only the following drivers have ALTQ support
3146
         */
3147
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3148
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3149
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3150
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
3151
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3152
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3153
			"l2tp", "ppp");
3154

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

    
3157
        if (in_array($int_family[0], $capable))
3158
                return true;
3159
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3160
		return true;
3161
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3162
		return true;
3163
        else
3164
                return false;
3165
}
3166

    
3167
/****f* interfaces/is_interface_wireless
3168
 * NAME
3169
 *   is_interface_wireless - Returns if an interface is wireless
3170
 * RESULT
3171
 *   $tmp       - Returns if an interface is wireless
3172
 ******/
3173
function is_interface_wireless($interface) {
3174
        global $config, $g;
3175

    
3176
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3177
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3178
                if (preg_match($g['wireless_regex'], $interface)) {
3179
                        if (isset($config['interfaces'][$friendly]))
3180
                                $config['interfaces'][$friendly]['wireless'] = array();
3181
                        return true;
3182
                }
3183
                return false;
3184
        } else
3185
                return true;
3186
}
3187

    
3188
function get_wireless_modes($interface) {
3189
	/* return wireless modes and channels */
3190
	$wireless_modes = array();
3191

    
3192
	$wlif = interface_translate_type_to_real($interface);
3193

    
3194
	if(is_interface_wireless($wlif)) {
3195
		$cloned_interface = get_real_interface($interface);
3196
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3197
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3198
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3199

    
3200
		$interface_channels = "";
3201
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3202
		$interface_channel_count = count($interface_channels);
3203

    
3204
		$c = 0;
3205
		while ($c < $interface_channel_count)
3206
		{
3207
			$channel_line = explode(",", $interface_channels["$c"]);
3208
			$wireless_mode = trim($channel_line[0]);
3209
			$wireless_channel = trim($channel_line[1]);
3210
			if(trim($wireless_mode) != "") {
3211
				/* if we only have 11g also set 11b channels */
3212
				if($wireless_mode == "11g") {
3213
					if(!isset($wireless_modes["11b"]))
3214
						$wireless_modes["11b"] = array();
3215
				} else if($wireless_mode == "11g ht") {
3216
					if(!isset($wireless_modes["11b"]))
3217
						$wireless_modes["11b"] = array();
3218
					if(!isset($wireless_modes["11g"]))
3219
						$wireless_modes["11g"] = array();
3220
					$wireless_mode = "11ng";
3221
				} else if($wireless_mode == "11a ht") {
3222
					if(!isset($wireless_modes["11a"]))
3223
						$wireless_modes["11a"] = array();
3224
					$wireless_mode = "11na";
3225
				}
3226
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3227
			}
3228
			$c++;
3229
		}
3230
	}
3231
	return($wireless_modes);
3232
}
3233

    
3234
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3235
function get_wireless_channel_info($interface) {
3236
	$wireless_channels = array();
3237

    
3238
	$wlif = interface_translate_type_to_real($interface);
3239

    
3240
	if(is_interface_wireless($wlif)) {
3241
		$cloned_interface = get_real_interface($interface);
3242
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3243
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3244
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3245

    
3246
		$interface_channels = "";
3247
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3248

    
3249
		foreach ($interface_channels as $channel_line) {
3250
			$channel_line = explode(",", $channel_line);
3251
			if(!isset($wireless_channels[$channel_line[0]]))
3252
				$wireless_channels[$channel_line[0]] = $channel_line;
3253
		}
3254
	}
3255
	return($wireless_channels);
3256
}
3257

    
3258
/****f* interfaces/get_interface_mtu
3259
 * NAME
3260
 *   get_interface_mtu - Return the mtu of an interface
3261
 * RESULT
3262
 *   $tmp       - Returns the mtu of an interface
3263
 ******/
3264
function get_interface_mtu($interface) {
3265
        $mtu = pfSense_get_interface_addresses($interface);
3266
        return $mtu['mtu'];
3267
}
3268

    
3269
function get_interface_mac($interface) {
3270

    
3271
	$macinfo = pfSense_get_interface_addresses($interface);
3272
	return $macinfo["macaddr"];
3273
}
3274

    
3275
/****f* pfsense-utils/generate_random_mac_address
3276
 * NAME
3277
 *   generate_random_mac - generates a random mac address
3278
 * INPUTS
3279
 *   none
3280
 * RESULT
3281
 *   $mac - a random mac address
3282
 ******/
3283
function generate_random_mac_address() {
3284
        $mac = "02";
3285
        for($x=0; $x<5; $x++)
3286
                $mac .= ":" . dechex(rand(16, 255));
3287
        return $mac;
3288
}
3289

    
3290
/****f* interfaces/is_jumbo_capable
3291
 * NAME
3292
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3293
 * INPUTS
3294
 *   $int             - string containing interface name
3295
 * RESULT
3296
 *   boolean          - true or false
3297
 ******/
3298
function is_jumbo_capable($int) {
3299
        global $g;
3300

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

    
3303
        if (in_array($int_family[0], $g['vlan_long_frame']))
3304
                return true;
3305
        else
3306
                return false;
3307
}
3308

    
3309
function setup_pppoe_reset_file($pppif, $iface="") {
3310
	global $g;
3311
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3312

    
3313
	if(!empty($iface) && !empty($pppif)){
3314
		$cron_cmd = "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$iface}); log_error(\"PPPoE periodic reset executed on {$iface}\"); ?>' | /usr/local/bin/php -q";
3315
		file_put_contents($cron_file, $cron_cmd);
3316
		chmod($cron_file, 0700);
3317
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3318
	} else
3319
		unlink_if_exists($cron_file);
3320
}
3321

    
3322
?>
(22-22/53)