Project

General

Profile

Download (94.3 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
	if (is_array($ports) && count($ports) > 1)
1112
		$multilink = "enable";
1113
	else
1114
		$multilink = "disable";
1115
	
1116
	if ($type == "modem"){
1117
		if (is_ipaddr($ppp['localip']))
1118
			$localip = $ppp['localip'];
1119
		else
1120
			$localip = '0.0.0.0';
1121

    
1122
		if (is_ipaddr($ppp['gateway']))
1123
			$gateway = $ppp['gateway'];
1124
		else
1125
			$gateway = "10.64.64.{$pppid}";
1126
		$ranges = "{$localip}/0 {$gateway}/0";
1127
		
1128
		if (empty($ppp['apnum']))	
1129
			$ppp['apnum'] = 1;
1130
	} else
1131
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1132

    
1133
	if (isset($ppp['ondemand'])) 
1134
		$ondemand = "enable";
1135
	else
1136
		$ondemand = "disable";
1137
	if (!isset($ppp['idletimeout']))
1138
		$ppp['idletimeout'] = 0;
1139

    
1140
	if (empty($ppp['username']) && $type == "modem"){
1141
		$ppp['username'] = "user";
1142
		$ppp['password'] = "none";
1143
	}
1144
	if (empty($ppp['password']) && $type == "modem")
1145
		$passwd = "none";
1146
	else
1147
		$passwd = base64_decode($ppp['password']);
1148

    
1149
	$bandwidths = explode(',',$ppp['bandwidth']);
1150
	$mtus = explode(',',$ppp['mtu']);
1151
	$mrus = explode(',',$ppp['mru']);
1152

    
1153
	if (isset($ppp['mrru']))
1154
		$mrrus = explode(',',$ppp['mrru']);
1155

    
1156
	// Construct the mpd.conf file
1157
	$mpdconf = <<<EOD
1158
startup:
1159
	# configure the console
1160
	set console close
1161
	# configure the web server
1162
	set web close
1163

    
1164
default:
1165
{$ppp['type']}client:
1166
	create bundle static {$interface}
1167
	set iface name {$pppif}
1168

    
1169
EOD;
1170
	$setdefaultgw = false;
1171
	$founddefaultgw = false;
1172
	if (is_array($config['gateways']['gateway_item'])) {
1173
		foreach($config['gateways']['gateway_item'] as $gateway) {
1174
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1175
				$setdefaultgw = true;
1176
				break;
1177
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1178
				$founddefaultgw = true;
1179
				break;
1180
			}
1181
		}
1182
	}
1183
	
1184
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1185
		$setdefaultgw = true;
1186
		$mpdconf .= <<<EOD
1187
	set iface route default
1188

    
1189
EOD;
1190
	}
1191
	$mpdconf .= <<<EOD
1192
	set iface {$ondemand} on-demand
1193
	set iface idle {$ppp['idletimeout']}
1194

    
1195
EOD;
1196

    
1197
	if (isset($ppp['ondemand']))
1198
		$mpdconf .= <<<EOD
1199
	set iface addrs 10.10.1.1 10.10.1.2
1200

    
1201
EOD;
1202
	
1203
	if (isset($ppp['tcpmssfix']))
1204
		$tcpmss = "disable";
1205
	else
1206
		$tcpmss = "enable";
1207
		$mpdconf .= <<<EOD
1208
	set iface {$tcpmss} tcpmssfix
1209

    
1210
EOD;
1211

    
1212
	$mpdconf .= <<<EOD
1213
	set iface up-script /usr/local/sbin/ppp-linkup
1214
	set iface down-script /usr/local/sbin/ppp-linkdown
1215
	set ipcp ranges {$ranges}
1216

    
1217
EOD;
1218
	if (isset($ppp['vjcomp']))
1219
		$mpdconf .= <<<EOD
1220
	set ipcp no vjcomp
1221

    
1222
EOD;
1223

    
1224
	if (isset($config['system']['dnsallowoverride']))
1225
		$mpdconf .= <<<EOD
1226
	set ipcp enable req-pri-dns
1227
	set ipcp enable req-sec-dns
1228

    
1229
EOD;
1230
	if (!isset($ppp['verbose_log']))
1231
		$mpdconf .= <<<EOD
1232
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1233

    
1234
EOD;
1235
	foreach($ports as $pid => $port){
1236
		$port = get_real_interface($port);
1237
		$mpdconf .= <<<EOD
1238

    
1239
	create link static {$interface}_link{$pid} {$type}
1240
	set link action bundle {$interface}
1241
	set link {$multilink} multilink
1242
	set link keep-alive 10 60
1243
	set link max-redial 0
1244

    
1245
EOD;
1246
		if (isset($ppp['shortseq']))
1247
			$mpdconf .= <<<EOD
1248
	set link no shortseq
1249

    
1250
EOD;
1251

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

    
1256
EOD;
1257

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

    
1262
EOD;
1263

    
1264
		$mpdconf .= <<<EOD
1265
	set link disable chap pap
1266
	set link accept chap pap eap
1267
	set link disable incoming
1268

    
1269
EOD;
1270

    
1271

    
1272
		if (!empty($bandwidths[$pid]))
1273
			$mpdconf .= <<<EOD
1274
	set link bandwidth {$bandwidths[$pid]}
1275

    
1276
EOD;
1277

    
1278
		if (empty($mtus[$pid]))
1279
			$mtus[$pid] = "1492";
1280
			$mpdconf .= <<<EOD
1281
	set link mtu {$mtus[$pid]}
1282

    
1283
EOD;
1284

    
1285
		if (!empty($mrus[$pid]))
1286
			$mpdconf .= <<<EOD
1287
	set link mru {$mrus[$pid]}
1288

    
1289
EOD;
1290

    
1291
		if (!empty($mrrus[$pid]))
1292
			$mpdconf .= <<<EOD
1293
	set link mrru {$mrrus[$pid]}
1294

    
1295
EOD;
1296

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

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

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

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

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

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

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

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

    
1350
EOD;
1351

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

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

    
1364

    
1365
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1366
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1367
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1368
	else {
1369
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1370
		if (!$fd) {
1371
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1372
			return 0;
1373
		}
1374
		// Write out mpd_ppp.conf
1375
		fwrite($fd, $mpdconf);
1376
		fclose($fd);
1377
	}
1378

    
1379
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1380
	if (isset($ppp['uptime'])) {
1381
		if (!file_exists("/conf/{$pppif}.log")) {
1382
			conf_mount_rw();
1383
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1384
			conf_mount_ro();
1385
		}
1386
	} else {
1387
		if (file_exists("/conf/{$pppif}.log")) {
1388
			conf_mount_rw();
1389
			mwexec("rm -f /conf/{$pppif}.log");
1390
			conf_mount_ro();
1391
		}
1392
	}
1393
		
1394
	/* fire up mpd */
1395
	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");
1396

    
1397
	// Check for PPPoE periodic reset request 
1398
	if ($type == "pppoe") {
1399
		if (isset($ppp['pppoe-reset-type']))
1400
			setup_pppoe_reset_file($ppp['if'], $interface);
1401
		else
1402
			setup_pppoe_reset_file($ppp['if']);
1403
	}
1404

    
1405
	return 1;
1406
}
1407

    
1408
function interfaces_carp_setup() {
1409
	global $g, $config;
1410

    
1411
	$balanacing = "";
1412
	$pfsyncinterface = "";
1413
	$pfsyncenabled = "";
1414
	if(isset($config['system']['developerspew'])) {
1415
		$mt = microtime();
1416
		echo "interfaces_carp_setup() being called $mt\n";
1417
	}
1418

    
1419
	// Prepare CmdCHAIN that will be used to execute commands.
1420
	$cmdchain = new CmdCHAIN();	
1421

    
1422
	if ($g['booting']) {
1423
		echo "Configuring CARP settings...";
1424
		mute_kernel_msgs();
1425
	}
1426

    
1427
	/* suck in configuration items */
1428
	if($config['installedpackages']['carpsettings']) {
1429
		if($config['installedpackages']['carpsettings']['config']) {
1430
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1431
				$pfsyncenabled = $carp['pfsyncenabled'];
1432
				$balanacing = $carp['balancing'];
1433
				$pfsyncinterface = $carp['pfsyncinterface'];
1434
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1435
			}
1436
		}
1437
	} else {
1438
		unset($pfsyncinterface);
1439
		unset($balanacing);
1440
		unset($pfsyncenabled);
1441
	}
1442

    
1443
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1444
	if($balanacing) {
1445
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1446
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1447
	} else
1448
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1449

    
1450
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1451
	if (!empty($pfsyncinterface))
1452
		$carp_sync_int = get_real_interface($pfsyncinterface);
1453

    
1454
	if($g['booting']) {
1455
		/*    install rules to alllow pfsync to sync up during boot
1456
		 *    carp interfaces will remain down until the bootup sequence finishes
1457
		 */
1458
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1459
		if ($fd) {
1460
			fwrite($fd, "pass quick proto carp all keep state\n");
1461
			fwrite($fd, "pass quick proto pfsync all\n");
1462
			fwrite($fd, "pass out quick from any to any keep state\n");
1463
			fclose($fd);
1464
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1465
		} else
1466
			log_error("Could not create rules.boot file!");
1467
	}
1468

    
1469
	/* setup pfsync interface */
1470
	if($carp_sync_int and $pfsyncenabled) {
1471
		if (is_ipaddr($pfsyncpeerip))
1472
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1473
		else
1474
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1475
	} else
1476
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1477

    
1478
	if($config['virtualip']['vip'])
1479
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1480
	else
1481
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1482
	
1483
	if($g['debug'])
1484
		$cmdchain->setdebug(); // optional for verbose logging
1485

    
1486
	$cmdchain->execute();
1487
	$cmdchain->clear();
1488

    
1489
	if ($g['booting']) {
1490
		unmute_kernel_msgs();
1491
		echo "done.\n";
1492
	}
1493
}
1494

    
1495
function interface_proxyarp_configure($interface = "") {
1496
	global $config, $g;
1497
	if(isset($config['system']['developerspew'])) {
1498
		$mt = microtime();
1499
		echo "interface_proxyarp_configure() being called $mt\n";
1500
	}
1501

    
1502
	/* kill any running choparp */
1503
	if (empty($interface))
1504
		killbyname("choparp");
1505

    
1506
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1507
		$paa = array();
1508

    
1509
		/* group by interface */
1510
		foreach ($config['virtualip']['vip'] as $vipent) {
1511
			if ($vipent['mode'] === "proxyarp") {
1512
				if ($vipent['interface'])
1513
					$proxyif = $vipent['interface'];
1514
				else
1515
					$proxyif = "wan";
1516

    
1517
				if (!is_array($paa[$if]))
1518
					$paa[$proxyif] = array();
1519

    
1520
				$paa[$proxyif][] = $vipent;
1521
			}
1522
		}
1523
	}
1524

    
1525
	if (!empty($interface)) {
1526
		if (is_array($paa[$interface])) {
1527
			$paaifip = get_interface_ip($interface);
1528
                        if (!is_ipaddr($paaifip))
1529
                                return;
1530
                        $args = get_real_interface($interface) . " auto";
1531
                        foreach ($paa[$interface] as $paent) {
1532
                                if (isset($paent['subnet']))
1533
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1534
                                else if (isset($paent['range']))
1535
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1536
                        }
1537
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1538
		}
1539
	} else if (count($paa)) {
1540
		foreach ($paa as $paif => $paents) {
1541
			$paaifip = get_interface_ip($paif);
1542
			if (!(is_ipaddr($paaifip)))
1543
				continue;
1544
			$args = get_real_interface($paif) . " auto";
1545
			foreach ($paents as $paent) {
1546
				if (isset($paent['subnet']))
1547
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1548
				else if (isset($paent['range']))
1549
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1550
			}
1551
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1552
		}
1553
	}
1554
}
1555

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

    
1601
function interface_ipalias_configure(&$vip) {
1602

    
1603
	if ($vip['mode'] == "ipalias") {
1604
		$if = get_real_interface($vip['interface']);
1605
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1606
	}
1607
}
1608

    
1609
function interface_reload_carps($cif) {
1610
	global $config;
1611

    
1612
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1613
	if (empty($carpifs))
1614
		return;
1615

    
1616
	$carps = explode(" ", $carpifs);
1617
	if(is_array($config['virtualip']['vip'])) {
1618
		$viparr = &$config['virtualip']['vip'];
1619
		foreach ($viparr as $vip) {
1620
			if (in_array($vip['carpif'], $carps)) {
1621
				switch ($vip['mode']) {
1622
				case "carp":
1623
					interface_vip_bring_down($vip);
1624
					sleep(1);
1625
					interface_carp_configure($vip);
1626
					break;
1627
				case "carpdev-dhcp":
1628
					interface_vip_bring_down($vip);
1629
					sleep(1);
1630
					interface_carpdev_configure($vip);
1631
					break;
1632
				case "ipalias":
1633
					interface_vip_bring_down($vip);
1634
					sleep(1);
1635
					interface_ipalias_configure($vip);
1636
					break;
1637
				}
1638
			}
1639
		}
1640
	}
1641
}
1642

    
1643
function interface_carp_configure(&$vip) {
1644
	global $config, $g;
1645
	if(isset($config['system']['developerspew'])) {
1646
		$mt = microtime();
1647
		echo "interface_carp_configure() being called $mt\n";
1648
	}
1649

    
1650
	if ($vip['mode'] != "carp")
1651
		return;
1652

    
1653
	$vip_password = $vip['password'];
1654
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1655
	if ($vip['password'] != "")
1656
		$password = " pass {$vip_password}";
1657

    
1658
	// set the vip interface to the vhid
1659
	$vipif = "vip{$vip['vhid']}";
1660

    
1661
	$interface = interface_translate_type_to_real($vip['interface']);
1662
	/*
1663
	 * ensure the interface containing the VIP really exists
1664
 	 * prevents a panic if the interface is missing or invalid
1665
	 */
1666
	$realif = get_real_interface($vip['interface']);
1667
	if (!does_interface_exist($realif)) {
1668
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1669
		return;
1670
	}
1671

    
1672
	/* Ensure CARP IP really exists prior to loading up. */
1673
	$ww_subnet_ip = find_interface_ip($realif);
1674
	$ww_subnet_bits = find_interface_subnet($realif);
1675
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1676
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1677
		return;
1678
	}
1679

    
1680
	/* create the carp interface and setup */
1681
	if (does_interface_exist($vipif)) {
1682
		pfSense_interface_flags($vipif, -IFF_UP);
1683
	} else {
1684
		$carpif = pfSense_interface_create("carp");
1685
		pfSense_interface_rename($carpif, $vipif);
1686
		pfSense_ngctl_name("{$carpif}:", $vipif);
1687
	}
1688

    
1689
	/* invalidate interface cache */
1690
	get_interface_arr(true);
1691

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

    
1695
	interfaces_bring_up($vipif);
1696
	
1697
	return $vipif;
1698
}
1699

    
1700
function interface_carpdev_configure(&$vip) {
1701
	global $g;
1702

    
1703
	if ($vip['mode'] != "carpdev-dhcp")
1704
		return;
1705

    
1706
	$vip_password = $vip['password'];
1707
	$vip_password = str_replace(" ", "", $vip_password);
1708
	if($vip['password'] != "")
1709
		$password = " pass \"" . $vip_password . "\"";
1710

    
1711
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1712
	if (empty($vip['interface']))
1713
		return;
1714

    
1715
	$vipif = "vip" . $vip['vhid'];
1716
	$realif = interface_translate_type_to_real($vip['interface']);
1717
	interfaces_bring_up($realif);
1718
	/*
1719
	 * ensure the interface containing the VIP really exists
1720
	 * prevents a panic if the interface is missing or invalid
1721
	 */
1722
	if (!does_interface_exist($realif)) {
1723
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1724
		return;
1725
	}
1726

    
1727
	if (does_interface_exist($vipif)) {
1728
		interface_bring_down($vipif);
1729
	} else {
1730
		$carpdevif = exec("/sbin/ifconfig carp create");
1731
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1732
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1733
	}
1734

    
1735
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1736
	interfaces_bring_up($vipif);
1737

    
1738
	/*
1739
	 * XXX: BIG HACK but carpdev needs ip services active
1740
	 *      before even starting something as dhclient.
1741
	 *      I do not know if this is a feature or a bug
1742
	 *      but better than track it make it work ;) .
1743
	 */
1744
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1745
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1746

    
1747
	/* generate dhclient_wan.conf */
1748
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1749
	if ($fd) {
1750
		$dhclientconf = "";
1751

    
1752
		$dhclientconf .= <<<EOD
1753
interface "{$vipif}" {
1754
timeout 60;
1755
retry 1;
1756
select-timeout 0;
1757
initial-interval 1;
1758
script "/sbin/dhclient-script";
1759
}
1760

    
1761
EOD;
1762

    
1763
		fwrite($fd, $dhclientconf);
1764
		fclose($fd);
1765

    
1766
		/* fire up dhclient */
1767
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1768
	} else {
1769
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1770
		mwexec("/sbin/dhclient -b {$vipif}");
1771
	}
1772

    
1773
	return $vipif;
1774
}
1775

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

    
1817
	if($needs_clone == true) {
1818
		/* remove previous instance if it exists */
1819
		if(does_interface_exist($realif))
1820
			pfSense_interface_destroy($realif);
1821

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

    
1839
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1840
	global $config, $g;
1841

    
1842
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1843
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1844
	                         'regdomain', 'regcountry', 'reglocation');
1845

    
1846
	if(!is_interface_wireless($ifcfg['if']))
1847
		return;
1848

    
1849
	$baseif = interface_get_wireless_base($ifcfg['if']);
1850

    
1851
	// Sync shared settings for assigned clones
1852
	$iflist = get_configured_interface_list(false, true);
1853
	foreach ($iflist as $if) {
1854
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1855
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1856
				foreach ($shared_settings as $setting) {
1857
					if ($sync_changes) {
1858
						if (isset($ifcfg['wireless'][$setting]))
1859
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1860
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1861
							unset($config['interfaces'][$if]['wireless'][$setting]);
1862
					} else {
1863
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1864
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1865
						else if (isset($ifcfg['wireless'][$setting]))
1866
							unset($ifcfg['wireless'][$setting]);
1867
					}
1868
				}
1869
				if (!$sync_changes)
1870
					break;
1871
			}
1872
		}
1873
	}
1874

    
1875
	// Read or write settings at shared area
1876
	if (isset($config['wireless']['interfaces'][$baseif])) {
1877
		foreach ($shared_settings as $setting) {
1878
			if ($sync_changes) {
1879
				if (isset($ifcfg['wireless'][$setting]))
1880
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
1881
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1882
					unset($config['wireless']['interfaces'][$baseif][$setting]);
1883
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
1884
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1885
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
1886
				else if (isset($ifcfg['wireless'][$setting]))
1887
					unset($ifcfg['wireless'][$setting]);
1888
			}
1889
		}
1890
	}
1891

    
1892
	// Sync the mode on the clone creation page with the configured mode on the interface
1893
	if (interface_is_wireless_clone($ifcfg['if'])) {
1894
		foreach ($config['wireless']['clone'] as &$clone) {
1895
			if ($clone['cloneif'] == $ifcfg['if']) {
1896
				if ($sync_changes) {
1897
					$clone['mode'] = $ifcfg['wireless']['mode'];
1898
				} else {
1899
					$ifcfg['wireless']['mode'] = $clone['mode'];
1900
				}
1901
				break;
1902
			}
1903
		}
1904
		unset($clone);
1905
	}
1906
}
1907

    
1908
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1909
	global $config, $g;
1910

    
1911
	/*    open up a shell script that will be used to output the commands.
1912
	 *    since wireless is changing a lot, these series of commands are fragile
1913
     *    and will sometimes need to be verified by a operator by executing the command
1914
     *    and returning the output of the command to the developers for inspection.  please
1915
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1916
	 */
1917

    
1918
	// Remove script file
1919
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1920

    
1921
	// Clone wireless nic if needed.
1922
	interface_wireless_clone($if, $wl);
1923

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

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

    
1931
	/* set values for /path/program */
1932
	$hostapd = "/usr/sbin/hostapd";
1933
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1934
	$ifconfig = "/sbin/ifconfig";
1935
	$sysctl = "/sbin/sysctl";
1936
	$killall = "/usr/bin/killall";
1937

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

    
1940
	$wlcmd = array();
1941
	$wl_sysctl = array();
1942
	/* Make sure it's up */
1943
	$wlcmd[] = "up";
1944
	/* Set a/b/g standard */
1945
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
1946
	$wlcmd[] = "mode " . escapeshellarg($standard);
1947

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

    
1953
	/* Set ssid */
1954
	if($wlcfg['ssid'])
1955
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1956

    
1957
	/* Set 802.11g protection mode */
1958
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1959

    
1960
	/* set wireless channel value */
1961
	if(isset($wlcfg['channel'])) {
1962
		if($wlcfg['channel'] == "0") {
1963
			$wlcmd[] = "channel any";
1964
		} else {
1965
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1966
		}
1967
	}
1968

    
1969
	/* Set antenna diversity value */
1970
	if(isset($wlcfg['diversity']))
1971
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
1972

    
1973
	/* Set txantenna value */
1974
	if(isset($wlcfg['txantenna']))
1975
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
1976

    
1977
	/* Set rxantenna value */
1978
	if(isset($wlcfg['rxantenna']))
1979
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
1980

    
1981
	/* set Distance value */
1982
	if($wlcfg['distance'])
1983
		$distance = escapeshellarg($wlcfg['distance']);
1984

    
1985
	/* Set wireless hostap mode */
1986
	if ($wlcfg['mode'] == "hostap") {
1987
		$wlcmd[] = "mediaopt hostap";
1988
	} else {
1989
		$wlcmd[] = "-mediaopt hostap";
1990
	}
1991

    
1992
	/* Set wireless adhoc mode */
1993
	if ($wlcfg['mode'] == "adhoc") {
1994
		$wlcmd[] = "mediaopt adhoc";
1995
	} else {
1996
		$wlcmd[] = "-mediaopt adhoc";
1997
	}
1998

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

    
2001
	/* handle hide ssid option */
2002
	if(isset($wlcfg['hidessid']['enable'])) {
2003
		$wlcmd[] = "hidessid";
2004
	} else {
2005
		$wlcmd[] = "-hidessid";
2006
	}
2007

    
2008
	/* handle pureg (802.11g) only option */
2009
	if(isset($wlcfg['pureg']['enable'])) {
2010
		$wlcmd[] = "mode 11g pureg";
2011
	} else {
2012
		$wlcmd[] = "-pureg";
2013
	}
2014

    
2015
	/* handle puren (802.11n) only option */
2016
	if(isset($wlcfg['puren']['enable'])) {
2017
		$wlcmd[] = "puren";
2018
	} else {
2019
		$wlcmd[] = "-puren";
2020
	}
2021

    
2022
	/* enable apbridge option */
2023
	if(isset($wlcfg['apbridge']['enable'])) {
2024
		$wlcmd[] = "apbridge";
2025
	} else {
2026
		$wlcmd[] = "-apbridge";
2027
	}
2028

    
2029
	/* handle turbo option */
2030
	if(isset($wlcfg['turbo']['enable'])) {
2031
		$wlcmd[] = "mediaopt turbo";
2032
	} else {
2033
		$wlcmd[] = "-mediaopt turbo";
2034
	}
2035

    
2036
	/* handle txpower setting */
2037
	/* if($wlcfg['txpower'] <> "")
2038
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2039
	*/
2040
	/* handle wme option */
2041
	if(isset($wlcfg['wme']['enable'])) {
2042
		$wlcmd[] = "wme";
2043
	} else {
2044
		$wlcmd[] = "-wme";
2045
	}
2046

    
2047
	/* set up wep if enabled */
2048
	$wepset = "";
2049
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2050
		switch($wlcfg['wpa']['auth_algs']) {
2051
			case "1":
2052
				$wepset .= "authmode open wepmode on ";
2053
				break;
2054
			case "2":
2055
				$wepset .= "authmode shared wepmode on ";
2056
				break;
2057
			case "3":
2058
				$wepset .= "authmode mixed wepmode on ";
2059
		}
2060
		$i = 1;
2061
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2062
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2063
			if (isset($wepkey['txkey'])) {
2064
				$wlcmd[] = "weptxkey {$i} ";
2065
			}
2066
			$i++;
2067
		}
2068
		$wlcmd[] = $wepset;
2069
	} else {
2070
		$wlcmd[] = "authmode open wepmode off ";
2071
	}
2072

    
2073
	mwexec(kill_hostapd("{$if}"));
2074
	mwexec(kill_wpasupplicant("{$if}"));
2075

    
2076
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2077
	conf_mount_rw();
2078

    
2079
	switch ($wlcfg['mode']) {
2080
		case 'bss':
2081
			if (isset($wlcfg['wpa']['enable'])) {
2082
				$wpa .= <<<EOD
2083
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2084
ctrl_interface_group=0
2085
ap_scan=1
2086
#fast_reauth=1
2087
network={
2088
ssid="{$wlcfg['ssid']}"
2089
scan_ssid=1
2090
priority=5
2091
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2092
psk="{$wlcfg['wpa']['passphrase']}"
2093
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2094
group={$wlcfg['wpa']['wpa_pairwise']}
2095
}
2096
EOD;
2097

    
2098
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2099
				fwrite($fd, "{$wpa}");
2100
				fclose($fd);
2101
			}
2102
			break;
2103
		case 'hostap':
2104
			if($wlcfg['wpa']['passphrase']) 
2105
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2106
			else 
2107
				$wpa_passphrase = "";
2108
			if (isset($wlcfg['wpa']['enable'])) {
2109
				$wpa .= <<<EOD
2110
interface={$if}
2111
driver=bsd
2112
logger_syslog=-1
2113
logger_syslog_level=0
2114
logger_stdout=-1
2115
logger_stdout_level=0
2116
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2117
ctrl_interface={$g['varrun_path']}/hostapd
2118
ctrl_interface_group=wheel
2119
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2120
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2121
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2122
ssid={$wlcfg['ssid']}
2123
debug={$wlcfg['wpa']['debug_mode']}
2124
auth_algs={$wlcfg['wpa']['auth_algs']}
2125
wpa={$wlcfg['wpa']['wpa_mode']}
2126
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2127
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2128
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2129
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2130
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2131
{$wpa_passphrase}
2132

    
2133
EOD;
2134

    
2135
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2136
	$wpa .= <<<EOD
2137
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2138
rsn_preauth=1
2139
rsn_preauth_interfaces={$if}
2140

    
2141
EOD;
2142

    
2143
}
2144
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2145
					$auth_server_port = "1812";
2146
					if($wlcfg['auth_server_port']) 
2147
						$auth_server_port = $wlcfg['auth_server_port'];
2148
					$wpa .= <<<EOD
2149

    
2150
ieee8021x=1
2151
auth_server_addr={$wlcfg['auth_server_addr']}
2152
auth_server_port={$auth_server_port}
2153
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2154

    
2155
EOD;
2156
				} else {
2157
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2158
				}
2159

    
2160
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2161
				fwrite($fd, "{$wpa}");
2162
				fclose($fd);
2163

    
2164
			}
2165
			break;
2166
	}
2167

    
2168
	/*
2169
	 *    all variables are set, lets start up everything
2170
	 */
2171

    
2172
	$baseif = interface_get_wireless_base($if);
2173
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2174
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2175

    
2176
	/* set sysctls for the wireless interface */
2177
	if (!empty($wl_sysctl)) {
2178
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2179
		foreach ($wl_sysctl as $wl_sysctl_line) {
2180
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2181
		}
2182
	}
2183

    
2184
	/* set ack timers according to users preference (if he/she has any) */
2185
	if($distance) {
2186
		fwrite($fd_set, "# Enable ATH distance settings\n");
2187
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2188
	}
2189

    
2190
	if (isset($wlcfg['wpa']['enable'])) {
2191
		if ($wlcfg['mode'] == "bss") {
2192
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2193
		}
2194
		if ($wlcfg['mode'] == "hostap") {
2195
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2196
		}
2197
	}
2198

    
2199
	fclose($fd_set);
2200
	conf_mount_ro();
2201

    
2202
	/* Making sure regulatory settings have actually changed
2203
	 * before applying, because changing them requires bringing
2204
	 * down all wireless networks on the interface. */
2205
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2206
	$ifconfig_str = implode($output);
2207
	unset($output);
2208
	$reg_changing = false;
2209

    
2210
	/* special case for the debug country code */
2211
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2212
		$reg_changing = true;
2213
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2214
		$reg_changing = true;
2215
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2216
		$reg_changing = true;
2217
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2218
		$reg_changing = true;
2219
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2220
		$reg_changing = true;
2221

    
2222
	if ($reg_changing) {
2223
		/* set regulatory domain */
2224
		if($wlcfg['regdomain'])
2225
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2226

    
2227
		/* set country */
2228
		if($wlcfg['regcountry'])
2229
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2230

    
2231
		/* set location */
2232
		if($wlcfg['reglocation'])
2233
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2234

    
2235
		$wlregcmd_args = implode(" ", $wlregcmd);
2236

    
2237
		/* build a complete list of the wireless clones for this interface */
2238
		$clone_list = array();
2239
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2240
			$clone_list[] = interface_get_wireless_clone($baseif);
2241
		if (is_array($config['wireless']['clone'])) {
2242
			foreach ($config['wireless']['clone'] as $clone) {
2243
				if ($clone['if'] == $baseif)
2244
					$clone_list[] = $clone['cloneif'];
2245
			}
2246
		}
2247

    
2248
		/* find which clones are up and bring them down */
2249
		$clones_up = array();
2250
		foreach ($clone_list as $clone_if) {
2251
			$clone_status = pfSense_get_interface_addresses($clone_if);
2252
			if ($clone_status['status'] == 'up') {
2253
				$clones_up[] = $clone_if;
2254
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2255
			}
2256
		}
2257

    
2258
		/* apply the regulatory settings */
2259
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2260

    
2261
		/* bring the clones back up that were previously up */
2262
		foreach ($clones_up as $clone_if) {
2263
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2264
		}
2265
	}
2266

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

    
2271
	/* configure wireless */
2272
	$wlcmd_args = implode(" ", $wlcmd);
2273
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2274

    
2275
	
2276
	sleep(1);
2277
	/* execute hostapd and wpa_supplicant if required in shell */
2278
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2279

    
2280
	return 0;
2281

    
2282
}
2283

    
2284
function kill_hostapd($interface) {
2285
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2286
}
2287

    
2288
function kill_wpasupplicant($interface) {
2289
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2290
}
2291

    
2292
function find_dhclient_process($interface) {
2293
	if($interface) {
2294
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2295
	}
2296
	return $pid;
2297
}
2298

    
2299
function interface_configure($interface = "wan", $reloadall = false) {
2300
	global $config, $g;
2301
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2302

    
2303
	$wancfg = $config['interfaces'][$interface];
2304

    
2305
	$realif = get_real_interface($interface);
2306

    
2307
	if (!$g['booting']) {
2308
		/* remove all IPv4 addresses */
2309
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2310
			interface_bring_down($interface);
2311
	}
2312

    
2313
	/* wireless configuration? */
2314
	if (is_array($wancfg['wireless']))
2315
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2316

    
2317
	if ($wancfg['spoofmac']) {
2318
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2319
			" link " . escapeshellarg($wancfg['spoofmac']));
2320

    
2321
                /*
2322
                 * All vlans need to spoof their parent mac address, too.  see
2323
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2324
                 */
2325
                if (is_array($config['vlans']['vlan'])) {
2326
                        foreach ($config['vlans']['vlan'] as $vlan) {
2327
                                if ($vlan['if'] == $realif)
2328
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2329
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2330
                        }
2331
                }
2332
	}  else {
2333
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2334
		if($mac == "ff:ff:ff:ff:ff:ff") {
2335
			/*   this is not a valid mac address.  generate a
2336
			 *   temporary mac address so the machine can get online.
2337
			 */
2338
			echo "Generating new MAC address.";
2339
			$random_mac = generate_random_mac_address();
2340
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2341
				" link " . escapeshellarg($random_mac));
2342
			$wancfg['spoofmac'] = $random_mac;
2343
			write_config();
2344
			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");
2345
		}
2346
	}
2347

    
2348
	/* media */
2349
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2350
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2351
		if ($wancfg['media'])
2352
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2353
		if ($wancfg['mediaopt'])
2354
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2355
		mwexec($cmd);
2356
	}
2357
	if (!empty($wancfg['mtu']))
2358
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2359

    
2360
	/* invalidate interface/ip/sn cache */
2361
	get_interface_arr(true);
2362
	unset($interface_ip_arr_cache[$realif]);
2363
	unset($interface_sn_arr_cache[$realif]);
2364

    
2365
	switch ($wancfg['ipaddr']) {
2366
		case 'carpdev-dhcp':
2367
			interface_carpdev_dhcp_configure($interface);
2368
			break;
2369
		case 'dhcp':
2370
			interface_dhcp_configure($interface);
2371
			break;
2372
		case 'pppoe':
2373
		case 'l2tp':
2374
		case 'pptp':
2375
		case 'ppp':
2376
			interface_ppps_configure($interface);
2377
			break;
2378
		default:
2379
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2380
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2381
			} else if (substr($realif, 0, 3) == "gre") {
2382
				if (is_array($config['gres']['gre'])) {
2383
					foreach ($config['gres']['gre'] as $gre)
2384
						if ($gre['greif'] == $realif)
2385
							interface_gre_configure($gre);
2386
				}
2387
			} else if (substr($realif, 0, 3) == "gif") {
2388
				 if (is_array($config['gifs']['gif'])) {
2389
					foreach ($config['gifs']['gif'] as $gif)
2390
						if($gif['gifif'] == $interface)
2391
							interface_gif_configure($gif);
2392
				}
2393
			} else if (substr($realif, 0, 4) == "ovpn") {
2394
				/* XXX: Should be done anything?! */
2395
			}
2396

    
2397
			if (is_ipaddr($wancfg['gateway']))
2398
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2399
			break;
2400
	}
2401

    
2402
	if(does_interface_exist($wancfg['if']))
2403
		interfaces_bring_up($wancfg['if']);
2404
 	
2405
	if (!$g['booting'])
2406
		interface_reload_carps($realif);
2407
	
2408
	if (!$g['booting']) {
2409
		unset($gre);
2410
		$gre = link_interface_to_gre($interface);
2411
		if (!empty($gre))
2412
			interface_gre_configure($gre);
2413

    
2414
		unset($gif);
2415
		$gif = link_interface_to_gif($interface);
2416
		if (!empty($gif))
2417
                       	interface_gif_configure($gif);
2418

    
2419
		unset($bridgetmp);
2420
		$bridgetmp = link_interface_to_bridge($interface);
2421
		if (!empty($bridgetmp))
2422
			interface_bridge_add_member($bridgetmp, $realif);
2423

    
2424
		link_interface_to_vips($interface, "update");
2425

    
2426
		if ($interface == "lan")
2427
			/* make new hosts file */
2428
			system_hosts_generate();
2429

    
2430
		if ($reloadall == true) {
2431

    
2432
			/* reconfigure static routes (kernel may have deleted them) */
2433
			system_routing_configure($interface);
2434

    
2435
			/* reload ipsec tunnels */
2436
			vpn_ipsec_configure();
2437

    
2438
			/* update dyndns */
2439
			services_dyndns_configure($interface);
2440

    
2441
			/* force DNS update */
2442
			services_dnsupdate_process($interface);
2443

    
2444
			/* restart dnsmasq */
2445
			services_dnsmasq_configure();
2446

    
2447
			/* reload captive portal */
2448
			captiveportal_init_rules();
2449

    
2450
			/* set the reload filter dity flag */
2451
			filter_configure();
2452
		}
2453
	}
2454

    
2455
	return 0;
2456
}
2457

    
2458
function interface_carpdev_dhcp_configure($interface = "wan") {
2459
	global $config, $g;
2460

    
2461
	$wancfg = $config['interfaces'][$interface];
2462
	$wanif = $wancfg['if'];
2463
	/* bring wan interface up before starting dhclient */
2464
	if($wanif)
2465
		interfaces_bring_up($wanif);
2466
	else 
2467
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2468

    
2469
	return 0;
2470
}
2471

    
2472
function interface_dhcp_configure($interface = "wan") {
2473
	global $config, $g;
2474

    
2475
	$wancfg = $config['interfaces'][$interface];
2476
	if (empty($wancfg))
2477
		$wancfg = array();
2478

    
2479
	/* generate dhclient_wan.conf */
2480
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2481
	if (!$fd) {
2482
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2483
		return 1;
2484
	}
2485

    
2486
	if ($wancfg['dhcphostname']) {
2487
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2488
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2489
	} else {
2490
		$dhclientconf_hostname = "";
2491
	}
2492

    
2493
	$wanif = get_real_interface($interface);
2494
	if (empty($wanif)) {
2495
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2496
		return 0;
2497
	}
2498
 	$dhclientconf = "";
2499
	
2500
	$dhclientconf .= <<<EOD
2501
interface "{$wanif}" {
2502
timeout 60;
2503
retry 1;
2504
select-timeout 0;
2505
initial-interval 1;
2506
	{$dhclientconf_hostname}
2507
	script "/sbin/dhclient-script";
2508
}
2509

    
2510
EOD;
2511

    
2512
if(is_ipaddr($wancfg['alias-address'])) {
2513
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2514
	$dhclientconf .= <<<EOD
2515
alias {
2516
	interface  "{$wanif}";
2517
	fixed-address {$wancfg['alias-address']};
2518
	option subnet-mask {$subnetmask};
2519
}
2520

    
2521
EOD;
2522
}
2523
	fwrite($fd, $dhclientconf);
2524
	fclose($fd);
2525

    
2526
	/* bring wan interface up before starting dhclient */
2527
	if($wanif)
2528
		interfaces_bring_up($wanif);
2529
	else 
2530
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2531

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

    
2535
	return 0;
2536
}
2537

    
2538
function interfaces_group_setup() {
2539
	global $config;
2540

    
2541
	if (!is_array($config['ifgroups']['ifgroupentry']))
2542
		return;
2543

    
2544
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2545
		interface_group_setup($groupar);
2546

    
2547
	return;
2548
}
2549

    
2550
function interface_group_setup(&$groupname /* The parameter is an array */) {
2551
	global $config;
2552

    
2553
	if (!is_array($groupname))
2554
		return;
2555
	$members = explode(" ", $groupname['members']);
2556
	foreach($members as $ifs) {
2557
		$realif = get_real_interface($ifs);
2558
		if ($realif)
2559
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2560
	}
2561

    
2562
	return;
2563
}
2564
 
2565
/* COMPAT Function */
2566
function convert_friendly_interface_to_real_interface_name($interface) {
2567
	return get_real_interface($interface);
2568
}
2569

    
2570
/* COMPAT Function */
2571
function get_real_wan_interface($interface = "wan") {
2572
	return get_real_interface($interface);
2573
}
2574

    
2575
/* COMPAT Function */
2576
function get_current_wan_address($interface = "wan") {
2577
	return get_interface_ip($interface);
2578
}
2579

    
2580
/*
2581
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2582
 */
2583
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2584
        global $config;
2585

    
2586
	if (stristr($interface, "vip")) {
2587
                $index = intval(substr($interface, 3));
2588
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2589
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2590
                                if ($index == $counter)
2591
                                        return $vip['interface'];
2592
                        }
2593
                }
2594
        }
2595

    
2596
        /* XXX: For speed reasons reference directly the interface array */
2597
	$ifdescrs =& $config['interfaces'];
2598
        //$ifdescrs = get_configured_interface_list(false, true);
2599

    
2600
        foreach ($ifdescrs as $if => $ifname) {
2601
                if ($config['interfaces'][$if]['if'] == $interface)
2602
                        return $if;
2603

    
2604
                if (get_real_interface($if) == $interface)
2605
                        return $if;
2606

    
2607
                $int = interface_translate_type_to_real($if);
2608
                if ($int == $interface)
2609
                        return $ifname;
2610
        }
2611
        return NULL;
2612
}
2613

    
2614
/* attempt to resolve interface to friendly descr */
2615
function convert_friendly_interface_to_friendly_descr($interface) {
2616
        global $config;
2617

    
2618
        switch ($interface) {
2619
                case "l2tp":
2620
                                $ifdesc = "L2TP";
2621
                                break;
2622
                case "pptp":
2623
                                $ifdesc = "PPTP";
2624
                                break;
2625
                case "pppoe":
2626
                                $ifdesc = "PPPoE";
2627
                                break;
2628
                case "openvpn":
2629
                                $ifdesc = "OpenVPN";
2630
                                break;
2631
                case "enc0":
2632
                        case "ipsec":
2633
                                $ifdesc = "IPsec";
2634
                                break;
2635
        default:
2636
                if (isset($config['interfaces'][$interface])) {
2637
                        if (empty($config['interfaces'][$interface]['descr']))
2638
                                $ifdesc = strtoupper($interface);
2639
                        else
2640
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2641
			break;
2642
		}
2643
                /* if list */
2644
                $ifdescrs = get_configured_interface_with_descr(false, true);
2645
                foreach ($ifdescrs as $if => $ifname) {
2646
                                if ($if == $interface || $ifname == $interface)
2647
                                        return $ifname;
2648
                }
2649
                break;
2650
        }
2651

    
2652
        return $ifdesc;
2653
}
2654

    
2655
function convert_real_interface_to_friendly_descr($interface) {
2656
        global $config;
2657

    
2658
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2659

    
2660
        if ($ifdesc) {
2661
                $iflist = get_configured_interface_with_descr(false, true);
2662
                return $iflist[$ifdesc];
2663
        }
2664

    
2665
        return $interface;
2666
}
2667

    
2668
/*
2669
 *  interface_translate_type_to_real($interface):
2670
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2671
 */
2672
function interface_translate_type_to_real($interface) {
2673
        global $config;
2674

    
2675
        if ($config['interfaces'][$interface]['if'] <> "")
2676
                return $config['interfaces'][$interface]['if'];
2677
        else
2678
		return $interface;
2679
}
2680

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

    
2689
function interface_get_wireless_base($wlif) {
2690
	if(!stristr($wlif, "_wlan")) {
2691
		return $wlif;
2692
	} else {
2693
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2694
	}
2695
}
2696

    
2697
function interface_get_wireless_clone($wlif) {
2698
	if(!stristr($wlif, "_wlan")) {
2699
		return $wlif . "_wlan0";
2700
	} else {
2701
		return $wlif;
2702
	}
2703
}
2704

    
2705
function get_real_interface($interface = "wan") {
2706
    global $config;
2707

    
2708
	$wanif = NULL;
2709

    
2710
	switch ($interface) {
2711
	case "l2tp":
2712
		$wanif = "l2tp";
2713
		break;
2714
	case "pptp":
2715
		$wanif = "pptp";
2716
		break;
2717
	case "pppoe":
2718
		$wanif = "pppoe";
2719
		break;
2720
	case "openvpn":
2721
		$wanif = "openvpn";
2722
		break;
2723
	case "ipsec":
2724
	case "enc0":
2725
		$wanif = "enc0";
2726
		break;
2727
	case "ppp":
2728
		$wanif = "ppp";
2729
		break;
2730
	default:
2731
		// If a real interface was alread passed simply
2732
		// pass the real interface back.  This encourages
2733
		// the usage of this function in more cases so that
2734
		// we can combine logic for more flexibility.
2735
		if(does_interface_exist($interface)) {
2736
			$wanif = $interface;
2737
			break;
2738
		}
2739
		if (empty($config['interfaces'][$interface]))
2740
			break;
2741

    
2742
		$cfg =& $config['interfaces'][$interface];
2743

    
2744
		// Wireless cloned NIC support (FreeBSD 8+)
2745
		// interface name format: $parentnic_wlanparentnic#
2746
		// example: ath0_wlan0
2747
		if (is_interface_wireless($cfg['if'])) {
2748
			$wanif = interface_get_wireless_clone($cfg['if']);
2749
			break;
2750
		}
2751
		/*
2752
		if (empty($cfg['if'])) {
2753
			$wancfg = $cfg['if'];
2754
			break;
2755
		}
2756
		*/
2757

    
2758
		switch ($cfg['ipaddr']) {
2759
			case "carpdev-dhcp":
2760
				$viparr = &$config['virtualip']['vip'];
2761
				if(is_array($viparr))
2762
				foreach ($viparr as $counter => $vip) {
2763
					if ($vip['mode'] == "carpdev-dhcp") {
2764
						if($vip['interface'] == $interface) {
2765
							$wanif = "carp{$counter}";
2766
							break;
2767
						}
2768
					}
2769
				}
2770
				break;
2771
			case "pppoe": 
2772
			case "pptp": 
2773
			case "l2tp": 
2774
			case "ppp":
2775
				$wanif = $cfg['if'];
2776
				break;
2777
			default:
2778
				$wanif = $cfg['if'];
2779
				break;
2780
		}
2781
		break;
2782
	}
2783

    
2784
    return $wanif;
2785
}
2786

    
2787
/* Guess the physical interface by providing a IP address */
2788
function guess_interface_from_ip($ipaddress) {
2789
	if(! is_ipaddr($ipaddress)) {
2790
		return false;
2791
	}
2792
	/* create a route table we can search */
2793
	exec("netstat -rnW", $output, $ret);
2794
	foreach($output as $line) {
2795
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2796
			$fields = preg_split("/[ ]+/", $line);
2797
			if(ip_in_subnet($ipaddress, $fields[0])) {
2798
				return $fields[6];
2799
			}
2800
		}
2801
	}
2802
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2803
	if(empty($ret)) {
2804
        	return false;
2805
	}
2806
	return $ret;
2807
}
2808

    
2809
/*
2810
 * find_ip_interface($ip): return the interface where an ip is defined
2811
 */
2812
function find_ip_interface($ip)
2813
{
2814
        /* if list */
2815
        $ifdescrs = get_configured_interface_list();
2816

    
2817
        foreach ($ifdescrs as $ifdescr => $ifname) {
2818
		if ($ip == get_interface_ip($ifname)) {
2819
                	$int = get_real_interface($ifname);
2820
			return $int;
2821
		}
2822
        }
2823
        return false;
2824
}
2825

    
2826
/*
2827
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2828
 */
2829
function find_number_of_created_carp_interfaces() {
2830
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2831
}
2832

    
2833
function get_all_carp_interfaces() {
2834
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2835
	$ints = explode(" ", $ints);
2836
	return $ints;
2837
}
2838

    
2839
/*
2840
 * find_carp_interface($ip): return the carp interface where an ip is defined
2841
 */
2842
function find_carp_interface($ip) {
2843
	global $config;
2844
	if (is_array($config['virtualip']['vip'])) {
2845
		foreach ($config['virtualip']['vip'] as $vip) {
2846
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2847
				$carp_ip = get_interface_ip($vip['interface']);
2848
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2849
				if ($if)
2850
					return $if;
2851
			}
2852
		}
2853
	}
2854
}
2855

    
2856
function link_carp_interface_to_parent($interface) {
2857
        global $config;
2858

    
2859
        if ($interface == "")
2860
                return;
2861

    
2862
        $carp_ip = get_interface_ip($interface);
2863
        if (!is_ipaddr($carp_ip))
2864
                return;
2865

    
2866
        /* if list */
2867
        $ifdescrs = get_configured_interface_list();
2868
        foreach ($ifdescrs as $ifdescr => $ifname) {
2869
                $interfaceip = get_interface_ip($ifname);
2870
                $subnet_bits = get_interface_subnet($ifname);
2871
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2872
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2873
                        return $ifname;
2874
        }
2875

    
2876
        return "";
2877
}
2878

    
2879
/****f* interfaces/link_ip_to_carp_interface
2880
 * NAME
2881
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2882
 * INPUTS
2883
 *   $ip
2884
 * RESULT
2885
 *   $carp_ints
2886
 ******/
2887
function link_ip_to_carp_interface($ip) {
2888
        global $config;
2889

    
2890
        if (!is_ipaddr($ip))
2891
                return;
2892

    
2893
        $carp_ints = "";
2894
        if (is_array($config['virtualip']['vip'])) {
2895
		$first = 0;
2896
		$carp_int = array();
2897
                foreach ($config['virtualip']['vip'] as $vip) {
2898
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2899
                                $carp_ip = $vip['subnet'];
2900
                                $carp_sn = $vip['subnet_bits'];
2901
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2902
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
2903
					$carp_int[] = "vip{$vip['vhid']}";
2904
                        }
2905
                }
2906
		if (!empty($carp_int))
2907
			$carp_ints = implode(" ", array_unique($carp_int));
2908
        }
2909

    
2910
        return $carp_ints;
2911
}
2912

    
2913
function link_interface_to_vlans($int, $action = "") {
2914
	global $config;
2915

    
2916
	if (empty($int))
2917
		return;
2918

    
2919
	if (is_array($config['vlans']['vlan'])) {
2920
                foreach ($config['vlans']['vlan'] as $vlan) {
2921
			if ($int == $vlan['if']) {
2922
				if ($action == "update") {
2923
					interfaces_bring_up($int);
2924
				} else if ($action == "")
2925
					return $vlan;
2926
			}
2927
		}
2928
	}
2929
}
2930

    
2931
function link_interface_to_vips($int, $action = "") {
2932
        global $config;
2933

    
2934
        if (is_array($config['virtualip']['vip']))
2935
                foreach ($config['virtualip']['vip'] as $vip)
2936
                        if ($int == $vip['interface']) {
2937
				if ($action == "update")
2938
					interfaces_vips_configure($int);
2939
				else
2940
                                	return $vip;
2941
			}
2942
}
2943

    
2944
/****f* interfaces/link_interface_to_bridge
2945
 * NAME
2946
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2947
 * INPUTS
2948
 *   $ip
2949
 * RESULT
2950
 *   bridge[0-99]
2951
 ******/
2952
function link_interface_to_bridge($int) {
2953
        global $config;
2954

    
2955
        if (is_array($config['bridges']['bridged'])) {
2956
                foreach ($config['bridges']['bridged'] as $bridge) {
2957
			if (in_array($int, explode(',', $bridge['members'])))
2958
                                return "{$bridge['bridgeif']}";
2959
		}
2960
	}
2961
}
2962

    
2963
function link_interface_to_gre($interface) {
2964
        global $config;
2965

    
2966
        if (is_array($config['gres']['gre']))
2967
                foreach ($config['gres']['gre'] as $gre)
2968
                        if($gre['if'] == $interface)
2969
                                return $gre;
2970
}
2971

    
2972
function link_interface_to_gif($interface) {
2973
        global $config;
2974

    
2975
        if (is_array($config['gifs']['gif']))
2976
                foreach ($config['gifs']['gif'] as $gif)
2977
                        if($gif['if'] == $interface)
2978
                                return $gif;
2979
}
2980

    
2981
/*
2982
 * find_interface_ip($interface): return the interface ip (first found)
2983
 */
2984
function find_interface_ip($interface, $flush = false)
2985
{
2986
	global $interface_ip_arr_cache;
2987

    
2988
	$interface = str_replace("\n", "", $interface);
2989
	
2990
	if (!does_interface_exist($interface))
2991
		return;
2992

    
2993
	/* Setup IP cache */
2994
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2995
		$ifinfo = pfSense_get_interface_addresses($interface);
2996
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
2997
	}
2998

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

    
3002
function find_interface_subnet($interface, $flush = false)
3003
{
3004
	global $interface_sn_arr_cache;
3005

    
3006
	$interface = str_replace("\n", "", $interface);
3007
	if (does_interface_exist($interface) == false)
3008
		return;
3009

    
3010
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3011
		$ifinfo = pfSense_get_interface_addresses($interface);
3012
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3013
        }
3014

    
3015
	return $interface_sn_arr_cache[$interface];
3016
}
3017

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

    
3030
	$curip = find_interface_ip($realif);
3031
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3032
		return $curip;
3033
	else
3034
		return null;
3035
}
3036

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

    
3049
	$cursn = find_interface_subnet($realif);
3050
	if (!empty($cursn))
3051
		return $cursn;
3052

    
3053
	return null;
3054
}
3055

    
3056
/* return outside interfaces with a gateway */
3057
function get_interfaces_with_gateway() {
3058
	global $config;
3059

    
3060
	$ints = array();
3061

    
3062
	/* loop interfaces, check config for outbound */
3063
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3064
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3065
			return true;
3066

    
3067
		switch ($ifname['ipaddr']) {
3068
			case "dhcp":
3069
			case "carpdev-dhcp":
3070
			case "ppp";
3071
			case "pppoe":
3072
			case "pptp":
3073
			case "l2tp":
3074
			case "ppp";
3075
				$ints[$ifdescr] = $ifdescr;
3076
			break;
3077
			default:
3078
				if (!empty($ifname['gateway']))
3079
					$ints[$ifdescr] = $ifdescr;
3080
			break;
3081
		}
3082
	}
3083
	return $ints;
3084
}
3085

    
3086
/* return true if interface has a gateway */
3087
function interface_has_gateway($friendly) {
3088
	global $config;
3089

    
3090
	if (!empty($config['interfaces'][$friendly])) {
3091
		if (substr($friendly, 0, 5) ==  "ovpnc")
3092
			return true;
3093
		$ifname =& $config['interfaces'][$friendly];
3094
		switch ($ifname['ipaddr']) {
3095
			case "dhcp":
3096
			case "carpdev-dhcp":
3097
			case "pppoe":
3098
			case "pptp":
3099
			case "l2tp":
3100
			case "ppp";
3101
				return true;
3102
			break;
3103
			default:
3104
				if (!empty($ifname['gateway']))
3105
					return true;
3106
			break;
3107
		}
3108
	}
3109

    
3110
	return false;
3111
}
3112

    
3113
/****f* interfaces/is_altq_capable
3114
 * NAME
3115
 *   is_altq_capable - Test if interface is capable of using ALTQ
3116
 * INPUTS
3117
 *   $int            - string containing interface name
3118
 * RESULT
3119
 *   boolean         - true or false
3120
 ******/
3121

    
3122
function is_altq_capable($int) {
3123
        /* Per:
3124
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3125
         * Only the following drivers have ALTQ support
3126
         */
3127
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3128
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3129
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3130
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
3131
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3132
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3133
			"l2tp", "ppp");
3134

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

    
3137
        if (in_array($int_family[0], $capable))
3138
                return true;
3139
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3140
		return true;
3141
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3142
		return true;
3143
        else
3144
                return false;
3145
}
3146

    
3147
/****f* interfaces/is_interface_wireless
3148
 * NAME
3149
 *   is_interface_wireless - Returns if an interface is wireless
3150
 * RESULT
3151
 *   $tmp       - Returns if an interface is wireless
3152
 ******/
3153
function is_interface_wireless($interface) {
3154
        global $config, $g;
3155

    
3156
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3157
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3158
                if (preg_match($g['wireless_regex'], $interface)) {
3159
                        if (isset($config['interfaces'][$friendly]))
3160
                                $config['interfaces'][$friendly]['wireless'] = array();
3161
                        return true;
3162
                }
3163
                return false;
3164
        } else
3165
                return true;
3166
}
3167

    
3168
function get_wireless_modes($interface) {
3169
	/* return wireless modes and channels */
3170
	$wireless_modes = array();
3171

    
3172
	$wlif = interface_translate_type_to_real($interface);
3173

    
3174
	if(is_interface_wireless($wlif)) {
3175
		$cloned_interface = get_real_interface($interface);
3176
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3177
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3178
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3179

    
3180
		$interface_channels = "";
3181
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3182
		$interface_channel_count = count($interface_channels);
3183

    
3184
		$c = 0;
3185
		while ($c < $interface_channel_count)
3186
		{
3187
			$channel_line = explode(",", $interface_channels["$c"]);
3188
			$wireless_mode = trim($channel_line[0]);
3189
			$wireless_channel = trim($channel_line[1]);
3190
			if(trim($wireless_mode) != "") {
3191
				/* if we only have 11g also set 11b channels */
3192
				if($wireless_mode == "11g") {
3193
					if(!isset($wireless_modes["11b"]))
3194
						$wireless_modes["11b"] = array();
3195
				} else if($wireless_mode == "11g ht") {
3196
					if(!isset($wireless_modes["11b"]))
3197
						$wireless_modes["11b"] = array();
3198
					if(!isset($wireless_modes["11g"]))
3199
						$wireless_modes["11g"] = array();
3200
					$wireless_mode = "11ng";
3201
				} else if($wireless_mode == "11a ht") {
3202
					if(!isset($wireless_modes["11a"]))
3203
						$wireless_modes["11a"] = array();
3204
					$wireless_mode = "11na";
3205
				}
3206
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3207
			}
3208
			$c++;
3209
		}
3210
	}
3211
	return($wireless_modes);
3212
}
3213

    
3214
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3215
function get_wireless_channel_info($interface) {
3216
	$wireless_channels = array();
3217

    
3218
	$wlif = interface_translate_type_to_real($interface);
3219

    
3220
	if(is_interface_wireless($wlif)) {
3221
		$cloned_interface = get_real_interface($interface);
3222
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3223
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3224
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3225

    
3226
		$interface_channels = "";
3227
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3228

    
3229
		foreach ($interface_channels as $channel_line) {
3230
			$channel_line = explode(",", $channel_line);
3231
			if(!isset($wireless_channels[$channel_line[0]]))
3232
				$wireless_channels[$channel_line[0]] = $channel_line;
3233
		}
3234
	}
3235
	return($wireless_channels);
3236
}
3237

    
3238
/****f* interfaces/get_interface_mtu
3239
 * NAME
3240
 *   get_interface_mtu - Return the mtu of an interface
3241
 * RESULT
3242
 *   $tmp       - Returns the mtu of an interface
3243
 ******/
3244
function get_interface_mtu($interface) {
3245
        $mtu = pfSense_get_interface_addresses($interface);
3246
        return $mtu['mtu'];
3247
}
3248

    
3249
function get_interface_mac($interface) {
3250

    
3251
	$macinfo = pfSense_get_interface_addresses($interface);
3252
	return $macinfo["macaddr"];
3253
}
3254

    
3255
/****f* pfsense-utils/generate_random_mac_address
3256
 * NAME
3257
 *   generate_random_mac - generates a random mac address
3258
 * INPUTS
3259
 *   none
3260
 * RESULT
3261
 *   $mac - a random mac address
3262
 ******/
3263
function generate_random_mac_address() {
3264
        $mac = "02";
3265
        for($x=0; $x<5; $x++)
3266
                $mac .= ":" . dechex(rand(16, 255));
3267
        return $mac;
3268
}
3269

    
3270
/****f* interfaces/is_jumbo_capable
3271
 * NAME
3272
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3273
 * INPUTS
3274
 *   $int             - string containing interface name
3275
 * RESULT
3276
 *   boolean          - true or false
3277
 ******/
3278
function is_jumbo_capable($int) {
3279
        global $g;
3280

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

    
3283
        if (in_array($int_family[0], $g['vlan_long_frame']))
3284
                return true;
3285
        else
3286
                return false;
3287
}
3288

    
3289
function setup_pppoe_reset_file($pppif, $iface="") {
3290
	global $g;
3291
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3292

    
3293
	if(!empty($iface) && !empty($pppif)){
3294
		$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";
3295
		file_put_contents($cron_file, $cron_cmd);
3296
		chmod($cron_file, 0700);
3297
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3298
	} else
3299
		unlink_if_exists($cron_file);
3300
}
3301

    
3302
?>
(22-22/53)