Project

General

Profile

Download (93.8 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
	foreach ($members as $member) {
331
		$realif = get_real_interface($member);
332
		$mtu = get_interface_mtu($realif);
333
		if ($smallermtu == 0 && !empty($mtu))
334
			$smallermtu = $mtu;
335
		else if (!empty($mtu) && $mtu < $smallermtu)
336
			$smallermtu = $mtu;
337
	}
338
	 
339
	/* Just in case anything is not working well */
340
	if ($smallermtu == 0)
341
		$smallermtu = 1500; 
342

    
343
	/* Add interfaces to bridge */
344
	foreach ($members as $member) {
345
		if (!array_key_exists($member, $checklist))
346
			continue;
347
		$realif1 = get_real_interface($member);
348
		$realif =  escapeshellarg($realif1);
349
		/* make sure the parent interface is up */
350
		pfSense_interface_mtu($realif, $smallermtu);
351
		if(!$realif) 
352
			log_error("realif not defined in interfaces bridge - up");
353
		interfaces_bring_up($realif1);
354
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
355
	}
356

    
357
	if (isset($bridge['enablestp'])) {
358
		/* Choose spanning tree proto */
359
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
360
		
361
		if (!empty($bridge['stp'])) {
362
			$stpifs = explode(',', $bridge['stp']);
363
			foreach ($stpifs as $stpif) {
364
				$realif = get_real_interface($stpif);
365
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
366
			}
367
		}
368
		if (!empty($bridge['maxage']))
369
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
370
		if (!empty($brige['fwdelay']))
371
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
372
		if (!empty($brige['hellotime']))
373
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
374
		if (!empty($brige['priority']))
375
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
376
		if (!empty($brige['holdcount']))
377
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
378
		if (!empty($bridge['ifpriority'])) {
379
			$pconfig = explode(",", $bridge['ifpriority']);
380
			$ifpriority = array();
381
			foreach ($pconfig as $cfg) {
382
				$embcfg = explode(":", $cfg);
383
				foreach ($embcfg as $key => $value)
384
					$ifpriority[$key] = $value;
385
			}
386
			foreach ($ifpriority as $key => $value) {
387
				$realif = get_real_interface($key);
388
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
389
			}
390
		}
391
		if (!empty($bridge['ifpathcost'])) {
392
			$pconfig = explode(",", $bridges['ifpathcost']);
393
			$ifpathcost = array();
394
			foreach ($pconfig as $cfg) {
395
				$embcfg = explode(":", $cfg);
396
				foreach ($embcfg as $key => $value)
397
					$ifpathcost[$key] = $value;
398
			}
399
			foreach ($ifpathcost as $key => $value) {
400
                        	$realif = get_real_interface($key);
401
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
402
                	}
403
		}
404
	}
405

    
406
	if ($bridge['maxaddr'] <> "")
407
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
408
        if ($bridge['timeout'] <> "")
409
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
410
        if ($bridge['span'] <> "") {
411
		$realif = get_real_interface($bridge['span']);
412
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
413
	}
414
	if (!empty($bridge['edge'])) {
415
        	$edgeifs = explode(',', $bridge['edge']);
416
        	foreach ($edgeifs as $edgeif) {
417
			$realif = get_real_interface($edgeif);
418
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
419
        	}
420
	}
421
	if (!empty($bridge['autoedge'])) {
422
        	$edgeifs = explode(',', $bridge['autoedge']);
423
        	foreach ($edgeifs as $edgeif) {
424
                	$realif = get_real_interface($edgeif);
425
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
426
        	}
427
	}
428
	if (!empty($bridge['ptp'])) {
429
        	$ptpifs = explode(',', $bridge['ptp']);
430
        	foreach ($ptpifs as $ptpif) {
431
                	$realif = get_real_interface($ptpif);
432
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
433
        	}
434
	}
435
	if (!empty($bridge['autoptp'])) {
436
        	$ptpifs = explode(',', $bridge['autoptp']);
437
        	foreach ($ptpifs as $ptpif) {
438
                	$realif = get_real_interface($ptpif);
439
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
440
        	}
441
	}
442
	if (!empty($bridge['static'])) {
443
        	$stickyifs = explode(',', $bridge['static']);
444
        	foreach ($stickyifs as $stickyif) {
445
                	$realif = get_real_interface($stickyif);
446
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
447
        	}
448
	}
449
	if (!empty($bridge['private'])) {
450
        	$privateifs = explode(',', $bridge['private']);
451
        	foreach ($privateifs as $privateif) {
452
                	$realif = get_real_interface($privateif);
453
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
454
        	}
455
	}
456

    
457
	if($bridgeif)
458
		interfaces_bring_up($bridgeif);	
459
	else 
460
		log_error("bridgeif not defined -- could not bring interface up");
461

    
462
	return $bridgeif;
463
}
464

    
465
function interface_bridge_add_member($bridgeif, $interface) {
466

    
467
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
468
		return;
469

    
470
	$mtu = get_interface_mtu($brigeif);
471
	$mtum = get_interface_mtu($interface);
472
	
473
	if ($mtu != $mtum)
474
		pfSense_interface_mtu($interface, $mtu);
475

    
476
	$options = pfSense_get_interface_addresses($bridgeif);
477
	if (isset($options['encaps']['txcsum']))
478
		pfSense_interface_capabilities($interface, IFCAP_TXCSUM);
479
	else
480
		pfSense_interface_capabilities($interface, -IFCAP_TXCSUM);
481

    
482
	if (isset($options['encaps']['rxcsum']))
483
		pfSense_interface_capabilities($interface, IFCAP_RXCSUM);
484
	else
485
		pfSense_interface_capabilities($interface, -IFCAP_RXCSUM);
486

    
487
	interfaces_bring_up($interface);
488
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
489
}
490

    
491
function interfaces_lagg_configure() 
492
{
493
        global $config, $g;
494
		if($g['booting']) 
495
			echo "Configuring LAGG interfaces...";
496
        $i = 0;
497
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
498
			foreach ($config['laggs']['lagg'] as $lagg) {
499
				if(empty($lagg['laggif']))
500
					$lagg['laggif'] = "lagg{$i}";
501
				/* XXX: Maybe we should report any errors?! */
502
				interface_lagg_configure($lagg);
503
				$i++;
504
			}
505
		}
506
		if($g['booting']) 
507
			echo "done.\n";
508
}
509

    
510
function interface_lagg_configure(&$lagg) {
511
        global $config, $g;
512

    
513
        if (!is_array($lagg))
514
		return -1;
515

    
516
	$members = explode(',', $lagg['members']);
517
	if (!count($members))
518
		return -1;
519
	
520
	$checklist = get_interface_list();
521

    
522
	if ($g['booting'] || !(empty($lagg['laggif']))) {
523
		pfSense_interface_destroy($lagg['laggif']);
524
		pfSense_interface_create($lagg['laggif']);
525
                $laggif = $lagg['laggif'];
526
        } else
527
		$laggif = pfSense_interface_create("lagg");
528

    
529
	/* Calculate smaller mtu and enforce it */
530
        $smallermtu = 0;
531
        foreach ($members as $member) {
532
                $mtu = get_interface_mtu($member);
533
		if ($smallermtu == 0 && !empty($mtu))
534
			$smallermtu = $mtu;
535
                else if (!empty($mtu) && $mtu < $smallermtu)
536
                        $smallermtu = $mtu;
537
        }
538

    
539
	/* Just in case anything is not working well */
540
        if ($smallermtu == 0)
541
                $smallermtu = 1500;
542

    
543
	foreach ($members as $member) {
544
		if (!array_key_exists($member, $checklist))
545
			continue;
546
		/* make sure the parent interface is up */
547
		pfSense_interface_mtu($member, $smallermtu);
548
		interfaces_bring_up($member);
549
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
550
	}
551
	
552
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
553

    
554
	interfaces_bring_up($laggif);
555

    
556
	return $laggif;
557
}
558

    
559
function interfaces_gre_configure() {
560
        global $config;
561

    
562
        $i = 0;
563
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
564
                foreach ($config['gres']['gre'] as $gre) {
565
                        if(empty($gre['greif']))
566
                                $gre['greif'] = "gre{$i}";
567
                        /* XXX: Maybe we should report any errors?! */
568
                        interface_gre_configure($gre);
569
                        $i++;
570
                }
571
        }
572
}
573

    
574
function interface_gre_configure(&$gre) {
575
        global $config, $g;
576

    
577
	if (!is_array($gre))
578
		return -1;
579

    
580
	$realif = get_real_interface($gre['if']);
581
	$realifip = get_interface_ip($gre['if']);
582

    
583
	/* make sure the parent interface is up */
584
	interfaces_bring_up($realif);
585

    
586
	if ($g['booting'] || !(empty($gre['greif']))) {
587
		pfSense_interface_destroy($gre['greif']);
588
		pfSense_interface_create($gre['greif']);
589
		$greif = $gre['greif'];
590
	} else
591
		$greif = pfSense_interface_create("gre");
592

    
593
	/* Do not change the order here for more see gre(4) NOTES section. */
594
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
595
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
596
	if (isset($gre['link0']) && $gre['link0'])
597
		pfSense_interface_flags($greif, IFF_LINK0);
598
	if (isset($gre['link1']) && $gre['link1'])
599
		pfSense_interface_flags($greif, IFF_LINK1);
600
	if (isset($gre['link2']) && $gre['link2'])
601
		pfSense_interface_flags($greif, IFF_LINK2);
602

    
603
	if($greif)
604
		interfaces_bring_up($greif);
605
	else 
606
		log_error("Could not bring greif up -- variable not defined.");
607

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

    
612
	return $greif;
613
}
614

    
615
function interfaces_gif_configure() {
616
	global $config;
617
	$i = 0;
618
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
619
		foreach ($config['gifs']['gif'] as $gif) {
620
			if(empty($gif['gifif']))
621
				$gre['gifif'] = "gif{$i}";
622
			/* XXX: Maybe we should report any errors?! */
623
			interface_gif_configure($gif);
624
			$i++;
625
		}
626
	}
627
}
628

    
629
function interface_gif_configure(&$gif) {
630
	global $config, $g;
631

    
632
	if (!is_array($gif))
633
		return -1;
634

    
635
	$realif = get_real_interface($gif['if']);
636
	$realifip = get_interface_ip($gif['if']);
637

    
638
	/* make sure the parent interface is up */
639
	if($realif)
640
		interfaces_bring_up($realif);
641
	else 
642
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
643

    
644
	if ($g['booting'] || !(empty($gif['gifif']))) {
645
		pfSense_interface_destroy($gif['gifif']);
646
		pfSense_interface_create($gif['gifif']);
647
		$gifif = $gif['gifif'];
648
	} else
649
		$gifif = pfSense_interface_create("gif");
650

    
651
	/* Do not change the order here for more see gif(4) NOTES section. */
652
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
653
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
654
	if (isset($gif['link0']) && $gif['link0'])
655
		pfSense_interface_flags($gifif, IFF_LINK0);
656
	if (isset($gif['link1']) && $gif['link1'])
657
		pfSense_interface_flags($gifif, IFF_LINK1);
658
	if($gifif)
659
		interfaces_bring_up($gifif);
660
	else
661
		log_error("could not bring gifif up -- variable not defined");
662

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

    
667
	return $gifif;
668
}
669

    
670
function interfaces_configure() {
671
	global $config, $g;
672

    
673
	/* Set up our loopback interface */
674
	interfaces_loopback_configure();
675

    
676
	/* set up LAGG virtual interfaces */
677
	interfaces_lagg_configure();
678

    
679
	/* set up VLAN virtual interfaces */
680
	interfaces_vlan_configure();
681

    
682
	interfaces_qinq_configure();
683

    
684
	$iflist = get_configured_interface_with_descr();
685
	$delayed_list = array();
686
	$bridge_list = array();
687
	
688
	/* This is needed to speedup interfaces on bootup. */
689
	$reload = false;
690
	if ($g['booting'])
691
		$reload = true;
692

    
693
	foreach($iflist as $if => $ifname) {
694
		$realif = $config['interfaces'][$if]['if'];
695
		if (strstr($realif, "bridge")) 
696
			$bridge_list[$if] = $ifname;
697
		else if (strstr($realif, "gre"))
698
			$delayed_list[$if] = $ifname;
699
		else if (strstr($realif, "gif"))
700
			$delayed_list[$if] = $ifname;
701
		else {
702
			if ($g['booting'])
703
				echo "Configuring {$ifname} interface...";
704
			if($g['debug'])
705
				log_error("Configuring {$ifname}");
706
			interface_configure($if, $reload);
707
			if ($g['booting']) 
708
				echo "done.\n";
709
		}
710
	}
711

    
712
	/* create the unconfigured wireless clones */
713
	interfaces_create_wireless_clones();
714

    
715
	/* set up GRE virtual interfaces */
716
	interfaces_gre_configure();
717

    
718
	/* set up GIF virtual interfaces */
719
	interfaces_gif_configure();
720
	
721
	foreach ($delayed_list as $if => $ifname) {
722
		if ($g['booting'])
723
			echo "Configuring {$ifname} interface...";
724
        	if ($g['debug'])
725
        		log_error("Configuring {$ifname}");
726

    
727
		interface_configure($if, $reload);
728

    
729
		if ($g['booting'])
730
			echo "done.\n";
731
	}
732

    
733
	/* set up BRIDGe virtual interfaces */
734
	interfaces_bridge_configure();
735

    
736
	foreach ($bridge_list as $if => $ifname) {
737
		if ($g['booting'])
738
			echo "Configuring {$ifname} interface...";
739
		if($g['debug'])
740
			log_error("Configuring {$ifname}");
741

    
742
		interface_configure($if, $reload);
743

    
744
		if ($g['booting'])
745
			echo "done.\n";
746
	}
747

    
748
	/* bring up vip interfaces */
749
	interfaces_vips_configure();
750

    
751
	/* configure interface groups */
752
	interfaces_group_setup();
753

    
754
	if (!$g['booting']) {
755
		/* reconfigure static routes (kernel may have deleted them) */
756
		system_routing_configure();
757

    
758
		/* reload IPsec tunnels */
759
		vpn_ipsec_configure();
760

    
761
		/* reload dhcpd (interface enabled/disabled status may have changed) */
762
		services_dhcpd_configure();
763

    
764
		/* restart dnsmasq */
765
		services_dnsmasq_configure();
766

    
767
		/* reload captive portal */
768
		captiveportal_init_rules();
769

    
770
		/* set the reload filter dity flag */
771
		filter_configure();
772
	}
773

    
774
	return 0;
775
}
776

    
777
function interface_reconfigure($interface = "wan") {
778
	interface_bring_down($interface);
779
	interface_configure($interface, true);
780
}
781

    
782
function interface_vip_bring_down(&$vip) {
783
	global $g;
784

    
785
	switch ($vip['mode']) {
786
	case "proxyarp":
787
		$vipif = get_real_interface($vip['interface']);
788
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
789
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
790
		break;
791
	case "ipalias":
792
		$vipif = get_real_interface($vip['interface']);
793
		if(does_interface_exist($vipif))
794
			pfSense_interface_deladdress($vipif, $vip['subnet']);
795
		break;
796
	case "carp":
797
		$vipif = "vip" . $vip['vhid'];
798
		if(does_interface_exist($vipif)) 
799
			pfSense_interface_destroy($vipif);
800
		break;
801
	case "carpdev-dhcp":
802
		$vipif = "vip" . $vip['vhid'];
803
		if(does_interface_exist($vipif)) 
804
			pfSense_interface_destroy($vipif);
805
		break;
806
	}
807
}
808

    
809
function interface_bring_down($interface = "wan", $destroy = false) {
810
	global $config, $g;
811

    
812
	if (!isset($config['interfaces'][$interface]))
813
		return; 
814

    
815
	$ifcfg = $config['interfaces'][$interface];
816

    
817
	$realif = get_real_interface($interface);
818

    
819
	switch ($ifcfg['ipaddr']) {
820
	case "ppp":
821
	case "pppoe":
822
	case "pptp":
823
	case "l2tp":
824
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
825
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
826
				if ($realif == $ppp['if']) {
827
					if (file_exists("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid")) {
828
						killbypid("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid");
829
						sleep(2);
830
					}
831
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
832
					if (isset($ppp['ondemand']) && !$destroy) {
833
						interface_configure($interface);
834
					}
835
					break;
836
				}
837
			}
838
		}
839
		break;
840
	case "carpdev-dhcp":
841
		/* 
842
		 * NB: When carpdev gets enabled it would be better to be handled as all
843
		 *	   other interfaces! 
844
		 */
845
	case "dhcp":
846
		$pid = find_dhclient_process($realif);
847
		if($pid)
848
			mwexec("kill {$pid}");
849
		sleep(1);
850
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
851
		if(does_interface_exist("$realif")) {
852
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
853
			pfSense_interface_flags($realif, -IFF_UP);
854
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
855
		}
856
		break;
857
	default:
858
		if(does_interface_exist("$realif")) {
859
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
860
			pfSense_interface_flags($realif, -IFF_UP);
861
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
862
		}
863
		break;
864
	}
865

    
866
	/* remove interface up file if it exists */
867
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
868
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
869
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
870
	
871
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
872
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
873
	if (is_array($ifcfg['wireless'])) {
874
		mwexec(kill_hostapd($realif));
875
		mwexec(kill_wpasupplicant($realif));
876
	}
877

    
878
	if ($destroy == true) {
879
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
880
			pfSense_interface_destroy($realif);
881
	}	
882

    
883
	return;
884
}
885

    
886
function interfaces_ptpid_used($ptpid) {
887
	global $config;
888

    
889
	if (is_array($config['ppps']['ppp']))
890
		foreach ($config['ppps']['ppp'] as & $settings)
891
			if ($ptpid == $settings['ptpid'])
892
				return true;
893

    
894
	return false;
895
}
896

    
897
function interfaces_ptpid_next() {
898

    
899
	$ptpid = 0;
900
	while(interfaces_ptpid_used($ptpid))
901
		$ptpid++;
902

    
903
	return $ptpid;
904
}
905

    
906
function getMPDCRONSettings($pppif_) {
907
	global $config;
908
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
909
	if (is_array($config['cron']['item'])) {
910
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
911
			$item = $config['cron']['item'][$i];
912
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
913
				return array("ID" => $i, "ITEM" => $item);
914
			}
915
		}
916
	}
917
	return NULL;
918
}
919

    
920
function handle_pppoe_reset($post_array) {
921
	global $config, $g;
922

    
923
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
924

    
925
	$pppif = $post_array['type'].$post_array['ptpid'];
926
	if (!is_array($config['cron']['item'])) 
927
		$config['cron']['item'] = array(); 
928
	$itemhash = getMPDCRONSettings($pppif);
929
	$item = $itemhash['ITEM'];
930
	
931
	// reset cron items if necessary and return
932
	if (empty($post_array['pppoe-reset-type'])) {
933
		if (isset($item))
934
			unset($config['cron']['item'][$itemhash['ID']]);
935
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
936
		return;
937
	}
938

    
939
	if (empty($item)) 
940
		$item = array();
941
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
942
		$item['minute'] = $post_array['pppoe_resetminute'];
943
		$item['hour'] = $post_array['pppoe_resethour'];
944
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
945
			$date = explode("/", $post_array['pppoe_resetdate']);
946
			$item['mday'] = $date[1];
947
			$item['month'] = $date[0];
948
		} else {
949
			$item['mday'] = "*";
950
			$item['month'] = "*";
951
		}
952
		$item['wday'] = "*";
953
		$item['who'] = "root";
954
		$item['command'] = $cron_cmd_file.$pppif;
955
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
956
		switch ($post_array['pppoe_pr_preset_val']) {
957
			case "monthly":
958
				$item['minute'] = "0";
959
				$item['hour'] = "0";
960
				$item['mday'] = "1";
961
				$item['month'] = "*";
962
				$item['wday'] = "*";
963
				$item['who'] = "root";
964
				$item['command'] = $cron_cmd_file.$pppif;
965
				break;
966
	        case "weekly":
967
				$item['minute'] = "0";
968
				$item['hour'] = "0";
969
				$item['mday'] = "*";
970
				$item['month'] = "*";
971
				$item['wday'] = "0";
972
				$item['who'] = "root";
973
				$item['command'] = $cron_cmd_file.$pppif;
974
				break;
975
			case "daily":
976
				$item['minute'] = "0";
977
				$item['hour'] = "0";
978
				$item['mday'] = "*";
979
				$item['month'] = "*";
980
				$item['wday'] = "*";
981
				$item['who'] = "root";
982
				$item['command'] = $cron_cmd_file.$pppif;
983
				break;
984
			case "hourly":
985
				$item['minute'] = "0";
986
				$item['hour'] = "*";
987
				$item['mday'] = "*";
988
				$item['month'] = "*";
989
				$item['wday'] = "*";
990
				$item['who'] = "root";
991
				$item['command'] = $cron_cmd_file.$pppif;
992
				break;
993
		} // end switch
994
	} else {
995
		/* test whether a cron item exists and unset() it if necessary */
996
		$itemhash = getMPDCRONSettings($pppif);
997
		$item = $itemhash['ITEM'];
998
		if (isset($item))
999
			unset($config['cron']['item'][$itemhash['ID']]); 
1000
	}// end if
1001
	if (isset($itemhash['ID'])) 
1002
		$config['cron']['item'][$itemhash['ID']] = $item;
1003
	else 
1004
		$config['cron']['item'][] = $item;
1005
}
1006

    
1007
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1008
*	It writes the mpd config file to /var/etc every time the link is opened.
1009
*/
1010

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

    
1111
	/* generate mpd.conf */
1112
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1113
	if (!$fd) {
1114
		log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1115
		return 0;
1116
	}
1117
	
1118
	if (is_array($ports) && count($ports) > 1)
1119
		$multilink = "enable";
1120
	else
1121
		$multilink = "disable";
1122
	
1123
	if ($type == "modem"){
1124
		if (is_ipaddr($ppp['localip']))
1125
			$localip = $ppp['localip'];
1126
		else
1127
			$localip = '0.0.0.0';
1128

    
1129
		if (is_ipaddr($ppp['gateway']))
1130
			$gateway = $ppp['gateway'];
1131
		else
1132
			$gateway = "10.64.64.{$pppid}";
1133
		$ranges = "{$localip}/0 {$gateway}/0";
1134
		
1135
		if (empty($ppp['apnum']))	
1136
			$ppp['apnum'] = 1;
1137
	} else
1138
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1139

    
1140
	if (isset($ppp['ondemand'])) 
1141
		$ondemand = "enable";
1142
	else
1143
		$ondemand = "disable";
1144
	if (!isset($ppp['idletimeout']))
1145
		$ppp['idletimeout'] = 0;
1146

    
1147
	if (empty($ppp['username']) && $type == "modem"){
1148
		$ppp['username'] = "user";
1149
		$ppp['password'] = "none";
1150
	}
1151
	if (empty($ppp['password']) && $type == "modem")
1152
		$passwd = "none";
1153
	else
1154
		$passwd = base64_decode($ppp['password']);
1155

    
1156
	$bandwidths = explode(',',$ppp['bandwidth']);
1157
	$mtus = explode(',',$ppp['mtu']);
1158
	$mrus = explode(',',$ppp['mru']);
1159

    
1160
	if (isset($ppp['mrru']))
1161
		$mrrus = explode(',',$ppp['mrru']);
1162

    
1163
	// Construct the mpd.conf file
1164
	$mpdconf = <<<EOD
1165
startup:
1166
	# configure the console
1167
	set console close
1168
	# configure the web server
1169
	set web close
1170

    
1171
default:
1172
{$ppp['type']}client:
1173
	create bundle static {$interface}
1174
	set iface name {$pppif}
1175

    
1176
EOD;
1177
	$setdefaultgw = false;
1178
	$founddefaultgw = false;
1179
	if (is_array($config['gateways']['gateway_item'])) {
1180
		foreach($config['gateways']['gateway_item'] as $gateway) {
1181
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1182
				$setdefaultgw = true;
1183
				break;
1184
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1185
				$founddefaultgw = true;
1186
				break;
1187
			}
1188
		}
1189
	}
1190
	
1191
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1192
		$setdefaultgw = true;
1193
		$mpdconf .= <<<EOD
1194
	set iface route default
1195

    
1196
EOD;
1197
	}
1198
	$mpdconf .= <<<EOD
1199
	set iface {$ondemand} on-demand
1200
	set iface idle {$ppp['idletimeout']}
1201

    
1202
EOD;
1203

    
1204
	if (isset($ppp['ondemand']))
1205
		$mpdconf .= <<<EOD
1206
	set iface addrs 10.10.1.1 10.10.1.2
1207

    
1208
EOD;
1209
	
1210
	if (isset($ppp['tcpmssfix']))
1211
		$tcpmss = "disable";
1212
	else
1213
		$tcpmss = "enable";
1214
		$mpdconf .= <<<EOD
1215
	set iface {$tcpmss} tcpmssfix
1216

    
1217
EOD;
1218

    
1219
	$mpdconf .= <<<EOD
1220
	set iface up-script /usr/local/sbin/ppp-linkup
1221
	set iface down-script /usr/local/sbin/ppp-linkdown
1222
	set ipcp ranges {$ranges}
1223

    
1224
EOD;
1225
	if (isset($ppp['vjcomp']))
1226
		$mpdconf .= <<<EOD
1227
	set ipcp no vjcomp
1228

    
1229
EOD;
1230

    
1231
	if (isset($config['system']['dnsallowoverride']))
1232
		$mpdconf .= <<<EOD
1233
	set ipcp enable req-pri-dns
1234
	set ipcp enable req-sec-dns
1235

    
1236
EOD;
1237
	if (!isset($ppp['verbose_log']))
1238
		$mpdconf .= <<<EOD
1239
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1240

    
1241
EOD;
1242
	foreach($ports as $pid => $port){
1243
		$port = get_real_interface($port);
1244
		$mpdconf .= <<<EOD
1245

    
1246
	create link static {$interface}_link{$pid} {$type}
1247
	set link action bundle {$interface}
1248
	set link {$multilink} multilink
1249
	set link keep-alive 10 60
1250
	set link max-redial 0
1251

    
1252
EOD;
1253
		if (isset($ppp['shortseq']))
1254
			$mpdconf .= <<<EOD
1255
	set link no shortseq
1256

    
1257
EOD;
1258

    
1259
		if (isset($ppp['acfcomp']))
1260
			$mpdconf .= <<<EOD
1261
	set link no acfcomp
1262

    
1263
EOD;
1264

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

    
1269
EOD;
1270

    
1271
		$mpdconf .= <<<EOD
1272
	set link disable chap pap
1273
	set link accept chap pap eap
1274
	set link disable incoming
1275

    
1276
EOD;
1277

    
1278

    
1279
		if (!empty($bandwidths[$pid]))
1280
			$mpdconf .= <<<EOD
1281
	set link bandwidth {$bandwidths[$pid]}
1282

    
1283
EOD;
1284

    
1285
		if (empty($mtus[$pid]))
1286
			$mtus[$pid] = "1492";
1287
			$mpdconf .= <<<EOD
1288
	set link mtu {$mtus[$pid]}
1289

    
1290
EOD;
1291

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

    
1296
EOD;
1297

    
1298
		$mpdconf .= <<<EOD
1299
	set auth authname "{$ppp['username']}"
1300
	set auth password {$passwd}
1301

    
1302
EOD;
1303
		if ($type == "modem") {
1304
			$mpdconf .= <<<EOD
1305
	set modem device {$ppp['ports']}
1306
	set modem script DialPeer
1307
	set modem idle-script Ringback
1308
	set modem watch -cd
1309
	set modem var \$DialPrefix "DT"
1310
	set modem var \$Telephone "{$ppp['phone']}"
1311

    
1312
EOD;
1313
		}
1314
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1315
			$mpdconf .= <<<EOD
1316
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1317

    
1318
EOD;
1319
		}
1320
		if (isset($ppp['initstr']) && $type == "modem") {
1321
			$initstr = base64_decode($ppp['initstr']);
1322
			$mpdconf .= <<<EOD
1323
	set modem var \$InitString "{$initstr}"
1324

    
1325
EOD;
1326
		}
1327
		if (isset($ppp['simpin']) && $type == "modem") {
1328
			$mpdconf .= <<<EOD
1329
	set modem var \$SimPin "{$ppp['simpin']}"
1330
	set modem var \$PinWait "{$ppp['pin-wait']}"
1331

    
1332
EOD;
1333
		}
1334
		if (isset($ppp['apn']) && $type == "modem") {
1335
			$mpdconf .= <<<EOD
1336
	set modem var \$APN "{$ppp['apn']}"
1337
	set modem var \$APNum "{$ppp['apnum']}"
1338

    
1339
EOD;
1340
		}
1341
		if (isset($ppp['provider']) && $type == "pppoe") {
1342
			$mpdconf .= <<<EOD
1343
	set pppoe service "{$ppp['provider']}"
1344

    
1345
EOD;
1346
		}
1347
		if ($type == "pppoe")
1348
			$mpdconf .= <<<EOD
1349
	set pppoe iface {$port}
1350

    
1351
EOD;
1352

    
1353
		if ($type == "pptp" || $type == "l2tp") {
1354
			$mpdconf .= <<<EOD
1355
	set {$type} self {$localips[$pid]}
1356
	set {$type} peer {$gateways[$pid]}
1357
	set {$type} disable windowing
1358

    
1359
EOD;
1360
		}
1361
		
1362
		$mpdconf .= "\topen\r\n";
1363
	} //end foreach($port)
1364

    
1365
	// Write out mpd_ppp.conf
1366
	fwrite($fd, $mpdconf);
1367
	fclose($fd);
1368

    
1369
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1370
	if (isset($ppp['uptime'])) {
1371
		if (!file_exists("/conf/{$pppif}.log")) {
1372
			conf_mount_rw();
1373
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1374
			conf_mount_ro();
1375
		}
1376
	} else {
1377
		if (file_exists("/conf/{$pppif}.log")) {
1378
			conf_mount_rw();
1379
			mwexec("rm -f /conf/{$pppif}.log");
1380
			conf_mount_ro();
1381
		}
1382
	}
1383
		
1384
	/* fire up mpd */
1385
	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");
1386

    
1387
	// Check for PPPoE periodic reset request 
1388
	if ($type == "pppoe") {
1389
		if (isset($ppp['pppoe-reset-type']))
1390
			setup_pppoe_reset_file($ppp['if'], $interface);
1391
		else
1392
			setup_pppoe_reset_file($ppp['if']);
1393
	}
1394

    
1395
	return 1;
1396
}
1397

    
1398
function interfaces_carp_setup() {
1399
	global $g, $config;
1400

    
1401
	$balanacing = "";
1402
	$pfsyncinterface = "";
1403
	$pfsyncenabled = "";
1404
	if(isset($config['system']['developerspew'])) {
1405
		$mt = microtime();
1406
		echo "interfaces_carp_setup() being called $mt\n";
1407
	}
1408

    
1409
	// Prepare CmdCHAIN that will be used to execute commands.
1410
	$cmdchain = new CmdCHAIN();	
1411

    
1412
	if ($g['booting']) {
1413
		echo "Configuring CARP settings...";
1414
		mute_kernel_msgs();
1415
	}
1416

    
1417
	/* suck in configuration items */
1418
	if($config['installedpackages']['carpsettings']) {
1419
		if($config['installedpackages']['carpsettings']['config']) {
1420
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1421
				$pfsyncenabled = $carp['pfsyncenabled'];
1422
				$balanacing = $carp['balancing'];
1423
				$pfsyncinterface = $carp['pfsyncinterface'];
1424
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1425
			}
1426
		}
1427
	} else {
1428
		unset($pfsyncinterface);
1429
		unset($balanacing);
1430
		unset($pfsyncenabled);
1431
	}
1432

    
1433
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1434
	if($balanacing) {
1435
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1436
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1437
	} else
1438
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1439

    
1440
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1441
	if (!empty($pfsyncinterface))
1442
		$carp_sync_int = get_real_interface($pfsyncinterface);
1443

    
1444
	if($g['booting']) {
1445
		/*    install rules to alllow pfsync to sync up during boot
1446
		 *    carp interfaces will remain down until the bootup sequence finishes
1447
		 */
1448
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1449
		if ($fd) {
1450
			fwrite($fd, "pass quick proto carp all keep state\n");
1451
			fwrite($fd, "pass quick proto pfsync all\n");
1452
			fwrite($fd, "pass out quick from any to any keep state\n");
1453
			fclose($fd);
1454
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1455
		} else
1456
			log_error("Could not create rules.boot file!");
1457
	}
1458

    
1459
	/* setup pfsync interface */
1460
	if($carp_sync_int and $pfsyncenabled) {
1461
		if (is_ipaddr($pfsyncpeerip))
1462
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1463
		else
1464
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1465
	} else
1466
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1467

    
1468
	if($config['virtualip']['vip'])
1469
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1470
	else
1471
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1472
	
1473
	if($g['debug'])
1474
		$cmdchain->setdebug(); // optional for verbose logging
1475

    
1476
	$cmdchain->execute();
1477
	$cmdchain->clear();
1478

    
1479
	if ($g['booting']) {
1480
		unmute_kernel_msgs();
1481
		echo "done.\n";
1482
	}
1483
}
1484

    
1485
function interface_proxyarp_configure($interface = "") {
1486
	global $config, $g;
1487
	if(isset($config['system']['developerspew'])) {
1488
		$mt = microtime();
1489
		echo "interface_proxyarp_configure() being called $mt\n";
1490
	}
1491

    
1492
	/* kill any running choparp */
1493
	if (empty($interface))
1494
		killbyname("choparp");
1495

    
1496
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1497
		$paa = array();
1498

    
1499
		/* group by interface */
1500
		foreach ($config['virtualip']['vip'] as $vipent) {
1501
			if ($vipent['mode'] === "proxyarp") {
1502
				if ($vipent['interface'])
1503
					$proxyif = $vipent['interface'];
1504
				else
1505
					$proxyif = "wan";
1506

    
1507
				if (!is_array($paa[$if]))
1508
					$paa[$proxyif] = array();
1509

    
1510
				$paa[$proxyif][] = $vipent;
1511
			}
1512
		}
1513
	}
1514

    
1515
	if (!empty($interface)) {
1516
		if (is_array($paa[$interface])) {
1517
			$paaifip = get_interface_ip($interface);
1518
                        if (!is_ipaddr($paaifip))
1519
                                return;
1520
                        $args = get_real_interface($interface) . " auto";
1521
                        foreach ($paa[$interface] as $paent) {
1522
                                if (isset($paent['subnet']))
1523
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1524
                                else if (isset($paent['range']))
1525
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1526
                        }
1527
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1528
		}
1529
	} else if (count($paa)) {
1530
		foreach ($paa as $paif => $paents) {
1531
			$paaifip = get_interface_ip($paif);
1532
			if (!(is_ipaddr($paaifip)))
1533
				continue;
1534
			$args = get_real_interface($paif) . " auto";
1535
			foreach ($paents as $paent) {
1536
				if (isset($paent['subnet']))
1537
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1538
				else if (isset($paent['range']))
1539
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1540
			}
1541
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1542
		}
1543
	}
1544
}
1545

    
1546
function interfaces_vips_configure($interface = "") {
1547
	global $g, $config;
1548
	if(isset($config['system']['developerspew'])) {
1549
		$mt = microtime();
1550
		echo "interfaces_vips_configure() being called $mt\n";
1551
	}
1552
	$paa = array();
1553
	if(is_array($config['virtualip']['vip'])) {
1554
		$carp_setuped = false;
1555
		$anyproxyarp = false;
1556
		foreach ($config['virtualip']['vip'] as $vip) {
1557
			switch ($vip['mode']) {
1558
			case "proxyarp":
1559
				/* nothing it is handled on interface_proxyarp_configure() */
1560
				if ($interface <> "" && $vip['interface'] <> $interface)
1561
					continue;
1562
				$anyproxyarp = true;
1563
				break;
1564
			case "ipalias":
1565
				if ($interface <> "" && $vip['interface'] <> $interface)
1566
					continue;
1567
				interface_ipalias_configure(&$vip);
1568
				break;
1569
			case "carp":
1570
				if ($interface <> "" && $vip['interface'] <> $interface)
1571
					continue;
1572
				if ($carp_setuped == false) {
1573
					interfaces_carp_setup();
1574
					$carp_setuped = true;
1575
				}
1576
				interface_carp_configure($vip);
1577
				break;
1578
			case "carpdev-dhcp":
1579
				if ($interface <> "" && $vip['interface'] <> $interface)
1580
					continue;
1581
				interface_carpdev_configure($vip);
1582
				break;
1583
			}
1584
		}
1585
		
1586
		if ($anyproxyarp == true)
1587
			interface_proxyarp_configure();
1588
	}
1589
}
1590

    
1591
function interface_ipalias_configure(&$vip) {
1592

    
1593
	if ($vip['mode'] == "ipalias") {
1594
		$if = get_real_interface($vip['interface']);
1595
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1596
	}
1597
}
1598

    
1599
function interface_reload_carps($cif) {
1600
	global $config;
1601

    
1602
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1603
	if (empty($carpifs))
1604
		return;
1605

    
1606
	$carps = explode(" ", $carpifs);
1607
	if(is_array($config['virtualip']['vip'])) {
1608
		$viparr = &$config['virtualip']['vip'];
1609
		foreach ($viparr as $vip) {
1610
			if (in_array($vip['carpif'], $carps)) {
1611
				switch ($vip['mode']) {
1612
				case "carp":
1613
					interface_vip_bring_down($vip);
1614
					sleep(1);
1615
					interface_carp_configure($vip);
1616
					break;
1617
				case "carpdev-dhcp":
1618
					interface_vip_bring_down($vip);
1619
					sleep(1);
1620
					interface_carpdev_configure($vip);
1621
					break;
1622
				case "ipalias":
1623
					interface_vip_bring_down($vip);
1624
					sleep(1);
1625
					interface_ipalias_configure($vip);
1626
					break;
1627
				}
1628
			}
1629
		}
1630
	}
1631
}
1632

    
1633
function interface_carp_configure(&$vip) {
1634
	global $config, $g;
1635
	if(isset($config['system']['developerspew'])) {
1636
		$mt = microtime();
1637
		echo "interface_carp_configure() being called $mt\n";
1638
	}
1639

    
1640
	if ($vip['mode'] != "carp")
1641
		return;
1642

    
1643
	$vip_password = $vip['password'];
1644
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1645
	if ($vip['password'] != "")
1646
		$password = " pass {$vip_password}";
1647

    
1648
	// set the vip interface to the vhid
1649
	$vipif = "vip{$vip['vhid']}";
1650

    
1651
	$interface = interface_translate_type_to_real($vip['interface']);
1652
	/*
1653
	 * ensure the interface containing the VIP really exists
1654
 	 * prevents a panic if the interface is missing or invalid
1655
	 */
1656
	$realif = get_real_interface($vip['interface']);
1657
	if (!does_interface_exist($realif)) {
1658
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1659
		return;
1660
	}
1661

    
1662
	/* Ensure CARP IP really exists prior to loading up. */
1663
	$ww_subnet_ip = find_interface_ip($realif);
1664
	$ww_subnet_bits = find_interface_subnet($realif);
1665
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1666
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1667
		return;
1668
	}
1669

    
1670
	/* create the carp interface and setup */
1671
	if (does_interface_exist($vipif)) {
1672
		pfSense_interface_flags($vipif, -IFF_UP);
1673
	} else {
1674
		$carpif = pfSense_interface_create("carp");
1675
		pfSense_interface_rename($carpif, $vipif);
1676
		pfSense_ngctl_name("{$carpif}:", $vipif);
1677
	}
1678

    
1679
	/* invalidate interface cache */
1680
	get_interface_arr(true);
1681

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

    
1685
	interfaces_bring_up($vipif);
1686
	
1687
	return $vipif;
1688
}
1689

    
1690
function interface_carpdev_configure(&$vip) {
1691
	global $g;
1692

    
1693
	if ($vip['mode'] != "carpdev-dhcp")
1694
		return;
1695

    
1696
	$vip_password = $vip['password'];
1697
	$vip_password = str_replace(" ", "", $vip_password);
1698
	if($vip['password'] != "")
1699
		$password = " pass \"" . $vip_password . "\"";
1700

    
1701
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1702
	if (empty($vip['interface']))
1703
		return;
1704

    
1705
	$vipif = "vip" . $vip['vhid'];
1706
	$realif = interface_translate_type_to_real($vip['interface']);
1707
	interfaces_bring_up($realif);
1708
	/*
1709
	 * ensure the interface containing the VIP really exists
1710
	 * prevents a panic if the interface is missing or invalid
1711
	 */
1712
	if (!does_interface_exist($realif)) {
1713
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1714
		return;
1715
	}
1716

    
1717
	if (does_interface_exist($vipif)) {
1718
		interface_bring_down($vipif);
1719
	} else {
1720
		$carpdevif = exec("/sbin/ifconfig carp create");
1721
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1722
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1723
	}
1724

    
1725
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1726
	interfaces_bring_up($vipif);
1727

    
1728
	/*
1729
	 * XXX: BIG HACK but carpdev needs ip services active
1730
	 *      before even starting something as dhclient.
1731
	 *      I do not know if this is a feature or a bug
1732
	 *      but better than track it make it work ;) .
1733
	 */
1734
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1735
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1736

    
1737
	/* generate dhclient_wan.conf */
1738
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1739
	if ($fd) {
1740
		$dhclientconf = "";
1741

    
1742
		$dhclientconf .= <<<EOD
1743
interface "{$vipif}" {
1744
timeout 60;
1745
retry 1;
1746
select-timeout 0;
1747
initial-interval 1;
1748
script "/sbin/dhclient-script";
1749
}
1750

    
1751
EOD;
1752

    
1753
		fwrite($fd, $dhclientconf);
1754
		fclose($fd);
1755

    
1756
		/* fire up dhclient */
1757
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1758
	} else {
1759
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1760
		mwexec("/sbin/dhclient -b {$vipif}");
1761
	}
1762

    
1763
	return $vipif;
1764
}
1765

    
1766
function interface_wireless_clone($realif, $wlcfg) {
1767
	global $config, $g;
1768
	/*   Check to see if interface has been cloned as of yet.  
1769
	 *   If it has not been cloned then go ahead and clone it.
1770
	 */
1771
	$needs_clone = false;
1772
	if(is_array($wlcfg['wireless']))
1773
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1774
	else
1775
		$wlcfg_mode = $wlcfg['mode'];
1776
	switch($wlcfg_mode) {
1777
		 case "hostap":
1778
			$mode = "wlanmode hostap";
1779
			break;
1780
		 case "adhoc":
1781
			$mode = "wlanmode adhoc";
1782
			break;
1783
		 default:
1784
			$mode = "";
1785
			break;
1786
	}
1787
	$baseif = interface_get_wireless_base($wlcfg['if']);
1788
	if(does_interface_exist($realif)) {
1789
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1790
		$ifconfig_str = implode($output);
1791
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1792
			log_error("Interface {$realif} changed to hostap mode");
1793
			$needs_clone = true;
1794
		}
1795
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1796
			log_error("Interface {$realif} changed to adhoc mode");
1797
			$needs_clone = true;
1798
		}
1799
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1800
			log_error("Interface {$realif} changed to infrastructure mode");
1801
			$needs_clone = true;
1802
		}
1803
	} else {
1804
		$needs_clone = true;
1805
	}
1806

    
1807
	if($needs_clone == true) {
1808
		/* remove previous instance if it exists */
1809
		if(does_interface_exist($realif))
1810
			pfSense_interface_destroy($realif);
1811

    
1812
		log_error("Cloning new wireless interface {$realif}");
1813
		// Create the new wlan interface. FreeBSD returns the new interface name.
1814
		// example:  wlan2
1815
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1816
		if($ret <> 0) {
1817
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1818
			return false;
1819
		}
1820
		$newif = trim($out[0]);
1821
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1822
		pfSense_interface_rename($newif, $realif);
1823
		// FIXME: not sure what ngctl is for. Doesn't work.
1824
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1825
	}
1826
	return true;
1827
}
1828

    
1829
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1830
	global $config, $g;
1831

    
1832
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1833
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1834
	                         'regdomain', 'regcountry', 'reglocation');
1835

    
1836
	if(!is_interface_wireless($ifcfg['if']))
1837
		return;
1838

    
1839
	$baseif = interface_get_wireless_base($ifcfg['if']);
1840

    
1841
	// Sync shared settings for assigned clones
1842
	$iflist = get_configured_interface_list(false, true);
1843
	foreach ($iflist as $if) {
1844
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1845
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1846
				foreach ($shared_settings as $setting) {
1847
					if ($sync_changes) {
1848
						if (isset($ifcfg['wireless'][$setting]))
1849
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1850
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1851
							unset($config['interfaces'][$if]['wireless'][$setting]);
1852
					} else {
1853
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1854
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1855
						else if (isset($ifcfg['wireless'][$setting]))
1856
							unset($ifcfg['wireless'][$setting]);
1857
					}
1858
				}
1859
				if (!$sync_changes)
1860
					break;
1861
			}
1862
		}
1863
	}
1864

    
1865
	// Read or write settings at shared area
1866
	if (isset($config['wireless']['interfaces'][$baseif])) {
1867
		foreach ($shared_settings as $setting) {
1868
			if ($sync_changes) {
1869
				if (isset($ifcfg['wireless'][$setting]))
1870
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
1871
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1872
					unset($config['wireless']['interfaces'][$baseif][$setting]);
1873
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
1874
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1875
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
1876
				else if (isset($ifcfg['wireless'][$setting]))
1877
					unset($ifcfg['wireless'][$setting]);
1878
			}
1879
		}
1880
	}
1881

    
1882
	// Sync the mode on the clone creation page with the configured mode on the interface
1883
	if (interface_is_wireless_clone($ifcfg['if'])) {
1884
		foreach ($config['wireless']['clone'] as &$clone) {
1885
			if ($clone['cloneif'] == $ifcfg['if']) {
1886
				if ($sync_changes) {
1887
					$clone['mode'] = $ifcfg['wireless']['mode'];
1888
				} else {
1889
					$ifcfg['wireless']['mode'] = $clone['mode'];
1890
				}
1891
				break;
1892
			}
1893
		}
1894
		unset($clone);
1895
	}
1896
}
1897

    
1898
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1899
	global $config, $g;
1900

    
1901
	/*    open up a shell script that will be used to output the commands.
1902
	 *    since wireless is changing a lot, these series of commands are fragile
1903
     *    and will sometimes need to be verified by a operator by executing the command
1904
     *    and returning the output of the command to the developers for inspection.  please
1905
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1906
	 */
1907

    
1908
	// Remove script file
1909
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1910

    
1911
	// Clone wireless nic if needed.
1912
	interface_wireless_clone($if, $wl);
1913

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

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

    
1921
	/* set values for /path/program */
1922
	$hostapd = "/usr/sbin/hostapd";
1923
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1924
	$ifconfig = "/sbin/ifconfig";
1925
	$sysctl = "/sbin/sysctl";
1926
	$killall = "/usr/bin/killall";
1927

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

    
1930
	$wlcmd = array();
1931
	$wl_sysctl = array();
1932
	/* Make sure it's up */
1933
	$wlcmd[] = "up";
1934
	/* Set a/b/g standard */
1935
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
1936
	$wlcmd[] = "mode " . escapeshellarg($standard);
1937

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

    
1943
	/* Set ssid */
1944
	if($wlcfg['ssid'])
1945
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1946

    
1947
	/* Set 802.11g protection mode */
1948
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1949

    
1950
	/* set wireless channel value */
1951
	if(isset($wlcfg['channel'])) {
1952
		if($wlcfg['channel'] == "0") {
1953
			$wlcmd[] = "channel any";
1954
		} else {
1955
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1956
		}
1957
	}
1958

    
1959
	/* Set antenna diversity value */
1960
	if(isset($wlcfg['diversity']))
1961
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
1962

    
1963
	/* Set txantenna value */
1964
	if(isset($wlcfg['txantenna']))
1965
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
1966

    
1967
	/* Set rxantenna value */
1968
	if(isset($wlcfg['rxantenna']))
1969
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
1970

    
1971
	/* set Distance value */
1972
	if($wlcfg['distance'])
1973
		$distance = escapeshellarg($wlcfg['distance']);
1974

    
1975
	/* Set wireless hostap mode */
1976
	if ($wlcfg['mode'] == "hostap") {
1977
		$wlcmd[] = "mediaopt hostap";
1978
	} else {
1979
		$wlcmd[] = "-mediaopt hostap";
1980
	}
1981

    
1982
	/* Set wireless adhoc mode */
1983
	if ($wlcfg['mode'] == "adhoc") {
1984
		$wlcmd[] = "mediaopt adhoc";
1985
	} else {
1986
		$wlcmd[] = "-mediaopt adhoc";
1987
	}
1988

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

    
1991
	/* handle hide ssid option */
1992
	if(isset($wlcfg['hidessid']['enable'])) {
1993
		$wlcmd[] = "hidessid";
1994
	} else {
1995
		$wlcmd[] = "-hidessid";
1996
	}
1997

    
1998
	/* handle pureg (802.11g) only option */
1999
	if(isset($wlcfg['pureg']['enable'])) {
2000
		$wlcmd[] = "mode 11g pureg";
2001
	} else {
2002
		$wlcmd[] = "-pureg";
2003
	}
2004

    
2005
	/* handle puren (802.11n) only option */
2006
	if(isset($wlcfg['puren']['enable'])) {
2007
		$wlcmd[] = "puren";
2008
	} else {
2009
		$wlcmd[] = "-puren";
2010
	}
2011

    
2012
	/* enable apbridge option */
2013
	if(isset($wlcfg['apbridge']['enable'])) {
2014
		$wlcmd[] = "apbridge";
2015
	} else {
2016
		$wlcmd[] = "-apbridge";
2017
	}
2018

    
2019
	/* handle turbo option */
2020
	if(isset($wlcfg['turbo']['enable'])) {
2021
		$wlcmd[] = "mediaopt turbo";
2022
	} else {
2023
		$wlcmd[] = "-mediaopt turbo";
2024
	}
2025

    
2026
	/* handle txpower setting */
2027
	/* if($wlcfg['txpower'] <> "")
2028
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2029
	*/
2030
	/* handle wme option */
2031
	if(isset($wlcfg['wme']['enable'])) {
2032
		$wlcmd[] = "wme";
2033
	} else {
2034
		$wlcmd[] = "-wme";
2035
	}
2036

    
2037
	/* set up wep if enabled */
2038
	$wepset = "";
2039
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2040
		switch($wlcfg['wpa']['auth_algs']) {
2041
			case "1":
2042
				$wepset .= "authmode open wepmode on ";
2043
				break;
2044
			case "2":
2045
				$wepset .= "authmode shared wepmode on ";
2046
				break;
2047
			case "3":
2048
				$wepset .= "authmode mixed wepmode on ";
2049
		}
2050
		$i = 1;
2051
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2052
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2053
			if (isset($wepkey['txkey'])) {
2054
				$wlcmd[] = "weptxkey {$i} ";
2055
			}
2056
			$i++;
2057
		}
2058
		$wlcmd[] = $wepset;
2059
	} else {
2060
		$wlcmd[] = "authmode open wepmode off ";
2061
	}
2062

    
2063
	mwexec(kill_hostapd("{$if}"));
2064
	mwexec(kill_wpasupplicant("{$if}"));
2065

    
2066
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2067
	conf_mount_rw();
2068

    
2069
	switch ($wlcfg['mode']) {
2070
		case 'bss':
2071
			if (isset($wlcfg['wpa']['enable'])) {
2072
				$wpa .= <<<EOD
2073
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2074
ctrl_interface_group=0
2075
ap_scan=1
2076
#fast_reauth=1
2077
network={
2078
ssid="{$wlcfg['ssid']}"
2079
scan_ssid=1
2080
priority=5
2081
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2082
psk="{$wlcfg['wpa']['passphrase']}"
2083
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2084
group={$wlcfg['wpa']['wpa_pairwise']}
2085
}
2086
EOD;
2087

    
2088
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2089
				fwrite($fd, "{$wpa}");
2090
				fclose($fd);
2091
			}
2092
			break;
2093
		case 'hostap':
2094
			if($wlcfg['wpa']['passphrase']) 
2095
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2096
			else 
2097
				$wpa_passphrase = "";
2098
			if (isset($wlcfg['wpa']['enable'])) {
2099
				$wpa .= <<<EOD
2100
interface={$if}
2101
driver=bsd
2102
logger_syslog=-1
2103
logger_syslog_level=0
2104
logger_stdout=-1
2105
logger_stdout_level=0
2106
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2107
ctrl_interface={$g['varrun_path']}/hostapd
2108
ctrl_interface_group=wheel
2109
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2110
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2111
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2112
ssid={$wlcfg['ssid']}
2113
debug={$wlcfg['wpa']['debug_mode']}
2114
auth_algs={$wlcfg['wpa']['auth_algs']}
2115
wpa={$wlcfg['wpa']['wpa_mode']}
2116
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2117
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2118
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2119
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2120
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2121
{$wpa_passphrase}
2122
#Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2123
#rsn_preauth=1
2124
#rsn_preauth_interfaces=eth0
2125

    
2126
EOD;
2127

    
2128
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2129
					$auth_server_port = "1812";
2130
					if($wlcfg['auth_server_port']) 
2131
						$auth_server_port = $wlcfg['auth_server_port'];
2132
					$wpa .= <<<EOD
2133

    
2134
ieee8021x=1
2135
auth_server_addr={$wlcfg['auth_server_addr']}
2136
auth_server_port={$auth_server_port}
2137
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2138

    
2139
EOD;
2140
				} else {
2141
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2142
				}
2143

    
2144
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2145
				fwrite($fd, "{$wpa}");
2146
				fclose($fd);
2147

    
2148
			}
2149
			break;
2150
	}
2151

    
2152
	/*
2153
	 *    all variables are set, lets start up everything
2154
	 */
2155

    
2156
	$baseif = interface_get_wireless_base($if);
2157
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2158
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2159

    
2160
	/* set sysctls for the wireless interface */
2161
	if (!empty($wl_sysctl)) {
2162
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2163
		foreach ($wl_sysctl as $wl_sysctl_line) {
2164
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2165
		}
2166
	}
2167

    
2168
	/* set ack timers according to users preference (if he/she has any) */
2169
	if($distance) {
2170
		fwrite($fd_set, "# Enable ATH distance settings\n");
2171
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2172
	}
2173

    
2174
	if (isset($wlcfg['wpa']['enable'])) {
2175
		if ($wlcfg['mode'] == "bss") {
2176
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2177
		}
2178
		if ($wlcfg['mode'] == "hostap") {
2179
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2180
		}
2181
	}
2182

    
2183
	fclose($fd_set);
2184
	conf_mount_ro();
2185

    
2186
	/* Making sure regulatory settings have actually changed
2187
	 * before applying, because changing them requires bringing
2188
	 * down all wireless networks on the interface. */
2189
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2190
	$ifconfig_str = implode($output);
2191
	unset($output);
2192
	$reg_changing = false;
2193

    
2194
	/* special case for the debug country code */
2195
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2196
		$reg_changing = true;
2197
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2198
		$reg_changing = true;
2199
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2200
		$reg_changing = true;
2201
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2202
		$reg_changing = true;
2203
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2204
		$reg_changing = true;
2205

    
2206
	if ($reg_changing) {
2207
		/* set regulatory domain */
2208
		if($wlcfg['regdomain'])
2209
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2210

    
2211
		/* set country */
2212
		if($wlcfg['regcountry'])
2213
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2214

    
2215
		/* set location */
2216
		if($wlcfg['reglocation'])
2217
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2218

    
2219
		$wlregcmd_args = implode(" ", $wlregcmd);
2220

    
2221
		/* build a complete list of the wireless clones for this interface */
2222
		$clone_list = array();
2223
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2224
			$clone_list[] = interface_get_wireless_clone($baseif);
2225
		if (is_array($config['wireless']['clone'])) {
2226
			foreach ($config['wireless']['clone'] as $clone) {
2227
				if ($clone['if'] == $baseif)
2228
					$clone_list[] = $clone['cloneif'];
2229
			}
2230
		}
2231

    
2232
		/* find which clones are up and bring them down */
2233
		$clones_up = array();
2234
		foreach ($clone_list as $clone_if) {
2235
			$clone_status = pfSense_get_interface_addresses($clone_if);
2236
			if ($clone_status['status'] == 'up') {
2237
				$clones_up[] = $clone_if;
2238
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2239
			}
2240
		}
2241

    
2242
		/* apply the regulatory settings */
2243
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2244

    
2245
		/* bring the clones back up that were previously up */
2246
		foreach ($clones_up as $clone_if) {
2247
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2248
		}
2249
	}
2250

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

    
2255
	/* configure wireless */
2256
	$wlcmd_args = implode(" ", $wlcmd);
2257
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2258

    
2259
	
2260
	sleep(1);
2261
	/* execute hostapd and wpa_supplicant if required in shell */
2262
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2263

    
2264
	return 0;
2265

    
2266
}
2267

    
2268
function kill_hostapd($interface) {
2269
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2270
}
2271

    
2272
function kill_wpasupplicant($interface) {
2273
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2274
}
2275

    
2276
function find_dhclient_process($interface) {
2277
	if($interface) {
2278
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2279
	}
2280
	return $pid;
2281
}
2282

    
2283
function interface_configure($interface = "wan", $reloadall = false) {
2284
	global $config, $g;
2285
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2286

    
2287
	$wancfg = $config['interfaces'][$interface];
2288

    
2289
	$realif = get_real_interface($interface);
2290

    
2291
	if (!$g['booting']) {
2292
		/* remove all IPv4 addresses */
2293
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2294
			interface_bring_down($interface);
2295
	}
2296

    
2297
	/* wireless configuration? */
2298
	if (is_array($wancfg['wireless']))
2299
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2300

    
2301
	if ($wancfg['spoofmac']) {
2302
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2303
			" link " . escapeshellarg($wancfg['spoofmac']));
2304

    
2305
                /*
2306
                 * All vlans need to spoof their parent mac address, too.  see
2307
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2308
                 */
2309
                if (is_array($config['vlans']['vlan'])) {
2310
                        foreach ($config['vlans']['vlan'] as $vlan) {
2311
                                if ($vlan['if'] == $realif)
2312
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2313
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2314
                        }
2315
                }
2316
	}  else {
2317
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2318
		if($mac == "ff:ff:ff:ff:ff:ff") {
2319
			/*   this is not a valid mac address.  generate a
2320
			 *   temporary mac address so the machine can get online.
2321
			 */
2322
			echo "Generating new MAC address.";
2323
			$random_mac = generate_random_mac_address();
2324
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2325
				" link " . escapeshellarg($random_mac));
2326
			$wancfg['spoofmac'] = $random_mac;
2327
			write_config();
2328
			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");
2329
		}
2330
	}
2331

    
2332
	/* media */
2333
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2334
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2335
		if ($wancfg['media'])
2336
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2337
		if ($wancfg['mediaopt'])
2338
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2339
		mwexec($cmd);
2340
	}
2341
	if (!empty($wancfg['mtu']))
2342
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2343

    
2344
	/* invalidate interface/ip/sn cache */
2345
	get_interface_arr(true);
2346
	unset($interface_ip_arr_cache[$realif]);
2347
	unset($interface_sn_arr_cache[$realif]);
2348

    
2349
	switch ($wancfg['ipaddr']) {
2350
		case 'carpdev-dhcp':
2351
			interface_carpdev_dhcp_configure($interface);
2352
			break;
2353
		case 'dhcp':
2354
			interface_dhcp_configure($interface);
2355
			break;
2356
		case 'pppoe':
2357
		case 'l2tp':
2358
		case 'pptp':
2359
		case 'ppp':
2360
			interface_ppps_configure($interface);
2361
			break;
2362
		default:
2363
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2364
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2365
			} else if (substr($realif, 0, 3) == "gre") {
2366
				if (is_array($config['gres']['gre'])) {
2367
					foreach ($config['gres']['gre'] as $gre)
2368
						if ($gre['greif'] == $realif)
2369
							interface_gre_configure($gre);
2370
				}
2371
			} else if (substr($realif, 0, 3) == "gif") {
2372
				 if (is_array($config['gifs']['gif'])) {
2373
					foreach ($config['gifs']['gif'] as $gif)
2374
						if($gif['gifif'] == $interface)
2375
							interface_gif_configure($gif);
2376
				}
2377
			} else if (substr($realif, 0, 4) == "ovpn") {
2378
				/* XXX: Should be done anything?! */
2379
			}
2380

    
2381
			if (is_ipaddr($wancfg['gateway']))
2382
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2383
			break;
2384
	}
2385

    
2386
	if(does_interface_exist($wancfg['if']))
2387
		interfaces_bring_up($wancfg['if']);
2388
 	
2389
	if (!$g['booting'])
2390
		interface_reload_carps($realif);
2391
	
2392
	if (!$g['booting']) {
2393
		unset($gre);
2394
		$gre = link_interface_to_gre($interface);
2395
		if (!empty($gre))
2396
			interface_gre_configure($gre);
2397

    
2398
		unset($gif);
2399
		$gif = link_interface_to_gif($interface);
2400
		if (!empty($gif))
2401
                       	interface_gif_configure($gif);
2402

    
2403
		unset($bridgetmp);
2404
		$bridgetmp = link_interface_to_bridge($interface);
2405
		if (!empty($bridgetmp))
2406
			interface_bridge_add_member($bridgetmp, $realif);
2407

    
2408
		link_interface_to_vips($interface, "update");
2409

    
2410
		if ($interface == "lan")
2411
			/* make new hosts file */
2412
			system_hosts_generate();
2413

    
2414
		if ($reloadall == true) {
2415

    
2416
			/* reconfigure static routes (kernel may have deleted them) */
2417
			system_routing_configure($interface);
2418

    
2419
			/* reload ipsec tunnels */
2420
			vpn_ipsec_configure();
2421

    
2422
			/* update dyndns */
2423
			services_dyndns_configure($interface);
2424

    
2425
			/* force DNS update */
2426
			services_dnsupdate_process($interface);
2427

    
2428
			/* restart dnsmasq */
2429
			services_dnsmasq_configure();
2430

    
2431
			/* reload captive portal */
2432
			captiveportal_init_rules();
2433

    
2434
			/* set the reload filter dity flag */
2435
			filter_configure();
2436
		}
2437
	}
2438

    
2439
	return 0;
2440
}
2441

    
2442
function interface_carpdev_dhcp_configure($interface = "wan") {
2443
	global $config, $g;
2444

    
2445
	$wancfg = $config['interfaces'][$interface];
2446
	$wanif = $wancfg['if'];
2447
	/* bring wan interface up before starting dhclient */
2448
	if($wanif)
2449
		interfaces_bring_up($wanif);
2450
	else 
2451
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2452

    
2453
	return 0;
2454
}
2455

    
2456
function interface_dhcp_configure($interface = "wan") {
2457
	global $config, $g;
2458

    
2459
	$wancfg = $config['interfaces'][$interface];
2460
	if (empty($wancfg))
2461
		$wancfg = array();
2462

    
2463
	/* generate dhclient_wan.conf */
2464
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2465
	if (!$fd) {
2466
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2467
		return 1;
2468
	}
2469

    
2470
	if ($wancfg['dhcphostname']) {
2471
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2472
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2473
	} else {
2474
		$dhclientconf_hostname = "";
2475
	}
2476

    
2477
	$wanif = get_real_interface($interface);
2478
	if (empty($wanif)) {
2479
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2480
		return 0;
2481
	}
2482
 	$dhclientconf = "";
2483
	
2484
	$dhclientconf .= <<<EOD
2485
interface "{$wanif}" {
2486
timeout 60;
2487
retry 1;
2488
select-timeout 0;
2489
initial-interval 1;
2490
	{$dhclientconf_hostname}
2491
	script "/sbin/dhclient-script";
2492
}
2493

    
2494
EOD;
2495

    
2496
if(is_ipaddr($wancfg['alias-address'])) {
2497
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2498
	$dhclientconf .= <<<EOD
2499
alias {
2500
	interface  "{$wanif}";
2501
	fixed-address {$wancfg['alias-address']};
2502
	option subnet-mask {$subnetmask};
2503
}
2504

    
2505
EOD;
2506
}
2507
	fwrite($fd, $dhclientconf);
2508
	fclose($fd);
2509

    
2510
	/* bring wan interface up before starting dhclient */
2511
	if($wanif)
2512
		interfaces_bring_up($wanif);
2513
	else 
2514
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2515

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

    
2519
	return 0;
2520
}
2521

    
2522
function interfaces_group_setup() {
2523
	global $config;
2524

    
2525
	if (!is_array($config['ifgroups']['ifgroupentry']))
2526
		return;
2527

    
2528
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2529
		interface_group_setup($groupar);
2530

    
2531
	return;
2532
}
2533

    
2534
function interface_group_setup(&$groupname /* The parameter is an array */) {
2535
	global $config;
2536

    
2537
	if (!is_array($groupname))
2538
		return;
2539
	$members = explode(" ", $groupname['members']);
2540
	foreach($members as $ifs) {
2541
		$realif = get_real_interface($ifs);
2542
		if ($realif)
2543
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2544
	}
2545

    
2546
	return;
2547
}
2548
 
2549
/* COMPAT Function */
2550
function convert_friendly_interface_to_real_interface_name($interface) {
2551
	return get_real_interface($interface);
2552
}
2553

    
2554
/* COMPAT Function */
2555
function get_real_wan_interface($interface = "wan") {
2556
	return get_real_interface($interface);
2557
}
2558

    
2559
/* COMPAT Function */
2560
function get_current_wan_address($interface = "wan") {
2561
	return get_interface_ip($interface);
2562
}
2563

    
2564
/*
2565
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2566
 */
2567
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2568
        global $config;
2569

    
2570
	if (stristr($interface, "vip")) {
2571
                $index = intval(substr($interface, 3));
2572
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2573
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2574
                                if ($index == $counter)
2575
                                        return $vip['interface'];
2576
                        }
2577
                }
2578
        }
2579

    
2580
        /* XXX: For speed reasons reference directly the interface array */
2581
	$ifdescrs =& $config['interfaces'];
2582
        //$ifdescrs = get_configured_interface_list(false, true);
2583

    
2584
        foreach ($ifdescrs as $if => $ifname) {
2585
                if ($config['interfaces'][$if]['if'] == $interface)
2586
                        return $if;
2587

    
2588
                if (get_real_interface($if) == $interface)
2589
                        return $if;
2590

    
2591
                $int = interface_translate_type_to_real($if);
2592
                if ($int == $interface)
2593
                        return $ifname;
2594
        }
2595
        return NULL;
2596
}
2597

    
2598
/* attempt to resolve interface to friendly descr */
2599
function convert_friendly_interface_to_friendly_descr($interface) {
2600
        global $config;
2601

    
2602
        switch ($interface) {
2603
                case "l2tp":
2604
                                $ifdesc = "L2TP";
2605
                                break;
2606
                case "pptp":
2607
                                $ifdesc = "PPTP";
2608
                                break;
2609
                case "pppoe":
2610
                                $ifdesc = "PPPoE";
2611
                                break;
2612
                case "openvpn":
2613
                                $ifdesc = "OpenVPN";
2614
                                break;
2615
                case "enc0":
2616
                        case "ipsec":
2617
                                $ifdesc = "IPsec";
2618
                                break;
2619
        default:
2620
                if (isset($config['interfaces'][$interface])) {
2621
                        if (empty($config['interfaces'][$interface]['descr']))
2622
                                $ifdesc = strtoupper($interface);
2623
                        else
2624
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2625
			break;
2626
		}
2627
                /* if list */
2628
                $ifdescrs = get_configured_interface_with_descr(false, true);
2629
                foreach ($ifdescrs as $if => $ifname) {
2630
                                if ($if == $interface || $ifname == $interface)
2631
                                        return $ifname;
2632
                }
2633
                break;
2634
        }
2635

    
2636
        return $ifdesc;
2637
}
2638

    
2639
function convert_real_interface_to_friendly_descr($interface) {
2640
        global $config;
2641

    
2642
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2643

    
2644
        if ($ifdesc) {
2645
                $iflist = get_configured_interface_with_descr(false, true);
2646
                return $iflist[$ifdesc];
2647
        }
2648

    
2649
        return $interface;
2650
}
2651

    
2652
/*
2653
 *  interface_translate_type_to_real($interface):
2654
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2655
 */
2656
function interface_translate_type_to_real($interface) {
2657
        global $config;
2658

    
2659
        if ($config['interfaces'][$interface]['if'] <> "")
2660
                return $config['interfaces'][$interface]['if'];
2661
        else
2662
		return $interface;
2663
}
2664

    
2665
function interface_is_wireless_clone($wlif) {
2666
	if(!stristr($wlif, "_wlan")) {
2667
		return false;
2668
	} else {
2669
		return true;
2670
	}
2671
}
2672

    
2673
function interface_get_wireless_base($wlif) {
2674
	if(!stristr($wlif, "_wlan")) {
2675
		return $wlif;
2676
	} else {
2677
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2678
	}
2679
}
2680

    
2681
function interface_get_wireless_clone($wlif) {
2682
	if(!stristr($wlif, "_wlan")) {
2683
		return $wlif . "_wlan0";
2684
	} else {
2685
		return $wlif;
2686
	}
2687
}
2688

    
2689
function get_real_interface($interface = "wan") {
2690
    global $config;
2691

    
2692
	$wanif = NULL;
2693

    
2694
	switch ($interface) {
2695
	case "l2tp":
2696
		$wanif = "l2tp";
2697
		break;
2698
	case "pptp":
2699
		$wanif = "pptp";
2700
		break;
2701
	case "pppoe":
2702
		$wanif = "pppoe";
2703
		break;
2704
	case "openvpn":
2705
		$wanif = "openvpn";
2706
		break;
2707
	case "ipsec":
2708
	case "enc0":
2709
		$wanif = "enc0";
2710
		break;
2711
	case "ppp":
2712
		$wanif = "ppp";
2713
		break;
2714
	default:
2715
		// If a real interface was alread passed simply
2716
		// pass the real interface back.  This encourages
2717
		// the usage of this function in more cases so that
2718
		// we can combine logic for more flexibility.
2719
		if(does_interface_exist($interface)) {
2720
			$wanif = $interface;
2721
			break;
2722
		}
2723
		if (empty($config['interfaces'][$interface]))
2724
			break;
2725

    
2726
		$cfg =& $config['interfaces'][$interface];
2727

    
2728
		// Wireless cloned NIC support (FreeBSD 8+)
2729
		// interface name format: $parentnic_wlanparentnic#
2730
		// example: ath0_wlan0
2731
		if (is_interface_wireless($cfg['if'])) {
2732
			$wanif = interface_get_wireless_clone($cfg['if']);
2733
			break;
2734
		}
2735
		/*
2736
		if (empty($cfg['if'])) {
2737
			$wancfg = $cfg['if'];
2738
			break;
2739
		}
2740
		*/
2741

    
2742
		switch ($cfg['ipaddr']) {
2743
			case "carpdev-dhcp":
2744
				$viparr = &$config['virtualip']['vip'];
2745
				if(is_array($viparr))
2746
				foreach ($viparr as $counter => $vip) {
2747
					if ($vip['mode'] == "carpdev-dhcp") {
2748
						if($vip['interface'] == $interface) {
2749
							$wanif = "carp{$counter}";
2750
							break;
2751
						}
2752
					}
2753
				}
2754
				break;
2755
			case "pppoe": 
2756
			case "pptp": 
2757
			case "l2tp": 
2758
			case "ppp":
2759
				$wanif = $cfg['if'];
2760
				break;
2761
			default:
2762
				$wanif = $cfg['if'];
2763
				break;
2764
		}
2765
		break;
2766
	}
2767

    
2768
    return $wanif;
2769
}
2770

    
2771
/* Guess the physical interface by providing a IP address */
2772
function guess_interface_from_ip($ipaddress) {
2773
	if(! is_ipaddr($ipaddress)) {
2774
		return false;
2775
	}
2776
	/* create a route table we can search */
2777
	exec("netstat -rnW", $output, $ret);
2778
	foreach($output as $line) {
2779
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2780
			$fields = preg_split("/[ ]+/", $line);
2781
			if(ip_in_subnet($ipaddress, $fields[0])) {
2782
				return $fields[6];
2783
			}
2784
		}
2785
	}
2786
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2787
	if(empty($ret)) {
2788
        	return false;
2789
	}
2790
	return $ret;
2791
}
2792

    
2793
/*
2794
 * find_ip_interface($ip): return the interface where an ip is defined
2795
 */
2796
function find_ip_interface($ip)
2797
{
2798
        /* if list */
2799
        $ifdescrs = get_configured_interface_list();
2800

    
2801
        foreach ($ifdescrs as $ifdescr => $ifname) {
2802
		if ($ip == get_interface_ip($ifname)) {
2803
                	$int = get_real_interface($ifname);
2804
			return $int;
2805
		}
2806
        }
2807
        return false;
2808
}
2809

    
2810
/*
2811
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2812
 */
2813
function find_number_of_created_carp_interfaces() {
2814
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2815
}
2816

    
2817
function get_all_carp_interfaces() {
2818
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2819
	$ints = explode(" ", $ints);
2820
	return $ints;
2821
}
2822

    
2823
/*
2824
 * find_carp_interface($ip): return the carp interface where an ip is defined
2825
 */
2826
function find_carp_interface($ip) {
2827
	global $config;
2828
	if (is_array($config['virtualip']['vip'])) {
2829
		foreach ($config['virtualip']['vip'] as $vip) {
2830
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2831
				$carp_ip = get_interface_ip($vip['interface']);
2832
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2833
				if ($if)
2834
					return $if;
2835
			}
2836
		}
2837
	}
2838
}
2839

    
2840
function link_carp_interface_to_parent($interface) {
2841
        global $config;
2842

    
2843
        if ($interface == "")
2844
                return;
2845

    
2846
        $carp_ip = get_interface_ip($interface);
2847
        if (!is_ipaddr($carp_ip))
2848
                return;
2849

    
2850
        /* if list */
2851
        $ifdescrs = get_configured_interface_list();
2852
        foreach ($ifdescrs as $ifdescr => $ifname) {
2853
                $interfaceip = get_interface_ip($ifname);
2854
                $subnet_bits = get_interface_subnet($ifname);
2855
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2856
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2857
                        return $ifname;
2858
        }
2859

    
2860
        return "";
2861
}
2862

    
2863
/****f* interfaces/link_ip_to_carp_interface
2864
 * NAME
2865
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2866
 * INPUTS
2867
 *   $ip
2868
 * RESULT
2869
 *   $carp_ints
2870
 ******/
2871
function link_ip_to_carp_interface($ip) {
2872
        global $config;
2873

    
2874
        if (!is_ipaddr($ip))
2875
                return;
2876

    
2877
        $carp_ints = "";
2878
        if (is_array($config['virtualip']['vip'])) {
2879
		$first = 0;
2880
		$carp_int = array();
2881
                foreach ($config['virtualip']['vip'] as $vip) {
2882
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2883
                                $carp_ip = $vip['subnet'];
2884
                                $carp_sn = $vip['subnet_bits'];
2885
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2886
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
2887
					$carp_int[] = "vip{$vip['vhid']}";
2888
                        }
2889
                }
2890
		if (!empty($carp_int))
2891
			$carp_ints = implode(" ", array_unique($carp_int));
2892
        }
2893

    
2894
        return $carp_ints;
2895
}
2896

    
2897
function link_interface_to_vlans($int, $action = "") {
2898
	global $config;
2899

    
2900
	if (empty($int))
2901
		return;
2902

    
2903
	if (is_array($config['vlans']['vlan'])) {
2904
                foreach ($config['vlans']['vlan'] as $vlan) {
2905
			if ($int == $vlan['if']) {
2906
				if ($action == "update") {
2907
					interfaces_bring_up($int);
2908
				} else if ($action == "")
2909
					return $vlan;
2910
			}
2911
		}
2912
	}
2913
}
2914

    
2915
function link_interface_to_vips($int, $action = "") {
2916
        global $config;
2917

    
2918
        if (is_array($config['virtualip']['vip']))
2919
                foreach ($config['virtualip']['vip'] as $vip)
2920
                        if ($int == $vip['interface']) {
2921
				if ($action == "update")
2922
					interfaces_vips_configure($int);
2923
				else
2924
                                	return $vip;
2925
			}
2926
}
2927

    
2928
/****f* interfaces/link_interface_to_bridge
2929
 * NAME
2930
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2931
 * INPUTS
2932
 *   $ip
2933
 * RESULT
2934
 *   bridge[0-99]
2935
 ******/
2936
function link_interface_to_bridge($int) {
2937
        global $config;
2938

    
2939
        if (is_array($config['bridges']['bridged'])) {
2940
                foreach ($config['bridges']['bridged'] as $bridge) {
2941
			if (in_array($int, explode(',', $bridge['members'])))
2942
                                return "{$bridge['bridgeif']}";
2943
		}
2944
	}
2945
}
2946

    
2947
function link_interface_to_gre($interface) {
2948
        global $config;
2949

    
2950
        if (is_array($config['gres']['gre']))
2951
                foreach ($config['gres']['gre'] as $gre)
2952
                        if($gre['if'] == $interface)
2953
                                return $gre;
2954
}
2955

    
2956
function link_interface_to_gif($interface) {
2957
        global $config;
2958

    
2959
        if (is_array($config['gifs']['gif']))
2960
                foreach ($config['gifs']['gif'] as $gif)
2961
                        if($gif['if'] == $interface)
2962
                                return $gif;
2963
}
2964

    
2965
/*
2966
 * find_interface_ip($interface): return the interface ip (first found)
2967
 */
2968
function find_interface_ip($interface, $flush = false)
2969
{
2970
	global $interface_ip_arr_cache;
2971

    
2972
	$interface = str_replace("\n", "", $interface);
2973
	
2974
	if (!does_interface_exist($interface))
2975
		return;
2976

    
2977
	/* Setup IP cache */
2978
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2979
		$ifinfo = pfSense_get_interface_addresses($interface);
2980
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
2981
	}
2982

    
2983
	return $interface_ip_arr_cache[$interface];
2984
}
2985

    
2986
function find_interface_subnet($interface, $flush = false)
2987
{
2988
	global $interface_sn_arr_cache;
2989

    
2990
	$interface = str_replace("\n", "", $interface);
2991
	if (does_interface_exist($interface) == false)
2992
		return;
2993

    
2994
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
2995
		$ifinfo = pfSense_get_interface_addresses($interface);
2996
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
2997
        }
2998

    
2999
	return $interface_sn_arr_cache[$interface];
3000
}
3001

    
3002
function get_interface_ip($interface = "wan")
3003
{
3004
	$realif = get_real_interface($interface);
3005
	if (!$realif) {
3006
		if (preg_match("/^carp/i", $interface))
3007
			$realif = $interface;
3008
		else if (preg_match("/^vip/i", $interface))
3009
			$realif = $interface;
3010
		else
3011
			return null;
3012
	}
3013

    
3014
	$curip = find_interface_ip($realif);
3015
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3016
		return $curip;
3017
	else
3018
		return null;
3019
}
3020

    
3021
function get_interface_subnet($interface = "wan")
3022
{
3023
	$realif = get_real_interface($interface);
3024
	if (!$realif) {
3025
                if (preg_match("/^carp/i", $interface))
3026
                        $realif = $interface;
3027
                else if (preg_match("/^vip/i", $interface))
3028
                        $realif = $interface;
3029
                else
3030
                        return null;
3031
        }
3032

    
3033
	$cursn = find_interface_subnet($realif);
3034
	if (!empty($cursn))
3035
		return $cursn;
3036

    
3037
	return null;
3038
}
3039

    
3040
/* return outside interfaces with a gateway */
3041
function get_interfaces_with_gateway() {
3042
	global $config;
3043

    
3044
	$ints = array();
3045

    
3046
	/* loop interfaces, check config for outbound */
3047
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3048
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3049
			return true;
3050

    
3051
		switch ($ifname['ipaddr']) {
3052
			case "dhcp":
3053
			case "carpdev-dhcp":
3054
			case "ppp";
3055
			case "pppoe":
3056
			case "pptp":
3057
			case "l2tp":
3058
			case "ppp";
3059
				$ints[$ifdescr] = $ifdescr;
3060
			break;
3061
			default:
3062
				if (!empty($ifname['gateway']))
3063
					$ints[$ifdescr] = $ifdescr;
3064
			break;
3065
		}
3066
	}
3067
	return $ints;
3068
}
3069

    
3070
/* return true if interface has a gateway */
3071
function interface_has_gateway($friendly) {
3072
	global $config;
3073

    
3074
	if (!empty($config['interfaces'][$friendly])) {
3075
		if (substr($friendly, 0, 5) ==  "ovpnc")
3076
			return true;
3077
		$ifname =& $config['interfaces'][$friendly];
3078
		switch ($ifname['ipaddr']) {
3079
			case "dhcp":
3080
			case "carpdev-dhcp":
3081
			case "pppoe":
3082
			case "pptp":
3083
			case "l2tp":
3084
			case "ppp";
3085
				return true;
3086
			break;
3087
			default:
3088
				if (!empty($ifname['gateway']))
3089
					return true;
3090
			break;
3091
		}
3092
	}
3093

    
3094
	return false;
3095
}
3096

    
3097
/****f* interfaces/is_altq_capable
3098
 * NAME
3099
 *   is_altq_capable - Test if interface is capable of using ALTQ
3100
 * INPUTS
3101
 *   $int            - string containing interface name
3102
 * RESULT
3103
 *   boolean         - true or false
3104
 ******/
3105

    
3106
function is_altq_capable($int) {
3107
        /* Per:
3108
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3109
         * Only the following drivers have ALTQ support
3110
         */
3111
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3112
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3113
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3114
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
3115
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3116
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng", "ppp");
3117

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

    
3120
        if (in_array($int_family[0], $capable))
3121
                return true;
3122
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
3123
		return true;
3124
        else
3125
                return false;
3126
}
3127

    
3128
/****f* interfaces/is_interface_wireless
3129
 * NAME
3130
 *   is_interface_wireless - Returns if an interface is wireless
3131
 * RESULT
3132
 *   $tmp       - Returns if an interface is wireless
3133
 ******/
3134
function is_interface_wireless($interface) {
3135
        global $config, $g;
3136

    
3137
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3138
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3139
                if (preg_match($g['wireless_regex'], $interface)) {
3140
                        if (isset($config['interfaces'][$friendly]))
3141
                                $config['interfaces'][$friendly]['wireless'] = array();
3142
                        return true;
3143
                }
3144
                return false;
3145
        } else
3146
                return true;
3147
}
3148

    
3149
function get_wireless_modes($interface) {
3150
	/* return wireless modes and channels */
3151
	$wireless_modes = array();
3152

    
3153
	$wlif = interface_translate_type_to_real($interface);
3154

    
3155
	if(is_interface_wireless($wlif)) {
3156
		$cloned_interface = get_real_interface($interface);
3157
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3158
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3159
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3160

    
3161
		$interface_channels = "";
3162
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3163
		$interface_channel_count = count($interface_channels);
3164

    
3165
		$c = 0;
3166
		while ($c < $interface_channel_count)
3167
		{
3168
			$channel_line = explode(",", $interface_channels["$c"]);
3169
			$wireless_mode = trim($channel_line[0]);
3170
			$wireless_channel = trim($channel_line[1]);
3171
			if(trim($wireless_mode) != "") {
3172
				/* if we only have 11g also set 11b channels */
3173
				if($wireless_mode == "11g") {
3174
					if(!isset($wireless_modes["11b"]))
3175
						$wireless_modes["11b"] = array();
3176
				} else if($wireless_mode == "11g ht") {
3177
					if(!isset($wireless_modes["11b"]))
3178
						$wireless_modes["11b"] = array();
3179
					if(!isset($wireless_modes["11g"]))
3180
						$wireless_modes["11g"] = array();
3181
					$wireless_mode = "11ng";
3182
				} else if($wireless_mode == "11a ht") {
3183
					if(!isset($wireless_modes["11a"]))
3184
						$wireless_modes["11a"] = array();
3185
					$wireless_mode = "11na";
3186
				}
3187
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3188
			}
3189
			$c++;
3190
		}
3191
	}
3192
	return($wireless_modes);
3193
}
3194

    
3195
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3196
function get_wireless_channel_info($interface) {
3197
	$wireless_channels = array();
3198

    
3199
	$wlif = interface_translate_type_to_real($interface);
3200

    
3201
	if(is_interface_wireless($wlif)) {
3202
		$cloned_interface = get_real_interface($interface);
3203
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3204
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3205
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3206

    
3207
		$interface_channels = "";
3208
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3209

    
3210
		foreach ($interface_channels as $channel_line) {
3211
			$channel_line = explode(",", $channel_line);
3212
			if(!isset($wireless_channels[$channel_line[0]]))
3213
				$wireless_channels[$channel_line[0]] = $channel_line;
3214
		}
3215
	}
3216
	return($wireless_channels);
3217
}
3218

    
3219
/****f* interfaces/get_interface_mtu
3220
 * NAME
3221
 *   get_interface_mtu - Return the mtu of an interface
3222
 * RESULT
3223
 *   $tmp       - Returns the mtu of an interface
3224
 ******/
3225
function get_interface_mtu($interface) {
3226
        $mtu = pfSense_get_interface_addresses($interface);
3227
        return $mtu['mtu'];
3228
}
3229

    
3230
function get_interface_mac($interface) {
3231

    
3232
	$macinfo = pfSense_get_interface_addresses($interface);
3233
	return $macinfo["macaddr"];
3234
}
3235

    
3236
/****f* pfsense-utils/generate_random_mac_address
3237
 * NAME
3238
 *   generate_random_mac - generates a random mac address
3239
 * INPUTS
3240
 *   none
3241
 * RESULT
3242
 *   $mac - a random mac address
3243
 ******/
3244
function generate_random_mac_address() {
3245
        $mac = "02";
3246
        for($x=0; $x<5; $x++)
3247
                $mac .= ":" . dechex(rand(16, 255));
3248
        return $mac;
3249
}
3250

    
3251
/****f* interfaces/is_jumbo_capable
3252
 * NAME
3253
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3254
 * INPUTS
3255
 *   $int             - string containing interface name
3256
 * RESULT
3257
 *   boolean          - true or false
3258
 ******/
3259
function is_jumbo_capable($int) {
3260
        global $g;
3261

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

    
3264
        if (in_array($int_family[0], $g['vlan_long_frame']))
3265
                return true;
3266
        else
3267
                return false;
3268
}
3269

    
3270
function setup_pppoe_reset_file($pppif, $iface="") {
3271
	global $g;
3272
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3273

    
3274
	if(!empty($iface) && !empty($pppif)){
3275
		$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";
3276
		file_put_contents($cron_file, $cron_cmd);
3277
		chmod($cron_file, 0700);
3278
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3279
	} else
3280
		unlink_if_exists($cron_file);
3281
}
3282

    
3283
?>
(22-22/52)